style(__init__): Formateado PEP8
This commit is contained in:
		| @@ -1,12 +1,14 @@ | ||||
| # This file is part of facho.  The COPYRIGHT file at the top level of | ||||
| # this repository contains the full copyright notices and license terms. | ||||
| import hashlib | ||||
| from functools import reduce | ||||
| import copy | ||||
|  | ||||
| # import hashlib | ||||
| # from functools import reduce | ||||
| # import copy | ||||
|  | ||||
| import dataclasses | ||||
| from dataclasses import dataclass, field | ||||
| from datetime import datetime, date | ||||
| from collections import defaultdict | ||||
| # from collections import defaultdict | ||||
| import decimal | ||||
| from decimal import Decimal | ||||
| import typing | ||||
| @@ -14,9 +16,11 @@ from ..data.dian import codelist | ||||
|  | ||||
| DECIMAL_PRECISION = 6 | ||||
|  | ||||
|  | ||||
| class AmountCurrencyError(TypeError): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Currency: | ||||
|     code: str | ||||
| @@ -27,6 +31,7 @@ class Currency: | ||||
|     def __str__(self): | ||||
|         return self.code | ||||
|  | ||||
|  | ||||
| class Collection: | ||||
|  | ||||
|     def __init__(self, array): | ||||
| @@ -43,6 +48,7 @@ class Collection: | ||||
|     def sum(self): | ||||
|         return sum(self.array) | ||||
|  | ||||
|  | ||||
| class AmountCollection(Collection): | ||||
|  | ||||
|     def sum(self): | ||||
| @@ -51,10 +57,13 @@ class AmountCollection(Collection): | ||||
|             total += v | ||||
|         return total | ||||
|  | ||||
| class Amount: | ||||
|     def __init__(self, amount: int or float or str or Amount, currency: Currency = Currency('COP')): | ||||
|  | ||||
|         #DIAN 1.7.-2020: 1.2.3.1 | ||||
| class Amount: | ||||
|     def __init__( | ||||
|             self, amount: typing.Union[int, float, str, "Amount"], | ||||
|             currency: Currency = Currency('COP')): | ||||
|  | ||||
|         # DIAN 1.7.-2020: 1.2.3.1 | ||||
|         if isinstance(amount, Amount): | ||||
|             if amount < Amount(0.0): | ||||
|                 raise ValueError('amount must be positive >= 0') | ||||
| @@ -65,14 +74,16 @@ class Amount: | ||||
|             if float(amount) < 0: | ||||
|                 raise ValueError('amount must be positive >= 0') | ||||
|  | ||||
|             self.amount = Decimal(amount, decimal.Context(prec=DECIMAL_PRECISION, | ||||
|                                                           #DIAN 1.7.-2020: 1.2.1.1 | ||||
|                                                           rounding=decimal.ROUND_HALF_EVEN )) | ||||
|             self.amount = Decimal( | ||||
|                 amount, decimal.Context( | ||||
|                     prec=DECIMAL_PRECISION, | ||||
|                     # DIAN 1.7.-2020: 1.2.1.1 | ||||
|                     rounding=decimal.ROUND_HALF_EVEN)) | ||||
|             self.currency = currency | ||||
|  | ||||
|     def fromNumber(self, val): | ||||
|         return Amount(val, currency=self.currency) | ||||
|      | ||||
|  | ||||
|     def round(self, prec): | ||||
|         return Amount(round(self.amount, prec), currency=self.currency) | ||||
|  | ||||
| @@ -90,7 +101,8 @@ class Amount: | ||||
|     def __eq__(self, other): | ||||
|         if not self.is_same_currency(other): | ||||
|             raise AmountCurrencyError() | ||||
|         return round(self.amount, DECIMAL_PRECISION) == round(other.amount, DECIMAL_PRECISION) | ||||
|         return round(self.amount, DECIMAL_PRECISION) == round( | ||||
|             other.amount, DECIMAL_PRECISION) | ||||
|  | ||||
|     def _cast(self, val): | ||||
|         if type(val) in [int, float]: | ||||
| @@ -98,7 +110,7 @@ class Amount: | ||||
|         if isinstance(val, Amount): | ||||
|             return val | ||||
|         raise TypeError("cant cast to amount") | ||||
|      | ||||
|  | ||||
|     def __add__(self, rother): | ||||
|         other = self._cast(rother) | ||||
|         if not self.is_same_currency(other): | ||||
| @@ -122,14 +134,14 @@ class Amount: | ||||
|  | ||||
|     def truncate_as_string(self, prec): | ||||
|         parts = str(self.float()).split('.', 1) | ||||
|         return '%s.%s' % (parts[0], parts[1][0:prec].ljust(prec,'0')) | ||||
|         return '%s.%s' % (parts[0], parts[1][0:prec].ljust(prec, '0')) | ||||
|  | ||||
|     def float(self): | ||||
|         return float(round(self.amount, DECIMAL_PRECISION)) | ||||
|      | ||||
|  | ||||
|  | ||||
| class Quantity: | ||||
|      | ||||
|  | ||||
|     def __init__(self, val, code): | ||||
|         if type(val) not in [float, int]: | ||||
|             raise ValueError('val expected int or float') | ||||
| @@ -151,6 +163,7 @@ class Quantity: | ||||
|     def __repr__(self): | ||||
|         return str(self) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Item: | ||||
|     scheme_name: str | ||||
| @@ -175,9 +188,9 @@ class UNSPSCItem(Item): | ||||
|                          description=description, | ||||
|                          scheme_name='UNSPSC', | ||||
|                          scheme_id='001', | ||||
|                          scheme_agency_id='10')         | ||||
|                          scheme_agency_id='10') | ||||
|  | ||||
|  | ||||
|          | ||||
| @dataclass | ||||
| class Country: | ||||
|     code: str | ||||
| @@ -188,6 +201,7 @@ class Country: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.Paises[self.code]['name'] | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class CountrySubentity: | ||||
|     code: str | ||||
| @@ -198,6 +212,7 @@ class CountrySubentity: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.Departamento[self.code]['name'] | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class City: | ||||
|     code: str | ||||
| @@ -208,19 +223,23 @@ class City: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.Municipio[self.code]['name'] | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class PostalZone: | ||||
|     code: str = '' | ||||
|          | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Address: | ||||
|     name: str | ||||
|     street: str = '' | ||||
|     city: City = field(default_factory=lambda: City('05001')) | ||||
|     country: Country = field(default_factory=lambda: Country('CO')) | ||||
|     countrysubentity: CountrySubentity = field(default_factory=lambda: CountrySubentity('05')) | ||||
|     countrysubentity: CountrySubentity = field( | ||||
|         default_factory=lambda: CountrySubentity('05')) | ||||
|     postalzone: PostalZone = field(default_factory=lambda: PostalZone('')) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class PartyIdentification: | ||||
|     number: str | ||||
| @@ -240,6 +259,7 @@ class PartyIdentification: | ||||
|         if self.type_fiscal not in codelist.TipoIdFiscal: | ||||
|             raise ValueError("type_fiscal [%s] not found" % (self.type_fiscal)) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Responsability: | ||||
|     codes: list | ||||
| @@ -269,6 +289,7 @@ class TaxScheme: | ||||
|             raise ValueError("code not found") | ||||
|         self.name = codelist.TipoImpuesto[self.code]['name'] | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Party: | ||||
|     name: str | ||||
| @@ -334,6 +355,7 @@ class TaxTotalOmit(TaxTotal): | ||||
|     def calculate(self, invline): | ||||
|         pass | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class WithholdingTaxSubTotal: | ||||
|     percent: float | ||||
| @@ -344,6 +366,7 @@ class WithholdingTaxSubTotal: | ||||
|         if self.percent is not None: | ||||
|             self.tax_amount = invline.total_amount * Amount(self.percent / 100) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class WithholdingTaxTotal: | ||||
|     subtotals: list | ||||
| @@ -356,7 +379,8 @@ class WithholdingTaxTotal: | ||||
|         for subtax in self.subtotals: | ||||
|             subtax.calculate(invline) | ||||
|             self.tax_amount += subtax.tax_amount | ||||
|      | ||||
|  | ||||
|  | ||||
| class WithholdingTaxTotalOmit(WithholdingTaxTotal): | ||||
|     def __init__(self): | ||||
|         super().__init__([]) | ||||
| @@ -364,6 +388,7 @@ class WithholdingTaxTotalOmit(WithholdingTaxTotal): | ||||
|     def calculate(self, invline): | ||||
|         pass | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Price: | ||||
|     amount: Amount | ||||
| @@ -379,6 +404,7 @@ class Price: | ||||
|  | ||||
|         self.amount *= self.quantity | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class PaymentMean: | ||||
|     DEBIT = '01' | ||||
| @@ -396,15 +422,17 @@ class PaymentMean: | ||||
|  | ||||
| @dataclass | ||||
| class PrePaidPayment: | ||||
|     #DIAN 1.7.-2020: FBD03 | ||||
|     # DIAN 1.7.-2020: FBD03 | ||||
|     paid_amount: Amount = field(default_factory=lambda: Amount(0.0)) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class BillingResponse: | ||||
|     id: str | ||||
|     code: str | ||||
|     description: str | ||||
|  | ||||
|  | ||||
| class SupportDocumentCreditNoteResponse(BillingResponse): | ||||
|     """ | ||||
|     ReferenceID: Identifica la sección del Documento | ||||
| @@ -414,13 +442,13 @@ class SupportDocumentCreditNoteResponse(BillingResponse): | ||||
|     """ | ||||
|  | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class BillingReference: | ||||
|     ident: str | ||||
|     uuid: str | ||||
|     date: date | ||||
|  | ||||
|  | ||||
| class CreditNoteDocumentReference(BillingReference): | ||||
|     """ | ||||
|     ident: Prefijo + Numero de la factura relacionada | ||||
| @@ -428,6 +456,7 @@ class CreditNoteDocumentReference(BillingReference): | ||||
|     date: fecha de emision de la factura relacionada | ||||
|     """ | ||||
|  | ||||
|  | ||||
| class DebitNoteDocumentReference(BillingReference): | ||||
|     """ | ||||
|     ident: Prefijo + Numero de la factura relacionada | ||||
| @@ -435,6 +464,7 @@ class DebitNoteDocumentReference(BillingReference): | ||||
|     date: fecha de emision de la factura relacionada | ||||
|     """ | ||||
|  | ||||
|  | ||||
| class InvoiceDocumentReference(BillingReference): | ||||
|     """ | ||||
|     ident: Prefijo + Numero de la nota credito relacionada | ||||
| @@ -442,6 +472,7 @@ class InvoiceDocumentReference(BillingReference): | ||||
|     date: fecha de emision de la nota credito relacionada | ||||
|     """ | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class AllowanceChargeReason: | ||||
|     code: str | ||||
| @@ -468,10 +499,12 @@ class AllowanceCharge: | ||||
|         default_factory=lambda: Amount(1.0)) | ||||
|  | ||||
|     def isCharge(self): | ||||
|         return self.charge_indicator == True | ||||
|         charge_indicator = self.charge_indicator is True | ||||
|         return charge_indicator | ||||
|  | ||||
|     def isDiscount(self): | ||||
|         return self.charge_indicator == False | ||||
|         charge_indicator = self.charge_indicator is False | ||||
|         return charge_indicator | ||||
|  | ||||
|     def asCharge(self): | ||||
|         self.charge_indicator = True | ||||
| @@ -485,11 +518,13 @@ class AllowanceCharge: | ||||
|     def set_base_amount(self, amount): | ||||
|         self.base_amount = amount | ||||
|  | ||||
|  | ||||
| class AllowanceChargeAsDiscount(AllowanceCharge): | ||||
|     def __init__(self, amount: Amount = Amount(0.0)): | ||||
|         self.charge_indicator = False | ||||
|         self.amount = amount | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class InvoiceLine: | ||||
|     # RESOLUCION 0004: pagina 155 | ||||
| @@ -503,7 +538,8 @@ class InvoiceLine: | ||||
|     # de subtotal | ||||
|     tax: typing.Optional[TaxTotal] | ||||
|     withholding: typing.Optional[WithholdingTaxTotal] | ||||
|     allowance_charge: typing.List[AllowanceCharge] = dataclasses.field(default_factory=list) | ||||
|     allowance_charge: typing.List[AllowanceCharge] = dataclasses.field( | ||||
|         default_factory=list) | ||||
|  | ||||
|     def add_allowance_charge(self, charge): | ||||
|         if not isinstance(charge, AllowanceCharge): | ||||
| @@ -514,7 +550,7 @@ class InvoiceLine: | ||||
|     @property | ||||
|     def total_amount_without_charge(self): | ||||
|         return (self.quantity * self.price.amount) | ||||
|      | ||||
|  | ||||
|     @property | ||||
|     def total_amount(self): | ||||
|         charge = AmountCollection(self.allowance_charge)\ | ||||
| @@ -568,6 +604,7 @@ class InvoiceLine: | ||||
|         if self.withholding is None: | ||||
|             self.withholding = WithholdingTaxTotalOmit() | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class LegalMonetaryTotal: | ||||
|     line_extension_amount: Amount = field(default_factory=lambda: Amount(0.0)) | ||||
| @@ -579,7 +616,7 @@ class LegalMonetaryTotal: | ||||
|     prepaid_amount: Amount = field(default_factory=lambda: Amount(0.0)) | ||||
|  | ||||
|     def calculate(self): | ||||
|         #DIAN 1.7.-2020: FAU14 | ||||
|         # DIAN 1.7.-2020: FAU14 | ||||
|         self.payable_amount = \ | ||||
|             self.tax_inclusive_amount \ | ||||
|             + self.allowance_total_amount \ | ||||
| @@ -587,26 +624,29 @@ class LegalMonetaryTotal: | ||||
|             - self.prepaid_amount | ||||
|  | ||||
|  | ||||
|  | ||||
| class NationalSalesInvoiceDocumentType(str): | ||||
|     def __str__(self): | ||||
|         # 6.1.3 | ||||
|         return '01' | ||||
|  | ||||
|  | ||||
| class CreditNoteDocumentType(str): | ||||
|     def __str__(self): | ||||
|         # 6.1.3 | ||||
|         return '91' | ||||
|  | ||||
|  | ||||
| class DebitNoteDocumentType(str): | ||||
|     def __str__(self): | ||||
|         # 6.1.3 | ||||
|         return '92' | ||||
|  | ||||
|  | ||||
| class CreditNoteSupportDocumentType(str): | ||||
|     def __str__(self): | ||||
|         return '95' | ||||
|  | ||||
|  | ||||
| class Invoice: | ||||
|     def __init__(self, type_code: str): | ||||
|         if str(type_code) not in codelist.TipoDocumento: | ||||
| @@ -652,7 +692,8 @@ class Invoice: | ||||
|             if len(prefix) <= 4: | ||||
|                 self.invoice_ident_prefix = prefix | ||||
|             else: | ||||
|                 raise ValueError('ident prefix failed to get, expected 0  to 4 chars') | ||||
|                 raise ValueError( | ||||
|                     'ident prefix failed to get, expected 0  to 4 chars') | ||||
|  | ||||
|     def set_ident(self, ident: str): | ||||
|         """ | ||||
| @@ -683,7 +724,7 @@ class Invoice: | ||||
|  | ||||
|     def _get_codelist_tipo_operacion(self): | ||||
|         return codelist.TipoOperacionF | ||||
|      | ||||
|  | ||||
|     def set_operation_type(self, operation): | ||||
|         if operation not in self._get_codelist_tipo_operacion(): | ||||
|             raise ValueError("operation not found") | ||||
| @@ -705,7 +746,6 @@ class Invoice: | ||||
|     def set_discrepancy_response(self, billing_response: BillingResponse): | ||||
|         self.invoice_discrepancy_response = billing_response | ||||
|  | ||||
|  | ||||
|     def accept(self, visitor): | ||||
|         visitor.visit_payment_mean(self.invoice_payment_mean) | ||||
|         visitor.visit_customer(self.invoice_customer) | ||||
| @@ -717,29 +757,34 @@ class Invoice: | ||||
|  | ||||
|     def _calculate_legal_monetary_total(self): | ||||
|         for invline in self.invoice_lines: | ||||
|             self.invoice_legal_monetary_total.line_extension_amount += invline.total_amount | ||||
|             self.invoice_legal_monetary_total.tax_exclusive_amount += invline.total_tax_exclusive_amount | ||||
|             #DIAN 1.7.-2020: FAU6 | ||||
|             self.invoice_legal_monetary_total.tax_inclusive_amount += invline.total_tax_inclusive_amount | ||||
|             self.invoice_legal_monetary_total.line_extension_amount +=\ | ||||
|                 invline.total_amount | ||||
|             self.invoice_legal_monetary_total.tax_exclusive_amount +=\ | ||||
|                 invline.total_tax_exclusive_amount | ||||
|             # DIAN 1.7.-2020: FAU6 | ||||
|             self.invoice_legal_monetary_total.tax_inclusive_amount +=\ | ||||
|                 invline.total_tax_inclusive_amount | ||||
|  | ||||
|         #DIAN 1.7.-2020: FAU08 | ||||
|         self.invoice_legal_monetary_total.allowance_total_amount = AmountCollection(self.invoice_allowance_charge)\ | ||||
|         # DIAN 1.7.-2020: FAU08 | ||||
|         self.invoice_legal_monetary_total.allowance_total_amount =\ | ||||
|             AmountCollection(self.invoice_allowance_charge)\ | ||||
|             .filter(lambda charge: charge.isDiscount())\ | ||||
|             .map(lambda charge: charge.amount)\ | ||||
|             .sum() | ||||
|  | ||||
|         #DIAN 1.7.-2020: FAU10 | ||||
|         self.invoice_legal_monetary_total.charge_total_amount = AmountCollection(self.invoice_allowance_charge)\ | ||||
|         # DIAN 1.7.-2020: FAU10 | ||||
|         self.invoice_legal_monetary_total.charge_total_amount =\ | ||||
|             AmountCollection(self.invoice_allowance_charge)\ | ||||
|             .filter(lambda charge: charge.isCharge())\ | ||||
|             .map(lambda charge: charge.amount)\ | ||||
|             .sum() | ||||
|  | ||||
|         #DIAN 1.7.-2020: FAU12 | ||||
|         self.invoice_legal_monetary_total.prepaid_amount = AmountCollection(self.invoice_prepaid_payment)\ | ||||
|             .map(lambda paid: paid.paid_amount)\ | ||||
|             .sum() | ||||
|         # DIAN 1.7.-2020: FAU12 | ||||
|         self.invoice_legal_monetary_total.prepaid_amount = AmountCollection( | ||||
|             self.invoice_prepaid_payment).map( | ||||
|                 lambda paid: paid.paid_amount).sum() | ||||
|  | ||||
|         #DIAN 1.7.-2020: FAU14 | ||||
|         # DIAN 1.7.-2020: FAU14 | ||||
|         self.invoice_legal_monetary_total.calculate() | ||||
|  | ||||
|     def _refresh_charges_base_amount(self): | ||||
| @@ -747,18 +792,21 @@ class Invoice: | ||||
|             for invline in self.invoice_lines: | ||||
|                 if invline.allowance_charge: | ||||
|                     # TODO actualmente solo uno de los cargos es permitido | ||||
|                     raise ValueError('allowance charge in invoice exclude invoice line') | ||||
|              | ||||
|                     raise ValueError( | ||||
|                         'allowance charge in invoice exclude invoice line') | ||||
|  | ||||
|         # cargos a nivel de factura | ||||
|         for charge in self.invoice_allowance_charge: | ||||
|             charge.set_base_amount(self.invoice_legal_monetary_total.line_extension_amount) | ||||
|          | ||||
|             charge.set_base_amount( | ||||
|                 self.invoice_legal_monetary_total.line_extension_amount) | ||||
|  | ||||
|     def calculate(self): | ||||
|         for invline in self.invoice_lines: | ||||
|             invline.calculate() | ||||
|         self._calculate_legal_monetary_total() | ||||
|         self._refresh_charges_base_amount() | ||||
|  | ||||
|  | ||||
| class NationalSalesInvoice(Invoice): | ||||
|     def __init__(self): | ||||
|         super().__init__(NationalSalesInvoiceDocumentType()) | ||||
| @@ -774,7 +822,7 @@ class CreditNote(Invoice): | ||||
|  | ||||
|     def _get_codelist_tipo_operacion(self): | ||||
|         return codelist.TipoOperacionNC | ||||
|      | ||||
|  | ||||
|     def _check_ident_prefix(self, prefix): | ||||
|         if len(prefix) != 6: | ||||
|             raise ValueError('prefix must be 6 length') | ||||
| @@ -803,12 +851,15 @@ class DebitNote(Invoice): | ||||
|         if not self.invoice_ident_prefix: | ||||
|             self.invoice_ident_prefix = self.invoice_ident[0:6] | ||||
|  | ||||
|  | ||||
| class SupportDocument(Invoice): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class SupportDocumentCreditNote(SupportDocument): | ||||
|     def __init__(self, invoice_document_reference: BillingReference, | ||||
|                 invoice_discrepancy_response: BillingResponse): | ||||
|     def __init__( | ||||
|             self, invoice_document_reference: BillingReference, | ||||
|             invoice_discrepancy_response: BillingResponse): | ||||
|         super().__init__(CreditNoteSupportDocumentType()) | ||||
|  | ||||
|         if not isinstance(invoice_document_reference, BillingReference): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user