Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions l10n_jp_summary_invoice/README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=====================
Japan Summary Invoice
=====================
Expand All @@ -17,7 +13,7 @@ Japan Summary Invoice
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
.. |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--japan-lightgray.png?logo=github
Expand Down Expand Up @@ -91,6 +87,12 @@ Usage
the summary of the tax amounts in the selected invoices.
3. Print the summary invoice report (合計請求書) from *Print > JP
Summary Invoice* of the billing.
4. Once a validated summary invoice has been printed or sent at least
once, the **Printed/Sent** field is checked automatically, and trying
to delete the billing raises an error, so that its sequence number is
never orphaned from accounting reports. Cancel it instead if it is no
longer valid. If you still need to delete it, uncheck the
**Printed/Sent** field manually first.

Bug Tracker
===========
Expand Down
2 changes: 1 addition & 1 deletion l10n_jp_summary_invoice/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Japan Summary Invoice",
"version": "18.0.1.5.0",
"version": "18.0.1.6.0",
"category": "Japanese Localization",
"author": "Quartile, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/l10n-japan",
Expand Down
1 change: 1 addition & 0 deletions l10n_jp_summary_invoice/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from . import account_billing
from . import ir_actions_report
from . import account_move_line
from . import account_move
from . import account_tax_group
Expand Down
21 changes: 20 additions & 1 deletion l10n_jp_summary_invoice/models/account_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import Command, _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.exceptions import UserError, ValidationError


class AccountBilling(models.Model):
Expand Down Expand Up @@ -52,6 +52,25 @@ class AccountBilling(models.Model):
report_subtitle = fields.Char(
help="Subtitle to be printed below the title of the summary invoice report.",
)
is_billing_sent = fields.Boolean(
string="Printed/Sent",
copy=False,
tracking=True,
help="It indicates that the summary invoice has been sent or its PDF "
"has been generated.",
)

@api.ondelete(at_uninstall=False)
def _unlink_except_billing_sent(self):
sent_billings = self.filtered("is_billing_sent")
if sent_billings:
raise UserError(
_(
"You cannot delete the following summary invoice(s) "
"because they have already been printed or sent: %s"
)
% ", ".join(sent_billings.mapped("display_name"))
)

@api.constrains("state", "billing_line_ids")
def _check_account_move_billability(self):
Expand Down
18 changes: 18 additions & 0 deletions l10n_jp_summary_invoice/models/ir_actions_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 Quartile (https://www.quartile.co)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import models


class IrActionsReport(models.Model):
_inherit = "ir.actions.report"

def _render_qweb_pdf(self, report_ref, res_ids=None, data=None):
result = super()._render_qweb_pdf(report_ref, res_ids, data)
report = self._get_report(report_ref)
if report.model == "account.billing" and res_ids:
if isinstance(res_ids, int):
res_ids = [res_ids]
billings = self.env["account.billing"].sudo().browse(res_ids)
billings.filtered("name").write({"is_billing_sent": True})
return result
6 changes: 6 additions & 0 deletions l10n_jp_summary_invoice/readme/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@
the summary of the tax amounts in the selected invoices.
3. Print the summary invoice report (合計請求書) from *Print \> JP
Summary Invoice* of the billing.
4. Once a validated summary invoice has been printed or sent at least
once, the **Printed/Sent** field is checked automatically, and
trying to delete the billing raises an error, so that its sequence
number is never orphaned from accounting reports. Cancel it instead
if it is no longer valid. If you still need to delete it, uncheck
the **Printed/Sent** field manually first.
34 changes: 17 additions & 17 deletions l10n_jp_summary_invoice/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>Japan Summary Invoice</title>
<style type="text/css">

/*
Expand Down Expand Up @@ -360,21 +360,16 @@
</style>
</head>
<body>
<div class="document">
<div class="document" id="japan-summary-invoice">
<h1 class="title">Japan Summary Invoice</h1>


<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="japan-summary-invoice">
<h1>Japan Summary Invoice</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:383b2c659d9ba8cabd01df1832910525f2878f0f18964c4d6023edee29c57747
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/l10n-japan/tree/18.0/l10n_jp_summary_invoice"><img alt="OCA/l10n-japan" src="https://img.shields.io/badge/github-OCA%2Fl10n--japan-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/l10n-japan-18-0/l10n-japan-18-0-l10n_jp_summary_invoice"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/l10n-japan&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/l10n-japan/tree/18.0/l10n_jp_summary_invoice"><img alt="OCA/l10n-japan" src="https://img.shields.io/badge/github-OCA%2Fl10n--japan-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/l10n-japan-18-0/l10n-japan-18-0-l10n_jp_summary_invoice"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/l10n-japan&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module adds a summary invoice report print functionality based on
the account_billing module.</p>
<p>The printed summary invoice is intended to serve as the Qualified Tax
Expand Down Expand Up @@ -402,7 +397,7 @@ <h1>Japan Summary Invoice</h1>
</ul>
</div>
<div class="section" id="configuration">
<h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>Go to <em>Invoicing/Accounting &gt; Configuration &gt; Settings</em> and update the
following settings as necessary:</p>
<ul class="simple">
Expand All @@ -422,7 +417,7 @@ <h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
</ul>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-2">Usage</a></h2>
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<ol class="arabic simple">
<li>Create a billing for customer invoices using the functionality of the
account_billing module, and make adjustments as necessary.<ul>
Expand All @@ -442,26 +437,32 @@ <h2><a class="toc-backref" href="#toc-entry-2">Usage</a></h2>
the summary of the tax amounts in the selected invoices.</li>
<li>Print the summary invoice report (合計請求書) from <em>Print &gt; JP
Summary Invoice</em> of the billing.</li>
<li>Once a validated summary invoice has been printed or sent at least
once, the <strong>Printed/Sent</strong> field is checked automatically, and trying
to delete the billing raises an error, so that its sequence number is
never orphaned from accounting reports. Cancel it instead if it is no
longer valid. If you still need to delete it, uncheck the
<strong>Printed/Sent</strong> field manually first.</li>
</ol>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h2>
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/l10n-japan/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/l10n-japan/issues/new?body=module:%20l10n_jp_summary_invoice%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-4">Credits</a></h2>
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-5">Authors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Quartile</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-6">Contributors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.quartile.co">Quartile</a>:<ul>
<li>Aung Ko Ko Lin</li>
Expand All @@ -471,7 +472,7 @@ <h3><a class="toc-backref" href="#toc-entry-6">Contributors</a></h3>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
Expand All @@ -484,6 +485,5 @@ <h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
</div>
</div>
</div>
</div>
</body>
</html>
83 changes: 82 additions & 1 deletion l10n_jp_summary_invoice/tests/test_l10n_jp_summary_invoice.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2024 Quartile
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.exceptions import ValidationError
from odoo.exceptions import UserError, ValidationError
from odoo.fields import Command
from odoo.tests.common import TransactionCase

Expand Down Expand Up @@ -289,6 +289,87 @@ def test_check_tax_adjustment_with_currency_rounding_issue(self):
self.assertEqual(billing.state, "billed")
self.assertFalse(billing.tax_adjustment_entry_id)

def test_print_draft_billing_does_not_set_is_billing_sent(self):
"""Printing a still-draft (unnumbered) billing must not lock it."""
invoice = self._create_invoice(100, self.tax_10)
billing = self.env["account.billing"].create(
{
"partner_id": self.partner.id,
"billing_line_ids": [Command.create({"move_id": invoice.id})],
}
)
self.assertEqual(billing.state, "draft")
self.assertFalse(billing.name)
report = self.env.ref("l10n_jp_summary_invoice.report_jp_summary_invoice")
report._render_qweb_pdf(report.id, billing.ids)
self.assertFalse(billing.is_billing_sent)
billing.unlink()
self.assertFalse(billing.exists())

def test_render_qweb_pdf_sets_is_billing_sent_after_validate(self):
invoice = self._create_invoice(100, self.tax_10)
billing = self.env["account.billing"].create(
{
"partner_id": self.partner.id,
"bill_type": "out_invoice",
"billing_line_ids": [Command.create({"move_id": invoice.id})],
}
)
billing.with_company(self.company).validate_billing()
self.assertFalse(billing.is_billing_sent)
report = self.env.ref("l10n_jp_summary_invoice.report_jp_summary_invoice")
report._render_qweb_pdf(report.id, billing.ids)
self.assertTrue(billing.is_billing_sent)

def test_render_qweb_pdf_other_report_also_sets_is_billing_sent(self):
"""Any report bound to account.billing sets the flag, not just the JP one."""
invoice = self._create_invoice(100, self.tax_10)
billing = self.env["account.billing"].create(
{
"partner_id": self.partner.id,
"bill_type": "out_invoice",
"billing_line_ids": [Command.create({"move_id": invoice.id})],
}
)
billing.with_company(self.company).validate_billing()
report = self.env.ref("account_billing.report_account_billing")
report._render_qweb_pdf(report.id, billing.ids)
self.assertTrue(billing.is_billing_sent)

def test_unlink_blocked_once_billing_sent(self):
invoice = self._create_invoice(100, self.tax_10)
billing = self.env["account.billing"].create(
{
"partner_id": self.partner.id,
"bill_type": "out_invoice",
"billing_line_ids": [Command.create({"move_id": invoice.id})],
}
)
billing.with_company(self.company).validate_billing()
billing.is_billing_sent = True
with self.assertRaises(UserError):
billing.unlink()
billing.action_cancel()
with self.assertRaises(UserError):
billing.unlink()
billing.action_cancel_draft()
with self.assertRaises(UserError):
billing.unlink()

def test_unlink_allowed_when_never_sent(self):
invoice = self._create_invoice(100, self.tax_10)
billing = self.env["account.billing"].create(
{
"partner_id": self.partner.id,
"bill_type": "out_invoice",
"billing_line_ids": [Command.create({"move_id": invoice.id})],
}
)
billing.with_company(self.company).validate_billing()
self.assertFalse(billing.is_billing_sent)
billing.unlink()
self.assertFalse(billing.exists())

def test_is_not_for_billing(self):
self.partner.is_not_for_billing = True
invoice = self._create_invoice(50, self.tax_10)
Expand Down
1 change: 1 addition & 0 deletions l10n_jp_summary_invoice/views/account_billing_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<field name="company_partner_id" invisible="1" />
<field name="remit_to_bank_id" invisible="bill_type != 'out_invoice'" />
<field name="report_subtitle" />
<field name="is_billing_sent" />
</xpath>
<xpath expr="//field[@name='date']" position="after">
<field name="date_due" invisible="bill_type != 'out_invoice'" />
Expand Down
Loading