[IMP] account_financial_report: Open items groupy by salesman

TT49193
This commit is contained in:
Carolina Fernandez
2024-05-22 13:38:05 +02:00
committed by Víctor Martínez
parent c81cfc0f98
commit e14373d995
10 changed files with 438 additions and 93 deletions

View File

@@ -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 (
@@ -236,7 +236,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
@@ -251,7 +253,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,
@@ -265,6 +267,7 @@ class OpenItemsReport(models.AbstractModel):
only_posted_moves,
company_id,
date_from,
grouped_by,
)
total_amount = self._calculate_amounts(open_items_move_lines_data)
@@ -290,6 +293,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):

View File

@@ -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().write_ending_balance_from_dict(
my_object, name, label, report_data
)

View File

@@ -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,51 +29,87 @@
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-if="Open_Items[account_id]">
<t
t-call="account_financial_report.report_open_items_lines_header"
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-foreach="partner_totals.get(account_id, {})"
t-as="partner_id_key"
>
<t
t-call="account_financial_report.report_open_items_lines"
/>
<t t-set="has_lines" t-value="False" />
<div
class="act_as_table data_table"
style="width: 100%;"
>
<t
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>
<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>
</div>
</t>
<!-- Display account footer -->
<t
t-call="account_financial_report.report_open_items_ending_cumul"
>
@@ -87,23 +124,92 @@
<t t-set="type" t-value='"partner_type"' />
</t>
</t>
</div>
</t>
<div style="page-break-after: always;" />
</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-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 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 +400,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 +432,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">