274 lines
9.7 KiB
Python
274 lines
9.7 KiB
Python
from invoice_base import *
|
|||
|
|
|
||
|
|
class Invoice(BaseInvoice):
|
||
|
|
def __str__(self):
|
||
|
|
taxestotal = ''
|
||
|
|
for x in self.taxes:
|
||
|
|
taxestotal += str(x)
|
||
|
|
allarticles = ''
|
||
|
|
for a in self.articles:
|
||
|
|
allarticles += str(a)
|
||
|
|
alltenders = ''
|
||
|
|
for t in self.tenders:
|
||
|
|
alltenders += str(t)
|
||
|
|
|
||
|
|
xml = f'''<?xml version="1.0" encoding="UTF-8"?>
|
||
|
|
<Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||
|
|
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
|
||
|
|
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||
|
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
|
||
|
|
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
||
|
|
<cbc:ID>{self.nr}</cbc:ID>
|
||
|
|
<cbc:IssueDate>{self.receipt.year}-{self.receipt.month}-{self.receipt.day}</cbc:IssueDate>
|
||
|
|
<cbc:DueDate>{self.receipt.year}-{self.receipt.month}-{self.receipt.day}</cbc:DueDate>
|
||
|
|
<cbc:InvoiceTypeCode>388</cbc:InvoiceTypeCode> <!-- invoice for tax purposes -->
|
||
|
|
<cbc:DocumentCurrencyCode>{self.currency()}</cbc:DocumentCurrencyCode>
|
||
|
|
<!--cbc:AccountingCost>4025:123:4343</cbc:AccountingCost-->
|
||
|
|
<cbc:BuyerReference>{self.receipt.store}{self.receipt.year}{self.receipt.month}{self.receipt.day}{self.receipt.till}{self.receipt.seq.zfill(6)}</cbc:BuyerReference>
|
||
|
|
|
||
|
|
{self.seller}
|
||
|
|
|
||
|
|
{self.buyer}
|
||
|
|
|
||
|
|
{alltenders}
|
||
|
|
|
||
|
|
<cac:PaymentTerms>
|
||
|
|
<cbc:Note>{self.receipt.year}-{self.receipt.month}-{self.receipt.day}</cbc:Note>
|
||
|
|
</cac:PaymentTerms>
|
||
|
|
|
||
|
|
{self.totals}
|
||
|
|
|
||
|
|
<cac:TaxTotal>
|
||
|
|
<cbc:TaxAmount currencyID="{self.currency()}">{self.total_taxes():.2f}</cbc:TaxAmount>
|
||
|
|
{taxestotal}
|
||
|
|
</cac:TaxTotal>
|
||
|
|
{allarticles}
|
||
|
|
</Invoice>
|
||
|
|
'''
|
||
|
|
result = ""
|
||
|
|
|
||
|
|
|
||
|
|
result += xml
|
||
|
|
# if self.seller:
|
||
|
|
# result += str(self.seller)
|
||
|
|
# else:
|
||
|
|
# result += "[ == no country / PVH-ofice found ==]\n"
|
||
|
|
# if self.buyer:
|
||
|
|
# result += str(self.buyer)
|
||
|
|
# for a in self.articles:
|
||
|
|
# result += str(a)
|
||
|
|
# for t in self.tenders:
|
||
|
|
# result += str(t)
|
||
|
|
|
||
|
|
return result
|
||
|
|
|
||
|
|
class Discount(BaseDiscount):
|
||
|
|
def __str__(self):
|
||
|
|
return f'''
|
||
|
|
<cac:AllowanceCharge>
|
||
|
|
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||
|
|
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
|
||
|
|
<cbc:AllowanceChargeReason>{self.promotionID}</cbc:AllowanceChargeReason>
|
||
|
|
<cbc:Amount currencyID="{self.currency()}">{self.net_amount():.2f}</cbc:Amount>
|
||
|
|
</cac:AllowanceCharge>
|
||
|
|
'''
|
||
|
|
|
||
|
|
class Tax(BaseTax):
|
||
|
|
spaces = 'tax'
|
||
|
|
|
||
|
|
#### TODO translation pls note self.country is always XX
|
||
|
|
def translated_group(self):
|
||
|
|
result = 'S' # peppol: S: standard
|
||
|
|
p = float(self.percentage)
|
||
|
|
if p < 18.0:
|
||
|
|
result = 'AA' # lower rate
|
||
|
|
if p <0.01:
|
||
|
|
result = 'E' # zero rate
|
||
|
|
return result
|
||
|
|
|
||
|
|
def __str__(self):
|
||
|
|
return f"{self.spaces},{self.typesubtype},{self.code},{self.amount},{self.percentage}%,{self.translated_group()},{self.taxableamount}\n"
|
||
|
|
|
||
|
|
class TotalTax(Tax):
|
||
|
|
def __str__(self):
|
||
|
|
return f'''
|
||
|
|
<cac:TaxSubtotal>
|
||
|
|
<cbc:TaxableAmount currencyID="{self.currency()}">{self.taxableamount:.2f}</cbc:TaxableAmount>
|
||
|
|
<cbc:TaxAmount currencyID="{self.currency()}">{self.amount:.2f}</cbc:TaxAmount>
|
||
|
|
<cac:TaxCategory>
|
||
|
|
<cbc:ID>{self.translated_group()}</cbc:ID>
|
||
|
|
<cbc:Percent>{self.percentage}</cbc:Percent>
|
||
|
|
<cac:TaxScheme>
|
||
|
|
<cbc:ID>VAT</cbc:ID>
|
||
|
|
</cac:TaxScheme>
|
||
|
|
</cac:TaxCategory>
|
||
|
|
</cac:TaxSubtotal>
|
||
|
|
'''
|
||
|
|
|
||
|
|
class Header(BaseHeader):
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
class Totals(BaseTotals):
|
||
|
|
def __str__(self):
|
||
|
|
return f'''
|
||
|
|
<cac:LegalMonetaryTotal>
|
||
|
|
<cbc:LineExtensionAmount currencyID="{self.currency()}">{self.netAmount:.2f}</cbc:LineExtensionAmount>
|
||
|
|
<cbc:TaxExclusiveAmount currencyID="{self.currency()}">{self.netAmount:.2f}</cbc:TaxExclusiveAmount>
|
||
|
|
<cbc:TaxInclusiveAmount currencyID="{self.currency()}">{self.grandAmount:.2f}</cbc:TaxInclusiveAmount>
|
||
|
|
<!--cbc:ChargeTotalAmount currencyID="{self.currency()}">0</cbc:ChargeTotalAmount-->
|
||
|
|
<cbc:PayableAmount currencyID="{self.currency()}">{self.grandAmount:.2f}</cbc:PayableAmount>
|
||
|
|
</cac:LegalMonetaryTotal>
|
||
|
|
'''
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
class Receipt(BaseReceipt):
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
class Buyer(BaseBuyer):
|
||
|
|
def __str__(self):
|
||
|
|
return f'''
|
||
|
|
<cac:AccountingCustomerParty>
|
||
|
|
<cac:Party>
|
||
|
|
<cbc:EndpointID schemeID="{self.scheme}">{self.orgid}</cbc:EndpointID>
|
||
|
|
<!--cac:PartyIdentification>
|
||
|
|
<cbc:ID schemeID="0002">FR23342</cbc:ID>
|
||
|
|
</cac:PartyIdentification-->
|
||
|
|
<cac:PartyName>
|
||
|
|
<cbc:Name>{self.name}</cbc:Name>
|
||
|
|
</cac:PartyName>
|
||
|
|
<cac:PostalAddress>
|
||
|
|
<cbc:StreetName>{self.street1}</cbc:StreetName>
|
||
|
|
<cbc:AdditionalStreetName>{self.street2}</cbc:AdditionalStreetName>
|
||
|
|
<cbc:CityName>{self.city}</cbc:CityName>
|
||
|
|
<cbc:PostalZone>{self.zip}</cbc:PostalZone>
|
||
|
|
<cac:Country>
|
||
|
|
<cbc:IdentificationCode>{self.country}</cbc:IdentificationCode>
|
||
|
|
</cac:Country>
|
||
|
|
</cac:PostalAddress>
|
||
|
|
<cac:PartyTaxScheme>
|
||
|
|
<cbc:CompanyID>{self.taxID}</cbc:CompanyID>
|
||
|
|
<cac:TaxScheme>
|
||
|
|
<cbc:ID>tax</cbc:ID>
|
||
|
|
</cac:TaxScheme>
|
||
|
|
</cac:PartyTaxScheme>
|
||
|
|
<cac:PartyLegalEntity>
|
||
|
|
<cbc:RegistrationName>{self.name}</cbc:RegistrationName>
|
||
|
|
<cbc:CompanyID schemeID="0183">{self.orgid}</cbc:CompanyID>
|
||
|
|
</cac:PartyLegalEntity>
|
||
|
|
<cac:Contact>
|
||
|
|
<cbc:Name>{self.name}</cbc:Name>
|
||
|
|
<cbc:Telephone>{self.phone}</cbc:Telephone>
|
||
|
|
<cbc:ElectronicMail>{self.email}</cbc:ElectronicMail>
|
||
|
|
</cac:Contact>
|
||
|
|
</cac:Party>
|
||
|
|
</cac:AccountingCustomerParty>
|
||
|
|
'''
|
||
|
|
|
||
|
|
class Delivery():
|
||
|
|
pass
|
||
|
|
|
||
|
|
class Seller(BaseSeller):
|
||
|
|
def __str__(self):
|
||
|
|
return f'''
|
||
|
|
<cac:AccountingSupplierParty>
|
||
|
|
<cac:Party>
|
||
|
|
<cbc:EndpointID schemeID="{self.scheme}">{self.orgid}</cbc:EndpointID>
|
||
|
|
<!--cac:PartyIdentification>
|
||
|
|
<cbc:ID>99887766</cbc:ID>
|
||
|
|
</cac:PartyIdentification-->
|
||
|
|
<cac:PartyName>
|
||
|
|
<cbc:Name>{self.name}</cbc:Name>
|
||
|
|
</cac:PartyName>
|
||
|
|
<cac:PostalAddress>
|
||
|
|
<cbc:StreetName>{self.street1}</cbc:StreetName>
|
||
|
|
<cbc:AdditionalStreetName>{self.street2}</cbc:AdditionalStreetName>
|
||
|
|
<cbc:CityName>{self.city}</cbc:CityName>
|
||
|
|
<cbc:PostalZone>{self.zip}</cbc:PostalZone>
|
||
|
|
<cac:Country>
|
||
|
|
<cbc:IdentificationCode>{self.country}</cbc:IdentificationCode>
|
||
|
|
</cac:Country>
|
||
|
|
</cac:PostalAddress>
|
||
|
|
<cac:PartyTaxScheme>
|
||
|
|
<cbc:CompanyID>{self.taxID}</cbc:CompanyID>
|
||
|
|
<cac:TaxScheme>
|
||
|
|
<cbc:ID>tax</cbc:ID>
|
||
|
|
</cac:TaxScheme>
|
||
|
|
</cac:PartyTaxScheme>
|
||
|
|
<cac:PartyLegalEntity>
|
||
|
|
<cbc:RegistrationName>{self.name}</cbc:RegistrationName>
|
||
|
|
<cbc:CompanyID>{self.orgid}</cbc:CompanyID>
|
||
|
|
</cac:PartyLegalEntity>
|
||
|
|
</cac:Party>
|
||
|
|
</cac:AccountingSupplierParty>
|
||
|
|
'''
|
||
|
|
|
||
|
|
class Tender(BaseTender):
|
||
|
|
|
||
|
|
def translate(self, code):
|
||
|
|
return '54' # credit card
|
||
|
|
|
||
|
|
def __str__(self):
|
||
|
|
return f'''
|
||
|
|
<cac:PaymentMeans>
|
||
|
|
<cbc:PaymentMeansCode name="{self.description}">{self.type}</cbc:PaymentMeansCode>
|
||
|
|
<!--cbc:PaymentID></cbc:PaymentID>
|
||
|
|
<cac:PayeeFinancialAccount>
|
||
|
|
<cbc:ID></cbc:ID>
|
||
|
|
<cbc:Name></cbc:Name>
|
||
|
|
<cac:FinancialInstitutionBranch>
|
||
|
|
<cbc:ID></cbc:ID>
|
||
|
|
</cac:FinancialInstitutionBranch>
|
||
|
|
</cac:PayeeFinancialAccount-->
|
||
|
|
</cac:PaymentMeans>
|
||
|
|
'''
|
||
|
|
|
||
|
|
class Article(BaseArticle):
|
||
|
|
def __str__(self):
|
||
|
|
discounts = ''
|
||
|
|
for d in self.discounts:
|
||
|
|
discounts += str(d)
|
||
|
|
|
||
|
|
return f'''
|
||
|
|
<cac:InvoiceLine>
|
||
|
|
<cbc:ID>{self.sequence}</cbc:ID>
|
||
|
|
<cbc:InvoicedQuantity unitCode="H87">{'-' if self.returnflag else ''}{self.quantity}</cbc:InvoicedQuantity>
|
||
|
|
<cbc:LineExtensionAmount currencyID="{self.currency()}">{'-' if self.returnflag else ''}{self.netSalesPrice():.2f}</cbc:LineExtensionAmount>
|
||
|
|
<!--cbc:AccountingCost>Konteringsstreng</cbc:AccountingCost-->
|
||
|
|
<!--cac:OrderLineReference>
|
||
|
|
<cbc:LineID>123</cbc:LineID>
|
||
|
|
</cac:OrderLineReference -->
|
||
|
|
{discounts}
|
||
|
|
<cac:Item>
|
||
|
|
<cbc:Description>{self.description}</cbc:Description>
|
||
|
|
<cbc:Name>{self.description}</cbc:Name>
|
||
|
|
<cac:SellersItemIdentification>
|
||
|
|
<cbc:ID>{self.itemid}</cbc:ID>
|
||
|
|
</cac:SellersItemIdentification>
|
||
|
|
<!-- cac:StandardItemIdentification>
|
||
|
|
<cbc:ID schemeID="0088">21382183120983</cbc:ID>
|
||
|
|
</cac:StandardItemIdentification -->
|
||
|
|
<!-- cac:OriginCountry>
|
||
|
|
<cbc:IdentificationCode>NO</cbc:IdentificationCode>
|
||
|
|
</cac:OriginCountry -->
|
||
|
|
<cac:CommodityClassification>
|
||
|
|
<cbc:ItemClassificationCode listID="AL">{self.upc}</cbc:ItemClassificationCode>
|
||
|
|
</cac:CommodityClassification>
|
||
|
|
<cac:ClassifiedTaxCategory>
|
||
|
|
<cbc:ID>{self.tax.translated_group()}</cbc:ID>
|
||
|
|
<cbc:Percent>{self.tax.percentage}</cbc:Percent>
|
||
|
|
<cac:TaxScheme>
|
||
|
|
<cbc:ID>VAT</cbc:ID>
|
||
|
|
</cac:TaxScheme>
|
||
|
|
</cac:ClassifiedTaxCategory>
|
||
|
|
</cac:Item>
|
||
|
|
<cac:Price>
|
||
|
|
<cbc:PriceAmount currencyID="{self.currency()}">{self.netBasePrice():.2f}</cbc:PriceAmount>
|
||
|
|
</cac:Price>
|
||
|
|
</cac:InvoiceLine>
|
||
|
|
'''
|