style(__init__): Formateado PEP8
This commit is contained in:
parent
a0321020c7
commit
f08954ee43
@ -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,8 +57,11 @@ class AmountCollection(Collection):
|
||||
total += v
|
||||
return total
|
||||
|
||||
|
||||
class Amount:
|
||||
def __init__(self, amount: int or float or str or Amount, currency: Currency = Currency('COP')):
|
||||
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):
|
||||
@ -65,7 +74,9 @@ class Amount:
|
||||
if float(amount) < 0:
|
||||
raise ValueError('amount must be positive >= 0')
|
||||
|
||||
self.amount = Decimal(amount, decimal.Context(prec=DECIMAL_PRECISION,
|
||||
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
|
||||
@ -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]:
|
||||
@ -151,6 +163,7 @@ class Quantity:
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Item:
|
||||
scheme_name: 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
|
||||
@ -357,6 +380,7 @@ class WithholdingTaxTotal:
|
||||
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'
|
||||
@ -399,12 +425,14 @@ class PrePaidPayment:
|
||||
# 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):
|
||||
@ -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))
|
||||
@ -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):
|
||||
"""
|
||||
@ -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,27 +757,32 @@ 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
|
||||
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.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)\
|
||||
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)\
|
||||
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()
|
||||
self.invoice_legal_monetary_total.prepaid_amount = AmountCollection(
|
||||
self.invoice_prepaid_payment).map(
|
||||
lambda paid: paid.paid_amount).sum()
|
||||
|
||||
# DIAN 1.7.-2020: FAU14
|
||||
self.invoice_legal_monetary_total.calculate()
|
||||
@ -747,11 +792,13 @@ 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:
|
||||
@ -759,6 +806,7 @@ class Invoice:
|
||||
self._calculate_legal_monetary_total()
|
||||
self._refresh_charges_base_amount()
|
||||
|
||||
|
||||
class NationalSalesInvoice(Invoice):
|
||||
def __init__(self):
|
||||
super().__init__(NationalSalesInvoiceDocumentType())
|
||||
@ -803,11 +851,14 @@ 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,
|
||||
def __init__(
|
||||
self, invoice_document_reference: BillingReference,
|
||||
invoice_discrepancy_response: BillingResponse):
|
||||
super().__init__(CreditNoteSupportDocumentType())
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user