Files
ncf_manager/ncf_manager.py
T
José Arturo García b96639f3e8
Publicar paquete PyPI / publish (push) Successful in 1m17s
Prepare NCF manager for production on Tryton 8.0
2026-08-16 13:36:51 -04:00

173 lines
5.6 KiB
Python

# This file is part of ncf_manager module for Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.model import ModelView, ModelSQL, fields
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.transaction import Transaction
NCF_TYPE = [
('', ''),
('1', 'Factura de Crédito Fiscal'),
('2', 'Factura de Consumo'),
('3', 'Nota de Débito'),
('4', 'Nota de Crédito'),
('11', 'Comprobante de Compras'),
('12', 'Registro Único de Ingresos'),
('13', 'Comprobante para Gastos Menores'),
('14', 'Comprobante de Regímenes Especiales'),
('15', 'Comprobante Gubernamental'),
('16', 'Comprobante para exportaciones'),
('17', 'Comprobante para Pagos al Exterior'),
('31', 'Factura de Crédito Fiscal Electrónica'),
('32', 'Factura de Consumo Electrónica'),
('33', 'Nota de Débito Electrónica'),
('34', 'Nota de Crédito Electrónica'),
('41', 'Compras Electrónico'),
('43', 'Gastos Menores Electrónico'),
('44', 'Regímenes Especiales Electrónico'),
('45', 'Gubernamental Electrónico'),
('46', 'Exportación Electrónico'),
('47', 'Pagos al Exterior Electrónico'),
('99', 'Factura sin NCF'),
]
class NCFManager(ModelSQL, ModelView):
'NCF Manager'
__name__ = 'ncf.manager'
_states = {
'readonly': Eval('state') != 'draft',
}
_depends = ['state']
company = fields.Many2One('company.company', 'Company', required=True,
states=_states, depends=_depends)
app_date = fields.Date('Application Date', required=True,
states=_states, depends=_depends)
app_number = fields.Char('Application Number', required=True, size=10,
states=_states, depends=_depends)
auth_number = fields.Char('Authorization Number', required=True, size=10,
states=_states, depends=_depends)
ncf_sequences = fields.One2Many('ncf.manager.sequence', 'pos',
'NCF Sequences', context={'company': Eval('company', -1)},
states=_states, depends=_depends)
state = fields.Selection([
('draft', 'Draft'),
('active', 'Active'),
('finished', 'Finished'),
], "State", sort=False)
state_string = state.translated('state')
del _states, _depends
@classmethod
def __setup__(cls):
super(NCFManager, cls).__setup__()
cls._order = [
('app_date', 'DESC'),
('id', 'DESC'),
]
def get_rec_name(self, name):
parts = []
if self.company:
parts.append(self.company.rec_name)
if self.app_number:
parts.append(self.app_number)
return ' - '.join(parts) if parts else str(self.id)
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_state():
return 'draft'
class NCFManagerSequences(ModelSQL, ModelView):
'NCF Manager Sequences'
__name__ = 'ncf.manager.sequence'
_states = {
'readonly': Eval('state') != 'draft',
}
_depends = ['state']
pos = fields.Many2One('ncf.manager', 'Point of Sale',
ondelete='CASCADE', required=True)
ncf_type = fields.Selection(NCF_TYPE, 'NCF Type',
required=True, sort=False,
states=_states, depends=_depends,
help='Choose a NCF Type')
ncf_type_string = ncf_type.translated('ncf_type')
ncf_sequences = fields.Many2One('ir.sequence.strict', 'NCF Sequences',
domain=[
('company', '=', Eval(
'context', {}).get('company', -1)),
], states=_states, depends=_depends)
invoice_type = fields.Selection([
('invoice_customer', 'Customer Invoice'),
('invoice_supplier', 'Supplier Invoice')
], 'Invoice Type', required=True,
states=_states, depends=_depends)
state = fields.Selection([
('draft', 'Draft'),
('active', 'Active'),
('finished', 'Finished'),
], "State", sort=False)
state_string = state.translated('state')
del _states, _depends
@staticmethod
def default_state():
return 'draft'
def get_rec_name(self, name):
if not self.ncf_type_string:
return ''
return self.ncf_type_string.split('-')[0]
@classmethod
def validate_fields(cls, records, field_names):
super().validate_fields(records, field_names)
if field_names & {'pos', 'ncf_sequences', 'ncf_type'}:
for record in records:
record._validate_fiscal_sequence()
def _validate_fiscal_sequence(self):
sequence = self.ncf_sequences
if not sequence:
return
if sequence.company != self.pos.company:
raise UserError(gettext(
'ncf_manager.msg_ncf_sequence_company_mismatch'))
expected_prefix = ('E' if self.ncf_type in {
'31', '32', '33', '34', '41', '43', '44', '45', '46', '47'
} else 'B') + self.ncf_type.zfill(2)
if self.ncf_type != '99' and sequence.prefix != expected_prefix:
raise UserError(gettext(
'ncf_manager.msg_ncf_sequence_prefix_mismatch',
prefix=expected_prefix))