se continua cumpliendo con dian xml para Invoice
FossilOrigin-Name: 74f6f39c22e7244ec20e5621394176575bc85a66f0f6a4351d9deb7d4a233053
This commit is contained in:
		| @@ -54,7 +54,7 @@ class DianXMLExtensionCUFE(FachoXMLExtension): | ||||
|  | ||||
|     def build(self, fachoxml): | ||||
|         cufe = self._generate_cufe(self.invoice, fachoxml) | ||||
|         fachoxml.set_element('/fe:Invoice/cbc:UUID[schemaName="CUFE-SHA384"]', cufe) | ||||
|         fachoxml.set_element('/fe:Invoice/cbc:UUID', cufe, schemeName='CUFE-SHA384') | ||||
|         fachoxml.set_element('/fe:Invoice/cbc:ProfileID', 'DIAN 2.1') | ||||
|         fachoxml.set_element('/fe:Invoice/cbc:ProfileExecutionID', self._tipo_ambiente()) | ||||
|         return '', [] | ||||
| @@ -161,8 +161,6 @@ class DianXMLExtensionSigner(FachoXMLExtension): | ||||
|  | ||||
|     # return (xpath, xml.Element) | ||||
|     def build(self, fachoxml): | ||||
|         dian_path = '/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent' | ||||
|          | ||||
|         signature = xmlsig.template.create( | ||||
|             xmlsig.constants.TransformInclC14N, | ||||
|             xmlsig.constants.TransformRsaSha256, | ||||
| @@ -227,8 +225,13 @@ class DianXMLExtensionSigner(FachoXMLExtension): | ||||
|         ctx.verify(signature) | ||||
|         #xmlsig take parent root | ||||
|         fachoxml.root.remove(signature) | ||||
|  | ||||
|  | ||||
|         ublextension = fachoxml.fragment('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True) | ||||
|         extcontent = ublextension.find_or_create_element('/ext:UBLExtension:/ext:ExtensionContent') | ||||
|         fachoxml.append_element(extcontent, signature) | ||||
|          | ||||
|         return (dian_path, [signature]) | ||||
|         return '', [] | ||||
|          | ||||
|  | ||||
| class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension): | ||||
|   | ||||
							
								
								
									
										190
									
								
								facho/fe/form.py
									
									
									
									
									
								
							
							
						
						
									
										190
									
								
								facho/fe/form.py
									
									
									
									
									
								
							| @@ -56,7 +56,8 @@ class Party: | ||||
| class TaxSubTotal: | ||||
|     percent: float | ||||
|     tax_scheme_ident: str = '01' | ||||
|  | ||||
|     tax_scheme_name: str = 'IVA' | ||||
|      | ||||
|     tax_amount: float = 0.0 | ||||
|     taxable_amount: float = 0.0 | ||||
|  | ||||
| @@ -99,6 +100,14 @@ class InvoiceLine: | ||||
|     def total_tax_exclusive_amount(self): | ||||
|         return self.tax.taxable_amount | ||||
|  | ||||
|     @property | ||||
|     def tax_amount(self): | ||||
|         return self.tax.tax_amount | ||||
|  | ||||
|     @property | ||||
|     def taxable_amount(self): | ||||
|         return self.tax.taxable_amount | ||||
|      | ||||
|     def calculate(self): | ||||
|         self.tax.calculate(self) | ||||
|  | ||||
| @@ -207,93 +216,120 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|         super().__init__('Invoice', 'http://www.dian.gov.co/contratos/facturaelectronica/v1') | ||||
|         self.attach_invoice(invoice) | ||||
|  | ||||
|     def attach_invoice(self, invoice): | ||||
|     def placeholder_for(fexml, xpath): | ||||
|         fexml.find_or_create_element(xpath) | ||||
|  | ||||
|     def set_supplier(fexml, invoice): | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cbc:AdditionalAccountID', | ||||
|                           invoice.invoice_supplier.organization_code) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name', | ||||
|                           invoice.invoice_supplier.name) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:AddressLine/cbc:Line', | ||||
|                           invoice.invoice_supplier.address.street) | ||||
|          | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', | ||||
|                           invoice.invoice_supplier.ident) | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode', | ||||
|                           invoice.invoice_supplier.responsability_code) | ||||
|  | ||||
|         fexml.find_or_create_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme') | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cbc:RegistrationName', | ||||
|                           invoice.invoice_supplier.legal_name) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cbc:CityName', invoice.invoice_supplier.address.city) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:AddressLine/cbc:Line', invoice.invoice_supplier.address.street) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:AddressLine/cbc:Line', invoice.invoice_supplier.address.street) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:Country/cbc:IdentificationCode', invoice.invoice_supplier.address.country.code) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:Country/cbc:Name', invoice.invoice_supplier.address.country.name) | ||||
|  | ||||
|     def set_customer(fexml, invoice): | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cbc:AdditionalAccountID', | ||||
|                           invoice.invoice_customer.organization_code) | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name', | ||||
|                           invoice.invoice_customer.name) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:AddressLine/cbc:Line', | ||||
|                           invoice.invoice_customer.address.street) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', | ||||
|                           invoice.invoice_customer.ident) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode', | ||||
|                           invoice.invoice_customer.responsability_code) | ||||
|         fexml.find_or_create_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme') | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:RegistrationName', | ||||
|                           invoice.invoice_customer.legal_name) | ||||
|          | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cbc:CityName', invoice.invoice_customer.address.city) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:AddressLine/cbc:Line', invoice.invoice_customer.address.street) | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:AddressLine/cbc:Line', invoice.invoice_customer.address.street) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:Country/cbc:IdentificationCode', invoice.invoice_customer.address.country.code) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cac:RegistrationAddress/cac:Country/cbc:Name', invoice.invoice_customer.address.country.name) | ||||
|  | ||||
|     def set_legal_monetary(fexml, invoice): | ||||
|         fexml.set_element('/fe:Invoice/cac:LegalMonetaryTotal/cbc:LineExtensionAmount', | ||||
|                           invoice.invoice_legal_monetary_total.line_extension_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount', | ||||
|                           invoice.invoice_legal_monetary_total.tax_exclusive_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount', | ||||
|                           invoice.invoice_legal_monetary_total.tax_inclusive_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/cac:LegalMonetaryTotal/cbc:ChargeTotalAmount', | ||||
|                           invoice.invoice_legal_monetary_total.charge_total_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount', | ||||
|                           invoice.invoice_legal_monetary_total.payable_amount, | ||||
|                           currencyID='COP') | ||||
|  | ||||
|     def set_invoice_lines(fexml, invoice): | ||||
|         next_append = False | ||||
|         for index, invoice_line in enumerate(invoice.invoice_lines): | ||||
|             line = fexml.fragment('/fe:Invoice/cac:InvoiceLine', append=next_append) | ||||
|             next_append = True | ||||
|  | ||||
|             line.set_element('/cac:InvoiceLine/cbc:ID', index + 1) | ||||
|             line.set_element('/cac:InvoiceLine/cbc:InvoicedQuantity', invoice_line.quantity, unitCode = 'NAR') | ||||
|             line.set_element('/cac:InvoiceLine/cbc:LineExtensionAmount', invoice_line.total_amount, currencyID="COP") | ||||
|             line.set_element('/cac:InvoiceLine/cac:TaxTotal/cbc:TaxAmount', invoice_line.tax_amount, currencyID='COP') | ||||
|             for subtotal in invoice_line.tax.subtotals: | ||||
|                 line.set_element('/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount', subtotal.taxable_amount, currencyID='COP') | ||||
|                 line.set_element('/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount', subtotal.tax_amount, currencyID='COP') | ||||
|                 line.set_element('/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent', subtotal.percent) | ||||
|                 line.set_element('/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID', subtotal.tax_scheme_ident) | ||||
|                 line.set_element('/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', subtotal.tax_scheme_name) | ||||
|             line.set_element('/cac:InvoiceLine/cac:Item/cbc:Description', invoice_line.item.description) | ||||
|             # TODO | ||||
|             line.set_element('/cac:InvoiceLine/cac:Item/cac:StandardItemIdentification/cbc:ID', invoice_line.item.id)  | ||||
|             line.set_element('/cac:InvoiceLine/cac:Price/cbc:PriceAmount', invoice_line.price_amount, currencyID="COP")  | ||||
|  | ||||
|     def attach_invoice(fexml, invoice): | ||||
|         """adiciona etiquetas a FEXML y retorna FEXML | ||||
|         en caso de fallar validacion retorna None""" | ||||
|         fexml = self | ||||
|  | ||||
|         invoice.calculate() | ||||
|  | ||||
|         fexml.placeholder_for('/fe:Invoice/ext:UBLExtensions') | ||||
|         fexml.set_element('/fe:Invoice/cbc:UBLVersionID', 'UBL 2.1') | ||||
|         fexml.placeholder_for('/fe:Invoice/cbc:ProfileID') | ||||
|         fexml.placeholder_for('/fe:Invoice/cbc:ProfileExecutionID') | ||||
|         fexml.set_element('/fe:Invoice/cbc:ID', invoice.invoice_ident) | ||||
|         fexml.placeholder_for('/fe:Invoice/cbc:UUID') | ||||
|          | ||||
|         fexml.set_element('/fe:Invoice/cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d')) | ||||
|         fexml.set_element('/fe:Invoice/cbc:IssueTime', invoice.invoice_issue.strftime('%H:%M:%S%z')) | ||||
|         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') | ||||
|         fexml.set_element('/fe:Invoice/cbc:UBLVersionID', 'UBL 2.1') | ||||
|         fexml.set_element('/fe:Invoice/cbc:ID', invoice.invoice_ident) | ||||
|         fexml.set_element('/fe:Invoice/cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d')) | ||||
|         fexml.set_element('/fe:Invoice/cbc:IssueTime', invoice.invoice_issue.strftime('%H:%M:%S%z')) | ||||
|         fexml.set_element('/fe:Invoice/cbc:LineCountNumeric', len(invoice.invoice_lines)) | ||||
|         fexml.set_element('/fe:Invoice/cac:InvoicePeriod/cbc:StartDate', invoice.invoice_period_start.strftime('%Y-%m-%d')) | ||||
|         fexml.set_element('/fe:Invoice/cac:InvoicePeriod/cbc:EndDate', invoice.invoice_period_end.strftime('%Y-%m-%d')) | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/cbc:LineCountNumeric', len(invoice.invoice_lines)) | ||||
|         fexml.set_supplier(invoice) | ||||
|         fexml.set_customer(invoice) | ||||
|         fexml.set_legal_monetary(invoice) | ||||
|         fexml.set_invoice_lines(invoice) | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/cac:PartyIdentification/cbc:ID', | ||||
|                           invoice.invoice_supplier.ident) | ||||
|         fexml.set_element('/Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', | ||||
|                           invoice.invoice_supplier.ident) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyTaxScheme/cbc:TaxLevelCode', | ||||
|                           invoice.invoice_supplier.responsability_code) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/cbc:AdditionalAccountID', | ||||
|                           invoice.invoice_supplier.organization_code) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/cac:PartyName/cbc:Name', | ||||
|                           invoice.invoice_supplier.name) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationName', | ||||
|                           invoice.invoice_supplier.legal_name) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cbc:CityName', invoice.invoice_supplier.address.city) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:AddressLine/cbc:Line', invoice.invoice_supplier.address.street) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:Country/cbc:IdentificationCode', invoice.invoice_supplier.address.country.code) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:Country/cbc:name', invoice.invoice_supplier.address.country.name) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:Country/cac:AddressLine/cbc:Line', invoice.invoice_supplier.address.street) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/fe:PhysicalLocation/fe:Address/cac:AddressLine/cbc:Line', | ||||
|                           invoice.invoice_supplier.address.street) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/cac:PartyIdentification/cbc:ID', | ||||
|                           invoice.invoice_customer.ident) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyTaxScheme/cbc:TaxLevelCode', | ||||
|                           invoice.invoice_customer.responsability_code) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/cbc:AdditionalAccountID', | ||||
|                           invoice.invoice_customer.organization_code) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/cac:PartyName/cbc:Name', | ||||
|                           invoice.invoice_customer.name) | ||||
|         fexml.set_element('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', | ||||
|                           invoice.invoice_customer.ident) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationName', | ||||
|                           invoice.invoice_customer.legal_name) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cbc:CityName', invoice.invoice_customer.address.city) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:Country/cbc:IdentificationCode', invoice.invoice_customer.address.country.code) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:Country/cbc:Name', invoice.invoice_customer.address.country.name) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:AddressLine/cbc:Line', invoice.invoice_customer.address.street) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PhysicalLocation/fe:Address/cac:AddressLine/cbc:Line', | ||||
|                           invoice.invoice_customer.address.street) | ||||
|         fexml.set_element('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/fe:PartyLegalEntity/cbc:RegistrationAddress/cac:Country/cac:AddressLine/cbc:Line', invoice.invoice_customer.address.street) | ||||
|          | ||||
|         fexml.set_element('/fe:Invoice/fe:LegalMonetaryTotal/cbc:LineExtensionAmount', | ||||
|                           invoice.invoice_legal_monetary_total.line_extension_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/fe:LegalMonetaryTotal/cbc:TaxExclusiveAmount', | ||||
|                           invoice.invoice_legal_monetary_total.tax_exclusive_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/fe:LegalMonetaryTotal/cbc:TaxInclusiveAmount', | ||||
|                           invoice.invoice_legal_monetary_total.tax_inclusive_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/fe:LegalMonetaryTotal/cbc:ChargeTotalAmount', | ||||
|                           invoice.invoice_legal_monetary_total.charge_total_amount, | ||||
|                           currencyID='COP') | ||||
|         fexml.set_element('/fe:Invoice/fe:LegalMonetaryTotal/cbc:PayableAmount', | ||||
|                           invoice.invoice_legal_monetary_total.payable_amount, | ||||
|                           currencyID='COP') | ||||
|  | ||||
|         fexml.set_element('/fe:Invoice/cbc:LineCountNumeric', len(invoice.invoice_lines)) | ||||
|         next_append = False | ||||
|         for index, invoice_line in enumerate(invoice.invoice_lines): | ||||
|             line = fexml.fragment('/fe:Invoice/fe:InvoiceLine', append=next_append) | ||||
|             next_append = True | ||||
|  | ||||
|             line.set_element('/fe:InvoiceLine/cbc:ID', index + 1) | ||||
|             line.set_element('/fe:InvoiceLine/cbc:InvoicedQuantity', invoice_line.quantity, unitCode = 'NAR') | ||||
|             line.set_element('/fe:InvoiceLine/cbc:LineExtensionAmount', invoice_line.total_amount, currencyID="COP") | ||||
|             line.set_element('/fe:InvoiceLine/fe:Price/cbc:PriceAmount', invoice_line.price_amount, currencyID="COP")  | ||||
|             line.set_element('/fe:InvoiceLine/fe:Item/cbc:Description', invoice_line.item.description) | ||||
|             # TODO | ||||
|             line.set_element('/fe:InvoiceLine/fe:Item/cac:StandardItemIdentification/cbc:ID', invoice_line.item.id)  | ||||
|  | ||||
|         return fexml | ||||
|   | ||||
		Reference in New Issue
	
	Block a user