odoo-addon-account-financial-report 15.0.2.9.2.3__py3-none-any.whl → 15.0.2.10.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.

Potentially problematic release.


This version of odoo-addon-account-financial-report might be problematic. Click here for more details.

Files changed (29) hide show
  1. odoo/addons/account_financial_report/README.rst +36 -1
  2. odoo/addons/account_financial_report/__manifest__.py +4 -1
  3. odoo/addons/account_financial_report/i18n/account_financial_report.pot +102 -4
  4. odoo/addons/account_financial_report/i18n/es.po +132 -84
  5. odoo/addons/account_financial_report/models/__init__.py +2 -0
  6. odoo/addons/account_financial_report/models/account_age_report_configuration.py +47 -0
  7. odoo/addons/account_financial_report/models/res_config_settings.py +14 -0
  8. odoo/addons/account_financial_report/readme/CONFIGURE.rst +26 -0
  9. odoo/addons/account_financial_report/readme/CONTRIBUTORS.rst +1 -0
  10. odoo/addons/account_financial_report/readme/DESCRIPTION.rst +4 -0
  11. odoo/addons/account_financial_report/report/aged_partner_balance.py +74 -8
  12. odoo/addons/account_financial_report/report/aged_partner_balance_xlsx.py +145 -104
  13. odoo/addons/account_financial_report/report/templates/aged_partner_balance.xml +428 -333
  14. odoo/addons/account_financial_report/security/ir.model.access.csv +2 -0
  15. odoo/addons/account_financial_report/security/security.xml +10 -0
  16. odoo/addons/account_financial_report/static/description/index.html +45 -21
  17. odoo/addons/account_financial_report/tests/__init__.py +1 -0
  18. odoo/addons/account_financial_report/tests/test_age_report_configuration.py +41 -0
  19. odoo/addons/account_financial_report/tests/test_aged_partner_balance.py +85 -4
  20. odoo/addons/account_financial_report/tests/test_general_ledger.py +5 -1
  21. odoo/addons/account_financial_report/tests/test_open_items.py +4 -1
  22. odoo/addons/account_financial_report/view/account_age_report_configuration_views.xml +44 -0
  23. odoo/addons/account_financial_report/view/res_config_settings_views.xml +56 -0
  24. odoo/addons/account_financial_report/wizard/aged_partner_balance_wizard.py +4 -0
  25. odoo/addons/account_financial_report/wizard/aged_partner_balance_wizard_view.xml +2 -0
  26. {odoo_addon_account_financial_report-15.0.2.9.2.3.dist-info → odoo_addon_account_financial_report-15.0.2.10.0.dist-info}/METADATA +37 -2
  27. {odoo_addon_account_financial_report-15.0.2.9.2.3.dist-info → odoo_addon_account_financial_report-15.0.2.10.0.dist-info}/RECORD +29 -22
  28. {odoo_addon_account_financial_report-15.0.2.9.2.3.dist-info → odoo_addon_account_financial_report-15.0.2.10.0.dist-info}/WHEEL +0 -0
  29. {odoo_addon_account_financial_report-15.0.2.9.2.3.dist-info → odoo_addon_account_financial_report-15.0.2.10.0.dist-info}/top_level.txt +0 -0
@@ -25,6 +25,8 @@ class AgedPartnerBalanceReport(models.AbstractModel):
25
25
  ag_pb_data[acc_id]["90_days"] = 0.0
26
26
  ag_pb_data[acc_id]["120_days"] = 0.0
27
27
  ag_pb_data[acc_id]["older"] = 0.0
28
+ for interval_line in self.env.context["age_partner_config"].line_ids:
29
+ ag_pb_data[acc_id][interval_line] = 0.0
28
30
  return ag_pb_data
29
31
 
30
32
  @api.model
@@ -39,6 +41,8 @@ class AgedPartnerBalanceReport(models.AbstractModel):
39
41
  ag_pb_data[acc_id][prt_id]["120_days"] = 0.0
40
42
  ag_pb_data[acc_id][prt_id]["older"] = 0.0
41
43
  ag_pb_data[acc_id][prt_id]["move_lines"] = []
44
+ for interval_line in self.env.context["age_partner_config"].line_ids:
45
+ ag_pb_data[acc_id][prt_id][interval_line] = 0.0
42
46
  return ag_pb_data
43
47
 
44
48
  @api.model
@@ -47,6 +51,7 @@ class AgedPartnerBalanceReport(models.AbstractModel):
47
51
  ):
48
52
  ag_pb_data[acc_id]["residual"] += residual
49
53
  ag_pb_data[acc_id][prt_id]["residual"] += residual
54
+ interval_lines = self.env.context["age_partner_config"].line_ids
50
55
  today = date_at_object
51
56
  if not due_date or today <= due_date:
52
57
  ag_pb_data[acc_id]["current"] += residual
@@ -66,6 +71,24 @@ class AgedPartnerBalanceReport(models.AbstractModel):
66
71
  else:
67
72
  ag_pb_data[acc_id]["older"] += residual
68
73
  ag_pb_data[acc_id][prt_id]["older"] += residual
74
+ for index, line in enumerate(interval_lines):
75
+ next_line = (
76
+ interval_lines[index + 1] if index + 1 < len(interval_lines) else None
77
+ )
78
+ lower_limit = 0 if not index else line.inferior_limit
79
+ if (
80
+ due_date
81
+ and next_line
82
+ and today > due_date
83
+ and today >= due_date + timedelta(days=lower_limit)
84
+ and today < due_date + timedelta(days=next_line.inferior_limit)
85
+ ):
86
+ ag_pb_data[acc_id][line] += residual
87
+ ag_pb_data[acc_id][prt_id][line] += residual
88
+ if not next_line and due_date:
89
+ if today >= due_date + timedelta(days=line.inferior_limit):
90
+ ag_pb_data[acc_id][line] += residual
91
+ ag_pb_data[acc_id][prt_id][line] += residual
69
92
  return ag_pb_data
70
93
 
71
94
  def _get_account_partial_reconciled(self, company_id, date_at_object):
@@ -235,6 +258,9 @@ class AgedPartnerBalanceReport(models.AbstractModel):
235
258
  "older": 0.0,
236
259
  }
237
260
  )
261
+ interval_lines = self.env.context["age_partner_config"].line_ids
262
+ for interval_line in interval_lines:
263
+ ml[interval_line] = 0.0
238
264
  due_date = ml["due_date"]
239
265
  amount = ml["residual"]
240
266
  today = date_at_object
@@ -251,6 +277,27 @@ class AgedPartnerBalanceReport(models.AbstractModel):
251
277
  else:
252
278
  ml["older"] += amount
253
279
 
280
+ for index, interval_line in enumerate(interval_lines):
281
+ next_line = (
282
+ interval_lines[index + 1] if index + 1 < len(interval_lines) else None
283
+ )
284
+ upper_limit = next_line.inferior_limit if next_line else None
285
+
286
+ if (
287
+ due_date
288
+ and (
289
+ next_line
290
+ and today > due_date
291
+ and today >= due_date + timedelta(days=interval_line.inferior_limit)
292
+ and today < due_date + timedelta(days=upper_limit)
293
+ )
294
+ or (
295
+ not next_line
296
+ and today >= due_date + timedelta(days=interval_line.inferior_limit)
297
+ )
298
+ ):
299
+ ml[interval_line] += amount
300
+
254
301
  def _create_account_list(
255
302
  self,
256
303
  ag_pb_data,
@@ -261,6 +308,7 @@ class AgedPartnerBalanceReport(models.AbstractModel):
261
308
  date_at_oject,
262
309
  ):
263
310
  aged_partner_data = []
311
+ interval_lines = self.env.context["age_partner_config"].line_ids
264
312
  for account in accounts_data.values():
265
313
  acc_id = account["id"]
266
314
  account.update(
@@ -275,6 +323,8 @@ class AgedPartnerBalanceReport(models.AbstractModel):
275
323
  "partners": [],
276
324
  }
277
325
  )
326
+ for interval_line in interval_lines:
327
+ account[interval_line] = ag_pb_data[acc_id][interval_line]
278
328
  for prt_id in ag_pb_data[acc_id]:
279
329
  if isinstance(prt_id, int):
280
330
  partner = {
@@ -287,6 +337,10 @@ class AgedPartnerBalanceReport(models.AbstractModel):
287
337
  "120_days": ag_pb_data[acc_id][prt_id]["120_days"],
288
338
  "older": ag_pb_data[acc_id][prt_id]["older"],
289
339
  }
340
+ for interval_line in interval_lines:
341
+ partner[interval_line] = ag_pb_data[acc_id][prt_id][
342
+ interval_line
343
+ ]
290
344
  if show_move_line_details:
291
345
  move_lines = []
292
346
  for ml in ag_pb_data[acc_id][prt_id]["move_lines"]:
@@ -306,6 +360,7 @@ class AgedPartnerBalanceReport(models.AbstractModel):
306
360
 
307
361
  @api.model
308
362
  def _calculate_percent(self, aged_partner_data):
363
+ interval_lines = self.env.context["age_partner_config"].line_ids
309
364
  for account in aged_partner_data:
310
365
  if abs(account["residual"]) > 0.01:
311
366
  total = account["residual"]
@@ -331,6 +386,10 @@ class AgedPartnerBalanceReport(models.AbstractModel):
331
386
  ),
332
387
  }
333
388
  )
389
+ for interval_line in interval_lines:
390
+ account[f"percent_{interval_line.id}"] = abs(
391
+ round((account[interval_line] / total) * 100, 2)
392
+ )
334
393
  else:
335
394
  account.update(
336
395
  {
@@ -342,6 +401,8 @@ class AgedPartnerBalanceReport(models.AbstractModel):
342
401
  "percent_older": 0.0,
343
402
  }
344
403
  )
404
+ for interval_line in interval_lines:
405
+ account[f"percent_{interval_line.id}"] = 0.0
345
406
  return aged_partner_data
346
407
 
347
408
  def _get_report_values(self, docids, data):
@@ -355,12 +416,12 @@ class AgedPartnerBalanceReport(models.AbstractModel):
355
416
  date_from = data["date_from"]
356
417
  only_posted_moves = data["only_posted_moves"]
357
418
  show_move_line_details = data["show_move_line_details"]
358
- (
359
- ag_pb_data,
360
- accounts_data,
361
- partners_data,
362
- journals_data,
363
- ) = self._get_move_lines_data(
419
+ aged_partner_configuration = self.env[
420
+ "account.age.report.configuration"
421
+ ].browse(data["age_partner_config_id"])
422
+ (ag_pb_data, accounts_data, partners_data, journals_data,) = self.with_context(
423
+ age_partner_config=aged_partner_configuration
424
+ )._get_move_lines_data(
364
425
  company_id,
365
426
  account_ids,
366
427
  partner_ids,
@@ -369,7 +430,9 @@ class AgedPartnerBalanceReport(models.AbstractModel):
369
430
  only_posted_moves,
370
431
  show_move_line_details,
371
432
  )
372
- aged_partner_data = self._create_account_list(
433
+ aged_partner_data = self.with_context(
434
+ age_partner_config=aged_partner_configuration
435
+ )._create_account_list(
373
436
  ag_pb_data,
374
437
  accounts_data,
375
438
  partners_data,
@@ -377,7 +440,9 @@ class AgedPartnerBalanceReport(models.AbstractModel):
377
440
  show_move_line_details,
378
441
  date_at_object,
379
442
  )
380
- aged_partner_data = self._calculate_percent(aged_partner_data)
443
+ aged_partner_data = self.with_context(
444
+ age_partner_config=aged_partner_configuration
445
+ )._calculate_percent(aged_partner_data)
381
446
  return {
382
447
  "doc_ids": [wizard_id],
383
448
  "doc_model": "open.items.report.wizard",
@@ -388,6 +453,7 @@ class AgedPartnerBalanceReport(models.AbstractModel):
388
453
  "only_posted_moves": only_posted_moves,
389
454
  "aged_partner_balance": aged_partner_data,
390
455
  "show_move_lines_details": show_move_line_details,
456
+ "age_partner_config": aged_partner_configuration,
391
457
  }
392
458
 
393
459
  def _get_ml_fields(self):
@@ -1,6 +1,7 @@
1
1
  # Author: Julien Coux
2
2
  # Copyright 2016 Camptocamp SA
3
3
  # Copyright 2021 Tecnativa - João Marques
4
+ # Copyright 2023 Tecnativa - Carolina Fernandez
4
5
  # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
5
6
 
6
7
  from odoo import _, models
@@ -20,67 +21,84 @@ class AgedPartnerBalanceXslx(models.AbstractModel):
20
21
  report_name = report_name + suffix
21
22
  return report_name
22
23
 
23
- def _get_report_columns(self, report):
24
- if not report.show_move_line_details:
25
- return {
26
- 0: {"header": _("Partner"), "field": "name", "width": 70},
27
- 1: {
28
- "header": _("Residual"),
29
- "field": "residual",
30
- "field_footer_total": "residual",
31
- "type": "amount",
32
- "width": 14,
33
- },
34
- 2: {
35
- "header": _("Current"),
36
- "field": "current",
37
- "field_footer_total": "current",
38
- "field_footer_percent": "percent_current",
39
- "type": "amount",
40
- "width": 14,
41
- },
42
- 3: {
43
- "header": _("Age ≤ 30 d."),
44
- "field": "30_days",
45
- "field_footer_total": "30_days",
46
- "field_footer_percent": "percent_30_days",
47
- "type": "amount",
48
- "width": 14,
49
- },
50
- 4: {
51
- "header": _("Age ≤ 60 d."),
52
- "field": "60_days",
53
- "field_footer_total": "60_days",
54
- "field_footer_percent": "percent_60_days",
55
- "type": "amount",
56
- "width": 14,
57
- },
58
- 5: {
59
- "header": _("Age ≤ 90 d."),
60
- "field": "90_days",
61
- "field_footer_total": "90_days",
62
- "field_footer_percent": "percent_90_days",
63
- "type": "amount",
64
- "width": 14,
65
- },
66
- 6: {
67
- "header": _("Age ≤ 120 d."),
68
- "field": "120_days",
69
- "field_footer_total": "120_days",
70
- "field_footer_percent": "percent_120_days",
71
- "type": "amount",
72
- "width": 14,
73
- },
74
- 7: {
75
- "header": _("Older"),
76
- "field": "older",
77
- "field_footer_total": "older",
78
- "field_footer_percent": "percent_older",
79
- "type": "amount",
80
- "width": 14,
81
- },
24
+ def _get_report_columns_without_move_line_details(self, report, column_index):
25
+ report_columns = {
26
+ 0: {"header": _("Partner"), "field": "name", "width": 70},
27
+ 1: {
28
+ "header": _("Residual"),
29
+ "field": "residual",
30
+ "field_footer_total": "residual",
31
+ "type": "amount",
32
+ "width": 14,
33
+ },
34
+ 2: {
35
+ "header": _("Current"),
36
+ "field": "current",
37
+ "field_footer_total": "current",
38
+ "field_footer_percent": "percent_current",
39
+ "type": "amount",
40
+ "width": 14,
41
+ },
42
+ }
43
+ if not report.age_partner_config_id:
44
+ report_columns.update(
45
+ {
46
+ 3: {
47
+ "header": _("Age ≤ 30 d."),
48
+ "field": "30_days",
49
+ "field_footer_total": "30_days",
50
+ "field_footer_percent": "percent_30_days",
51
+ "type": "amount",
52
+ "width": 14,
53
+ },
54
+ 4: {
55
+ "header": _("Age ≤ 60 d."),
56
+ "field": "60_days",
57
+ "field_footer_total": "60_days",
58
+ "field_footer_percent": "percent_60_days",
59
+ "type": "amount",
60
+ "width": 14,
61
+ },
62
+ 5: {
63
+ "header": _("Age ≤ 90 d."),
64
+ "field": "90_days",
65
+ "field_footer_total": "90_days",
66
+ "field_footer_percent": "percent_90_days",
67
+ "type": "amount",
68
+ "width": 14,
69
+ },
70
+ 6: {
71
+ "header": _("Age ≤ 120 d."),
72
+ "field": "120_days",
73
+ "field_footer_total": "120_days",
74
+ "field_footer_percent": "percent_120_days",
75
+ "type": "amount",
76
+ "width": 14,
77
+ },
78
+ 7: {
79
+ "header": _("Older"),
80
+ "field": "older",
81
+ "field_footer_total": "older",
82
+ "field_footer_percent": "percent_older",
83
+ "type": "amount",
84
+ "width": 14,
85
+ },
86
+ }
87
+ )
88
+ for interval in report.age_partner_config_id.line_ids:
89
+ report_columns[column_index] = {
90
+ "header": interval.name,
91
+ "field": interval,
92
+ "field_footer_total": interval,
93
+ "field_footer_percent": f"percent_{interval.id}",
94
+ "type": "amount",
95
+ "width": 14,
82
96
  }
83
- return {
97
+ column_index += 1
98
+ return report_columns
99
+
100
+ def _get_report_columns_with_move_line_details(self, report, column_index):
101
+ report_columns = {
84
102
  0: {"header": _("Date"), "field": "date", "width": 11},
85
103
  1: {"header": _("Entry"), "field": "entry", "width": 18},
86
104
  2: {"header": _("Journal"), "field": "journal", "width": 8},
@@ -105,52 +123,75 @@ class AgedPartnerBalanceXslx(models.AbstractModel):
105
123
  "type": "amount",
106
124
  "width": 14,
107
125
  },
108
- 9: {
109
- "header": _("Age ≤ 30 d."),
110
- "field": "30_days",
111
- "field_footer_total": "30_days",
112
- "field_footer_percent": "percent_30_days",
113
- "field_final_balance": "30_days",
114
- "type": "amount",
115
- "width": 14,
116
- },
117
- 10: {
118
- "header": _("Age ≤ 60 d."),
119
- "field": "60_days",
120
- "field_footer_total": "60_days",
121
- "field_footer_percent": "percent_60_days",
122
- "field_final_balance": "60_days",
123
- "type": "amount",
124
- "width": 14,
125
- },
126
- 11: {
127
- "header": _("Age ≤ 90 d."),
128
- "field": "90_days",
129
- "field_footer_total": "90_days",
130
- "field_footer_percent": "percent_90_days",
131
- "field_final_balance": "90_days",
132
- "type": "amount",
133
- "width": 14,
134
- },
135
- 12: {
136
- "header": _("Age ≤ 120 d."),
137
- "field": "120_days",
138
- "field_footer_total": "120_days",
139
- "field_footer_percent": "percent_120_days",
140
- "field_final_balance": "120_days",
141
- "type": "amount",
142
- "width": 14,
143
- },
144
- 13: {
145
- "header": _("Older"),
146
- "field": "older",
147
- "field_footer_total": "older",
148
- "field_footer_percent": "percent_older",
149
- "field_final_balance": "older",
126
+ }
127
+ if not report.age_partner_config_id:
128
+ report_columns.update(
129
+ {
130
+ 9: {
131
+ "header": _("Age ≤ 30 d."),
132
+ "field": "30_days",
133
+ "field_footer_total": "30_days",
134
+ "field_footer_percent": "percent_30_days",
135
+ "field_final_balance": "30_days",
136
+ "type": "amount",
137
+ "width": 14,
138
+ },
139
+ 10: {
140
+ "header": _("Age ≤ 60 d."),
141
+ "field": "60_days",
142
+ "field_footer_total": "60_days",
143
+ "field_footer_percent": "percent_60_days",
144
+ "field_final_balance": "60_days",
145
+ "type": "amount",
146
+ "width": 14,
147
+ },
148
+ 11: {
149
+ "header": _("Age ≤ 90 d."),
150
+ "field": "90_days",
151
+ "field_footer_total": "90_days",
152
+ "field_footer_percent": "percent_90_days",
153
+ "field_final_balance": "90_days",
154
+ "type": "amount",
155
+ "width": 14,
156
+ },
157
+ 12: {
158
+ "header": _("Age ≤ 120 d."),
159
+ "field": "120_days",
160
+ "field_footer_total": "120_days",
161
+ "field_footer_percent": "percent_120_days",
162
+ "field_final_balance": "120_days",
163
+ "type": "amount",
164
+ "width": 14,
165
+ },
166
+ 13: {
167
+ "header": _("Older"),
168
+ "field": "older",
169
+ "field_footer_total": "older",
170
+ "field_footer_percent": "percent_older",
171
+ "field_final_balance": "older",
172
+ "type": "amount",
173
+ "width": 14,
174
+ },
175
+ }
176
+ )
177
+ for interval in report.age_partner_config_id.line_ids:
178
+ report_columns[column_index] = {
179
+ "header": interval.name,
180
+ "field": interval,
181
+ "field_footer_total": interval,
182
+ "field_footer_percent": f"percent_{interval.id}",
150
183
  "type": "amount",
151
184
  "width": 14,
152
- },
153
- }
185
+ }
186
+ column_index += 1
187
+ return report_columns
188
+
189
+ def _get_report_columns(self, report):
190
+ if not report.show_move_line_details:
191
+ return self._get_report_columns_without_move_line_details(
192
+ report, column_index=3
193
+ )
194
+ return self._get_report_columns_with_move_line_details(report, column_index=9)
154
195
 
155
196
  def _get_report_filters(self, report):
156
197
  return [