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 @@