[IMP] partner_statement: add Detailed Activity report

This commit is contained in:
Miquel Raïch
2022-12-16 10:29:17 +01:00
parent c18ab91075
commit b9b4f1e67f
22 changed files with 1537 additions and 345 deletions

View File

@@ -1,5 +1,7 @@
from . import report_statement_common
from . import activity_statement
from . import detailed_activity_statement
from . import outstanding_statement
from . import activity_statement_xlsx
from . import detailed_activity_statement_xlsx
from . import outstanting_statement_xlsx

View File

@@ -5,6 +5,8 @@ from collections import defaultdict
from odoo import api, models
from .outstanding_statement import OutstandingStatement
class ActivityStatement(models.AbstractModel):
"""Model of Activity Statement"""
@@ -17,40 +19,74 @@ class ActivityStatement(models.AbstractModel):
return str(
self._cr.mogrify(
"""
SELECT l.partner_id, l.currency_id, l.company_id,
sum(CASE WHEN l.currency_id is not null AND l.amount_currency > 0.0
THEN l.amount_currency
ELSE l.debit
END) as debit,
sum(CASE WHEN l.currency_id is not null AND l.amount_currency < 0.0
THEN l.amount_currency * (-1)
ELSE l.credit
END) as credit
SELECT l.partner_id, l.currency_id, l.company_id, l.id,
CASE WHEN l.balance > 0.0
THEN l.balance - sum(coalesce(pd.amount, 0.0))
ELSE l.balance + sum(coalesce(pc.amount, 0.0))
END AS open_amount,
CASE WHEN l.balance > 0.0
THEN l.amount_currency - sum(coalesce(pd.debit_amount_currency, 0.0))
ELSE l.amount_currency + sum(coalesce(pc.credit_amount_currency, 0.0))
END AS open_amount_currency
FROM account_move_line l
JOIN account_account aa ON (aa.id = l.account_id)
JOIN account_account_type at ON (at.id = aa.user_type_id)
JOIN account_move m ON (l.move_id = m.id)
LEFT JOIN (SELECT pr.*
FROM account_partial_reconcile pr
INNER JOIN account_move_line l2
ON pr.credit_move_id = l2.id
WHERE l2.date < %(date_start)s
) as pd ON pd.debit_move_id = l.id
LEFT JOIN (SELECT pr.*
FROM account_partial_reconcile pr
INNER JOIN account_move_line l2
ON pr.debit_move_id = l2.id
WHERE l2.date < %(date_start)s
) as pc ON pc.credit_move_id = l.id
WHERE l.partner_id IN %(partners)s
AND at.type = %(account_type)s
AND l.date < %(date_start)s AND not l.blocked
AND m.state IN ('posted')
GROUP BY l.partner_id, l.currency_id, l.company_id
AND (
(pd.id IS NOT NULL AND
pd.max_date < %(date_start)s) OR
(pc.id IS NOT NULL AND
pc.max_date < %(date_start)s) OR
(pd.id IS NULL AND pc.id IS NULL)
)
GROUP BY l.partner_id, l.currency_id, l.company_id, l.balance, l.id
""",
locals(),
),
"utf-8",
)
def _initial_balance_sql_q2(self, company_id):
def _initial_balance_sql_q2(self, sub):
return str(
self._cr.mogrify(
"""
SELECT Q1.partner_id, debit-credit AS balance,
COALESCE(Q1.currency_id, c.currency_id) AS currency_id
FROM Q1
JOIN res_company c ON (c.id = Q1.company_id)
WHERE c.id = %(company_id)s
""",
f"""
SELECT {sub}.partner_id, {sub}.currency_id,
sum(CASE WHEN {sub}.currency_id is not null
THEN {sub}.open_amount_currency
ELSE {sub}.open_amount
END) as balance, {sub}.company_id
FROM {sub}
GROUP BY {sub}.partner_id, {sub}.currency_id, {sub}.company_id""",
locals(),
),
"utf-8",
)
def _initial_balance_sql_q3(self, sub, company_id):
return str(
self._cr.mogrify(
f"""
SELECT {sub}.partner_id, {sub}.balance,
COALESCE({sub}.currency_id, c.currency_id) AS currency_id
FROM {sub}
JOIN res_company c ON (c.id = {sub}.company_id)
WHERE c.id = %(company_id)s""",
locals(),
),
"utf-8",
@@ -63,23 +99,30 @@ class ActivityStatement(models.AbstractModel):
partners = tuple(partner_ids)
# pylint: disable=E8103
self.env.cr.execute(
"""WITH Q1 AS (%s), Q2 AS (%s)
SELECT partner_id, currency_id, balance
FROM Q2"""
"""WITH Q1 AS (%s),
Q2 AS (%s),
Q3 AS (%s)
SELECT partner_id, currency_id, sum(balance) as balance
FROM Q3
GROUP BY partner_id, currency_id"""
% (
self._initial_balance_sql_q1(partners, date_start, account_type),
self._initial_balance_sql_q2(company_id),
self._initial_balance_sql_q2("Q1"),
self._initial_balance_sql_q3("Q2", company_id),
)
)
for row in self.env.cr.dictfetchall():
balance_start[row.pop("partner_id")].append(row)
return balance_start
def _display_lines_sql_q1(self, partners, date_start, date_end, account_type):
def _display_activity_lines_sql_q1(
self, partners, date_start, date_end, account_type
):
return str(
self._cr.mogrify(
"""
SELECT m.name AS move_id, l.partner_id, l.date,
array_agg(l.id ORDER BY l.id) as ids,
CASE WHEN (aj.type IN ('sale', 'purchase'))
THEN l.name
ELSE '/'
@@ -92,7 +135,7 @@ class ActivityStatement(models.AbstractModel):
WHEN (aj.type in ('bank', 'cash'))
THEN 'Payment'
ELSE ''
END as ref,
END as case_ref,
l.blocked, l.currency_id, l.company_id,
sum(CASE WHEN (l.currency_id is not null AND l.amount_currency > 0.0)
THEN l.amount_currency
@@ -120,33 +163,23 @@ class ActivityStatement(models.AbstractModel):
CASE WHEN (aj.type IN ('sale', 'purchase'))
THEN l.name
ELSE '/'
END,
CASE
WHEN (aj.type IN ('sale', 'purchase')) AND l.name IS NOT NULL
THEN l.ref
WHEN aj.type IN ('sale', 'purchase') AND l.name IS NULL
THEN m.ref
WHEN (aj.type in ('bank', 'cash'))
THEN 'Payment'
ELSE ''
END,
l.blocked, l.currency_id, l.company_id
END, case_ref, l.blocked, l.currency_id, l.company_id
""",
locals(),
),
"utf-8",
)
def _display_lines_sql_q2(self, company_id):
def _display_activity_lines_sql_q2(self, sub, company_id):
return str(
self._cr.mogrify(
"""
SELECT Q1.partner_id, Q1.move_id, Q1.date, Q1.date_maturity,
Q1.name, Q1.ref, Q1.debit, Q1.credit,
Q1.debit-Q1.credit as amount, Q1.blocked,
COALESCE(Q1.currency_id, c.currency_id) AS currency_id
FROM Q1
JOIN res_company c ON (c.id = Q1.company_id)
f"""
SELECT {sub}.partner_id, {sub}.move_id, {sub}.date, {sub}.date_maturity,
{sub}.name, {sub}.case_ref as ref, {sub}.debit, {sub}.credit, {sub}.ids,
{sub}.debit-{sub}.credit as amount, {sub}.blocked,
COALESCE({sub}.currency_id, c.currency_id) AS currency_id
FROM {sub}
JOIN res_company c ON (c.id = {sub}.company_id)
WHERE c.id = %(company_id)s
""",
locals(),
@@ -165,21 +198,117 @@ class ActivityStatement(models.AbstractModel):
"""
WITH Q1 AS (%s),
Q2 AS (%s)
SELECT partner_id, move_id, date, date_maturity, name, ref, debit,
credit, amount, blocked, currency_id
SELECT partner_id, move_id, date, date_maturity, ids,
COALESCE(name, '') as name, COALESCE(ref, '') as ref,
debit, credit, amount, blocked, currency_id
FROM Q2
ORDER BY date, date_maturity, move_id"""
% (
self._display_lines_sql_q1(
self._display_activity_lines_sql_q1(
partners, date_start, date_end, account_type
),
self._display_lines_sql_q2(company_id),
self._display_activity_lines_sql_q2("Q1", company_id),
)
)
for row in self.env.cr.dictfetchall():
res[row.pop("partner_id")].append(row)
return res
def _display_activity_reconciled_lines_sql_q1(self, sub):
return str(
self._cr.mogrify(
f"""
SELECT unnest(ids) as id
FROM {sub}
""",
locals(),
),
"utf-8",
)
def _display_activity_reconciled_lines_sql_q2(self, sub, date_end):
return str(
self._cr.mogrify(
f"""
SELECT l.id as rel_id, m.name AS move_id, l.partner_id, l.date, l.name,
l.blocked, l.currency_id, l.company_id, {sub}.id,
CASE WHEN l.ref IS NOT NULL
THEN l.ref
ELSE m.ref
END as ref,
CASE WHEN (l.currency_id is not null AND l.amount_currency > 0.0)
THEN avg(l.amount_currency)
ELSE avg(l.debit)
END as debit,
CASE WHEN (l.currency_id is not null AND l.amount_currency < 0.0)
THEN avg(l.amount_currency * (-1))
ELSE avg(l.credit)
END as credit,
CASE WHEN l.balance > 0.0
THEN sum(coalesce(pc.amount, 0.0))
ELSE -sum(coalesce(pd.amount, 0.0))
END AS open_amount,
CASE WHEN l.balance > 0.0
THEN sum(coalesce(pc.debit_amount_currency, 0.0))
ELSE -sum(coalesce(pd.credit_amount_currency, 0.0))
END AS open_amount_currency,
CASE WHEN l.date_maturity is null
THEN l.date
ELSE l.date_maturity
END as date_maturity
FROM {sub}
LEFT JOIN account_partial_reconcile pd ON (
pd.debit_move_id = {sub}.id AND pd.max_date <= %(date_end)s)
LEFT JOIN account_partial_reconcile pc ON (
pc.credit_move_id = {sub}.id AND pc.max_date <= %(date_end)s)
LEFT JOIN account_move_line l ON (
pd.credit_move_id = l.id OR pc.debit_move_id = l.id)
LEFT JOIN account_move m ON (l.move_id = m.id)
WHERE l.date <= %(date_end)s AND m.state IN ('posted')
GROUP BY l.id, l.partner_id, m.name, l.date, l.date_maturity, l.name,
CASE WHEN l.ref IS NOT NULL
THEN l.ref
ELSE m.ref
END, {sub}.id,
l.blocked, l.currency_id, l.balance, l.amount_currency, l.company_id
""",
locals(),
),
"utf-8",
)
def _get_account_display_reconciled_lines(
self, company_id, partner_ids, date_start, date_end, account_type
):
partners = tuple(partner_ids)
# pylint: disable=E8103
self.env.cr.execute(
"""
WITH Q1 AS (%s),
Q2 AS (%s),
Q3 AS (%s),
Q4 AS (%s),
Q5 AS (%s),
Q6 AS (%s)
SELECT partner_id, currency_id, move_id, date, date_maturity, debit,
credit, amount, open_amount, COALESCE(name, '') as name,
COALESCE(ref, '') as ref, blocked, id
FROM Q6
ORDER BY date, date_maturity, move_id"""
% (
self._display_activity_lines_sql_q1(
partners, date_start, date_end, account_type
),
self._display_activity_lines_sql_q2("Q1", company_id),
self._display_activity_reconciled_lines_sql_q1("Q2"),
self._display_activity_reconciled_lines_sql_q2("Q3", date_end),
self._display_outstanding_lines_sql_q2("Q4"),
self._display_outstanding_lines_sql_q3("Q5", company_id),
)
)
return self.env.cr.dictfetchall()
@api.model
def _get_report_values(self, docids, data=None):
if not data:
@@ -191,3 +320,11 @@ class ActivityStatement(models.AbstractModel):
data.update(wiz.create({})._prepare_statement())
data["amount_field"] = "amount"
return super()._get_report_values(docids, data)
ActivityStatement._display_outstanding_lines_sql_q2 = (
OutstandingStatement._display_outstanding_lines_sql_q2
)
ActivityStatement._display_outstanding_lines_sql_q3 = (
OutstandingStatement._display_outstanding_lines_sql_q3
)

View File

@@ -2,11 +2,23 @@
# Copyright 2021 ForgeFlow S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, fields, models
from odoo import _, models
from odoo.addons.report_xlsx_helper.report.report_xlsx_format import FORMATS
def copy_format(book, fmt):
properties = [f[4:] for f in dir(fmt) if f[0:4] == "set_"]
dft_fmt = book.add_format()
return book.add_format(
{
k: v
for k, v in fmt.__dict__.items()
if k in properties and dft_fmt.__dict__[k] != v
}
)
class ActivityStatementXslx(models.AbstractModel):
_name = "report.p_s.report_activity_statement_xlsx"
_description = "Activity Statement XLSL Report"
@@ -36,7 +48,7 @@ class ActivityStatementXslx(models.AbstractModel):
}
sheet.merge_range(
row_pos, 0, row_pos, 6, statement_header, FORMATS["format_right_bold"]
row_pos, 0, row_pos, 6, statement_header, FORMATS["format_left_bold"]
)
row_pos += 1
sheet.write(
@@ -47,20 +59,25 @@ class ActivityStatementXslx(models.AbstractModel):
row_pos,
2,
row_pos,
4,
3,
_("Description"),
FORMATS["format_theader_yellow_center"],
)
sheet.write(
row_pos, 5, _("Open Amount"), FORMATS["format_theader_yellow_center"]
row_pos, 4, _("Original Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(
row_pos, 5, _("Applied Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(
row_pos, 6, _("Open Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 6, _("Balance"), FORMATS["format_theader_yellow_center"])
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("start"), FORMATS["format_tcell_date_left"]
row_pos, 1, partner_data.get("prior_day"), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos, 2, row_pos, 4, _("Balance Forward"), FORMATS["format_tcell_left"]
row_pos, 2, row_pos, 5, _("Balance Forward"), FORMATS["format_tcell_left"]
)
sheet.write(
row_pos,
@@ -68,12 +85,21 @@ class ActivityStatementXslx(models.AbstractModel):
currency_data.get("balance_forward"),
FORMATS["current_money_format"],
)
format_tcell_left = FORMATS["format_tcell_left"]
format_tcell_date_left = FORMATS["format_tcell_date_left"]
format_distributed = FORMATS["format_distributed"]
current_money_format = FORMATS["current_money_format"]
for line in currency_data.get("lines"):
if line.get("blocked"):
format_tcell_left = FORMATS["format_tcell_left_blocked"]
format_tcell_date_left = FORMATS["format_tcell_date_left_blocked"]
format_distributed = FORMATS["format_distributed_blocked"]
current_money_format = FORMATS["current_money_format_blocked"]
row_pos += 1
name_to_show = (
line.get("name", "") == "/" or not line.get("name", "")
) and line.get("ref", "")
if line.get("name", "") != "/":
if line.get("name", "") and line.get("name", "") != "/":
if not line.get("ref", ""):
name_to_show = line.get("name", "")
else:
@@ -83,30 +109,26 @@ class ActivityStatementXslx(models.AbstractModel):
name_to_show = line.get("name", "")
elif line.get("ref", "") not in line.get("name", ""):
name_to_show = line.get("ref", "")
sheet.write(row_pos, 0, line.get("move_id", ""), format_tcell_left)
sheet.write(row_pos, 1, line.get("date", ""), format_tcell_date_left)
sheet.merge_range(row_pos, 2, row_pos, 3, name_to_show, format_distributed)
sheet.write(row_pos, 4, line.get("amount", ""), current_money_format)
sheet.write(
row_pos, 0, line.get("move_id", ""), FORMATS["format_tcell_left"]
)
sheet.write(
row_pos, 1, line.get("date", ""), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos, 2, row_pos, 4, name_to_show, FORMATS["format_distributed"]
)
sheet.write(
row_pos, 5, line.get("amount", ""), FORMATS["current_money_format"]
)
sheet.write(
row_pos, 6, line.get("balance", ""), FORMATS["current_money_format"]
row_pos, 5, line.get("applied_amount", ""), current_money_format
)
sheet.write(row_pos, 6, line.get("open_amount", ""), current_money_format)
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("end"), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos, 2, row_pos, 4, _("Ending Balance"), FORMATS["format_tcell_left"]
row_pos, 2, row_pos, 5, _("Ending Balance"), FORMATS["format_tcell_left"]
)
sheet.write(
row_pos, 6, currency_data.get("amount_due"), FORMATS["current_money_format"]
row_pos,
6,
currency_data.get("amount_due"),
FORMATS["current_money_format"],
)
return row_pos
@@ -180,7 +202,7 @@ class ActivityStatementXslx(models.AbstractModel):
)
return row_pos
def _size_columns(self, sheet):
def _size_columns(self, sheet, data):
for i in range(7):
sheet.set_column(0, i, 20)
@@ -203,7 +225,7 @@ class ActivityStatementXslx(models.AbstractModel):
0,
row_pos,
6,
_("Statement of Account from %s") % (company.display_name),
_("Statement of Account from %s") % (company.display_name,),
FORMATS["format_ws_title"],
)
row_pos += 1
@@ -211,10 +233,10 @@ class ActivityStatementXslx(models.AbstractModel):
sheet.write(
row_pos,
2,
fields.Date.from_string(data.get("date_end")),
data.get("data", {}).get(partners.ids[0], {}).get("today"),
FORMATS["format_date_left"],
)
self._size_columns(sheet)
self._size_columns(sheet, data)
for partner in partners:
invoice_address = data.get(
"get_inv_addr", lambda x: self.env["res.partner"]
@@ -286,6 +308,23 @@ class ActivityStatementXslx(models.AbstractModel):
FORMATS["current_money_format"] = workbook.add_format(
{"align": "right", "num_format": money_string}
)
bg_grey = "#CCCCCC"
FORMATS["format_tcell_left_blocked"] = copy_format(
workbook, FORMATS["format_tcell_left"]
)
FORMATS["format_tcell_left_blocked"].set_bg_color(bg_grey)
FORMATS["format_tcell_date_left_blocked"] = copy_format(
workbook, FORMATS["format_tcell_date_left"]
)
FORMATS["format_tcell_date_left_blocked"].set_bg_color(bg_grey)
FORMATS["format_distributed_blocked"] = copy_format(
workbook, FORMATS["format_distributed"]
)
FORMATS["format_distributed_blocked"].set_bg_color(bg_grey)
FORMATS["current_money_format_blocked"] = copy_format(
workbook, FORMATS["current_money_format"]
)
FORMATS["current_money_format_blocked"].set_bg_color(bg_grey)
row_pos = self._write_currency_lines(
row_pos, sheet, partner, currency, data
)

View File

@@ -0,0 +1,43 @@
# Copyright 2022 ForgeFlow, S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models
from .outstanding_statement import OutstandingStatement
class DetailedActivityStatement(models.AbstractModel):
"""Model of Detailed Activity Statement"""
_inherit = "report.partner_statement.activity_statement"
_name = "report.partner_statement.detailed_activity_statement"
_description = "Partner Detailed Activity Statement"
def _get_account_display_prior_lines(
self, company_id, partner_ids, date_start, date_end, account_type
):
return self._get_account_display_lines2(
company_id, partner_ids, date_start, date_end, account_type
)
def _get_account_display_ending_lines(
self, company_id, partner_ids, date_start, date_end, account_type
):
return self._get_account_display_lines2(
company_id, partner_ids, date_start, date_end, account_type
)
def _add_currency_prior_line(self, line, currency):
return self._add_currency_line2(line, currency)
def _add_currency_ending_line(self, line, currency):
return self._add_currency_line2(line, currency)
DetailedActivityStatement._get_account_display_lines2 = (
OutstandingStatement._get_account_display_lines
)
DetailedActivityStatement._display_outstanding_lines_sql_q1 = (
OutstandingStatement._display_outstanding_lines_sql_q1
)
DetailedActivityStatement._add_currency_line2 = OutstandingStatement._add_currency_line

View File

@@ -0,0 +1,568 @@
# Author: Miquel Raïch
# Copyright 2022 ForgeFlow S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, models
from odoo.addons.report_xlsx_helper.report.report_xlsx_format import FORMATS
def copy_format(book, fmt):
properties = [f[4:] for f in dir(fmt) if f[0:4] == "set_"]
dft_fmt = book.add_format()
return book.add_format(
{
k: v
for k, v in fmt.__dict__.items()
if k in properties and dft_fmt.__dict__[k] != v
}
)
class DetailedActivityStatementXslx(models.AbstractModel):
_name = "report.p_s.report_detailed_activity_statement_xlsx"
_description = "Detailed Activity Statement XLSL Report"
_inherit = "report.p_s.report_activity_statement_xlsx"
def _get_report_name(self, report, data=False):
company_id = data.get("company_id", False)
report_name = _("Detailed Activity Statement")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
def _write_currency_lines(self, row_pos, sheet, partner, currency, data):
partner_data = data.get("data", {}).get(partner.id, {})
currency_data = partner_data.get("currencies", {}).get(currency.id)
account_type = data.get("account_type", False)
row_pos += 2
statement_header = _(
"Detailed %(payable)sStatement between %(start)s and %(end)s in %(currency)s"
) % {
"payable": account_type == "payable" and _("Supplier ") or "",
"start": partner_data.get("start"),
"end": partner_data.get("end"),
"currency": currency.display_name,
}
sheet.merge_range(
row_pos,
0,
row_pos,
6,
statement_header,
FORMATS["format_left_bold"],
)
row_pos += 1
sheet.write(
row_pos, 0, _("Reference Number"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 1, _("Date"), FORMATS["format_theader_yellow_center"])
sheet.merge_range(
row_pos,
2,
row_pos,
3,
_("Description"),
FORMATS["format_theader_yellow_center"],
)
sheet.write(
row_pos, 4, _("Original Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(
row_pos, 5, _("Applied Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(
row_pos, 6, _("Open Amount"), FORMATS["format_theader_yellow_center"]
)
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("prior_day"), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos,
2,
row_pos,
5,
_("Initial Balance"),
FORMATS["format_tcell_left"],
)
sheet.write(
row_pos,
6,
currency_data.get("balance_forward"),
FORMATS["current_money_format"],
)
for line in currency_data.get("lines"):
if line.get("blocked") and not line.get("reconciled_line"):
format_tcell_left = FORMATS["format_tcell_left_blocked"]
format_tcell_date_left = FORMATS["format_tcell_date_left_blocked"]
format_distributed = FORMATS["format_distributed_blocked"]
current_money_format = FORMATS["current_money_format_blocked"]
elif line.get("reconciled_line") and not line.get("blocked"):
format_tcell_left = FORMATS["format_tcell_left_reconciled"]
format_tcell_date_left = FORMATS["format_tcell_date_left_reconciled"]
format_distributed = FORMATS["format_distributed_reconciled"]
current_money_format = FORMATS["current_money_format_reconciled"]
elif line.get("blocked") and line.get("reconciled_line"):
format_tcell_left = FORMATS["format_tcell_left_blocked_reconciled"]
format_tcell_date_left = FORMATS[
"format_tcell_date_left_blocked_reconciled"
]
format_distributed = FORMATS["format_distributed_blocked_reconciled"]
current_money_format = FORMATS[
"current_money_format_blocked_reconciled"
]
else:
format_tcell_left = FORMATS["format_tcell_left"]
format_tcell_date_left = FORMATS["format_tcell_date_left"]
format_distributed = FORMATS["format_distributed"]
current_money_format = FORMATS["current_money_format"]
row_pos += 1
name_to_show = (
line.get("name", "") == "/" or not line.get("name", "")
) and line.get("ref", "")
if line.get("name", "") and line.get("name", "") != "/":
if not line.get("ref", ""):
name_to_show = line.get("name", "")
else:
if (line.get("name", "") in line.get("ref", "")) or (
line.get("name", "") == line.get("ref", "")
):
name_to_show = line.get("name", "")
elif line.get("ref", "") not in line.get("name", ""):
name_to_show = line.get("ref", "")
sheet.write(row_pos, 0, line.get("move_id", ""), format_tcell_left)
sheet.write(row_pos, 1, line.get("date", ""), format_tcell_date_left)
sheet.merge_range(row_pos, 2, row_pos, 3, name_to_show, format_distributed)
sheet.write(
row_pos,
4,
line.get("amount", "") if not line.get("reconciled_line") else "",
current_money_format,
)
sheet.write(
row_pos, 5, line.get("applied_amount", ""), current_money_format
)
sheet.write(
row_pos,
6,
line.get("open_amount", "") if not line.get("reconciled_line") else "",
current_money_format,
)
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("end"), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos,
2,
row_pos,
5,
_("Ending Balance"),
FORMATS["format_tcell_left"],
)
sheet.write(
row_pos,
6,
currency_data.get("amount_due"),
FORMATS["current_money_format"],
)
return row_pos
def _write_currency_prior_lines(self, row_pos, sheet, partner, currency, data):
partner_data = data.get("data", {}).get(partner.id, {})
currency_data = partner_data.get("currencies", {}).get(currency.id)
account_type = data.get("account_type", False)
row_pos += 2
statement_header = _(
"%(payable)sStatement up to %(prior_day)s in %(currency)s"
) % {
"payable": account_type == "payable" and _("Supplier ") or "",
"prior_day": partner_data.get("prior_day"),
"currency": currency.display_name,
}
sheet.merge_range(
row_pos,
0,
row_pos,
6,
statement_header,
FORMATS["format_left_bold"],
)
row_pos += 1
sheet.write(
row_pos, 0, _("Reference Number"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 1, _("Date"), FORMATS["format_theader_yellow_center"])
sheet.write(row_pos, 2, _("Due Date"), FORMATS["format_theader_yellow_center"])
sheet.write(
row_pos,
3,
_("Description"),
FORMATS["format_theader_yellow_center"],
)
sheet.write(row_pos, 4, _("Original"), FORMATS["format_theader_yellow_center"])
sheet.write(
row_pos, 5, _("Open Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 6, _("Balance"), FORMATS["format_theader_yellow_center"])
format_tcell_left = FORMATS["format_tcell_left"]
format_tcell_date_left = FORMATS["format_tcell_date_left"]
format_distributed = FORMATS["format_distributed"]
current_money_format = FORMATS["current_money_format"]
for line in currency_data.get("prior_lines"):
if line.get("blocked") and not line.get("reconciled_line"):
format_tcell_left = FORMATS["format_tcell_left_blocked"]
format_tcell_date_left = FORMATS["format_tcell_date_left_blocked"]
format_distributed = FORMATS["format_distributed_blocked"]
current_money_format = FORMATS["current_money_format_blocked"]
elif line.get("reconciled_line") and not line.get("blocked"):
format_tcell_left = FORMATS["format_tcell_left_reconciled"]
format_tcell_date_left = FORMATS["format_tcell_date_left_reconciled"]
format_distributed = FORMATS["format_distributed_reconciled"]
current_money_format = FORMATS["current_money_format_reconciled"]
elif line.get("blocked") and line.get("reconciled_line"):
format_tcell_left = FORMATS["format_tcell_left_blocked_reconciled"]
format_tcell_date_left = FORMATS[
"format_tcell_date_left_blocked_reconciled"
]
format_distributed = FORMATS["format_distributed_blocked_reconciled"]
current_money_format = FORMATS[
"current_money_format_blocked_reconciled"
]
row_pos += 1
name_to_show = (
line.get("name", "") == "/" or not line.get("name", "")
) and line.get("ref", "")
if line.get("name", "") and line.get("name", "") != "/":
if not line.get("ref", ""):
name_to_show = line.get("name", "")
else:
if (line.get("ref", "") in line.get("name", "")) or (
line.get("name", "") == line.get("ref", "")
):
name_to_show = line.get("name", "")
else:
name_to_show = line.get("ref", "")
sheet.write(row_pos, 0, line.get("move_id", ""), format_tcell_left)
sheet.write(row_pos, 1, line.get("date", ""), format_tcell_date_left)
sheet.write(
row_pos,
2,
line.get("date_maturity", ""),
format_tcell_date_left,
)
sheet.write(row_pos, 3, name_to_show, format_distributed)
sheet.write(row_pos, 4, line.get("amount", ""), current_money_format)
sheet.write(row_pos, 5, line.get("open_amount", ""), current_money_format)
sheet.write(row_pos, 6, line.get("balance", ""), current_money_format)
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("prior_day"), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos,
2,
row_pos,
5,
_("Ending Balance"),
FORMATS["format_tcell_left"],
)
sheet.write(
row_pos,
6,
currency_data.get("balance_forward"),
FORMATS["current_money_format"],
)
return row_pos
def _write_currency_ending_lines(self, row_pos, sheet, partner, currency, data):
partner_data = data.get("data", {}).get(partner.id, {})
currency_data = partner_data.get("currencies", {}).get(currency.id)
account_type = data.get("account_type", False)
row_pos += 2
statement_header = _("%(payable)sStatement up to %(end)s in %(currency)s") % {
"payable": account_type == "payable" and _("Supplier ") or "",
"end": partner_data.get("end"),
"currency": currency.display_name,
}
sheet.merge_range(
row_pos,
0,
row_pos,
6,
statement_header,
FORMATS["format_left_bold"],
)
row_pos += 1
sheet.write(
row_pos, 0, _("Reference Number"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 1, _("Date"), FORMATS["format_theader_yellow_center"])
sheet.write(row_pos, 2, _("Due Date"), FORMATS["format_theader_yellow_center"])
sheet.write(
row_pos,
3,
_("Description"),
FORMATS["format_theader_yellow_center"],
)
sheet.write(row_pos, 4, _("Original"), FORMATS["format_theader_yellow_center"])
sheet.write(
row_pos, 5, _("Open Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 6, _("Balance"), FORMATS["format_theader_yellow_center"])
format_tcell_left = FORMATS["format_tcell_left"]
format_tcell_date_left = FORMATS["format_tcell_date_left"]
format_distributed = FORMATS["format_distributed"]
current_money_format = FORMATS["current_money_format"]
for line in currency_data.get("ending_lines"):
if line.get("blocked") and not line.get("reconciled_line"):
format_tcell_left = FORMATS["format_tcell_left_blocked"]
format_tcell_date_left = FORMATS["format_tcell_date_left_blocked"]
format_distributed = FORMATS["format_distributed_blocked"]
current_money_format = FORMATS["current_money_format_blocked"]
elif line.get("reconciled_line") and not line.get("blocked"):
format_tcell_left = FORMATS["format_tcell_left_reconciled"]
format_tcell_date_left = FORMATS["format_tcell_date_left_reconciled"]
format_distributed = FORMATS["format_distributed_reconciled"]
current_money_format = FORMATS["current_money_format_reconciled"]
elif line.get("blocked") and line.get("reconciled_line"):
format_tcell_left = FORMATS["format_tcell_left_blocked_reconciled"]
format_tcell_date_left = FORMATS[
"format_tcell_date_left_blocked_reconciled"
]
format_distributed = FORMATS["format_distributed_blocked_reconciled"]
current_money_format = FORMATS[
"current_money_format_blocked_reconciled"
]
row_pos += 1
name_to_show = (
line.get("name", "") == "/" or not line.get("name", "")
) and line.get("ref", "")
if line.get("name", "") and line.get("name", "") != "/":
if not line.get("ref", ""):
name_to_show = line.get("name", "")
else:
if (line.get("ref", "") in line.get("name", "")) or (
line.get("name", "") == line.get("ref", "")
):
name_to_show = line.get("name", "")
else:
name_to_show = line.get("ref", "")
sheet.write(row_pos, 0, line.get("move_id", ""), format_tcell_left)
sheet.write(row_pos, 1, line.get("date", ""), format_tcell_date_left)
sheet.write(
row_pos,
2,
line.get("date_maturity", ""),
format_tcell_date_left,
)
sheet.write(row_pos, 3, name_to_show, format_distributed)
sheet.write(row_pos, 4, line.get("amount", ""), current_money_format)
sheet.write(row_pos, 5, line.get("open_amount", ""), current_money_format)
sheet.write(row_pos, 6, line.get("balance", ""), current_money_format)
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("end"), FORMATS["format_tcell_date_left"]
)
sheet.merge_range(
row_pos,
2,
row_pos,
5,
_("Ending Balance"),
FORMATS["format_tcell_left"],
)
sheet.write(
row_pos,
6,
currency_data.get("amount_due"),
FORMATS["current_money_format"],
)
return row_pos
def _size_columns(self, sheet, data):
for i in range(7):
sheet.set_column(0, i, 20)
def generate_xlsx_report(self, workbook, data, objects):
report_model = self.env["report.partner_statement.detailed_activity_statement"]
self._define_formats(workbook)
FORMATS["format_distributed"] = workbook.add_format({"align": "vdistributed"})
company_id = data.get("company_id", False)
if company_id:
company = self.env["res.company"].browse(company_id)
else:
company = self.env.user.company_id
data.update(report_model._get_report_values(data.get("partner_ids"), data))
partners = self.env["res.partner"].browse(data.get("partner_ids"))
sheet = workbook.add_worksheet(_("Detailed Activity Statement"))
sheet.set_landscape()
row_pos = 0
sheet.merge_range(
row_pos,
0,
row_pos,
6,
_("Statement of Account from %s") % (company.display_name,),
FORMATS["format_ws_title"],
)
row_pos += 1
sheet.write(row_pos, 1, _("Date:"), FORMATS["format_theader_yellow_right"])
sheet.write(
row_pos,
2,
data.get("data", {}).get(partners.ids[0], {}).get("today"),
FORMATS["format_date_left"],
)
self._size_columns(sheet, data)
for partner in partners:
invoice_address = data.get(
"get_inv_addr", lambda x: self.env["res.partner"]
)(partner)
row_pos += 3
sheet.write(
row_pos, 1, _("Statement to:"), FORMATS["format_theader_yellow_right"]
)
sheet.merge_range(
row_pos,
2,
row_pos,
3,
invoice_address.display_name,
FORMATS["format_left"],
)
if invoice_address.vat:
sheet.write(
row_pos,
4,
_("VAT:"),
FORMATS["format_theader_yellow_right"],
)
sheet.write(
row_pos,
5,
invoice_address.vat,
FORMATS["format_left"],
)
row_pos += 1
sheet.write(
row_pos, 1, _("Statement from:"), FORMATS["format_theader_yellow_right"]
)
sheet.merge_range(
row_pos,
2,
row_pos,
3,
company.partner_id.display_name,
FORMATS["format_left"],
)
if company.vat:
sheet.write(
row_pos,
4,
_("VAT:"),
FORMATS["format_theader_yellow_right"],
)
sheet.write(
row_pos,
5,
company.vat,
FORMATS["format_left"],
)
partner_data = data.get("data", {}).get(partner.id)
currencies = partner_data.get("currencies", {}).keys()
if currencies:
row_pos += 1
for currency_id in currencies:
currency = self.env["res.currency"].browse(currency_id)
if currency.position == "after":
money_string = "#,##0.%s " % (
"0" * currency.decimal_places
) + "[${}]".format(currency.symbol)
elif currency.position == "before":
money_string = "[${}]".format(currency.symbol) + " #,##0.%s" % (
"0" * currency.decimal_places
)
FORMATS["current_money_format"] = workbook.add_format(
{"align": "right", "num_format": money_string}
)
bg_grey = "#CCCCCC"
FORMATS["format_tcell_left_blocked"] = copy_format(
workbook, FORMATS["format_tcell_left"]
)
FORMATS["format_tcell_left_blocked"].set_bg_color(bg_grey)
FORMATS["format_tcell_date_left_blocked"] = copy_format(
workbook, FORMATS["format_tcell_date_left"]
)
FORMATS["format_tcell_date_left_blocked"].set_bg_color(bg_grey)
FORMATS["format_distributed_blocked"] = copy_format(
workbook, FORMATS["format_distributed"]
)
FORMATS["format_distributed_blocked"].set_bg_color(bg_grey)
FORMATS["current_money_format_blocked"] = copy_format(
workbook, FORMATS["current_money_format"]
)
FORMATS["current_money_format_blocked"].set_bg_color(bg_grey)
FORMATS["format_tcell_left_reconciled"] = copy_format(
workbook, FORMATS["format_tcell_left"]
)
FORMATS["format_tcell_left_reconciled"].set_italic(True)
FORMATS["format_tcell_left_reconciled"].set_font_size(10)
FORMATS["format_tcell_left_reconciled"].set_indent(1)
FORMATS["format_tcell_date_left_reconciled"] = copy_format(
workbook, FORMATS["format_tcell_date_left"]
)
FORMATS["format_tcell_date_left_reconciled"].set_italic(True)
FORMATS["format_tcell_date_left_reconciled"].set_font_size(10)
FORMATS["format_distributed_reconciled"] = copy_format(
workbook, FORMATS["format_distributed"]
)
FORMATS["format_distributed_reconciled"].set_italic(True)
FORMATS["format_distributed_reconciled"].set_font_size(10)
FORMATS["current_money_format_reconciled"] = copy_format(
workbook, FORMATS["current_money_format"]
)
FORMATS["current_money_format_reconciled"].set_italic(True)
FORMATS["current_money_format_reconciled"].set_font_size(10)
FORMATS["format_tcell_left_blocked_reconciled"] = copy_format(
workbook, FORMATS["format_tcell_left"]
)
FORMATS["format_tcell_left_blocked_reconciled"].set_bg_color(bg_grey)
FORMATS["format_tcell_left_blocked_reconciled"].set_italic(True)
FORMATS["format_tcell_left_blocked_reconciled"].set_font_size(10)
FORMATS["format_tcell_left_blocked_reconciled"].set_indent(1)
FORMATS["format_tcell_date_left_blocked_reconciled"] = copy_format(
workbook, FORMATS["format_tcell_date_left"]
)
FORMATS["format_tcell_date_left_blocked_reconciled"].set_bg_color(
bg_grey
)
FORMATS["format_tcell_date_left_blocked_reconciled"].set_italic(True)
FORMATS["format_tcell_date_left_blocked_reconciled"].set_font_size(10)
FORMATS["format_distributed_blocked_reconciled"] = copy_format(
workbook, FORMATS["format_distributed"]
)
FORMATS["format_distributed_blocked_reconciled"].set_bg_color(bg_grey)
FORMATS["format_distributed_blocked_reconciled"].set_italic(True)
FORMATS["format_distributed_blocked_reconciled"].set_font_size(10)
FORMATS["current_money_format_blocked_reconciled"] = copy_format(
workbook, FORMATS["current_money_format"]
)
FORMATS["current_money_format_blocked_reconciled"].set_bg_color(bg_grey)
FORMATS["current_money_format_blocked_reconciled"].set_italic(True)
FORMATS["current_money_format_blocked_reconciled"].set_font_size(10)
row_pos = self._write_currency_prior_lines(
row_pos, sheet, partner, currency, data
)
row_pos = self._write_currency_lines(
row_pos, sheet, partner, currency, data
)
row_pos = self._write_currency_ending_lines(
row_pos, sheet, partner, currency, data
)
row_pos = self._write_currency_buckets(
row_pos, sheet, partner, currency, data
)

View File

@@ -12,13 +12,13 @@ class OutstandingStatement(models.AbstractModel):
_name = "report.partner_statement.outstanding_statement"
_description = "Partner Outstanding Statement"
def _display_lines_sql_q1(self, partners, date_end, account_type):
def _display_outstanding_lines_sql_q1(self, partners, date_end, account_type):
partners = tuple(partners)
return str(
self._cr.mogrify(
"""
SELECT l.id, m.name AS move_id, l.partner_id, l.date, l.name,
l.blocked, l.currency_id, l.company_id,
l.blocked, l.currency_id, l.company_id,
CASE WHEN l.ref IS NOT NULL
THEN l.ref
ELSE m.ref
@@ -60,13 +60,13 @@ class OutstandingStatement(models.AbstractModel):
WHERE l2.date <= %(date_end)s
) as pc ON pc.credit_move_id = l.id
WHERE l.partner_id IN %(partners)s AND at.type = %(account_type)s
AND (
(pd.id IS NOT NULL AND
pd.max_date <= %(date_end)s) OR
(pc.id IS NOT NULL AND
pc.max_date <= %(date_end)s) OR
(pd.id IS NULL AND pc.id IS NULL)
) AND l.date <= %(date_end)s AND m.state IN ('posted')
AND (
(pd.id IS NOT NULL AND
pd.max_date <= %(date_end)s) OR
(pc.id IS NOT NULL AND
pc.max_date <= %(date_end)s) OR
(pd.id IS NULL AND pc.id IS NULL)
) AND l.date <= %(date_end)s AND m.state IN ('posted')
GROUP BY l.id, l.partner_id, m.name, l.date, l.date_maturity, l.name,
CASE WHEN l.ref IS NOT NULL
THEN l.ref
@@ -79,36 +79,36 @@ class OutstandingStatement(models.AbstractModel):
"utf-8",
)
def _display_lines_sql_q2(self):
def _display_outstanding_lines_sql_q2(self, sub):
return str(
self._cr.mogrify(
"""
SELECT Q1.partner_id, Q1.currency_id, Q1.move_id,
Q1.date, Q1.date_maturity, Q1.debit, Q1.credit,
Q1.name, Q1.ref, Q1.blocked, Q1.company_id,
CASE WHEN Q1.currency_id is not null
THEN Q1.open_amount_currency
ELSE Q1.open_amount
END as open_amount
FROM Q1
f"""
SELECT {sub}.partner_id, {sub}.currency_id, {sub}.move_id,
{sub}.date, {sub}.date_maturity, {sub}.debit, {sub}.credit,
{sub}.name, {sub}.ref, {sub}.blocked, {sub}.company_id,
CASE WHEN {sub}.currency_id is not null
THEN {sub}.open_amount_currency
ELSE {sub}.open_amount
END as open_amount, {sub}.id
FROM {sub}
""",
locals(),
),
"utf-8",
)
def _display_lines_sql_q3(self, company_id):
def _display_outstanding_lines_sql_q3(self, sub, company_id):
return str(
self._cr.mogrify(
"""
SELECT Q2.partner_id, Q2.move_id, Q2.date, Q2.date_maturity,
Q2.name, Q2.ref, Q2.debit, Q2.credit,
Q2.debit-Q2.credit AS amount, blocked,
COALESCE(Q2.currency_id, c.currency_id) AS currency_id,
Q2.open_amount
FROM Q2
JOIN res_company c ON (c.id = Q2.company_id)
WHERE c.id = %(company_id)s AND Q2.open_amount != 0.0
f"""
SELECT {sub}.partner_id, {sub}.move_id, {sub}.date,
{sub}.date_maturity, {sub}.name, {sub}.ref, {sub}.debit,
{sub}.credit, {sub}.debit-{sub}.credit AS amount,
COALESCE({sub}.currency_id, c.currency_id) AS currency_id,
{sub}.open_amount, {sub}.blocked, {sub}.id
FROM {sub}
JOIN res_company c ON (c.id = {sub}.company_id)
WHERE c.id = %(company_id)s AND {sub}.open_amount != 0.0
""",
locals(),
),
@@ -127,13 +127,16 @@ class OutstandingStatement(models.AbstractModel):
Q2 AS (%s),
Q3 AS (%s)
SELECT partner_id, currency_id, move_id, date, date_maturity, debit,
credit, amount, open_amount, name, ref, blocked
credit, amount, open_amount, COALESCE(name, '') as name,
COALESCE(ref, '') as ref, blocked, id
FROM Q3
ORDER BY date, date_maturity, move_id"""
% (
self._display_lines_sql_q1(partners, date_end, account_type),
self._display_lines_sql_q2(),
self._display_lines_sql_q3(company_id),
self._display_outstanding_lines_sql_q1(
partners, date_end, account_type
),
self._display_outstanding_lines_sql_q2("Q1"),
self._display_outstanding_lines_sql_q3("Q2", company_id),
)
)
for row in self.env.cr.dictfetchall():

View File

@@ -2,11 +2,23 @@
# Copyright 2021 ForgeFlow S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, fields, models
from odoo import _, models
from odoo.addons.report_xlsx_helper.report.report_xlsx_format import FORMATS
def copy_format(book, fmt):
properties = [f[4:] for f in dir(fmt) if f[0:4] == "set_"]
dft_fmt = book.add_format()
return book.add_format(
{
k: v
for k, v in fmt.__dict__.items()
if k in properties and dft_fmt.__dict__[k] != v
}
)
class OutstandingStatementXslx(models.AbstractModel):
_name = "report.p_s.report_outstanding_statement_xlsx"
_description = "Outstanding Statement XLSL Report"
@@ -33,7 +45,7 @@ class OutstandingStatementXslx(models.AbstractModel):
}
sheet.merge_range(
row_pos, 0, row_pos, 6, statement_header, FORMATS["format_right_bold"]
row_pos, 0, row_pos, 6, statement_header, FORMATS["format_left_bold"]
)
row_pos += 1
sheet.write(
@@ -49,12 +61,21 @@ class OutstandingStatementXslx(models.AbstractModel):
row_pos, 5, _("Open Amount"), FORMATS["format_theader_yellow_center"]
)
sheet.write(row_pos, 6, _("Balance"), FORMATS["format_theader_yellow_center"])
format_tcell_left = FORMATS["format_tcell_left"]
format_tcell_date_left = FORMATS["format_tcell_date_left"]
format_distributed = FORMATS["format_distributed"]
current_money_format = FORMATS["current_money_format"]
for line in currency_data.get("lines"):
if line.get("blocked"):
format_tcell_left = FORMATS["format_tcell_left_blocked"]
format_tcell_date_left = FORMATS["format_tcell_date_left_blocked"]
format_distributed = FORMATS["format_distributed_blocked"]
current_money_format = FORMATS["current_money_format_blocked"]
row_pos += 1
name_to_show = (
line.get("name", "") == "/" or not line.get("name", "")
) and line.get("ref", "")
if line.get("name", "") != "/":
if line.get("name", "") and line.get("name", "") != "/":
if not line.get("ref", ""):
name_to_show = line.get("name", "")
else:
@@ -64,28 +85,18 @@ class OutstandingStatementXslx(models.AbstractModel):
name_to_show = line.get("name", "")
else:
name_to_show = line.get("ref", "")
sheet.write(
row_pos, 0, line.get("move_id", ""), FORMATS["format_tcell_left"]
)
sheet.write(
row_pos, 1, line.get("date", ""), FORMATS["format_tcell_date_left"]
)
sheet.write(row_pos, 0, line.get("move_id", ""), format_tcell_left)
sheet.write(row_pos, 1, line.get("date", ""), format_tcell_date_left)
sheet.write(
row_pos,
2,
line.get("date_maturity", ""),
FORMATS["format_tcell_date_left"],
)
sheet.write(row_pos, 3, name_to_show, FORMATS["format_distributed"])
sheet.write(
row_pos, 4, line.get("amount", ""), FORMATS["current_money_format"]
)
sheet.write(
row_pos, 5, line.get("open_amount", ""), FORMATS["current_money_format"]
)
sheet.write(
row_pos, 6, line.get("balance", ""), FORMATS["current_money_format"]
format_tcell_date_left,
)
sheet.write(row_pos, 3, name_to_show, format_distributed)
sheet.write(row_pos, 4, line.get("amount", ""), current_money_format)
sheet.write(row_pos, 5, line.get("open_amount", ""), current_money_format)
sheet.write(row_pos, 6, line.get("balance", ""), current_money_format)
row_pos += 1
sheet.write(
row_pos, 1, partner_data.get("end"), FORMATS["format_tcell_date_left"]
@@ -169,7 +180,7 @@ class OutstandingStatementXslx(models.AbstractModel):
)
return row_pos
def _size_columns(self, sheet):
def _size_columns(self, sheet, data):
for i in range(7):
sheet.set_column(0, i, 20)
@@ -192,7 +203,7 @@ class OutstandingStatementXslx(models.AbstractModel):
0,
row_pos,
6,
_("Statement of Account from %s") % (company.display_name),
_("Statement of Account from %s") % (company.display_name,),
FORMATS["format_ws_title"],
)
row_pos += 1
@@ -200,10 +211,10 @@ class OutstandingStatementXslx(models.AbstractModel):
sheet.write(
row_pos,
2,
fields.Date.from_string(data.get("date_end")),
data.get("data", {}).get(partners.ids[0], {}).get("today"),
FORMATS["format_date_left"],
)
self._size_columns(sheet)
self._size_columns(sheet, data)
for partner in partners:
invoice_address = data.get(
"get_inv_addr", lambda x: self.env["res.partner"]
@@ -275,6 +286,23 @@ class OutstandingStatementXslx(models.AbstractModel):
FORMATS["current_money_format"] = workbook.add_format(
{"align": "right", "num_format": money_string}
)
bg_grey = "#CCCCCC"
FORMATS["format_tcell_left_blocked"] = copy_format(
workbook, FORMATS["format_tcell_left"]
)
FORMATS["format_tcell_left_blocked"].set_bg_color(bg_grey)
FORMATS["format_tcell_date_left_blocked"] = copy_format(
workbook, FORMATS["format_tcell_date_left"]
)
FORMATS["format_tcell_date_left_blocked"].set_bg_color(bg_grey)
FORMATS["format_distributed_blocked"] = copy_format(
workbook, FORMATS["format_distributed"]
)
FORMATS["format_distributed_blocked"].set_bg_color(bg_grey)
FORMATS["current_money_format_blocked"] = copy_format(
workbook, FORMATS["current_money_format"]
)
FORMATS["current_money_format_blocked"].set_bg_color(bg_grey)
row_pos = self._write_currency_lines(
row_pos, sheet, partner, currency, data
)

View File

@@ -34,6 +34,21 @@ class ReportStatementCommon(models.AbstractModel):
):
return {}
def _get_account_display_prior_lines(
self, company_id, partner_ids, date_start, date_end, account_type
):
return {}
def _get_account_display_reconciled_lines(
self, company_id, partner_ids, date_start, date_end, account_type
):
return {}
def _get_account_display_ending_lines(
self, company_id, partner_ids, date_start, date_end, account_type
):
return {}
def _show_buckets_sql_q1(self, partners, date_end, account_type):
return str(
self._cr.mogrify(
@@ -273,16 +288,21 @@ class ReportStatementCommon(models.AbstractModel):
_("Total"),
]
def _get_line_currency_defaults(self, currency_id, currencies, balance_forward):
def _get_line_currency_defaults(
self, currency_id, currencies, balance_forward, amount_due
):
if currency_id not in currencies:
# This will only happen if currency is inactive
currencies[currency_id] = self.env["res.currency"].browse(currency_id)
return (
{
"prior_lines": [],
"lines": [],
"ending_lines": [],
"buckets": [],
"balance_forward": balance_forward,
"amount_due": balance_forward,
"amount_due": amount_due,
"ending_balance": 0.0,
},
currencies,
)
@@ -290,6 +310,12 @@ class ReportStatementCommon(models.AbstractModel):
def _add_currency_line(self, line, currency):
return [line]
def _add_currency_prior_line(self, line, currency):
return [line]
def _add_currency_ending_line(self, line, currency):
return [line]
@api.model
def _get_report_values(self, docids, data=None):
# flake8: noqa: C901
@@ -325,6 +351,8 @@ class ReportStatementCommon(models.AbstractModel):
date_end = datetime.strptime(date_end, DEFAULT_SERVER_DATE_FORMAT).date()
account_type = data["account_type"]
aging_type = data["aging_type"]
is_activity = data.get("is_activity")
is_detailed = data.get("is_detailed")
today = fields.Date.today()
amount_field = data.get("amount_field", "amount")
@@ -344,9 +372,31 @@ class ReportStatementCommon(models.AbstractModel):
res = {}
# get base data
prior_day = date_start - timedelta(days=1) if date_start else None
prior_lines = (
self._get_account_display_prior_lines(
company_id, partner_ids, prior_day, prior_day, account_type
)
if is_detailed
else {}
)
lines = self._get_account_display_lines(
company_id, partner_ids, date_start, date_end, account_type
)
ending_lines = (
self._get_account_display_ending_lines(
company_id, partner_ids, date_start, date_end, account_type
)
if is_detailed
else {}
)
reconciled_lines = (
self._get_account_display_reconciled_lines(
company_id, partner_ids, date_start, date_end, account_type
)
if is_activity
else {}
)
balances_forward = self._get_account_initial_balance(
company_id, partner_ids, date_start, account_type
)
@@ -359,7 +409,7 @@ class ReportStatementCommon(models.AbstractModel):
else:
bucket_labels = {}
# organise and format for report
# organize and format for report
format_date = self._format_date_to_partner_lang
partners_to_remove = set()
for partner_id in partner_ids:
@@ -369,6 +419,9 @@ class ReportStatementCommon(models.AbstractModel):
date_start, date_formats.get(partner_id, default_fmt)
),
"end": format_date(date_end, date_formats.get(partner_id, default_fmt)),
"prior_day": format_date(
prior_day, date_formats.get(partner_id, default_fmt)
),
"currencies": {},
}
currency_dict = res[partner_id]["currencies"]
@@ -378,7 +431,32 @@ class ReportStatementCommon(models.AbstractModel):
currency_dict[line["currency_id"]],
currencies,
) = self._get_line_currency_defaults(
line["currency_id"], currencies, line["balance"]
line["currency_id"],
currencies,
line["balance"],
0.0 if is_detailed else line["balance"],
)
for line in prior_lines.get(partner_id, []):
if line["currency_id"] not in currency_dict:
(
currency_dict[line["currency_id"]],
currencies,
) = self._get_line_currency_defaults(
line["currency_id"], currencies, 0.0, 0.0
)
line_currency = currency_dict[line["currency_id"]]
if not line["blocked"]:
line_currency["amount_due"] += line["open_amount"]
line["balance"] = line_currency["amount_due"]
line["date"] = format_date(
line["date"], date_formats.get(partner_id, default_fmt)
)
line["date_maturity"] = format_date(
line["date_maturity"], date_formats.get(partner_id, default_fmt)
)
line_currency["prior_lines"].extend(
self._add_currency_prior_line(line, currencies[line["currency_id"]])
)
for line in lines[partner_id]:
@@ -387,11 +465,59 @@ class ReportStatementCommon(models.AbstractModel):
currency_dict[line["currency_id"]],
currencies,
) = self._get_line_currency_defaults(
line["currency_id"], currencies, 0.0
line["currency_id"], currencies, 0.0, 0.0
)
line_currency = currency_dict[line["currency_id"]]
if not line["blocked"]:
line_currency["amount_due"] += line[amount_field]
if not is_activity:
line_currency["amount_due"] += line[amount_field]
line["balance"] = line_currency["amount_due"]
else:
line_currency["ending_balance"] += line[amount_field]
line["balance"] = line_currency["ending_balance"]
line["date"] = format_date(
line["date"], date_formats.get(partner_id, default_fmt)
)
line["date_maturity"] = format_date(
line["date_maturity"], date_formats.get(partner_id, default_fmt)
)
line["reconciled_line"] = False
if is_activity:
line["open_amount"] = 0.0
line["applied_amount"] = 0.0
line_currency["lines"].extend(
self._add_currency_line(line, currencies[line["currency_id"]])
)
for line2 in reconciled_lines:
if line2["id"] in line["ids"]:
line2["date"] = format_date(
line2["date"], date_formats.get(partner_id, default_fmt)
)
line2["date_maturity"] = format_date(
line2["date_maturity"],
date_formats.get(partner_id, default_fmt),
)
line2["reconciled_line"] = True
line2["applied_amount"] = line2["open_amount"]
line["applied_amount"] += line2["open_amount"]
if is_detailed:
line_currency["lines"].extend(
self._add_currency_line(
line2, currencies[line["currency_id"]]
)
)
if is_activity:
line["open_amount"] = line["amount"] + line["applied_amount"]
line_currency["amount_due"] += line["open_amount"]
if is_detailed:
for line_currency in currency_dict.values():
line_currency["amount_due"] = 0.0
for line in ending_lines.get(partner_id, []):
line_currency = currency_dict[line["currency_id"]]
if not line["blocked"]:
line_currency["amount_due"] += line["open_amount"]
line["balance"] = line_currency["amount_due"]
line["date"] = format_date(
line["date"], date_formats.get(partner_id, default_fmt)
@@ -399,8 +525,10 @@ class ReportStatementCommon(models.AbstractModel):
line["date_maturity"] = format_date(
line["date_maturity"], date_formats.get(partner_id, default_fmt)
)
line_currency["lines"].extend(
self._add_currency_line(line, currencies[line["currency_id"]])
line_currency["ending_lines"].extend(
self._add_currency_ending_line(
line, currencies[line["currency_id"]]
)
)
if data["show_aging_buckets"]:
@@ -410,7 +538,7 @@ class ReportStatementCommon(models.AbstractModel):
currency_dict[line["currency_id"]],
currencies,
) = self._get_line_currency_defaults(
line["currency_id"], currencies, 0.0
line["currency_id"], currencies, 0.0, 0.0
)
line_currency = currency_dict[line["currency_id"]]
line_currency["buckets"] = line
@@ -439,6 +567,7 @@ class ReportStatementCommon(models.AbstractModel):
"company": self.env["res.company"].browse(company_id),
"Currencies": currencies,
"account_type": account_type,
"is_detailed": is_detailed,
"bucket_labels": bucket_labels,
"get_inv_addr": self._get_invoice_address,
}