Prepare NCF manager for production on Tryton 8.0
Publicar paquete PyPI / publish (push) Successful in 1m17s
Publicar paquete PyPI / publish (push) Successful in 1m17s
This commit is contained in:
+53
-2
@@ -3,6 +3,7 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
from datetime import date
|
||||
import re
|
||||
from sql.aggregate import Sum
|
||||
from sql.conditionals import Coalesce
|
||||
from sql.functions import Round
|
||||
@@ -1563,7 +1564,7 @@ class Invoice(metaclass=PoolMeta):
|
||||
|
||||
ncf_code = invoice.ncf_type
|
||||
|
||||
if invoice.type == 'in' and ncf_code == '99':
|
||||
if ncf_code == '99':
|
||||
continue
|
||||
|
||||
ncf_sequence = invoice.ncf_sequence or cls._ncf_find_active_sequence(
|
||||
@@ -1712,6 +1713,53 @@ class Invoice(metaclass=PoolMeta):
|
||||
raise UserError(gettext(
|
||||
'ncf_manager.msg_incorrect_lenght_ncf_number_modified'))
|
||||
|
||||
@staticmethod
|
||||
def _ncf_normalize_number(number):
|
||||
return (number or '').strip().upper()
|
||||
|
||||
@classmethod
|
||||
def _ncf_validate_number(cls, invoice):
|
||||
number = cls._ncf_normalize_number(invoice.ncf_number)
|
||||
if not number:
|
||||
return
|
||||
legacy_supplier_ncf = (
|
||||
invoice.type == 'in' and re.fullmatch(r'[A-Z]\d{18}', number))
|
||||
if not legacy_supplier_ncf and not re.fullmatch(
|
||||
r'(?:B\d{10}|E\d{12})', number):
|
||||
raise UserError(gettext(
|
||||
'ncf_manager.msg_invalid_ncf_structure', number=number))
|
||||
if legacy_supplier_ncf:
|
||||
invoice.ncf_number = number
|
||||
return
|
||||
expected = ('E' if invoice.ncf_type in _ECF_CODES else 'B') + \
|
||||
invoice.ncf_type.zfill(2)
|
||||
if invoice.ncf_type != '99' and not number.startswith(expected):
|
||||
raise UserError(gettext(
|
||||
'ncf_manager.msg_invalid_ncf_type_prefix',
|
||||
number=number, prefix=expected))
|
||||
invoice.ncf_number = number
|
||||
|
||||
@classmethod
|
||||
def _ncf_check_duplicate(cls, invoice):
|
||||
if not invoice.ncf_number:
|
||||
return
|
||||
domain = [
|
||||
('id', '!=', invoice.id),
|
||||
('company', '=', invoice.company.id),
|
||||
('ncf_number', '=', invoice.ncf_number),
|
||||
]
|
||||
# Supplier NCF sequences are unique per issuer, not globally.
|
||||
if invoice.type == 'in':
|
||||
domain.extend([
|
||||
('type', '=', 'in'),
|
||||
('party', '=', invoice.party.id),
|
||||
])
|
||||
else:
|
||||
domain.append(('type', '=', 'out'))
|
||||
if cls.search(domain, limit=1):
|
||||
raise UserError(gettext(
|
||||
'ncf_manager.msg_duplicated_ncf_number_invoice'))
|
||||
|
||||
@staticmethod
|
||||
def _ncf_is_fiscal_cancellation_required(invoice):
|
||||
return (
|
||||
@@ -1782,6 +1830,8 @@ class Invoice(metaclass=PoolMeta):
|
||||
cls.set_ncf_number(invoices)
|
||||
|
||||
for invoice in invoices:
|
||||
cls._ncf_validate_number(invoice)
|
||||
cls._ncf_check_duplicate(invoice)
|
||||
ncf_code = invoice.ncf_type
|
||||
is_debit_note = cls._ncf_is_debit_note(invoice)
|
||||
is_credit_note = cls._ncf_is_credit_note(invoice)
|
||||
@@ -1789,7 +1839,8 @@ class Invoice(metaclass=PoolMeta):
|
||||
is_without_ncf = ncf_code == '99'
|
||||
|
||||
if invoice.type == 'out':
|
||||
invoice._ncf_validate_selected_sequence()
|
||||
if not is_without_ncf:
|
||||
invoice._ncf_validate_selected_sequence()
|
||||
if is_credit_note:
|
||||
invoice.check_credit_note()
|
||||
invoice.check_ncf_number_modified()
|
||||
|
||||
Reference in New Issue
Block a user