diff --git a/facho/fe/client/dian.py b/facho/fe/client/dian.py index 8b3e4c2..b57b74d 100644 --- a/facho/fe/client/dian.py +++ b/facho/fe/client/dian.py @@ -91,13 +91,13 @@ class SendBillAsync(SOAPService): @dataclass class SendTestSetAsyncResponse: ZipKey: str - ErrorMessageList: List[str] = [] + ErrorMessageList: List[str] @classmethod def fromdict(cls, data): return cls( data['ZipKey'], - data['ErrorMessageList'] + data['ErrorMessageList'] or [] ) @dataclass diff --git a/facho/fe/data/dian/codelist/__init__.py b/facho/fe/data/dian/codelist/__init__.py index e030b78..f3c23bc 100644 --- a/facho/fe/data/dian/codelist/__init__.py +++ b/facho/fe/data/dian/codelist/__init__.py @@ -8,14 +8,15 @@ DATA_DIR = os.path.dirname(os.path.abspath(__file__)) class CodeList: - def __init__(self, filename, primary_column): + def __init__(self, filename, primary_column, name_column): self.short_name = '' self.long_name = '' self.version = 1 self.canonical_uri = '' self.canonical_version_uri = '' self.location_uri = '' - + + self.name_column = name_column self.rows = {} self._load(filename, primary_column) @@ -49,6 +50,12 @@ class CodeList: return self.rows[str(key)] + def by_name(self, name): + for k, v in self.rows.items(): + if v[self.name_column] == name: + return v + raise KeyError + # nombres de variables igual a ./Identification/ShortName # TODO: garantizar unica carga en python @@ -59,7 +66,7 @@ __all__ = ['TipoOrganizacion', def path_for_codelist(name): return os.path.join(DATA_DIR, name) -TipoOrganizacion = CodeList(path_for_codelist('TipoOrganizacion-2.1.gc'), 'name') -TipoResponsabilidad = CodeList(path_for_codelist('TipoResponsabilidad-2.1.gc'), 'name') -TipoAmbiente = CodeList(path_for_codelist('TipoAmbiente-2.1.gc'), 'name') -TipoDocumento = CodeList(path_for_codelist('TipoDocumento-2.1.gc'), 'name') +TipoOrganizacion = CodeList(path_for_codelist('TipoOrganizacion-2.1.gc'), 'code', 'name') +TipoResponsabilidad = CodeList(path_for_codelist('TipoResponsabilidad-2.1.gc'), 'code', 'name') +TipoAmbiente = CodeList(path_for_codelist('TipoAmbiente-2.1.gc'), 'code', 'name') +TipoDocumento = CodeList(path_for_codelist('TipoDocumento-2.1.gc'), 'code', 'name') diff --git a/facho/fe/fe.py b/facho/fe/fe.py index 308594d..1c3b62f 100644 --- a/facho/fe/fe.py +++ b/facho/fe/fe.py @@ -41,8 +41,8 @@ class FeXML(FachoXML): class DianXMLExtensionCUFE(FachoXMLExtension): - AMBIENTE_PRUEBAS = 'Pruebas' - AMBIENTE_PRODUCCION = 'Producción' + AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code'] + AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code'] def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS, clave_tecnica = ''): self.tipo_ambiente = tipo_ambiente @@ -50,7 +50,7 @@ class DianXMLExtensionCUFE(FachoXMLExtension): self.invoice = invoice def _tipo_ambiente(self): - return int(codelist.TipoAmbiente[self.tipo_ambiente]['code']) + return int(self.tipo_ambiente) def build(self, fachoxml): cufe = self._generate_cufe(self.invoice, fachoxml) diff --git a/facho/fe/form.py b/facho/fe/form.py index b777844..00706ab 100644 --- a/facho/fe/form.py +++ b/facho/fe/form.py @@ -18,7 +18,7 @@ class Item: @dataclass -class StandarItem(Item): +class StandardItem(Item): pass @@ -174,12 +174,15 @@ class DianResolucion0001Validator: try: codelist.TipoResponsabilidad[party.responsability_code] except KeyError: - self.errors.append((model, 'responsability_code', 'not found')) + self.errors.append((model, + 'responsability_code', + 'not found %s' % (party.responsability_code))) try: codelist.TipoOrganizacion[party.organization_code] except KeyError: - self.errors.append((model, 'organization_code', 'not found')) + self.errors.append((model, 'organization_code' , + 'not found %s' % (party.organization_code))) def validate(self, invoice): invoice.accept(self) @@ -211,7 +214,7 @@ class DIANInvoiceXML(fe.FeXML): invoice.calculate() - fexml.set_element('/fe:Invoice/cbc:InvoiceTypeCode', codelist.TipoDocumento['Factura de Venta Nacional']['code'], + fexml.set_element('/fe:Invoice/cbc:InvoiceTypeCode', codelist.TipoDocumento.by_name('Factura de Venta Nacional')['code'], listAgencyID='195', listAgencyName='No matching global declaration available for the validation root', listURI='http://www.dian.gov.co') diff --git a/tests/test_data.py b/tests/test_data.py index 8991133..6374393 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -10,12 +10,12 @@ from facho.fe.data.dian import codelist def test_tiporesponsabilidad(): assert codelist.TipoResponsabilidad.short_name == 'TipoResponsabilidad' - assert codelist.TipoResponsabilidad['Autorretenedor']['name'] == 'Autorretenedor' + assert codelist.TipoResponsabilidad.by_name('Autorretenedor')['name'] == 'Autorretenedor' def test_tipoorganizacion(): assert codelist.TipoOrganizacion.short_name == 'TipoOrganizacion' - assert codelist.TipoOrganizacion['Persona Natural']['name'] == 'Persona Natural' + assert codelist.TipoOrganizacion.by_name('Persona Natural')['name'] == 'Persona Natural' def test_tipodocumento(): assert codelist.TipoDocumento.short_name == 'TipoDocumento' - assert codelist.TipoDocumento['Factura de Venta Nacional']['code'] == '01' + assert codelist.TipoDocumento.by_name('Factura de Venta Nacional')['code'] == '01' diff --git a/tests/test_fe_form.py b/tests/test_fe_form.py index 7ea2c1a..e136a04 100644 --- a/tests/test_fe_form.py +++ b/tests/test_fe_form.py @@ -23,15 +23,15 @@ def simple_invoice_without_lines(): inv.set_supplier(form.Party( name = 'facho-supplier', ident = 123, - responsability_code = 'No aplica', - organization_code = 'Persona Natural', + responsability_code = 'ZZ', + organization_code = '1', address = form.Address(name='Test Building') )) inv.set_customer(form.Party( name = 'facho-customer', ident = 321, - responsability_code = 'No aplica', - organization_code = 'Persona Natural', + responsability_code = 'ZZ', + organization_code = '1', address = form.Address(name='Test Building') )) return inv @@ -45,19 +45,19 @@ def simple_invoice(): inv.set_supplier(form.Party( name = 'facho-supplier', ident = 123, - responsability_code = 'No aplica', - organization_code = 'Persona Natural' + responsability_code = 'ZZ', + organization_code = '1' )) inv.set_customer(form.Party( name = 'facho-customer', ident = 321, - responsability_code = 'No aplica', - organization_code = 'Persona Natural' + responsability_code = 'ZZ', + organization_code = '1' )) inv.add_invoice_line(form.InvoiceLine( quantity = 1, description = 'producto facho', - item = form.StandarItem('test', 9999), + item = form.StandardItem('test', 9999), price_amount = 100.0, tax = form.TaxTotal( tax_amount = 0.0, @@ -159,7 +159,7 @@ def test_invoice_totals(simple_invoice_without_lines): simple_invoice.add_invoice_line(form.InvoiceLine( quantity = 1, description = 'producto', - item = form.StandarItem('test', 9999), + item = form.StandardItem('test', 9999), price_amount = 1_500_000, tax = form.TaxTotal( subtotals = [ @@ -182,7 +182,7 @@ def test_invoice_cufe(simple_invoice_without_lines): simple_invoice.add_invoice_line(form.InvoiceLine( quantity = 1, description = 'producto', - item = form.StandarItem('test', 111), + item = form.StandardItem('test', 111), price_amount = 1_500_000, tax = form.TaxTotal( subtotals = [