diff --git a/addons/mcs_operating_system/models/dashboard.py b/addons/mcs_operating_system/models/dashboard.py index 1e899aa..40f9364 100644 --- a/addons/mcs_operating_system/models/dashboard.py +++ b/addons/mcs_operating_system/models/dashboard.py @@ -181,13 +181,13 @@ class McsOperatingDashboard(models.Model): return True @api.model - def get_ceo_dashboard_v2_data(self): + def get_ceo_dashboard_v2_data(self, selected_company_ids=None): today = fields.Date.context_today(self) month_start = today.replace(day=1) month_end = month_start + relativedelta(months=1, days=-1) week_start = today - relativedelta(days=today.weekday()) week_end = week_start + relativedelta(days=6) - company_ids = self._dashboard_company_ids() + company_ids = self._dashboard_company_ids(selected_company_ids) Lead = self.env["crm.lead"] Project = self.env["project.project"] @@ -275,7 +275,7 @@ class McsOperatingDashboard(models.Model): cash_collected = sum( invoice.amount_total - invoice.amount_residual for invoice in invoices_month ) - operating_cost = self._monthly_operating_cost() + operating_cost = self._monthly_operating_cost(company_ids) revenue_gap = max(monthly_target - contracted_revenue, 0) open_pipeline_value = sum(open_pipeline.mapped("expected_revenue")) weighted_pipeline = sum( @@ -319,6 +319,12 @@ class McsOperatingDashboard(models.Model): "week_end": fields.Date.to_string(week_end), "company_ids": company_ids, "companies": self.env["res.company"].browse(company_ids).mapped("name"), + "company_options": [ + {"id": company.id, "name": company.name} + for company in self.env["res.company"].browse( + self._dashboard_company_ids() + ) + ], }, "company_pulse": { "revenue_coverage": self._format_percent(revenue_coverage), @@ -377,9 +383,20 @@ class McsOperatingDashboard(models.Model): def _format_percent(self, value): return round(value or 0, 1) - def _dashboard_company_ids(self): - company_ids = self.env.context.get("allowed_company_ids") or self.env.companies.ids - return company_ids or [self.env.company.id] + def _dashboard_company_ids(self, selected_company_ids=None): + allowed_company_ids = ( + self.env.context.get("allowed_company_ids") or self.env.companies.ids + ) + allowed_company_ids = allowed_company_ids or [self.env.company.id] + if not selected_company_ids: + return allowed_company_ids + selected_company_ids = [int(company_id) for company_id in selected_company_ids] + selected_company_ids = [ + company_id + for company_id in selected_company_ids + if company_id in allowed_company_ids + ] + return selected_company_ids or allowed_company_ids def _company_domain(self, Model, company_ids, include_shared=True): if "company_id" not in Model._fields: @@ -388,16 +405,15 @@ class McsOperatingDashboard(models.Model): return ["|", ("company_id", "=", False), ("company_id", "in", company_ids)] return [("company_id", "in", company_ids)] - def _monthly_operating_cost(self): + def _monthly_operating_cost(self, company_ids=None): try: Contract = self.env["hr.contract"] except KeyError: return 0 + company_ids = company_ids or self._dashboard_company_ids() contracts = Contract.sudo().search( [("state", "=", "open"), ("employee_id.active", "=", True)] - + self._company_domain( - Contract, self._dashboard_company_ids(), include_shared=True - ) + + self._company_domain(Contract, company_ids, include_shared=True) ) return sum(contracts.mapped("wage")) diff --git a/addons/mcs_operating_system/static/src/js/ceo_dashboard_v2.js b/addons/mcs_operating_system/static/src/js/ceo_dashboard_v2.js index 12694d6..ac7e099 100644 --- a/addons/mcs_operating_system/static/src/js/ceo_dashboard_v2.js +++ b/addons/mcs_operating_system/static/src/js/ceo_dashboard_v2.js @@ -8,7 +8,7 @@ export class McsCeoDashboardV2 extends Component { setup() { this.action = useService("action"); this.orm = useService("orm"); - this.state = useState({ data: null, loading: true }); + this.state = useState({ data: null, loading: true, selectedCompanyId: "all" }); onWillStart(async () => { await this.loadDashboard(); @@ -17,14 +17,31 @@ export class McsCeoDashboardV2 extends Component { async loadDashboard() { this.state.loading = true; + const selectedCompanyIds = this.selectedCompanyIds(); this.state.data = await this.orm.call( "mcs.operating.dashboard", "get_ceo_dashboard_v2_data", - [] + [selectedCompanyIds] ); this.state.loading = false; } + selectedCompanyIds() { + if (this.state.selectedCompanyId === "all") { + return []; + } + return [Number(this.state.selectedCompanyId)]; + } + + async selectCompany(companyId) { + this.state.selectedCompanyId = String(companyId); + await this.loadDashboard(); + } + + isCompanySelected(companyId) { + return this.state.selectedCompanyId === String(companyId); + } + openAction(actionKey) { const action = this.state.data?.actions?.[actionKey]; if (action) { diff --git a/addons/mcs_operating_system/static/src/scss/ceo_dashboard_v2.scss b/addons/mcs_operating_system/static/src/scss/ceo_dashboard_v2.scss index 2bf3163..5baed70 100644 --- a/addons/mcs_operating_system/static/src/scss/ceo_dashboard_v2.scss +++ b/addons/mcs_operating_system/static/src/scss/ceo_dashboard_v2.scss @@ -33,6 +33,25 @@ } } +.o_mcs_header_controls, +.o_mcs_company_switcher { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} + +.o_mcs_company_switcher { + justify-content: flex-end; + + .btn { + max-width: 220px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +} + .o_mcs_pulse { display: grid; grid-template-columns: minmax(220px, 1.4fr) repeat(4, minmax(140px, 1fr)); diff --git a/addons/mcs_operating_system/static/src/xml/ceo_dashboard_v2.xml b/addons/mcs_operating_system/static/src/xml/ceo_dashboard_v2.xml index bfe11f5..10f3e68 100644 --- a/addons/mcs_operating_system/static/src/xml/ceo_dashboard_v2.xml +++ b/addons/mcs_operating_system/static/src/xml/ceo_dashboard_v2.xml @@ -13,9 +13,21 @@ to + - + - +
+
+ + + + +
+ +
@@ -153,7 +165,7 @@ @@ -169,7 +181,7 @@