From 7dc434f4968550766ca4cf081057cd22e40da063 Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Wed, 18 Sep 2024 20:23:27 +0200 Subject: [PATCH] Add module l10n_ch_credit_control_dunning_fees_qr_report --- .../README.rst | 78 ++++ .../__init__.py | 1 + .../__manifest__.py | 20 + .../models/__init__.py | 3 + .../models/account_move.py | 17 + .../credit_control_communication_report.py | 108 +++++ .../models/res_partner_bank.py | 15 + .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 2 + .../reports/credit_control_summary_report.xml | 14 + .../reports/swissqr_report.xml | 11 + .../static/description/index.html | 425 ++++++++++++++++++ ...n_ch_credit_control_dunning_fees_qr_report | 1 + .../setup.py | 6 + 14 files changed, 703 insertions(+) create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/README.rst create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/__init__.py create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/__manifest__.py create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/models/__init__.py create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/models/account_move.py create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/models/credit_control_communication_report.py create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/models/res_partner_bank.py create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/readme/CONTRIBUTORS.rst create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/readme/DESCRIPTION.rst create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/reports/credit_control_summary_report.xml create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/reports/swissqr_report.xml create mode 100644 l10n_ch_credit_control_dunning_fees_qr_report/static/description/index.html create mode 120000 setup/l10n_ch_credit_control_dunning_fees_qr_report/odoo/addons/l10n_ch_credit_control_dunning_fees_qr_report create mode 100644 setup/l10n_ch_credit_control_dunning_fees_qr_report/setup.py diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/README.rst b/l10n_ch_credit_control_dunning_fees_qr_report/README.rst new file mode 100644 index 000000000..a85f9ae95 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/README.rst @@ -0,0 +1,78 @@ +============================== +init7 Credit Control QR report +============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ba30572df8df628f948364e9c8208bca61775732ce304582f9f1c900e6c8cef9 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--switzerland-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-switzerland/tree/16.0/l10n_ch_credit_control_dunning_fees_qr_report + :alt: OCA/l10n-switzerland +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-switzerland-16-0/l10n-switzerland-16-0-l10n_ch_credit_control_dunning_fees_qr_report + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/l10n-switzerland&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module will ensure dunning fees are considered when generating swiss +QR-bill from credit control lines. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* Anna Janiszewska +* Akim Juillerat + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/l10n-switzerland `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/__init__.py b/l10n_ch_credit_control_dunning_fees_qr_report/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/__manifest__.py b/l10n_ch_credit_control_dunning_fees_qr_report/__manifest__.py new file mode 100644 index 000000000..60ede977a --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Swiss Credit Control QR report", + "version": "16.0.1.0.0", + "author": "Camptocamp, Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Finance", + "website": "https://github.com/OCA/l10n-switzerland", + "depends": [ + "account_credit_control", + "account_credit_control_dunning_fees", + "l10n_ch", + ], + "data": [ + "reports/swissqr_report.xml", + "reports/credit_control_summary_report.xml", + ], +} diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/models/__init__.py b/l10n_ch_credit_control_dunning_fees_qr_report/models/__init__.py new file mode 100644 index 000000000..9336cc349 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/models/__init__.py @@ -0,0 +1,3 @@ +from . import credit_control_communication_report +from . import account_move +from . import res_partner_bank diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/models/account_move.py b/l10n_ch_credit_control_dunning_fees_qr_report/models/account_move.py new file mode 100644 index 000000000..97ab086f2 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/models/account_move.py @@ -0,0 +1,17 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def get_qr_amount(self): + qr_dunning_fees_amounts = self.env.context.get("qr_dunning_fees_amounts", {}) + if self.id in qr_dunning_fees_amounts: + return "{:,.2f}".format(qr_dunning_fees_amounts[self.id]).replace( + ",", "\xa0" + ) + else: + return "{:,.2f}".format(self.amount_residual).replace(",", "\xa0") diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/models/credit_control_communication_report.py b/l10n_ch_credit_control_dunning_fees_qr_report/models/credit_control_communication_report.py new file mode 100644 index 000000000..0e9cd801d --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/models/credit_control_communication_report.py @@ -0,0 +1,108 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) +import io +from collections import OrderedDict + +from odoo import api, models + + +class ReportSwissQR(models.AbstractModel): + _inherit = "report.l10n_ch.qr_report_main" + + @api.model + def _get_report_values(self, docids, data=None): + """Replace QR URL to consider dunning fees""" + self = self.with_context(credit_control_run_print_report=True) + res = super()._get_report_values(docids, data=data) + dunning_fees_qr_amounts = self.env.context.get("qr_dunning_fees_amounts", {}) + if not dunning_fees_qr_amounts: + return res + qr_code_urls = {} + invoices = self.env["account.move"].browse(docids) + for invoice in invoices: + if invoice.id not in dunning_fees_qr_amounts: + continue + qr_code_urls[invoice.id] = invoice.partner_bank_id.build_qr_code_base64( + dunning_fees_qr_amounts[invoice.id], + invoice.ref or invoice.name, + invoice.payment_reference, + invoice.currency_id, + invoice.partner_id, + qr_method="ch_qr", + silent_errors=False, + ) + res["qr_code_urls"].update(qr_code_urls) + return res + + +class Report(models.Model): + """Print pay slip form credit line""" + + _inherit = "ir.actions.report" + + def _render_qweb_pdf_prepare_streams(self, report_ref, data, res_ids=None): + credit_control_communication_report_name = ( + "account_credit_control.report_credit_control_summary" + ) + report = self._get_report(report_ref) + report_name = report.report_name + if report_name != credit_control_communication_report_name: + return super()._render_qweb_pdf_prepare_streams( + report_ref, data, res_ids=res_ids + ) + + collected_streams = OrderedDict() + communications = self.env["credit.control.communication"].browse(res_ids) + + communications_streams = super()._render_qweb_pdf_prepare_streams( + self.env["ir.actions.report"]._get_report_from_name( + credit_control_communication_report_name + ), + data, + res_ids=communications.ids, + ) + + for com_id, com_streams in communications_streams.items(): + collected_streams[com_id] = [com_streams["stream"]] + + for communication in communications: + dunning_fees_qr_amounts = {} + for cr_line in communication.credit_control_line_ids: + if not cr_line.move_line_id: + continue + + invoice = cr_line.invoice_id + dunning_fees_qr_amounts[invoice.id] = cr_line.balance_due_total + + # generate QR slips for each communication as the QR report doesn't include valid outlines + # to split the QRs for each communication afterwards + invoice_ids = list(dunning_fees_qr_amounts.keys()) + qr_streams = super( + Report, + self.with_context( + active_ids=invoice_ids, + qr_dunning_fees_amounts=dunning_fees_qr_amounts, + ), + )._render_qweb_pdf_prepare_streams( + "l10n_ch.qr_report_main", data, res_ids=invoice_ids + ) + qr_streams_to_merge = [ + x["stream"] for x in qr_streams.values() if x["stream"] + ] + # attach QR reports to related communication report + collected_streams[communication.id].extend(qr_streams_to_merge) + + # merge streams by communication + for com_id, streams_to_merge in collected_streams.items(): + result_stream = io.BytesIO() + with self._merge_pdfs(streams_to_merge) as pdf_merged_stream: + # Write result stream in a new buffer because the result is added to the array + # passed as argument and we want to close streams in this array + result_stream.write(pdf_merged_stream.getvalue()) + + for stream in streams_to_merge: + stream.close() + + collected_streams[com_id] = {"stream": result_stream, "attachment": None} + + return collected_streams diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/models/res_partner_bank.py b/l10n_ch_credit_control_dunning_fees_qr_report/models/res_partner_bank.py new file mode 100644 index 000000000..2804d56ab --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/models/res_partner_bank.py @@ -0,0 +1,15 @@ +from odoo import models + + +class ResPartnerBank(models.Model): + _inherit = "res.partner.bank" + + def _eligible_for_qr_code( + self, qr_method, debtor_partner, currency, raises_error=True + ): + if self.env.context.get("credit_control_run_print_report"): + raises_error = False + res = super()._eligible_for_qr_code( + qr_method, debtor_partner, currency, raises_error=raises_error + ) + return res diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/readme/CONTRIBUTORS.rst b/l10n_ch_credit_control_dunning_fees_qr_report/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..584887c19 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Anna Janiszewska +* Akim Juillerat diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/readme/DESCRIPTION.rst b/l10n_ch_credit_control_dunning_fees_qr_report/readme/DESCRIPTION.rst new file mode 100644 index 000000000..8bda0710a --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module will ensure dunning fees are considered when generating swiss +QR-bill from credit control lines. diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/reports/credit_control_summary_report.xml b/l10n_ch_credit_control_dunning_fees_qr_report/reports/credit_control_summary_report.xml new file mode 100644 index 000000000..d7eefef65 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/reports/credit_control_summary_report.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/reports/swissqr_report.xml b/l10n_ch_credit_control_dunning_fees_qr_report/reports/swissqr_report.xml new file mode 100644 index 000000000..6968d5dc4 --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/reports/swissqr_report.xml @@ -0,0 +1,11 @@ + + + + diff --git a/l10n_ch_credit_control_dunning_fees_qr_report/static/description/index.html b/l10n_ch_credit_control_dunning_fees_qr_report/static/description/index.html new file mode 100644 index 000000000..18964678e --- /dev/null +++ b/l10n_ch_credit_control_dunning_fees_qr_report/static/description/index.html @@ -0,0 +1,425 @@ + + + + + +init7 Credit Control QR report + + + +
+

init7 Credit Control QR report

+ + +

Beta License: AGPL-3 OCA/l10n-switzerland Translate me on Weblate Try me on Runboat

+

This module will ensure dunning fees are considered when generating swiss +QR-bill from credit control lines.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/l10n-switzerland project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/setup/l10n_ch_credit_control_dunning_fees_qr_report/odoo/addons/l10n_ch_credit_control_dunning_fees_qr_report b/setup/l10n_ch_credit_control_dunning_fees_qr_report/odoo/addons/l10n_ch_credit_control_dunning_fees_qr_report new file mode 120000 index 000000000..8d1b5cf29 --- /dev/null +++ b/setup/l10n_ch_credit_control_dunning_fees_qr_report/odoo/addons/l10n_ch_credit_control_dunning_fees_qr_report @@ -0,0 +1 @@ +../../../../l10n_ch_credit_control_dunning_fees_qr_report \ No newline at end of file diff --git a/setup/l10n_ch_credit_control_dunning_fees_qr_report/setup.py b/setup/l10n_ch_credit_control_dunning_fees_qr_report/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/l10n_ch_credit_control_dunning_fees_qr_report/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)