Raise a warning when posting supplier invoice with same reference

issue8244
review265201002
This commit is contained in:
Cédric Krier committed 2022-02-14 00:11:38 +01:00
1 parent be7c00ff70
commit 33e7892bca
5 files changed
+87 -2

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Raise a warning when validating supplier invoice with same reference
* Add support for Python 3.10
* Remove support for Python 3.6
+4
View File
@@ -39,3 +39,7 @@ class InvoicePaymentTermDateWarning(UserWarning):
class InvoiceFutureWarning(UserWarning):
pass
class InvoiceSimilarWarning(UserWarning):
pass
+57 -2
View File
@@ -1,5 +1,6 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime as dt
from collections import defaultdict, namedtuple
from decimal import Decimal
from itertools import chain, combinations, groupby
@@ -30,8 +31,8 @@ from trytond.wizard import (
from .exceptions import (
InvoiceFutureWarning, InvoiceLineValidationError, InvoiceNumberError,
InvoicePaymentTermDateWarning, InvoiceTaxValidationError,
InvoiceValidationError, PayInvoiceError)
InvoicePaymentTermDateWarning, InvoiceSimilarWarning,
InvoiceTaxValidationError, InvoiceValidationError, PayInvoiceError)
if config.getboolean('account_invoice', 'filestore', default=False):
file_id = 'invoice_report_cache_id'
@@ -1524,6 +1525,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
invoices_in = cls.browse([i for i in invoices if i.type == 'in'])
cls.set_number(invoices_in)
cls._check_similar(invoices)
moves = []
for invoice in invoices_in:
move = invoice.get_move()
@@ -1576,6 +1578,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
raise InvoiceFutureWarning(warning_key,
gettext('account_invoice.msg_invoice_date_future',
invoices=names))
cls._check_similar([i for i in invoices if i.state != 'validated'])
cls._post(invoices)
@classmethod
@@ -1605,6 +1608,58 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
if reconciled:
cls.__queue__.process(reconciled)
@classmethod
def _check_similar(cls, invoices, type='in'):
pool = Pool()
Warning = pool.get('res.user.warning')
for sub_invoices in grouped_slice(invoices):
sub_invoices = list(sub_invoices)
domain = list(filter(None,
(i._similar_domain() for i in sub_invoices
if i.type == type)))
if not domain:
continue
if cls.search(['OR'] + domain, order=[]):
for invoice in sub_invoices:
domain = invoice._similar_domain()
if not domain:
continue
try:
similar, = cls.search(domain, limit=1)
except ValueError:
continue
warning_key = Warning.format(
'invoice_similar', [invoice])
if Warning.check(warning_key):
raise InvoiceSimilarWarning(warning_key,
gettext('account_invoice.msg_invoice_similar',
similar=similar.rec_name,
invoice=invoice.rec_name))
def _similar_domain(self, delay=None):
pool = Pool()
Date = pool.get('ir.date')
if not self.reference:
return
with Transaction().set_context(company=self.company.id):
invoice_date = self.invoice_date or Date.today()
if delay is None:
delay = dt.timedelta(days=60)
return [
('company', '=', self.company.id),
('type', '=', self.type),
('party', '=', self.party.id),
('reference', '=', self.reference),
('id', '!=', self.id),
['OR',
('invoice_date', '=', None),
[
('invoice_date', '>=', invoice_date - delay),
('invoice_date', '<=', invoice_date + delay),
],
],
]
@classmethod
@ModelView.button_action('account_invoice.wizard_pay')
def pay(cls, invoices):
+3
View File
@@ -81,6 +81,9 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_invoice_date_future">
<field name="text">The invoices "%(invoices)s" have an invoice date in the future.</field>
</record>
<record model="ir.message" id="msg_invoice_similar">
<field name="text">The invoice "%(invoice)s" is similar to invoice "%(similar)s".</field>
</record>
</data>
</tryton>
+22
View File
@@ -3,6 +3,7 @@ Invoice Supplier Scenario
=========================
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
@@ -102,6 +103,7 @@ Create invoice::
>>> invoice.party = party
>>> invoice.payment_term = payment_term
>>> invoice.invoice_date = today
>>> invoice.reference = 'FAC001'
>>> line = InvoiceLine()
>>> invoice.lines.append(line)
>>> line.product = product
@@ -192,6 +194,26 @@ Credit invoice::
>>> credit_note.total_amount == -invoice.total_amount
True
A warning is raised when creating an invoice with same reference::
>>> invoice = Invoice()
>>> invoice.type = 'in'
>>> invoice.party = party
>>> invoice.invoice_date = today
>>> invoice.reference = 'FAC001'
>>> line = invoice.lines.new()
>>> line.product = product
>>> line.quantity = 1
>>> line.unit_price = Decimal('20')
>>> invoice.click('post') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
InvoiceSimilarWarning: ...
>>> invoice.reference = 'FAC002'
>>> invoice.click('post')
>>> invoice.state
'posted'
Create a posted and a draft invoice to cancel::
>>> invoice = Invoice()