oc-facho/facho/fe/form_xml/support_document.py
2024-08-14 12:50:53 -05:00

648 lines
26 KiB
Python

from .. import fe
from ..form import (
Amount, DebitNoteDocumentReference, CreditNoteDocumentReference,
InvoiceDocumentReference, TaxTotalOmit, WithholdingTaxTotalOmit
)
from collections import defaultdict
from datetime import datetime
# from .attached_document import *
__all__ = ['DIANSupportDocumentXML']
class DIANSupportDocumentXML(fe.FeXML):
"""
DianSupportDocumentXML mapea objeto form.Invoice a XML segun
lo indicado para él Documento soporte en adquisiciones efectuadas con sujetos no obligados a expedir factura de venta o documento equivalente.
"""
def __init__(self, invoice, tag_document='Invoice'):
super().__init__(tag_document, 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
# DIAN 1.1.-2021: DSAB03
# DIAN 1.1.-2021: NSAB03
self.placeholder_for(
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceControl')
# DIAN 1.1.-2021: DSAB13
# DIAN 1.1.-2021: NSAB13
self.placeholder_for(
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource')
# DIAN 1.1.-2021: DSAB18
# DIAN 1.1.-2021: NSAB18
self.placeholder_for(
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareProvider')
# DIAN 1.1.-2021: DSAB27
# DIAN 1.1.-2021: NSAB27
self.placeholder_for(
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareSecurityCode')
# DIAN 1.1.-2021: DSAB30 DSAB31
# DIAN 1.1.-2021: NSAB30 NSAB31
self.placeholder_for(
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider/sts:AuthorizationProviderID')
# ZE02 se requiere existencia para firmar
# DIAN 1.1.-2021: DSAA02 DSAB01
# DIAN 1.1.-2021: NSAA02 NSAB01
ublextension = self.fragment(
'./ext:UBLExtensions/ext:UBLExtension', append=True)
# DIAN 1.1.-2021: DSAB02
# DIAN 1.1.-2021: NSAB02
extcontent = ublextension.find_or_create_element(
'/ext:UBLExtension/ext:ExtensionContent')
self.attach_invoice(invoice)
def set_supplier(fexml, invoice):
# DIAN 1.1.-2021: DSAJ01
# DIAN 1.1.-2021: NSAB01
fexml.placeholder_for('./cac:AccountingSupplierParty')
# DIAN 1.1.-2021: DSAJ02
# DIAN 1.1.-2021: NSAJ02
fexml.set_element(
'./cac:AccountingSupplierParty/cbc:AdditionalAccountID',
invoice.invoice_supplier.organization_code)
# DIAN 1.1.-2021: DSAJ07 DSAJ08
# DIAN 1.1.-2021: NSAJ07 NSAJ08
fexml.placeholder_for(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address')
# DIAN 1.1.-2021: DSAJ09
# DIAN 1.1.-2021: NSAJ09
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:ID',
invoice.invoice_supplier.address.city.code)
# DIAN 1.1.-2021: DSAJ10
# DIAN 1.1.-2021: NSAJ10
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CityName',
invoice.invoice_supplier.address.city.name)
# DIAN 1.1.-2021: DSAJ73
# DIAN 1.1.-2021: NSAJ73
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:PostalZone',
invoice.invoice_supplier.address.postalzone.code)
# DIAN 1.1.-2021: DSAJ11
# DIAN 1.1.-2021: NSAJ11
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CountrySubentity',
invoice.invoice_supplier.address.countrysubentity.name)
# DIAN 1.1.-2021: DSAJ12
# DIAN 1.1.-2021: NSAJ12
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CountrySubentityCode',
invoice.invoice_supplier.address.countrysubentity.code)
# DIAN 1.1.-2021: NSAJ13 NSAJ14
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:AddressLine/cbc:Line',
invoice.invoice_supplier.address.street)
# DIAN 1.1.-2021: DSAJ15 DSAJ16
# DIAN 1.1.-2021: NSAJ15 NSAJ16
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:Country/cbc:IdentificationCode',
invoice.invoice_supplier.address.country.code)
# DIAN 1.1.-2021: DSAJ17
# DIAN 1.1.-2021: NSAJ17
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:Country/cbc:Name',
invoice.invoice_supplier.address.country.name,
# DIAN 1.1.-2021: DSAJ18
# # DIAN 1.1.-2021: NSAJ18
languageID='es')
supplier_company_id_attrs = fe.SCHEME_AGENCY_ATTRS.copy()
supplier_company_id_attrs.update(
{
'schemeID': invoice.invoice_supplier.ident.dv,
'schemeName': invoice.invoice_supplier.ident.type_fiscal})
# DIAN 1.1.-2021: DSAJ19
# DIAN 1.1.-2021: NSAJ19
fexml.placeholder_for(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme')
# DIAN 1.1.-2021: DSAJ20
# DIAN 1.1.-2021: NSAJ20
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:RegistrationName',
invoice.invoice_supplier.legal_name)
# DIAN 1.1.-2021: DSAJ21
# DIAN 1.1.-2021: NSAJ21
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID',
invoice.invoice_supplier.ident,
# DIAN 1.1.-2021: DSAJ22 DSAJ23 DSAJ24 DSAJ25
# DIAN 1.1.-2021: NSAJ22 NSAJ23 NSAJ24 NSAJ25
**supplier_company_id_attrs)
# DIAN 1.1.-2021: DSAJ26
# DIAN 1.1.-2021: NSAJ26
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode',
invoice.invoice_supplier.responsability_code,
listName=invoice.invoice_supplier.responsability_regime_code)
# DIAN 1.1.-2021: DSAJ39
# DIAN 1.1.-2021: NSAJ39
fexml.placeholder_for(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme')
# DIAN 1.1.-2021: DSAJ40
# DIAN 1.1.-2021: NSAJ40
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
invoice.invoice_customer.tax_scheme.code)
# DIAN 1.1.-2021: DSAJ41
# DIAN 1.1.-2021: NSAJ41
fexml.set_element(
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
invoice.invoice_customer.tax_scheme.name)
def set_customer(fexml, invoice):
# DIAN 1.1.-2021: DSAK01
# DIAN 1.1.-2021: NSAK01
fexml.placeholder_for('./cac:AccountingCustomerParty')
# DIAN 1.1.-2021: DSAK02
# DIAN 1.1.-2021: NSAK02
fexml.set_element(
'./cac:AccountingCustomerParty/cbc:AdditionalAccountID',
invoice.invoice_customer.organization_code)
# DIAN 1.1.-2021: DSAK03
# DIAN 1.1.-2021: NSAK03
fexml.placeholder_for('./cac:AccountingCustomerParty/cac:Party')
# DIAN 1.1.-2021: DSAK19
# DIAN 1.1.-2021: NSAK19
fexml.placeholder_for(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme')
# DIAN 1.1.-2021: DSAK20
# DIAN 1.1.-2021: NSAK20
fexml.set_element(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:RegistrationName',
invoice.invoice_customer.legal_name)
customer_company_id_attrs = fe.SCHEME_AGENCY_ATTRS.copy()
customer_company_id_attrs.update(
{
'schemeID': invoice.invoice_customer.ident.dv,
'schemeName': invoice.invoice_customer.ident.type_fiscal})
# DIAN 1.1.-2021: DSAK21
# DIAN 1.1.-2021: NSAK21
fexml.set_element(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID',
invoice.invoice_customer.ident,
# DIAN 1.1.-2021: DSAK22 DSAK23 DSAK24 DSAK25
# DIAN 1.1.-2021: NSAK22 NSAK23 NSAK24 NSAK25
**customer_company_id_attrs)
# DIAN 1.1.-2021: DSAK26
# DIAN 1.1.-2021: NSAK26
fexml.set_element(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode',
invoice.invoice_customer.responsability_code)
# DIAN 1.1.-2021: DSAK39
# DIAN 1.1.-2021: NSAK39
fexml.placeholder_for(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme')
# DIAN 1.1.-2021: DSAK40
# DIAN 1.1.-2021: NSAK40
fexml.set_element(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
invoice.invoice_customer.tax_scheme.code)
# DIAN 1.1.-2021: DSAK41
# DIAN 1.1.-2021: NSAK41
fexml.set_element(
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
invoice.invoice_customer.tax_scheme.name)
def set_payment_mean(fexml, invoice):
payment_mean = invoice.invoice_payment_mean
# DIAN 1.1.-2021: DSAN01 DSAN02
# DIAN 1.1.-2021: NSAN02 NSAN02
fexml.set_element('./cac:PaymentMeans/cbc:ID', payment_mean.id)
# DIAN 1.1.-2021: DSAN03
# DIAN 1.1.-2021: NSAN03
fexml.set_element(
'./cac:PaymentMeans/cbc:PaymentMeansCode',
payment_mean.code)
# DIAN 1.1.-2021: DSAN04
# DIAN 1.1.-2021: NSAN04
fexml.set_element(
'./cac:PaymentMeans/cbc:PaymentDueDate',
payment_mean.due_at.strftime('%Y-%m-%d'))
# DIAN 1.1.-2021: DSAN05
# DIAN 1.1.-2021: NSAN05
fexml.set_element(
'./cac:PaymentMeans/cbc:PaymentID',
payment_mean.payment_id)
def set_element_amount_for(fexml, xml, xpath, amount):
if not isinstance(amount, Amount):
raise TypeError("amount not is Amount")
xml.set_element(xpath, amount, currencyID=amount.currency.code)
def set_element_amount(fexml, xpath, amount):
if not isinstance(amount, Amount):
raise TypeError("amount not is Amount")
fexml.set_element(xpath, amount, currencyID=amount.currency.code)
def set_legal_monetary(fexml, invoice):
# DIAN 1.1.-2021: DSAU01 DSAU02 DSAU03
# DIAN 1.1.-2021: NSAU01 NSAU02 NSAU03
fexml.set_element_amount(
'./cac:LegalMonetaryTotal/cbc:LineExtensionAmount',
invoice.invoice_legal_monetary_total.line_extension_amount)
# DIAN 1.1.-2021: DSAU04 DSAU05
# DIAN 1.1.-2021: NSAU04 NSAU05
fexml.set_element_amount(
'./cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount',
invoice.invoice_legal_monetary_total.tax_exclusive_amount)
# DIAN 1.1.-2021: DSAU06 DSAU07
# DIAN 1.1.-2021: NSAU06 DSAU07
fexml.set_element_amount(
'./cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount',
invoice.invoice_legal_monetary_total.tax_inclusive_amount)
# DIAN 1.1.-2021: DSAU10 DSAU11
# DIAN 1.1.-2021: NSAU10 DSAU11
fexml.set_element_amount(
'./cac:LegalMonetaryTotal/cbc:ChargeTotalAmount',
invoice.invoice_legal_monetary_total.charge_total_amount)
# DIAN 1.1.-2021: DSAU14 DSAU15
# DIAN 1.1.-2021: NSAU14 DSAU15
fexml.set_element_amount(
'./cac:LegalMonetaryTotal/cbc:PayableAmount',
invoice.invoice_legal_monetary_total.payable_amount)
def _set_invoice_document_reference(fexml, reference):
fexml._do_set_billing_reference(
reference, 'cac:InvoiceDocumentReference')
def _set_credit_note_document_reference(fexml, reference):
fexml._do_set_billing_reference(
reference, 'cac:CreditNoteDocumentReference')
def _set_debit_note_document_reference(fexml, reference):
fexml._do_set_billing_reference(
reference, 'cac:DebitNoteDocumentReference')
def _do_set_billing_reference(fexml, reference, tag_document):
if tag_document == 'Invoice':
schemeName = 'CUFE-SHA384'
else:
schemeName = 'CUDS-SHA384'
fexml.set_element('./cac:BillingReference/%s/cbc:ID' % (tag_document),
reference.ident)
fexml.set_element(
'./cac:BillingReference/cac:InvoiceDocumentReference/cbc:UUID',
reference.uuid,
schemeName=schemeName)
fexml.set_element(
'./cac:BillingReference/cac:InvoiceDocumentReference/cbc:IssueDate',
reference.date.strftime("%Y-%m-%d"))
def set_billing_reference(fexml, invoice):
reference = invoice.invoice_billing_reference
if reference is None:
return
if isinstance(reference, DebitNoteDocumentReference):
return fexml._set_debit_note_document_reference(reference)
if isinstance(reference, CreditNoteDocumentReference):
return fexml._set_credit_note_document_reference(reference)
if isinstance(reference, InvoiceDocumentReference):
return fexml._set_invoice_document_reference(reference)
def set_discrepancy_response(fexml, invoice):
reference = invoice.invoice_discrepancy_response
if reference is None:
return
if isinstance(reference, DebitNoteDocumentReference):
return fexml._set_debit_note_document_reference(reference)
if isinstance(reference, CreditNoteDocumentReference):
return fexml._set_credit_note_document_reference(reference)
if isinstance(reference, InvoiceDocumentReference):
return fexml._set_invoice_document_reference(reference)
fexml.set_element('./cac:DiscrepancyResponse/cbc:ReferenceID',
reference.id)
fexml.set_element('./cac:DiscrepancyResponse/cbc:ResponseCode',
reference.code)
fexml.set_element('./cac:DiscrepancyResponse/cbc:Description',
reference.description)
def set_invoice_totals(fexml, invoice):
tax_amount_for = defaultdict(lambda: defaultdict(lambda: Amount(0.0)))
percent_for = defaultdict(lambda: None)
total_tax_amount = Amount(0.0)
for invoice_line in invoice.invoice_lines:
for subtotal in invoice_line.tax.subtotals:
if subtotal.scheme is not None:
tax_amount_for[
subtotal.scheme.code][
'tax_amount'] += subtotal.tax_amount
tax_amount_for[subtotal.scheme.code][
'taxable_amount'] += invoice_line.taxable_amount
# MACHETE ojo InvoiceLine.tax pasar a Invoice
percent_for[subtotal.scheme.code] = subtotal.percent
total_tax_amount += subtotal.tax_amount
if total_tax_amount != Amount(0.0):
fexml.placeholder_for('./cac:TaxTotal')
fexml.set_element_amount('./cac:TaxTotal/cbc:TaxAmount',
total_tax_amount)
for index, item in enumerate(tax_amount_for.items()):
cod_impuesto, amount_of = item
next_append = index > 0
# DIAN 1.7.-2020: FAS01
line = fexml.fragment('./cac:TaxTotal', append=next_append)
# DIAN 1.7.-2020: FAU06
tax_amount = amount_of['tax_amount']
fexml.set_element_amount_for(line,
'/cac:TaxTotal/cbc:TaxAmount',
tax_amount)
# DIAN 1.7.-2020: FAS05
fexml.set_element_amount_for(
line,
'/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
amount_of['taxable_amount'])
# DIAN 1.7.-2020: FAU06
fexml.set_element_amount_for(
line,
'/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
amount_of['tax_amount'])
# DIAN 1.7.-2020: FAS07
if percent_for[cod_impuesto]:
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cbc:Percent',
percent_for[cod_impuesto])
if percent_for[cod_impuesto]:
line.set_element(
'/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
percent_for[cod_impuesto])
line.set_element(
'/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
cod_impuesto)
line.set_element(
'/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', 'IVA')
# abstract method
def tag_document(fexml):
return 'Invoice'
# abstract method
def tag_document_concilied(fexml):
return 'Invoiced'
def set_invoice_line_withholding(fexml, line, invoice_line):
fexml.set_element_amount_for(line,
'./cac:WithholdingTaxTotal/cbc:TaxAmount',
invoice_line.withholding_amount)
# DIAN 1.7.-2020: FAX05
fexml.set_element_amount_for(
line,
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
invoice_line.withholding_taxable_amount)
for subtotal in invoice_line.withholding.subtotals:
line.set_element(
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
subtotal.tax_amount,
currencyID='COP')
if subtotal.percent is not None:
line.set_element(
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
'%0.2f' %
round(
subtotal.percent,
2))
if subtotal.scheme is not None:
# DIAN 1.7.-2020: FAX15
line.set_element(
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
subtotal.scheme.code)
line.set_element(
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name',
subtotal.scheme.name)
def set_invoice_line_tax(fexml, line, invoice_line):
fexml.set_element_amount_for(line,
'./cac:TaxTotal/cbc:TaxAmount',
invoice_line.tax_amount)
# DIAN 1.7.-2020: FAX05
fexml.set_element_amount_for(
line,
'./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
invoice_line.taxable_amount)
for subtotal in invoice_line.tax.subtotals:
line.set_element(
'./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
subtotal.tax_amount,
currencyID='COP')
if subtotal.percent is not None:
line.set_element(
'./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
'%0.2f' %
round(
subtotal.percent,
2))
if subtotal.scheme is not None:
# DIAN 1.7.-2020: FAX15
line.set_element(
'./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
subtotal.scheme.code)
line.set_element(
'./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name',
subtotal.scheme.name)
def set_invoice_lines(fexml, invoice):
next_append = False
for index, invoice_line in enumerate(invoice.invoice_lines):
line = fexml.fragment(
'./cac:%sLine' %
(fexml.tag_document()),
append=next_append)
next_append = True
line.set_element('./cbc:ID', index + 1)
line.set_element(
'./cbc:%sQuantity' %
(fexml.tag_document_concilied()),
invoice_line.quantity,
unitCode='NAR')
fexml.set_element_amount_for(line,
'./cbc:LineExtensionAmount',
invoice_line.total_amount)
period = line.fragment('./cac:InvoicePeriod')
period.set_element('./cbc:StartDate',
datetime.now().strftime('%Y-%m-%d'))
period.set_element(
'./cbc:DescriptionCode', '1')
period.set_element('./cbc:Description',
'Por operación')
if not isinstance(invoice_line.tax, TaxTotalOmit):
fexml.set_invoice_line_tax(line, invoice_line)
if not isinstance(
invoice_line.withholding,
WithholdingTaxTotalOmit):
fexml.set_invoice_line_withholding(line, invoice_line)
line.set_element(
'./cac:Item/cbc:Description',
invoice_line.item.description)
line.set_element(
'./cac:Item/cac:StandardItemIdentification/cbc:ID',
invoice_line.item.id,
schemeID=invoice_line.item.scheme_id,
schemeName=invoice_line.item.scheme_name,
schemeAgencyID=invoice_line.item.scheme_agency_id)
line.set_element(
'./cac:Price/cbc:PriceAmount',
invoice_line.price.amount,
currencyID=invoice_line.price.amount.currency.code)
# DIAN 1.7.-2020: FBB04
line.set_element('./cac:Price/cbc:BaseQuantity',
invoice_line.quantity,
unitCode=invoice_line.quantity.code)
for idx, charge in enumerate(invoice_line.allowance_charge):
next_append_charge = idx > 0
fexml.append_allowance_charge(
line, index + 1, charge, append=next_append_charge)
def set_allowance_charge(fexml, invoice):
for idx, charge in enumerate(invoice.invoice_allowance_charge):
next_append = idx > 0
fexml.append_allowance_charge(
fexml, idx + 1, charge, append=next_append)
def append_allowance_charge(fexml, parent, idx, charge, append=False):
line = parent.fragment('./cac:AllowanceCharge', append=append)
# DIAN 1.7.-2020: FAQ02
line.set_element('./cbc:ID', idx)
# DIAN 1.7.-2020: FAQ03
line.set_element('./cbc:ChargeIndicator',
str(charge.charge_indicator).lower())
if charge.reason:
line.set_element(
'./cbc:AllowanceChargeReasonCode',
charge.reason.code)
line.set_element(
'./cbc:allowanceChargeReason',
charge.reason.reason)
line.set_element('./cbc:MultiplierFactorNumeric',
str(round(charge.multiplier_factor_numeric, 2)))
fexml.set_element_amount_for(line, './cbc:Amount', charge.amount)
fexml.set_element_amount_for(
line, './cbc:BaseAmount', charge.base_amount)
def attach_invoice(fexml, invoice):
"""adiciona etiquetas a FEXML y retorna FEXML
en caso de fallar validacion retorna None"""
fexml.placeholder_for('./ext:UBLExtensions')
fexml.set_element('./cbc:UBLVersionID', 'UBL 2.1')
fexml.set_element(
'./cbc:CustomizationID',
invoice.invoice_operation_type)
fexml.placeholder_for('./cbc:ProfileID')
fexml.placeholder_for('./cbc:ProfileExecutionID')
fexml.set_element('./cbc:ID', invoice.invoice_ident)
fexml.placeholder_for('./cbc:UUID')
fexml.set_element('./cbc:DocumentCurrencyCode', 'COP')
fexml.set_element(
'./cbc:IssueDate',
invoice.invoice_issue.strftime('%Y-%m-%d'))
# DIAN 1.7.-2020: FAD10
fexml.set_element(
'./cbc:IssueTime',
invoice.invoice_issue.strftime('%H:%M:%S-05:00'))
fexml.set_element(
'./cbc:%sTypeCode' %
(fexml.tag_document()),
invoice.invoice_type_code,
listAgencyID='195',
listAgencyName='No matching global declaration available for the validation root',
listURI='http://www.dian.gov.co')
fexml.set_element('./cbc:LineCountNumeric', len(invoice.invoice_lines))
fexml.set_element(
'./cac:%sPeriod/cbc:StartDate' %
(fexml.tag_document()),
invoice.invoice_period_start.strftime('%Y-%m-%d'))
fexml.set_element(
'./cac:%sPeriod/cbc:EndDate' %
(fexml.tag_document()),
invoice.invoice_period_end.strftime('%Y-%m-%d'))
fexml.customize(invoice)
fexml.set_supplier(invoice)
fexml.set_customer(invoice)
fexml.set_legal_monetary(invoice)
fexml.set_invoice_totals(invoice)
fexml.set_invoice_lines(invoice)
fexml.set_payment_mean(invoice)
fexml.set_allowance_charge(invoice)
fexml.set_discrepancy_response(invoice)
fexml.set_billing_reference(invoice)
return fexml
def customize(fexml, invoice):
"""adiciona etiquetas a FEXML y retorna FEXML
en caso de fallar validacion retorna None"""