From 3d492eb2361bf143569521e60c937cc8a1e63d58 Mon Sep 17 00:00:00 2001 From: Carolina Fernandez <carolina.fernandez@tecnativa.com> Date: Wed, 22 May 2024 13:38:05 +0200 Subject: [PATCH] [IMP] account_financial_report: Open items groupy by salesman TT49193 --- account_financial_report/README.rst | 3 + .../i18n/account_financial_report.pot | 14 + account_financial_report/i18n/es.po | 16 +- account_financial_report/report/open_items.py | 54 ++-- .../report/open_items_xlsx.py | 167 ++++++++++-- .../report/templates/open_items.xml | 239 ++++++++++++++---- .../static/description/index.html | 2 + .../tests/test_open_items.py | 22 ++ .../wizard/open_items_wizard.py | 18 ++ .../wizard/open_items_wizard_view.xml | 1 + 10 files changed, 437 insertions(+), 99 deletions(-) diff --git a/account_financial_report/README.rst b/account_financial_report/README.rst index fed874bd..56b9f61d 100644 --- a/account_financial_report/README.rst +++ b/account_financial_report/README.rst @@ -49,6 +49,9 @@ Invoicing / Settings / Invoicing / OCA Aged Report Configuration you will be abl dynamic intervals that will appear on the Aged Partner Balance. For further information, check CONFIGURE.rst +Add new grouped by field to export Open items report grouped by partner salesperson. +If grouped by is empty or selected partner option it will grouped by Open items by partner. + **Table of contents** .. contents:: diff --git a/account_financial_report/i18n/account_financial_report.pot b/account_financial_report/i18n/account_financial_report.pot index 785accf6..53df812c 100644 --- a/account_financial_report/i18n/account_financial_report.pot +++ b/account_financial_report/i18n/account_financial_report.pot @@ -945,6 +945,7 @@ msgstr "" #. module: account_financial_report #: model:ir.model.fields,field_description:account_financial_report.field_general_ledger_report_wizard__grouped_by +#: model:ir.model.fields,field_description:account_financial_report.field_open_items_report_wizard__grouped_by msgid "Grouped By" msgstr "" @@ -1187,6 +1188,12 @@ msgstr "" msgid "Missing Partner" msgstr "" +#. module: account_financial_report +#: code:addons/account_financial_report/report/open_items.py:0 +#, python-format +msgid "Missing Salesperson" +msgstr "" + #. module: account_financial_report #: model:ir.model,name:account_financial_report.model_account_age_report_configuration_line msgid "Model to set interval lines for Age partner balance report" @@ -1397,6 +1404,12 @@ msgstr "" msgid "Partner Initial balance" msgstr "" +#. module: account_financial_report +#. odoo-python +#: model:ir.model.fields.selection,name:account_financial_report.selection__open_items_report_wizard__grouped_by__salesperson +msgid "Partner Salesperson" +msgstr "" + #. module: account_financial_report #. odoo-python #: code:addons/account_financial_report/report/aged_partner_balance_xlsx.py:0 @@ -1421,6 +1434,7 @@ msgstr "" #. module: account_financial_report #: model:ir.model.fields.selection,name:account_financial_report.selection__general_ledger_report_wizard__grouped_by__partners +#: model:ir.model.fields.selection,name:account_financial_report.selection__open_items_report_wizard__grouped_by__partners msgid "Partners" msgstr "" diff --git a/account_financial_report/i18n/es.po b/account_financial_report/i18n/es.po index aecf0f4e..9e3c69d9 100644 --- a/account_financial_report/i18n/es.po +++ b/account_financial_report/i18n/es.po @@ -960,6 +960,7 @@ msgstr "Agrupar por" #. module: account_financial_report #: model:ir.model.fields,field_description:account_financial_report.field_general_ledger_report_wizard__grouped_by +#: model:ir.model.fields,field_description:account_financial_report.field_open_items_report_wizard__grouped_by msgid "Grouped By" msgstr "Agrupado por" @@ -1203,7 +1204,13 @@ msgstr "Línea" #: code:addons/account_financial_report/report/trial_balance.py:0 #, python-format msgid "Missing Partner" -msgstr "Falta el Socio" +msgstr "Falta la empresa" + +#. module: account_financial_report +#: code:addons/account_financial_report/report/open_items.py:0 +#, python-format +msgid "Missing Salesperson" +msgstr "Sin comercial" #. module: account_financial_report #: model:ir.model,name:account_financial_report.model_account_age_report_configuration_line @@ -1418,6 +1425,12 @@ msgstr "" msgid "Partner Initial balance" msgstr "Saldo Inicial de empresa" +#. module: account_financial_report +#. odoo-python +#: model:ir.model.fields.selection,name:account_financial_report.selection__open_items_report_wizard__grouped_by__salesperson +msgid "Partner Salesperson" +msgstr "Comercial de la empresa" + #. module: account_financial_report #. odoo-python #: code:addons/account_financial_report/report/aged_partner_balance_xlsx.py:0 @@ -1442,6 +1455,7 @@ msgstr "Saldo inicial de empresa" #. module: account_financial_report #: model:ir.model.fields.selection,name:account_financial_report.selection__general_ledger_report_wizard__grouped_by__partners +#: model:ir.model.fields.selection,name:account_financial_report.selection__open_items_report_wizard__grouped_by__partners msgid "Partners" msgstr "Empresas" diff --git a/account_financial_report/report/open_items.py b/account_financial_report/report/open_items.py index efc3e9c6..67f8c2b9 100644 --- a/account_financial_report/report/open_items.py +++ b/account_financial_report/report/open_items.py @@ -1,5 +1,6 @@ # © 2016 Julien Coux (Camptocamp) # Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# Copyright 2024 Tecnativa - Carolina Fernandez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import operator @@ -66,6 +67,7 @@ class OpenItemsReport(models.AbstractModel): only_posted_moves, company_id, date_from, + grouped_by, ): domain = self._get_move_lines_domain_not_reconciled( company_id, account_ids, partner_ids, only_posted_moves, date_from @@ -75,7 +77,7 @@ class OpenItemsReport(models.AbstractModel): domain=domain, fields=ml_fields ) journals_ids = set() - partners_ids = set() + group_ids = set() partners_data = {} if date_at_object < date.today(): ( @@ -119,29 +121,27 @@ class OpenItemsReport(models.AbstractModel): journals_ids.add(move_line["journal_id"][0]) acc_id = move_line["account_id"][0] # Partners data - if move_line["partner_id"]: - prt_id = move_line["partner_id"][0] - prt_name = move_line["partner_id"][1] + partner = self.env["res.partner"] + if move_line.get("partner_id"): + partner = self.env["res.partner"].browse(move_line["partner_id"][0]) + if grouped_by == "salesperson": + user = partner.user_id + group_id = user.id or 0 + group_name = user.name or _("Missing Salesperson") else: - prt_id = 0 - prt_name = _("Missing Partner") - if prt_id not in partners_ids: - partners_data.update({prt_id: {"id": prt_id, "name": prt_name}}) - partners_ids.add(prt_id) - + group_id = partner.id or 0 + group_name = partner.name or _("Missing Partner") + if group_id not in group_ids: + partners_data.update({group_id: {"id": group_id, "name": group_name}}) + group_ids.add(group_id) # Move line update - original = 0 - if not float_is_zero(move_line["credit"], precision_digits=2): original = move_line["credit"] * (-1) - if not float_is_zero(move_line["debit"], precision_digits=2): + else: original = move_line["debit"] if move_line["ref"] == move_line["name"]: - if move_line["ref"]: - ref_label = move_line["ref"] - else: - ref_label = "" + ref_label = move_line["ref"] or "" elif not move_line["ref"]: ref_label = move_line["name"] elif not move_line["name"]: @@ -155,8 +155,8 @@ class OpenItemsReport(models.AbstractModel): "date_maturity": move_line["date_maturity"] and move_line["date_maturity"].strftime("%d/%m/%Y"), "original": original, - "partner_id": prt_id, - "partner_name": prt_name, + "partner_id": partner.id or 0, + "partner_name": partner.name or "", "ref_label": ref_label, "journal_id": move_line["journal_id"][0], "move_name": move_line["move_id"][1], @@ -172,12 +172,12 @@ class OpenItemsReport(models.AbstractModel): # Open Items Move Lines Data if acc_id not in open_items_move_lines_data.keys(): - open_items_move_lines_data[acc_id] = {prt_id: [move_line]} + open_items_move_lines_data[acc_id] = {group_id: [move_line]} else: - if prt_id not in open_items_move_lines_data[acc_id].keys(): - open_items_move_lines_data[acc_id][prt_id] = [move_line] + if group_id not in open_items_move_lines_data[acc_id].keys(): + open_items_move_lines_data[acc_id][group_id] = [move_line] else: - open_items_move_lines_data[acc_id][prt_id].append(move_line) + open_items_move_lines_data[acc_id][group_id].append(move_line) journals_data = self._get_journals_data(list(journals_ids)) accounts_data = self._get_accounts_data(open_items_move_lines_data.keys()) return ( @@ -229,7 +229,9 @@ class OpenItemsReport(models.AbstractModel): move_lines = [] for move_line in open_items_move_lines_data[acc_id][prt_id]: move_lines += [move_line] - move_lines = sorted(move_lines, key=lambda k: (k["date"])) + move_lines = sorted( + move_lines, key=lambda k: (k["date"], k["partner_id"]) + ) new_open_items[acc_id][prt_id] = move_lines return new_open_items @@ -244,7 +246,7 @@ class OpenItemsReport(models.AbstractModel): date_from = data["date_from"] only_posted_moves = data["only_posted_moves"] show_partner_details = data["show_partner_details"] - + grouped_by = data["grouped_by"] ( move_lines_data, partners_data, @@ -258,6 +260,7 @@ class OpenItemsReport(models.AbstractModel): only_posted_moves, company_id, date_from, + grouped_by, ) total_amount = self._calculate_amounts(open_items_move_lines_data) @@ -280,6 +283,7 @@ class OpenItemsReport(models.AbstractModel): "accounts_data": accounts_data, "total_amount": total_amount, "Open_Items": open_items_move_lines_data, + "grouped_by": grouped_by, } def _get_ml_fields(self): diff --git a/account_financial_report/report/open_items_xlsx.py b/account_financial_report/report/open_items_xlsx.py index 2e412448..42c7a4af 100644 --- a/account_financial_report/report/open_items_xlsx.py +++ b/account_financial_report/report/open_items_xlsx.py @@ -101,11 +101,126 @@ class OpenItemsXslx(models.AbstractModel): def _get_col_pos_final_balance_label(self): return 5 - def _generate_report_content(self, workbook, report, data, report_data): - res_data = self.env[ - "report.account_financial_report.open_items" - ]._get_report_values(report, data) - # For each account + def _calculate_amounts_by_partner(self, account_id, open_items_move_lines_data): + total_amount = {} + for line in open_items_move_lines_data: + partner_id_key = line["partner_id"] + if account_id not in total_amount: + total_amount[account_id] = {} + if partner_id_key not in total_amount[account_id]: + total_amount[account_id][partner_id_key] = {"residual": 0.0} + total_amount[account_id][partner_id_key]["residual"] += line[ + "amount_residual" + ] + return total_amount + + def _generate_report_content_by_salesperson( + self, workbook, report, data, report_data, res_data + ): + Open_items = res_data["Open_Items"] + accounts_data = res_data["accounts_data"] + partners_data = res_data["partners_data"] + journals_data = res_data["journals_data"] + total_amount = res_data["total_amount"] + + for partner_id in partners_data.keys(): + # Create a new sheet for each partner + partner_totals = {} + partner_name = partners_data[partner_id]["name"] + new_sheet = workbook.add_worksheet(partner_name[:31]) + report_data["sheet"] = new_sheet + report_data["row_pos"] = 0 + + for account_id in Open_items.keys(): + if partner_id in Open_items[account_id]: + self.write_array_title( + accounts_data[account_id]["code"] + + " - " + + accounts_data[account_id]["name"], + report_data, + ) + + # For each partner + if Open_items[account_id]: + type_object = "partner" + # Write partner title + self.write_array_title( + partners_data[partner_id]["name"], report_data + ) + + # Calculate totals by partner_id + partner_totals = self._calculate_amounts_by_partner( + account_id, Open_items[account_id][partner_id] + ) + # Display array header for move lines + self.write_array_header(report_data) + # Display account move lines + has_lines = False + for partner_id_key, total_amount_dict in partner_totals.get( + account_id, {} + ).items(): + for line in Open_items[account_id][partner_id]: + if line["partner_id"] == partner_id_key: + line.update( + { + "account": accounts_data[account_id][ + "code" + ], + "journal": journals_data[ + line["journal_id"] + ]["code"], + } + ) + self.write_line_from_dict(line, report_data) + has_lines = True + if has_lines: + partner = self.env["res.partner"].browse(partner_id_key) + # Display ending balance line for partner + partner_data = { + "id": partner_id_key, + "name": partner.name + if partner + else _("Missing Partner"), + "currency_id": accounts_data[account_id][ + "currency_id" + ], + "currency_name": accounts_data[account_id][ + "currency_name" + ], + "residual": total_amount_dict, + } + self.write_ending_balance_from_dict( + partner_data, + "partner_subtotal", + partner_totals, + report_data, + account_id=account_id, + partner_id=partner_id_key, + ) + has_lines = False + # Display ending balance line for salesperson + partners_data[partner_id].update( + { + "currency_id": accounts_data[account_id]["currency_id"], + "currency_name": accounts_data[account_id][ + "currency_name" + ], + } + ) + self.write_ending_balance_from_dict( + partners_data[partner_id], + type_object, + total_amount, + report_data, + account_id=account_id, + partner_id=partner_id, + ) + # Line break + report_data["row_pos"] += 1 + + def _generate_report_content_by_partner( + self, workbook, report, data, report_data, res_data + ): Open_items = res_data["Open_Items"] accounts_data = res_data["accounts_data"] partners_data = res_data["partners_data"] @@ -120,7 +235,6 @@ class OpenItemsXslx(models.AbstractModel): + accounts_data[account_id]["name"], report_data, ) - # For each partner if Open_items[account_id]: if show_partner_details: @@ -180,18 +294,33 @@ class OpenItemsXslx(models.AbstractModel): ) self.write_line_from_dict(line, report_data) - # Display ending balance line for account - type_object = "account" - self.write_ending_balance_from_dict( - accounts_data[account_id], - type_object, - total_amount, - report_data, - account_id=account_id, - ) + # Display ending balance line for account + type_object = "account" + self.write_ending_balance_from_dict( + accounts_data[account_id], + type_object, + total_amount, + report_data, + account_id=account_id, + ) - # 2 lines break - report_data["row_pos"] += 2 + # 2 lines break + report_data["row_pos"] += 2 + + def _generate_report_content(self, workbook, report, data, report_data): + res_data = self.env[ + "report.account_financial_report.open_items" + ]._get_report_values(report, data) + show_partner_details = res_data["show_partner_details"] + grouped_by = res_data["grouped_by"] + if grouped_by == "salesperson" and show_partner_details: + return self._generate_report_content_by_salesperson( + workbook, report, data, report_data, res_data + ) + else: + return self._generate_report_content_by_partner( + workbook, report, data, report_data, res_data + ) def write_ending_balance_from_dict( self, @@ -211,6 +340,10 @@ class OpenItemsXslx(models.AbstractModel): name = my_object["code"] + " - " + my_object["name"] my_object["residual"] = total_amount[account_id]["residual"] label = _("Ending balance") + elif type_object == "partner_subtotal": + name = my_object["name"] + my_object["residual"] = total_amount[account_id][partner_id]["residual"] + label = _("Ending balance") return super(OpenItemsXslx, self).write_ending_balance_from_dict( my_object, name, label, report_data ) diff --git a/account_financial_report/report/templates/open_items.xml b/account_financial_report/report/templates/open_items.xml index 1e410464..ab4cb35b 100644 --- a/account_financial_report/report/templates/open_items.xml +++ b/account_financial_report/report/templates/open_items.xml @@ -9,6 +9,7 @@ </t> </t> </template> + <template id="account_financial_report.report_open_items_base"> <!-- Saved flag fields into variables, used to define columns display --> <t t-set="foreign_currency" t-value="foreign_currency" /> @@ -28,82 +29,188 @@ style="text-align: center;" /> </div> - <!-- Display filters --> - <t t-call="account_financial_report.report_open_items_filters" /> - <t t-foreach="Open_Items.keys()" t-as="account_id"> - <!-- Display account header --> - <div class="act_as_table list_table" style="margin-top: 10px;" /> - <div class="account_title" style="width: 100%;"> - <span t-esc="accounts_data[account_id]['code']" /> - - - <span t-esc="accounts_data[account_id]['name']" /> - </div> - <t t-if="not show_partner_details"> - <div class="act_as_table data_table" style="width: 100%;"> - <t - t-call="account_financial_report.report_open_items_lines_header" - /> - <!-- Display account move lines --> - <t t-foreach="Open_Items[account_id]" t-as="line"> - <t - t-call="account_financial_report.report_open_items_lines" - /> - </t> + <t t-if="grouped_by == 'salesperson' and show_partner_details"> + <t t-foreach="partners_data.keys()" t-as="partner_id"> + <t t-call="account_financial_report.report_open_items_filters" /> + <div class="act_as_caption account_title"> + <span t-esc="partners_data[partner_id]['name']" /> </div> - </t> - <t t-if="show_partner_details"> - <div class="page_break"> - <!-- Display account partners --> - <t t-foreach="Open_Items[account_id]" t-as="partner_id"> - <div class="act_as_caption account_title"> - <span t-esc="partners_data[partner_id]['name']" /> + <t t-foreach="Open_Items.keys()" t-as="account_id"> + <t t-if="partner_id in Open_Items[account_id]"> + <div + class="act_as_table list_table" + style="margin-top: 10px;" + /> + <div class="account_title" style="width: 100%;"> + <span t-esc="accounts_data[account_id]['code']" /> + - + <span t-esc="accounts_data[account_id]['name']" /> </div> - <div class="act_as_table data_table" style="width: 100%;"> - <!-- Display partner header --> - <t - t-call="account_financial_report.report_open_items_lines_header" + + <t t-if="Open_Items[account_id]"> + <t + t-set="partner_totals" + t-value="o._calculate_amounts_by_partner(account_id,Open_Items[account_id][partner_id])" /> - <!-- Display partner move lines --> - <t - t-foreach="Open_Items[account_id][partner_id]" - t-as="line" + <t + t-foreach="partner_totals.get(account_id, {})" + t-as="partner_id_key" > + <t t-set="has_lines" t-value="False" /> + <div + class="act_as_table data_table" + style="width: 100%;" + > + <t - t-call="account_financial_report.report_open_items_lines" - /> + t-foreach="Open_Items[account_id][partner_id]" + t-as="line" + > + <t t-if="line['partner_id'] == partner_id_key"> + <t t-set="has_lines" t-value="True" /> + </t> + </t> - </div> + <t t-if="has_lines"> + <!-- Display partner header --> + <t + t-call="account_financial_report.report_open_items_lines_header" + /> + </t> + <t + t-foreach="Open_Items[account_id][partner_id]" + t-as="line" + > + <t t-if="line['partner_id'] == partner_id_key"> + <!-- Display partner move lines --> + <t + t-call="account_financial_report.report_open_items_lines" + /> + </t> + + </t> + </div> + <!-- Check if there were any lines displayed for the partner --> + <t t-if="has_lines"> + <!-- Calculate and display subtotal for current partner_id --> + <t + t-call="account_financial_report.report_open_items_ending_cumul" + > + <t + t-set="currency_id" + t-value="accounts_data[account_id]['currency_name']" + /> + <t + t-set="type" + t-value="'partner_subtotal_type'" + /> + </t> + </t> + </t> + + </t> + <!-- Display account footer --> <t t-call="account_financial_report.report_open_items_ending_cumul" > - <t + <t t-set="account_or_partner_id" t-value="partners_data[partner_id]" /> - <t + <t t-set="currency_id" t-value="accounts_data[account_id]['currency_name']" /> - <t t-set="type" t-value='"partner_type"' /> - </t> + <t t-set="type" t-value='"partner_type"' /> </t> + </t> + + </t> + <div style="page-break-after: always;" /> + </t> + </t> + <t t-else=""> + <!-- Display filters --> + <t t-call="account_financial_report.report_open_items_filters" /> + <t t-foreach="Open_Items.keys()" t-as="account_id"> + <!-- Display account header --> + <div class="act_as_table list_table" style="margin-top: 10px;" /> + <div class="account_title" style="width: 100%;"> + <span t-esc="accounts_data[account_id]['code']" /> + - + <span t-esc="accounts_data[account_id]['name']" /> </div> - </t> - <!-- Display account footer --> - <t t-call="account_financial_report.report_open_items_ending_cumul"> - <t - t-set="account_or_partner_id" - t-value="accounts_data[account_id]" - /> - <t - t-set="currency_id" - t-value="accounts_data[account_id]['currency_name']" - /> - <t t-set="type" t-value='"account_type"' /> - </t> + <t t-if="not show_partner_details"> + <div class="act_as_table data_table" style="width: 100%;"> + <t + t-call="account_financial_report.report_open_items_lines_header" + /> + <!-- Display account move lines --> + <t t-foreach="Open_Items[account_id]" t-as="line"> + <t + t-call="account_financial_report.report_open_items_lines" + /> + </t> + </div> + </t> + <t t-if="show_partner_details"> + <div class="page_break"> + <!-- Display account partners --> + <t t-foreach="Open_Items[account_id]" t-as="partner_id"> + <div class="act_as_caption account_title"> + <span t-esc="partners_data[partner_id]['name']" /> + </div> + <div + class="act_as_table data_table" + style="width: 100%;" + > + <!-- Display partner header --> + <t + t-call="account_financial_report.report_open_items_lines_header" + /> + <!-- Display partner move lines --> + <t + t-foreach="Open_Items[account_id][partner_id]" + t-as="line" + > + <t + t-call="account_financial_report.report_open_items_lines" + /> + </t> + </div> + <t + t-call="account_financial_report.report_open_items_ending_cumul" + > + <t + t-set="account_or_partner_id" + t-value="partners_data[partner_id]" + /> + <t + t-set="currency_id" + t-value="accounts_data[account_id]['currency_name']" + /> + <t t-set="type" t-value='"partner_type"' /> + </t> + </t> + </div> + </t> + <!-- Display account footer --> + <t t-call="account_financial_report.report_open_items_ending_cumul"> + <t + t-set="account_or_partner_id" + t-value="accounts_data[account_id]" + /> + <t + t-set="currency_id" + t-value="accounts_data[account_id]['currency_name']" + /> + <t t-set="type" t-value='"account_type"' /> + </t> + </t> </t> </div> </template> + <template id="account_financial_report.report_open_items_filters"> <div class="act_as_table data_table" style="width: 100%;"> <div class="act_as_row labels"> @@ -294,6 +401,20 @@ Partner ending balance </div> </t> + <t t-if='type == "partner_subtotal_type"'> + <div class="act_as_cell first_column" style="width: 36.34%;" /> + <t + t-set="partner" + t-value="env['res.partner'].browse(partner_id_key)" + /> + <t t-if="partner"> + <span t-esc="partner.name" /> + </t> + <div class="act_as_cell right" style="width: 28.66%;"> + Ending + balance + </div> + </t> <!--## date_due--> <div class="act_as_cell" style="width: 6.47%;" /> <!--## amount_total_due--> @@ -312,6 +433,12 @@ t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" /> </t> + <t t-if='type == "partner_subtotal_type"'> + <span + t-esc="partner_totals[account_id][partner_id_key]['residual']" + t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" + /> + </t> </div> <!--## amount_total_due_currency + amount_residual_currency --> <t t-if="foreign_currency"> diff --git a/account_financial_report/static/description/index.html b/account_financial_report/static/description/index.html index 381e13f5..6ddc5721 100644 --- a/account_financial_report/static/description/index.html +++ b/account_financial_report/static/description/index.html @@ -387,6 +387,8 @@ currency balances are not available.</p> <p>Invoicing / Settings / Invoicing / OCA Aged Report Configuration you will be able to set dynamic intervals that will appear on the Aged Partner Balance. For further information, check CONFIGURE.rst</p> +<p>Add new grouped by field to export Open items report grouped by partner salesperson. +If grouped by is empty or selected partner option it will grouped by Open items by partner.</p> <p><strong>Table of contents</strong></p> <div class="contents local topic" id="contents"> <ul class="simple"> diff --git a/account_financial_report/tests/test_open_items.py b/account_financial_report/tests/test_open_items.py index 4cfc7c88..1229de2d 100644 --- a/account_financial_report/tests/test_open_items.py +++ b/account_financial_report/tests/test_open_items.py @@ -1,7 +1,9 @@ # Author: Julien Coux # Copyright 2016 Camptocamp SA +# Copyright 2024 Tecnativa - Carolina Fernandez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.fields import Date from odoo.tests import tagged from odoo.addons.account.tests.common import AccountTestInvoicingCommon @@ -66,3 +68,23 @@ class TestOpenItems(AccountTestInvoicingCommon): [open_items_code_set.add(account.code) for account in open_items.account_ids] self.assertEqual(len(open_items_code_set), len(all_accounts_code_set)) self.assertTrue(open_items_code_set == all_accounts_code_set) + + def test_open_items_grouped_by(self): + open_item_wizard = self.env["open.items.report.wizard"] + all_accounts = self.env["account.account"].search( + [ + ("reconcile", "=", True), + ], + order="code", + ) + wizard = open_item_wizard.create( + { + "date_at": Date.today(), + "account_code_from": self.account001.id, + "account_code_to": all_accounts[-1].id, + "grouped_by": "salesperson", + } + ) + wizard.on_change_account_range() + res = wizard._prepare_report_open_items() + self.assertEqual(res["grouped_by"], wizard.grouped_by) diff --git a/account_financial_report/wizard/open_items_wizard.py b/account_financial_report/wizard/open_items_wizard.py index 7e696f48..467164db 100644 --- a/account_financial_report/wizard/open_items_wizard.py +++ b/account_financial_report/wizard/open_items_wizard.py @@ -59,6 +59,10 @@ class OpenItemsReportWizard(models.TransientModel): comodel_name="account.account", help="Ending account in a range", ) + grouped_by = fields.Selection( + selection=[("partners", "Partners"), ("salesperson", "Partner Salesperson")], + default="partners", + ) @api.onchange("account_code_from", "account_code_to") def on_change_account_range(self): @@ -134,6 +138,19 @@ class OpenItemsReportWizard(models.TransientModel): else: self.account_ids = None + def _calculate_amounts_by_partner(self, account_id, open_items_move_lines_data): + total_amount = {} + for line in open_items_move_lines_data: + partner_id_key = line["partner_id"] + if account_id not in total_amount: + total_amount[account_id] = {} + if partner_id_key not in total_amount[account_id]: + total_amount[account_id][partner_id_key] = {"residual": 0.0} + total_amount[account_id][partner_id_key]["residual"] += line[ + "amount_residual" + ] + return total_amount + def _print_report(self, report_type): self.ensure_one() data = self._prepare_report_open_items() @@ -165,6 +182,7 @@ class OpenItemsReportWizard(models.TransientModel): "account_ids": self.account_ids.ids, "partner_ids": self.partner_ids.ids or [], "account_financial_report_lang": self.env.lang, + "grouped_by": self.grouped_by, } def _export(self, report_type): diff --git a/account_financial_report/wizard/open_items_wizard_view.xml b/account_financial_report/wizard/open_items_wizard_view.xml index 3b65204d..610b5367 100644 --- a/account_financial_report/wizard/open_items_wizard_view.xml +++ b/account_financial_report/wizard/open_items_wizard_view.xml @@ -21,6 +21,7 @@ <group name="other_filters"> <field name="target_move" widget="radio" /> <field name="show_partner_details" /> + <field name="grouped_by" /> <field name="hide_account_at_0" /> <field name="foreign_currency" /> </group>