Skip to content

Commit 1617767

Browse files
author
Laurent Stukkens
committed
[IMP] mis-builder: set analytic account constraint in the filter when displayed
This commit extracts, when the filters are displayed, the domain info from the `mis_analytic_domain` context key or from the analyticAccountIdField props and add it to the active filters. The system prevents the user from removing the constraint.
1 parent 313bee0 commit 1617767

File tree

3 files changed

+150
-33
lines changed

3 files changed

+150
-33
lines changed

Diff for: mis_builder/__manifest__.py

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
],
3030
"assets": {
3131
"web.assets_backend": [
32+
"mis_builder/static/src/components/search_model.esm.js",
3233
"mis_builder/static/src/components/mis_report_widget.esm.js",
3334
"mis_builder/static/src/components/mis_report_widget.xml",
3435
"mis_builder/static/src/components/mis_report_widget.css",

Diff for: mis_builder/static/src/components/mis_report_widget.esm.js

+44-33
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import {Component, onWillStart, useState, useSubEnv} from "@odoo/owl";
44
import {useBus, useService} from "@web/core/utils/hooks";
55
import {DatePicker} from "@web/core/datepicker/datepicker";
6-
import {Domain} from "@web/core/domain";
76
import {FilterMenu} from "@web/search/filter_menu/filter_menu";
7+
import {MisReportSearchModel} from "@mis_builder/components/search_model.esm";
88
import {SearchBar} from "@web/search/search_bar/search_bar";
9-
import {SearchModel} from "@web/search/search_model";
109
import {parseDate} from "@web/core/l10n/dates";
1110
import {registry} from "@web/core/registry";
1211
import {standardFieldProps} from "@web/views/fields/standard_field_props";
@@ -23,7 +22,7 @@ export class MisReportWidget extends Component {
2322
mis_report_data: {header: [], body: []},
2423
pivot_date: null,
2524
});
26-
this.searchModel = new SearchModel(this.env, {
25+
this.searchModel = new MisReportSearchModel(this.env, {
2726
user: this.user,
2827
orm: this.orm,
2928
view: this.view,
@@ -63,6 +62,7 @@ export class MisReportWidget extends Component {
6362
await this.searchModel.load({
6463
resModel: this.source_aml_model_name,
6564
searchViewId: this.widget_search_view_id,
65+
analyticAccountId: this.analyticAccountId,
6666
});
6767
}
6868

@@ -111,12 +111,10 @@ export class MisReportWidget extends Component {
111111

112112
get context() {
113113
let ctx = this.props.record.context;
114-
this.setMisAnalyticDomainContextKey(ctx);
115114
if (this.showSearchBar && this.searchModel.searchDomain) {
116-
ctx[this.misAnalyticDomainContextKey] = Domain.and([
117-
ctx[this.misAnalyticDomainContextKey],
118-
new Domain(this.searchModel.searchDomain),
119-
]).toList();
115+
ctx[this.misAnalyticDomainContextKey] = this.searchModel.searchDomain;
116+
} else {
117+
this._setMisAnalyticDomainContextKey(ctx);
120118
}
121119
if (this.showPivotDate && this.state.pivot_date) {
122120
ctx = {
@@ -147,34 +145,47 @@ export class MisReportWidget extends Component {
147145
);
148146
}
149147

150-
setMisAnalyticDomainContextKey(context) {
148+
get analyticAccountId() {
149+
let analyticAccountId = this._getAnalyticAccountIdFromData();
151150
if (
152-
this.props.analytic_account_id_field &&
153-
!(this.misAnalyticDomainContextKey in context)
151+
!analyticAccountId &&
152+
this.props.record.context &&
153+
this.props.record.context.mis_analytic_domain
154154
) {
155-
let analyticAccountId = false;
156-
const analyticAccountIdFieldType =
157-
this.props.record.fields[this.props.analytic_account_id_field].type;
158-
switch (analyticAccountIdFieldType) {
159-
case "many2one":
160-
analyticAccountId =
161-
this.props.record.data[this.props.analytic_account_id_field][0];
162-
break;
163-
case "integer":
164-
analyticAccountId =
165-
this.props.record.data[this.props.analytic_account_id_field];
166-
break;
167-
default:
168-
throw new Error(
169-
```Unsupported field type for analytic_account_id: ${analyticAccountIdFieldType}```
170-
);
171-
}
172-
if (analyticAccountId) {
173-
context[this.misAnalyticDomainContextKey] = [
174-
["analytic_account_id", "=", analyticAccountId],
175-
];
176-
}
155+
analyticAccountId = this.props.record.context.mis_analytic_domain[0][2];
177156
}
157+
return analyticAccountId;
158+
}
159+
160+
_getAnalyticAccountIdFromData() {
161+
if (
162+
!this.props.analyticAccountIdField ||
163+
!(this.props.analyticAccountIdField in this.props.record.fields)
164+
) {
165+
return false;
166+
}
167+
const analyticAccountIdFieldType =
168+
this.props.record.fields[this.props.analyticAccountIdField].type;
169+
switch (analyticAccountIdFieldType) {
170+
case "many2one":
171+
return this.props.record.data[this.props.analyticAccountIdField][0];
172+
case "integer":
173+
return this.props.record.data[this.props.analyticAccountIdField];
174+
default:
175+
throw new Error(
176+
```Unsupported field type for analytic_account_id: ${analyticAccountIdFieldType}```
177+
);
178+
}
179+
}
180+
181+
_setMisAnalyticDomainContextKey(context) {
182+
const analyticAccountId = this._getAnalyticAccountIdFromData();
183+
if (!analyticAccountId) {
184+
return;
185+
}
186+
context[this.misAnalyticDomainContextKey] = [
187+
["analytic_account_id", "=", analyticAccountId],
188+
];
178189
}
179190

180191
async printPdf() {
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/** @odoo-module **/
2+
3+
import {SearchModel} from "@web/search/search_model";
4+
import {useService} from "@web/core/utils/hooks";
5+
6+
export class MisReportSearchModel extends SearchModel {
7+
/**
8+
* @override
9+
*/
10+
setup() {
11+
this.notificationService = useService("notification");
12+
super.setup(...arguments);
13+
}
14+
15+
/**
16+
* @override
17+
*/
18+
deactivateGroup(groupId) {
19+
// Prevent removing the analytic account filter and let the user know.
20+
let reactivateAnalyticAccountFilter = false;
21+
if (this.analyticAccountSearchItem.groupId === groupId) {
22+
if (
23+
this.query.filter(
24+
(query) => query.searchItemId === this.analyticAccountSearchItem.id
25+
).length === 1
26+
) {
27+
this.notificationService.add(
28+
this.env._t("The analytic account filter cannot be removed"),
29+
{type: "info"}
30+
);
31+
return;
32+
}
33+
// As there are more than one filter on the analytic account, let
34+
// super remove them and add it back after.
35+
reactivateAnalyticAccountFilter = true;
36+
}
37+
super.deactivateGroup(groupId);
38+
if (reactivateAnalyticAccountFilter) {
39+
this._addAnalyticAccountFilter();
40+
}
41+
}
42+
43+
/**
44+
* @override
45+
*/
46+
async load(config) {
47+
// Store analytic account id in the SearchModel for reuse in other functions.
48+
this.analyticAccountId = config.analyticAccountId;
49+
const analyticAccountNamePromise = this._loadAnalyticAccountName();
50+
await Promise.all([analyticAccountNamePromise, super.load(...arguments)]);
51+
this._determineAnalyticAccountSearchItem();
52+
this._addAnalyticAccountFilter();
53+
}
54+
55+
/**
56+
* Add the filter regarding the analytic account in the search model.
57+
* @private
58+
*/
59+
_addAnalyticAccountFilter() {
60+
if (!this.analyticAccountSearchItem || !this.analyticAccountName) {
61+
return;
62+
}
63+
this.addAutoCompletionValues(this.analyticAccountSearchItem.id, {
64+
label: this.analyticAccountName,
65+
operator: "=",
66+
value: this.analyticAccountId,
67+
});
68+
}
69+
70+
/**
71+
* Find the searchItem that correspond to the analytic account field and store it
72+
* under analyticAccountSearchItem.
73+
* @private
74+
*/
75+
_determineAnalyticAccountSearchItem() {
76+
// Store analytic account searchItem in the SearchModel for reuse in other functions.
77+
for (const searchItem of Object.values(this.searchItems)) {
78+
if (
79+
searchItem.type === "field" &&
80+
searchItem.fieldName === "analytic_account_id"
81+
) {
82+
this.analyticAccountSearchItem = searchItem;
83+
break;
84+
}
85+
}
86+
}
87+
88+
/**
89+
* Load the analytic account name and store it under analyticAccountName.
90+
* @returns {Promise<void>}
91+
* @private
92+
*/
93+
async _loadAnalyticAccountName() {
94+
if (!this.analyticAccountId) {
95+
return;
96+
}
97+
const readResult = await this.orm.read(
98+
"account.analytic.account",
99+
[this.analyticAccountId],
100+
["display_name"]
101+
);
102+
const analyticAccount = readResult[0];
103+
this.analyticAccountName = analyticAccount.display_name;
104+
}
105+
}

0 commit comments

Comments
 (0)