19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:02 +01:00
parent 62d197ac8b
commit 184bb0e321
667 changed files with 691406 additions and 239886 deletions

View file

@ -2,3 +2,4 @@
from . import spreadsheet_dashboard_group
from . import spreadsheet_dashboard
from . import spreadsheet_dashboard_share

View file

@ -1,63 +1,82 @@
import base64
import json
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo import Command, _, api, fields, models
from odoo.tools import file_open
class SpreadsheetDashboard(models.Model):
_name = 'spreadsheet.dashboard'
_description = 'Spreadsheet Dashboard'
_inherit = ["spreadsheet.mixin"]
_order = 'sequence'
name = fields.Char(required=True)
dashboard_group_id = fields.Many2one('spreadsheet.dashboard.group', required=True)
data = fields.Binary(required=True, default=lambda self: self._default_data())
raw = fields.Binary(compute='_compute_raw', inverse='_inverse_raw')
thumbnail = fields.Binary()
name = fields.Char(required=True, translate=True)
dashboard_group_id = fields.Many2one('spreadsheet.dashboard.group', required=True, index=True)
sequence = fields.Integer()
sample_dashboard_file_path = fields.Char(export_string_translation=False)
is_published = fields.Boolean(default=True)
company_ids = fields.Many2many('res.company', string="Companies")
group_ids = fields.Many2many('res.groups', default=lambda self: self.env.ref('base.group_user'))
favorite_user_ids = fields.Many2many(
'res.users',
domain=lambda self: [('id', '=', self.env.uid)],
string='Favorite Users',
help='Users who have favorited this dashboard'
)
is_favorite = fields.Boolean(
compute='_compute_is_favorite',
string='Is Favorite',
help='Indicates whether the dashboard is favorited by the current user'
)
main_data_model_ids = fields.Many2many('ir.model', copy=False)
def _default_data(self):
data = json.dumps(self._empty_workbook_data())
return base64.b64encode(data.encode())
def _empty_workbook_data(self):
"""Create an empty spreadsheet workbook.
The sheet name should be the same for all users to allow consistent references
in formulas. It is translated for the user creating the spreadsheet.
"""
return {
"version": 1,
"sheets": [
{
"id": "sheet1",
"name": _("Sheet1"),
}
]
}
@api.depends('data')
def _compute_raw(self):
@api.depends_context('uid')
@api.depends('favorite_user_ids')
def _compute_is_favorite(self):
for dashboard in self:
dashboard.raw = base64.decodebytes(dashboard.data)
dashboard.is_favorite = self.env.uid in dashboard.favorite_user_ids.ids
def _inverse_raw(self):
for dashboard in self:
dashboard.data = base64.encodebytes(dashboard.raw)
@api.onchange('data')
def _onchange_data_(self):
if self.data:
try:
data_str = base64.b64decode(self.data).decode('utf-8')
json.loads(data_str)
except:
raise ValidationError(_('Invalid JSON Data'))
def copy(self, default=None):
def action_toggle_favorite(self):
self.ensure_one()
if default is None:
default = {}
current_user_id = self.env.uid
if current_user_id in self.favorite_user_ids.ids:
self.sudo().favorite_user_ids = [Command.unlink(current_user_id)]
else:
self.sudo().favorite_user_ids = [Command.link(current_user_id)]
def _get_serialized_readonly_dashboard(self):
snapshot = json.loads(self.spreadsheet_data)
user_locale = self.env['res.lang']._get_user_spreadsheet_locale()
snapshot.setdefault('settings', {})['locale'] = user_locale
default_currency = self.env['res.currency'].get_company_currency_for_spreadsheet()
return json.dumps({
'snapshot': snapshot,
'revisions': [],
'default_currency': default_currency,
'translation_namespace': self._get_dashboard_translation_namespace(),
})
def _get_sample_dashboard(self):
try:
with file_open(self.sample_dashboard_file_path) as f:
return json.load(f)
except FileNotFoundError:
return
def _dashboard_is_empty(self):
return any(self.env[model].search_count([], limit=1) == 0 for model in self.sudo().main_data_model_ids.mapped("model"))
def _get_dashboard_translation_namespace(self):
data = self.env['ir.model.data'].sudo().search([
('model', '=', self._name),
('res_id', 'in', self.ids),
], limit=1)
return data.module
def copy_data(self, default=None):
default = dict(default or {})
vals_list = super().copy_data(default=default)
if 'name' not in default:
default['name'] = _("%s (copy)") % self.name
return super().copy(default=default)
for dashboard, vals in zip(self, vals_list):
vals['name'] = _("%s (copy)", dashboard.name)
return vals_list

View file

@ -7,8 +7,9 @@ class SpreadsheetDashboardGroup(models.Model):
_description = 'Group of dashboards'
_order = 'sequence'
name = fields.Char(required=True)
name = fields.Char(required=True, translate=True)
dashboard_ids = fields.One2many('spreadsheet.dashboard', 'dashboard_group_id')
published_dashboard_ids = fields.One2many('spreadsheet.dashboard', 'dashboard_group_id', domain=[('is_published', '=', True)])
sequence = fields.Integer()
@api.ondelete(at_uninstall=False)

View file

@ -0,0 +1,46 @@
import base64
import uuid
from werkzeug.exceptions import Forbidden
from odoo import models, fields, api, _
from odoo.tools import consteq
class SpreadsheetDashboardShare(models.Model):
_name = 'spreadsheet.dashboard.share'
_inherit = ['spreadsheet.mixin']
_description = 'Copy of a shared dashboard'
dashboard_id = fields.Many2one('spreadsheet.dashboard', required=True, ondelete='cascade')
excel_export = fields.Binary()
access_token = fields.Char(required=True, default=lambda _x: str(uuid.uuid4()))
full_url = fields.Char(string="URL", compute='_compute_full_url')
name = fields.Char(related='dashboard_id.name')
@api.depends('access_token')
def _compute_full_url(self):
for share in self:
share.full_url = "%s/dashboard/share/%s/%s" % (share.get_base_url(), share.id, share.access_token)
@api.model
def action_get_share_url(self, vals):
if "excel_files" in vals:
excel_zip = self._zip_xslx_files(
vals["excel_files"]
)
del vals["excel_files"]
vals["excel_export"] = base64.b64encode(excel_zip)
return self.create(vals).full_url
def _check_token(self, access_token):
if not access_token:
return False
return consteq(access_token, self.access_token)
def _check_dashboard_access(self, access_token):
self.ensure_one()
token_access = self._check_token(access_token)
dashboard = self.dashboard_id.with_user(self.create_uid)
user_access = dashboard.has_access("read")
if not (token_access and user_access):
raise Forbidden(_("You don't have access to this dashboard. "))