odoo-addon-mis-builder 16.0.5.2.3.1__py3-none-any.whl → 16.0.5.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/mis_builder/README.rst +1 -1
- odoo/addons/mis_builder/__manifest__.py +2 -1
- odoo/addons/mis_builder/i18n/ca.po +91 -0
- odoo/addons/mis_builder/i18n/de.po +91 -0
- odoo/addons/mis_builder/i18n/el.po +91 -0
- odoo/addons/mis_builder/i18n/el_GR.po +91 -0
- odoo/addons/mis_builder/i18n/es.po +91 -0
- odoo/addons/mis_builder/i18n/fr.po +91 -0
- odoo/addons/mis_builder/i18n/hr.po +91 -0
- odoo/addons/mis_builder/i18n/it.po +91 -0
- odoo/addons/mis_builder/i18n/mis_builder.pot +97 -0
- odoo/addons/mis_builder/i18n/nl.po +91 -0
- odoo/addons/mis_builder/i18n/nl_NL.po +91 -0
- odoo/addons/mis_builder/i18n/pt.po +91 -0
- odoo/addons/mis_builder/i18n/pt_BR.po +91 -0
- odoo/addons/mis_builder/i18n/sv.po +91 -0
- odoo/addons/mis_builder/i18n/tr.po +91 -0
- odoo/addons/mis_builder/models/__init__.py +1 -0
- odoo/addons/mis_builder/models/kpimatrix.py +39 -4
- odoo/addons/mis_builder/models/mis_report_instance.py +71 -1
- odoo/addons/mis_builder/models/mis_report_instance_annotation.py +113 -0
- odoo/addons/mis_builder/report/mis_report_instance_qweb.xml +23 -0
- odoo/addons/mis_builder/report/mis_report_instance_xlsx.py +11 -1
- odoo/addons/mis_builder/security/ir.model.access.csv +2 -0
- odoo/addons/mis_builder/security/res_groups.xml +17 -0
- odoo/addons/mis_builder/static/description/index.html +1 -1
- odoo/addons/mis_builder/static/src/components/mis_report_widget.css +41 -0
- odoo/addons/mis_builder/static/src/components/mis_report_widget.esm.js +109 -4
- odoo/addons/mis_builder/static/src/components/mis_report_widget.xml +104 -13
- odoo/addons/mis_builder/static/src/css/report.css +22 -0
- odoo/addons/mis_builder/tests/__init__.py +1 -0
- odoo/addons/mis_builder/tests/test_mis_report_instance_annotation.py +154 -0
- odoo/addons/mis_builder/views/mis_report_instance.xml +1 -0
- {odoo_addon_mis_builder-16.0.5.2.3.1.dist-info → odoo_addon_mis_builder-16.0.5.4.0.dist-info}/METADATA +2 -2
- {odoo_addon_mis_builder-16.0.5.2.3.1.dist-info → odoo_addon_mis_builder-16.0.5.4.0.dist-info}/RECORD +37 -34
- {odoo_addon_mis_builder-16.0.5.2.3.1.dist-info → odoo_addon_mis_builder-16.0.5.4.0.dist-info}/WHEEL +0 -0
- {odoo_addon_mis_builder-16.0.5.2.3.1.dist-info → odoo_addon_mis_builder-16.0.5.4.0.dist-info}/top_level.txt +0 -0
@@ -23,6 +23,10 @@
|
|
23
23
|
.oe_mis_builder_content {
|
24
24
|
}
|
25
25
|
|
26
|
+
.oe_mis_builder_report_wide_sheet {
|
27
|
+
max-width: 95% !important;
|
28
|
+
}
|
29
|
+
|
26
30
|
/* style for the control panel (search box and buttons) */
|
27
31
|
|
28
32
|
.oe_mis_builder_cp {
|
@@ -44,6 +48,11 @@
|
|
44
48
|
max-width: 1280px;
|
45
49
|
}
|
46
50
|
|
51
|
+
.oe_mis_builder_cp_right_top_right {
|
52
|
+
display: flex;
|
53
|
+
flex-direction: row;
|
54
|
+
}
|
55
|
+
|
47
56
|
.oe_mis_builder_cp_right_top {
|
48
57
|
display: flex;
|
49
58
|
flex-direction: row;
|
@@ -65,3 +74,35 @@
|
|
65
74
|
flex-grow: 1;
|
66
75
|
justify-content: flex-end;
|
67
76
|
}
|
77
|
+
|
78
|
+
.oe_mis_builder_dropdown {
|
79
|
+
overflow: visible !important;
|
80
|
+
}
|
81
|
+
|
82
|
+
.oe_mis_builder_footnote {
|
83
|
+
font-size: 80%;
|
84
|
+
color: red;
|
85
|
+
position: relative;
|
86
|
+
bottom: 1ex;
|
87
|
+
width: 1em;
|
88
|
+
display: inline-block;
|
89
|
+
padding-right: 1px;
|
90
|
+
}
|
91
|
+
|
92
|
+
.oe_mis_builder_footnote_table {
|
93
|
+
list-style: none;
|
94
|
+
white-space: pre-wrap;
|
95
|
+
display: inline-block;
|
96
|
+
|
97
|
+
td {
|
98
|
+
vertical-align: top;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
.oe_mis_builder_footnote_div {
|
103
|
+
padding-top: 1em;
|
104
|
+
}
|
105
|
+
|
106
|
+
.oe_mis_builder_menu_disabled {
|
107
|
+
color: gainsboro;
|
108
|
+
}
|
@@ -1,13 +1,15 @@
|
|
1
1
|
/** @odoo-module **/
|
2
2
|
|
3
|
-
import
|
4
|
-
import {
|
3
|
+
import Dialog from "web.Dialog";
|
4
|
+
import {Component, onMounted, onWillStart, useState, useSubEnv} from "@odoo/owl";
|
5
5
|
import {DatePicker} from "@web/core/datepicker/datepicker";
|
6
6
|
import {FilterMenu} from "@web/search/filter_menu/filter_menu";
|
7
7
|
import {SearchBar} from "@web/search/search_bar/search_bar";
|
8
8
|
import {SearchModel} from "@web/search/search_model";
|
9
9
|
import {parseDate} from "@web/core/l10n/dates";
|
10
|
+
import {qweb} from "web.core";
|
10
11
|
import {registry} from "@web/core/registry";
|
12
|
+
import {useBus, useService} from "@web/core/utils/hooks";
|
11
13
|
|
12
14
|
export class MisReportWidget extends Component {
|
13
15
|
setup() {
|
@@ -18,8 +20,10 @@ export class MisReportWidget extends Component {
|
|
18
20
|
this.view = useService("view");
|
19
21
|
this.JSON = JSON;
|
20
22
|
this.state = useState({
|
21
|
-
mis_report_data: {header: [], body: []},
|
23
|
+
mis_report_data: {header: [], body: [], notes: {}},
|
22
24
|
pivot_date: null,
|
25
|
+
can_edit_annotation: false,
|
26
|
+
can_read_annotation: false,
|
23
27
|
});
|
24
28
|
this.searchModel = new SearchModel(this.env, {
|
25
29
|
user: this.user,
|
@@ -32,6 +36,8 @@ export class MisReportWidget extends Component {
|
|
32
36
|
this.refresh();
|
33
37
|
});
|
34
38
|
onWillStart(this.willStart);
|
39
|
+
|
40
|
+
onMounted(this._onMounted);
|
35
41
|
}
|
36
42
|
|
37
43
|
// Lifecycle
|
@@ -46,6 +52,9 @@ export class MisReportWidget extends Component {
|
|
46
52
|
"widget_search_view_id",
|
47
53
|
"pivot_date",
|
48
54
|
"widget_show_pivot_date",
|
55
|
+
"user_can_read_annotation",
|
56
|
+
"user_can_edit_annotation",
|
57
|
+
"wide_display_by_default",
|
49
58
|
],
|
50
59
|
{context: this.context}
|
51
60
|
);
|
@@ -64,8 +73,16 @@ export class MisReportWidget extends Component {
|
|
64
73
|
});
|
65
74
|
}
|
66
75
|
|
76
|
+
this.wide_display = result.wide_display_by_default;
|
77
|
+
|
67
78
|
// Compute the report
|
68
79
|
this.refresh();
|
80
|
+
this.state.can_edit_annotation = result.user_can_edit_annotation;
|
81
|
+
this.state.can_read_annotation = result.user_can_read_annotation;
|
82
|
+
}
|
83
|
+
|
84
|
+
async _onMounted() {
|
85
|
+
this.resize_sheet();
|
69
86
|
}
|
70
87
|
|
71
88
|
get showSearchBar() {
|
@@ -121,7 +138,7 @@ export class MisReportWidget extends Component {
|
|
121
138
|
}
|
122
139
|
|
123
140
|
async drilldown(event) {
|
124
|
-
const drilldown =
|
141
|
+
const drilldown = JSON.parse(event.target.dataset.drilldown);
|
125
142
|
const action = await this.orm.call(
|
126
143
|
"mis.report.instance",
|
127
144
|
"drilldown",
|
@@ -140,6 +157,15 @@ export class MisReportWidget extends Component {
|
|
140
157
|
);
|
141
158
|
}
|
142
159
|
|
160
|
+
async refresh_annotation() {
|
161
|
+
this.state.mis_report_data.notes = await this.orm.call(
|
162
|
+
"mis.report.instance",
|
163
|
+
"get_notes_by_cell_id",
|
164
|
+
[this._instanceId()],
|
165
|
+
{context: this.context}
|
166
|
+
);
|
167
|
+
}
|
168
|
+
|
143
169
|
async printPdf() {
|
144
170
|
const action = await this.orm.call(
|
145
171
|
"mis.report.instance",
|
@@ -170,10 +196,89 @@ export class MisReportWidget extends Component {
|
|
170
196
|
this.action.doAction(action);
|
171
197
|
}
|
172
198
|
|
199
|
+
async _remove_annotation(cell_id) {
|
200
|
+
await this.orm.call(
|
201
|
+
"mis.report.instance.annotation",
|
202
|
+
"remove_annotation",
|
203
|
+
[cell_id, this._instanceId()],
|
204
|
+
{context: this.context}
|
205
|
+
);
|
206
|
+
this.refresh_annotation();
|
207
|
+
}
|
208
|
+
|
209
|
+
async _save_annotation(cell_id) {
|
210
|
+
const text = document.querySelector(".o_mis_builder_annotation_text").value;
|
211
|
+
await this.orm.call(
|
212
|
+
"mis.report.instance.annotation",
|
213
|
+
"set_annotation",
|
214
|
+
[cell_id, this._instanceId(), text],
|
215
|
+
{context: this.context}
|
216
|
+
);
|
217
|
+
await this.refresh_annotation();
|
218
|
+
}
|
219
|
+
|
220
|
+
async annotate(event) {
|
221
|
+
const cell_id = event.target.dataset.cellId;
|
222
|
+
const note = this.state.mis_report_data.notes[cell_id];
|
223
|
+
const note_text = (note && note.text) || "";
|
224
|
+
var buttons = [
|
225
|
+
{
|
226
|
+
text: this.env._t("Save"),
|
227
|
+
classes: "btn-primary",
|
228
|
+
close: true,
|
229
|
+
click: this._save_annotation.bind(this, cell_id),
|
230
|
+
},
|
231
|
+
{
|
232
|
+
text: this.env._t("Cancel"),
|
233
|
+
close: true,
|
234
|
+
},
|
235
|
+
];
|
236
|
+
if (typeof note !== "undefined") {
|
237
|
+
buttons.push({
|
238
|
+
text: this.env._t("Remove"),
|
239
|
+
classes: "btn-secondary",
|
240
|
+
close: true,
|
241
|
+
click: this._remove_annotation.bind(this, cell_id),
|
242
|
+
});
|
243
|
+
}
|
244
|
+
|
245
|
+
new Dialog(this, {
|
246
|
+
title: "Annotate",
|
247
|
+
size: "medium",
|
248
|
+
$content: $(
|
249
|
+
qweb.render("mis_builder.annotation_dialog", {
|
250
|
+
text: note_text,
|
251
|
+
})
|
252
|
+
),
|
253
|
+
buttons: buttons,
|
254
|
+
}).open();
|
255
|
+
}
|
256
|
+
|
257
|
+
async remove_annotation(event) {
|
258
|
+
const cell_id = event.target.dataset.cellId;
|
259
|
+
this._remove_annotation(cell_id);
|
260
|
+
}
|
261
|
+
|
173
262
|
onDateTimeChanged(ev) {
|
174
263
|
this.state.pivot_date = ev;
|
175
264
|
this.refresh();
|
176
265
|
}
|
266
|
+
|
267
|
+
async toggle_wide_display() {
|
268
|
+
this.wide_display = !this.wide_display;
|
269
|
+
this.resize_sheet();
|
270
|
+
}
|
271
|
+
|
272
|
+
async resize_sheet() {
|
273
|
+
var sheet_element = document.getElementsByClassName("o_form_sheet")[0];
|
274
|
+
sheet_element.classList.toggle(
|
275
|
+
"oe_mis_builder_report_wide_sheet",
|
276
|
+
this.wide_display
|
277
|
+
);
|
278
|
+
var button_resize_element = document.getElementById("icon_resize");
|
279
|
+
button_resize_element.classList.toggle("fa-expand", !this.wide_display);
|
280
|
+
button_resize_element.classList.toggle("fa-compress", this.wide_display);
|
281
|
+
}
|
177
282
|
}
|
178
283
|
|
179
284
|
MisReportWidget.components = {FilterMenu, SearchBar, DatePicker};
|
@@ -4,10 +4,21 @@
|
|
4
4
|
<t t-name="mis_builder.MisReportWidget" owl="1">
|
5
5
|
<div class="oe_mis_builder_content">
|
6
6
|
<t t-if="state.mis_report_data">
|
7
|
+
<t t-set="notes" t-value="state.mis_report_data.notes" />
|
7
8
|
<div class="oe_mis_builder_cp">
|
8
9
|
<div class="oe_mis_builder_cp_left">
|
9
10
|
</div>
|
10
11
|
<div class="oe_mis_builder_cp_right">
|
12
|
+
<div class="oe_mis_builder_cp_right_top_right">
|
13
|
+
<div class="oe_mis_builder_action_buttons">
|
14
|
+
<button
|
15
|
+
t-on-click="toggle_wide_display"
|
16
|
+
class="btn btn-secondary"
|
17
|
+
>
|
18
|
+
<i id="icon_resize" class="fa" />
|
19
|
+
</button>
|
20
|
+
</div>
|
21
|
+
</div>
|
11
22
|
<div class="oe_mis_builder_cp_right_top">
|
12
23
|
<SearchBar t-if="showSearchBar" />
|
13
24
|
</div>
|
@@ -85,21 +96,65 @@
|
|
85
96
|
t-as="cell"
|
86
97
|
t-key="cell_index"
|
87
98
|
t-att="{'style': cell.style, 'title': cell.val_c}"
|
88
|
-
class="mis_builder_amount"
|
99
|
+
class="mis_builder_amount oe_mis_builder_dropdown"
|
89
100
|
>
|
90
|
-
<
|
91
|
-
<
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
101
|
+
<div>
|
102
|
+
<t t-if="cell.drilldown_arg">
|
103
|
+
<a
|
104
|
+
href="javascript:void(0)"
|
105
|
+
class="mis_builder_drilldown"
|
106
|
+
t-on-click="drilldown"
|
107
|
+
t-att-data-drilldown="JSON.stringify(cell.drilldown_arg)"
|
108
|
+
>
|
109
|
+
<t t-esc="cell.val_r" />
|
110
|
+
</a>
|
111
|
+
</t>
|
112
|
+
<t t-else="">
|
97
113
|
<t t-esc="cell.val_r" />
|
98
|
-
</
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
114
|
+
</t>
|
115
|
+
<span class="oe_mis_builder_footnote">
|
116
|
+
<div t-if="notes[cell.cell_id]">
|
117
|
+
<a
|
118
|
+
t-att-id="'note_'+notes[cell.cell_id].sequence"
|
119
|
+
t-out="notes[cell.cell_id] and notes[cell.cell_id].sequence"
|
120
|
+
t-att="{'title': notes[cell.cell_id].text}"
|
121
|
+
href="#footnotes"
|
122
|
+
/>
|
123
|
+
</div>
|
124
|
+
</span>
|
125
|
+
|
126
|
+
<div id="dropdown_menu" class="btn-group">
|
127
|
+
<div
|
128
|
+
class="dropdown"
|
129
|
+
t-if="state.can_edit_annotation and cell.can_be_annotated"
|
130
|
+
>
|
131
|
+
<div
|
132
|
+
data-bs-toggle="dropdown"
|
133
|
+
t-attf-class="dropdown-toggle"
|
134
|
+
/>
|
135
|
+
|
136
|
+
<div
|
137
|
+
class="dropdown-menu o_filter_menu"
|
138
|
+
role="menu"
|
139
|
+
>
|
140
|
+
<a
|
141
|
+
href="javascript:void(0)"
|
142
|
+
t-on-click="annotate"
|
143
|
+
t-att-data-cell-id="cell.cell_id"
|
144
|
+
role="menuitem"
|
145
|
+
class="dropdown-item js_tag"
|
146
|
+
>
|
147
|
+
Annotate
|
148
|
+
</a>
|
149
|
+
</div>
|
150
|
+
</div>
|
151
|
+
<!-- show menu as disabled -->
|
152
|
+
<div
|
153
|
+
t-else=""
|
154
|
+
class="dropdown-toggle oe_mis_builder_menu_disabled"
|
155
|
+
/>
|
156
|
+
</div>
|
157
|
+
</div>
|
103
158
|
</td>
|
104
159
|
</tr>
|
105
160
|
</tbody>
|
@@ -108,8 +163,44 @@
|
|
108
163
|
</tfoot>
|
109
164
|
</table>
|
110
165
|
</div>
|
166
|
+
<!-- Adding notes -->
|
167
|
+
<div class="oe_mis_builder_footnote_div" id="footnotes">
|
168
|
+
<table class="oe_mis_builder_footnote_table">
|
169
|
+
<t
|
170
|
+
t-foreach="state.mis_report_data.notes"
|
171
|
+
t-as="cell_id"
|
172
|
+
t-key="cell_id"
|
173
|
+
>
|
174
|
+
<tr>
|
175
|
+
<td><a
|
176
|
+
t-out="notes[cell_id].sequence"
|
177
|
+
t-att-href="'#note_'+notes[cell_id].sequence"
|
178
|
+
/>. </td>
|
179
|
+
<td><t t-out="notes[cell_id].text" /></td>
|
180
|
+
<td><i
|
181
|
+
href="javascript:void(0)"
|
182
|
+
t-on-click="remove_annotation"
|
183
|
+
t-att-data-cell-id="cell_id"
|
184
|
+
class="btn fa fa-trash-o"
|
185
|
+
t-if="state.can_edit_annotation"
|
186
|
+
/></td>
|
187
|
+
</tr>
|
188
|
+
</t>
|
189
|
+
</table>
|
190
|
+
</div>
|
111
191
|
</t>
|
112
192
|
</div>
|
113
193
|
</t>
|
114
194
|
|
195
|
+
<t t-name="mis_builder.annotation_dialog">
|
196
|
+
<form role="form">
|
197
|
+
<textarea
|
198
|
+
class="o_mis_builder_annotation_text"
|
199
|
+
name="note"
|
200
|
+
rows='4'
|
201
|
+
placeholder="Insert note here"
|
202
|
+
><t t-out="text" t-att-data-textnote="text" /></textarea>
|
203
|
+
</form>
|
204
|
+
</t>
|
205
|
+
|
115
206
|
</templates>
|
@@ -44,3 +44,25 @@
|
|
44
44
|
.mis_table .mis_cell.mis_amount {
|
45
45
|
text-align: right;
|
46
46
|
}
|
47
|
+
.oe_mis_builder_footnote {
|
48
|
+
font-size: 70%;
|
49
|
+
color: red;
|
50
|
+
position: relative;
|
51
|
+
bottom: 1ex;
|
52
|
+
width: 1em;
|
53
|
+
display: inline-block;
|
54
|
+
padding-right: 1px;
|
55
|
+
}
|
56
|
+
.oe_mis_builder_footnote_div {
|
57
|
+
padding-top: 1em;
|
58
|
+
}
|
59
|
+
|
60
|
+
.oe_mis_builder_footnote_table {
|
61
|
+
list-style: none;
|
62
|
+
white-space: pre-wrap;
|
63
|
+
display: inline-block;
|
64
|
+
|
65
|
+
td {
|
66
|
+
vertical-align: top;
|
67
|
+
}
|
68
|
+
}
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# Copyright 2025 ACSONE SA/NV
|
2
|
+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
3
|
+
|
4
|
+
from odoo import Command
|
5
|
+
from odoo.tests.common import TransactionCase
|
6
|
+
|
7
|
+
|
8
|
+
class TestMisReportInstanceAnnotation(TransactionCase):
|
9
|
+
def setUp(self):
|
10
|
+
super().setUp()
|
11
|
+
self.report = self.env["mis.report"].create(
|
12
|
+
dict(
|
13
|
+
name="test report",
|
14
|
+
subkpi_ids=[
|
15
|
+
Command.create(
|
16
|
+
dict(
|
17
|
+
name="subkpi1_report2",
|
18
|
+
description="subkpi 1, report 2",
|
19
|
+
sequence=1,
|
20
|
+
)
|
21
|
+
),
|
22
|
+
Command.create(
|
23
|
+
dict(
|
24
|
+
name="subkpi2_report2",
|
25
|
+
description="subkpi 2, report 2",
|
26
|
+
sequence=2,
|
27
|
+
),
|
28
|
+
),
|
29
|
+
],
|
30
|
+
)
|
31
|
+
)
|
32
|
+
|
33
|
+
self.kpi = self.env["mis.report.kpi"].create(
|
34
|
+
dict(
|
35
|
+
report_id=self.report.id,
|
36
|
+
description="kpi 1",
|
37
|
+
name="k1",
|
38
|
+
multi=True,
|
39
|
+
expression_ids=[
|
40
|
+
Command.create(
|
41
|
+
dict(name="bale[200%]", subkpi_id=self.report.subkpi_ids[0].id),
|
42
|
+
),
|
43
|
+
Command.create(
|
44
|
+
dict(name="balp[200%]", subkpi_id=self.report.subkpi_ids[1].id),
|
45
|
+
),
|
46
|
+
],
|
47
|
+
)
|
48
|
+
)
|
49
|
+
|
50
|
+
self.report_instance = self.env["mis.report.instance"].create(
|
51
|
+
dict(
|
52
|
+
name="test instance",
|
53
|
+
report_id=self.report.id,
|
54
|
+
company_id=self.env.ref("base.main_company").id,
|
55
|
+
period_ids=[
|
56
|
+
Command.create(
|
57
|
+
dict(
|
58
|
+
name="p1",
|
59
|
+
mode="fix",
|
60
|
+
manual_date_from="2013-01-01",
|
61
|
+
manual_date_to="2013-12-31",
|
62
|
+
sequence=1,
|
63
|
+
),
|
64
|
+
),
|
65
|
+
Command.create(
|
66
|
+
dict(
|
67
|
+
name="p2",
|
68
|
+
mode="fix",
|
69
|
+
manual_date_from="2014-01-01",
|
70
|
+
manual_date_to="2014-12-31",
|
71
|
+
sequence=2,
|
72
|
+
),
|
73
|
+
),
|
74
|
+
],
|
75
|
+
)
|
76
|
+
)
|
77
|
+
|
78
|
+
def test_adding_note(self):
|
79
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
80
|
+
|
81
|
+
self.assertEqual({}, notes)
|
82
|
+
|
83
|
+
# report with 4 cells, 2 periods and 2 subkpis
|
84
|
+
matrix = self.report_instance._compute_matrix()
|
85
|
+
cell_ids = [c.cell_id for row in matrix.iter_rows() for c in row.iter_cells()]
|
86
|
+
self.assertEqual(len(cell_ids), 4)
|
87
|
+
|
88
|
+
first_cell_id, second_cell_id, third_cell_id, _fourth_cell_id = cell_ids
|
89
|
+
|
90
|
+
# adding one note
|
91
|
+
self.env["mis.report.instance.annotation"].set_annotation(
|
92
|
+
first_cell_id, self.report_instance.id, "This is a note"
|
93
|
+
)
|
94
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
95
|
+
self.assertDictEqual(
|
96
|
+
{first_cell_id: {"text": "This is a note", "sequence": 1}}, notes
|
97
|
+
)
|
98
|
+
|
99
|
+
# adding another note
|
100
|
+
self.env["mis.report.instance.annotation"].set_annotation(
|
101
|
+
third_cell_id, self.report_instance.id, "This is another note"
|
102
|
+
)
|
103
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
104
|
+
self.assertDictEqual(
|
105
|
+
{
|
106
|
+
first_cell_id: {"text": "This is a note", "sequence": 1},
|
107
|
+
third_cell_id: {"text": "This is another note", "sequence": 2},
|
108
|
+
},
|
109
|
+
notes,
|
110
|
+
)
|
111
|
+
|
112
|
+
self.env["mis.report.instance.annotation"].set_annotation(
|
113
|
+
second_cell_id, self.report_instance.id, "This is third note"
|
114
|
+
)
|
115
|
+
|
116
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
117
|
+
# Last note added should have a sequence of
|
118
|
+
# 2 since it is deplayed in the second cell
|
119
|
+
self.assertDictEqual(
|
120
|
+
{
|
121
|
+
first_cell_id: {"text": "This is a note", "sequence": 1},
|
122
|
+
second_cell_id: {"text": "This is third note", "sequence": 2},
|
123
|
+
third_cell_id: {"text": "This is another note", "sequence": 3},
|
124
|
+
},
|
125
|
+
notes,
|
126
|
+
)
|
127
|
+
|
128
|
+
def test_remove_note(self):
|
129
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
130
|
+
|
131
|
+
self.assertEqual({}, notes)
|
132
|
+
|
133
|
+
# report with 4 cells, 2 periods and 2 subkpis
|
134
|
+
matrix = self.report_instance._compute_matrix()
|
135
|
+
cell_ids = [c.cell_id for row in matrix.iter_rows() for c in row.iter_cells()]
|
136
|
+
self.assertEqual(len(cell_ids), 4)
|
137
|
+
|
138
|
+
first_cell_id = cell_ids[0]
|
139
|
+
|
140
|
+
# adding one note
|
141
|
+
self.env["mis.report.instance.annotation"].set_annotation(
|
142
|
+
first_cell_id, self.report_instance.id, "This is a note"
|
143
|
+
)
|
144
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
145
|
+
self.assertDictEqual(
|
146
|
+
{first_cell_id: {"text": "This is a note", "sequence": 1}}, notes
|
147
|
+
)
|
148
|
+
|
149
|
+
# remove note
|
150
|
+
self.env["mis.report.instance.annotation"].remove_annotation(
|
151
|
+
first_cell_id, self.report_instance.id
|
152
|
+
)
|
153
|
+
notes = self.report_instance.get_notes_by_cell_id()
|
154
|
+
self.assertEqual({}, notes)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: odoo-addon-mis_builder
|
3
|
-
Version: 16.0.5.
|
3
|
+
Version: 16.0.5.4.0
|
4
4
|
Requires-Python: >=3.10
|
5
5
|
Requires-Dist: odoo-addon-date_range>=16.0dev,<16.1dev
|
6
6
|
Requires-Dist: odoo-addon-report_xlsx>=16.0dev,<16.1dev
|
@@ -25,7 +25,7 @@ MIS Builder
|
|
25
25
|
!! This file is generated by oca-gen-addon-readme !!
|
26
26
|
!! changes will be overwritten. !!
|
27
27
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
28
|
-
!! source digest: sha256:
|
28
|
+
!! source digest: sha256:eaf310c997ae9746cf01edf102baa7c519355121536c5a695b45470f6ab27dee
|
29
29
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
30
30
|
|
31
31
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|