diff --git a/__init__.py b/__init__.py
index 9909ace..340f9ac 100644
--- a/__init__.py
+++ b/__init__.py
@@ -16,6 +16,8 @@ def register():
invoice.Invoice,
invoice.InvoiceLine,
invoice.Product,
+ invoice.PartyFeIdentifier,
+ invoice.PartyFeOrganization,
invoice.Party,
invoice.Cron,
dian.RangoFacturacion,
diff --git a/invoice.py b/invoice.py
index 264a808..87f50ea 100644
--- a/invoice.py
+++ b/invoice.py
@@ -1,4 +1,4 @@
-from trytond.model import fields, ModelView
+from trytond.model import fields, ModelView, ModelSQL
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval
from trytond.transaction import Transaction
@@ -10,6 +10,8 @@ from facho import fe
from facho.fe.client import dian
import io
+from datetime import datetime
+
class Cron(metaclass=PoolMeta):
__name__ = 'ir.cron'
@@ -21,35 +23,82 @@ class Cron(metaclass=PoolMeta):
('account.invoice|fe_delivery', 'FE Delivery')
])
+
class Party(metaclass=PoolMeta):
__name__ = 'party.party'
- fe_tipo_responsabilidad = fields.Many2One('account_invoice_facho.fe_generic_code',
- 'Tipo Responsabilidad',
- domain=[('resource', '=', 'tipo_responsabilidad')],
- required=True)
- fe_tipo_organizacion = fields.Many2One('account_invoice_facho.fe_generic_code',
- 'Tipo Organizacion',
- domain=[('resource', '=', 'tipo_organizacion')],
- required=True)
+ fe_identifiers = fields.One2Many('account_invoice_facho.party.fe_identifier',
+ 'party', 'Fe Identifiers', required=True)
+ fe_organizations = fields.One2Many('account_invoice_facho.party.fe_organization',
+ 'party', 'Fe Organizations', required=True)
-
+ @property
+ def fe_identifier(self):
+ try:
+ return self.fe_identifiers[0]
+ except IndexError:
+ return None
+
+ @property
+ def fe_organization(self):
+ try:
+ return self.fe_organizations[0]
+ except IndexError:
+ return None
def tofacho(self):
+ tax_identifier = self.tax_identifer
+ if tax_identifer is None:
+ tax_identifer = ''
return form.Party(
name = self.name,
- ident = self.name, # TODO
- responsability_code = self.fe_tipo_responsabilidad.code,
- organization_code = self.fe_tipo_organizacion.code,
+ ident = tax_identifer,
+ responsability_code = self.fe_identifier.fe_code,
+ organization_code = self.fe_organization.fe_code,
)
+class PartyFeOrganization(ModelSQL, ModelView):
+ 'Party Facturacion Electronica Organizacion'
+ __name__ = 'account_invoice_facho.party.fe_organization'
+
+ name = fields.Char('Name', required=True)
+ party = fields.Many2One('party.party', 'Party', ondelete='CASCADE',
+ required=True, select=True)
+ fe_tipo = fields.Many2One('account_invoice_facho.fe_generic_code',
+ 'Tipo Organizacion',
+ domain=[('resource', '=', 'tipo_organizacion')],
+ required=True)
+
+ @property
+ def fe_code(self):
+ return self.fe_tipo.code
+
+
+class PartyFeIdentifier(ModelSQL, ModelView):
+ 'Party Facturaction Electron Identificador'
+ __name__ = 'account_invoice_facho.party.fe_identifier'
+ _rec_name = 'code'
+ code = fields.Char('Code', required=True)
+ party = fields.Many2One('party.party', 'Party', ondelete='CASCADE',
+ required=True, select=True)
+ fe_tipo = fields.Many2One('account_invoice_facho.fe_generic_code',
+ 'Tipo Responsabilidad',
+ domain=[('resource', '=', 'tipo_responsabilidad')],
+ required=True)
+
+ @property
+ def fe_code(self):
+ return self.fe_tipo.code
+
+
class Invoice(metaclass=PoolMeta):
__name__ = 'account.invoice'
- _states = {'invisible': ~Eval('is_fe_colombia', False)}
-
- _depends = ['is_fe_colombia']
+ _states = {'invisible': ~Eval('is_fe_colombia', False),
+ 'readonly': Eval('state') != 'draft'}
+ _states_readonly = {'readonly': Eval('state') != 'draft'}
+ _depends = ['is_fe_colombia', 'state']
is_fe_colombia = fields.Boolean('FE Colombia?',
states={'invisible': False})
@@ -63,14 +112,18 @@ class Invoice(metaclass=PoolMeta):
('exception', 'Exception'), # local exception
('failure', 'Failure'), # remoto fallo
('done', 'Done') # remoto ok
- ], 'Delivery State', states=_states, depends=_depends)
+ ], 'Delivery State', states=_states_readonly, depends=_depends)
fe_delivery_trackid = fields.Char('Delivery TrackID',
- states=_states,
+ states=_states_readonly,
depends=_depends)
fe_delivery_status = fields.Text('Delivery Status',
- states=_states,
+ states=_states_readonly,
depends=_depends)
- del _states
+ fe_delivery_checked_at = fields.DateTime('Delivery Checked At',
+ states=_states_readonly,
+ depends=_depends)
+
+ del _states, _states_readonly
del _depends
@staticmethod
@@ -137,9 +190,9 @@ class Invoice(metaclass=PoolMeta):
def _force_write(self, params):
self.state = 'draft'
+ params['fe_delivery_checked_at'] = datetime.now()
self.write([self], params)
-
def fe_delivery_test(self):
config = Pool().get('account_invoice_facho.configuration')(1)
if self.fe_delivery_state not in ['queued', 'draft']:
@@ -161,11 +214,9 @@ class Invoice(metaclass=PoolMeta):
))
if not res.ZipKey:
raise UserError(str(res))
- # HACK force draft for allow write
self._force_write({'fe_delivery_state': 'delivered',
'fe_delivery_trackid': res.ZipKey})
-
def fe_process(self):
if self.fe_habilitacion:
# TODO forzar facturas contabilidadas
@@ -176,7 +227,7 @@ class Invoice(metaclass=PoolMeta):
for inv in cls.search([('is_fe_colombia', '=', True),
('state', 'in', ['posted', 'paid'])]):
inv.fe_process()
- if inv.fe_delivery_state == 'delivered':
+ if inv.fe_delivery_state in ['delivered', 'failure']:
inv.fe_update_status()
diff --git a/view/invoice_page_form.xml b/view/invoice_page_form.xml
index 21cce3e..a1f225d 100644
--- a/view/invoice_page_form.xml
+++ b/view/invoice_page_form.xml
@@ -5,10 +5,15 @@
+
+
+
+
+
diff --git a/view/party_form.xml b/view/party_form.xml
index 506ec72..37a7460 100644
--- a/view/party_form.xml
+++ b/view/party_form.xml
@@ -3,10 +3,8 @@
-
-
-
-
+
+