parent
f100e5a156
commit
04cfc5a47c
21
invoice.py
21
invoice.py
|
@ -9,6 +9,7 @@ import random
|
||||||
import xmlsig
|
import xmlsig
|
||||||
import hashlib
|
import hashlib
|
||||||
import datetime
|
import datetime
|
||||||
|
import math
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
@ -297,6 +298,7 @@ class Invoice(metaclass=PoolMeta):
|
||||||
"""Return the content to render in factura-e XML file"""
|
"""Return the content to render in factura-e XML file"""
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
Currency = pool.get('currency.currency')
|
Currency = pool.get('currency.currency')
|
||||||
|
Invoice = pool.get('account.invoice')
|
||||||
Date = pool.get('ir.date')
|
Date = pool.get('ir.date')
|
||||||
Rate = pool.get('currency.currency.rate')
|
Rate = pool.get('currency.currency.rate')
|
||||||
|
|
||||||
|
@ -436,6 +438,7 @@ class Invoice(metaclass=PoolMeta):
|
||||||
'invoice': self,
|
'invoice': self,
|
||||||
'Decimal': Decimal,
|
'Decimal': Decimal,
|
||||||
'Currency': Currency,
|
'Currency': Currency,
|
||||||
|
'Invoice': Invoice,
|
||||||
'euro': euro,
|
'euro': euro,
|
||||||
'exchange_rate': exchange_rate,
|
'exchange_rate': exchange_rate,
|
||||||
'exchange_rate_date': exchange_rate_date,
|
'exchange_rate_date': exchange_rate_date,
|
||||||
|
@ -718,6 +721,24 @@ class Invoice(metaclass=PoolMeta):
|
||||||
|
|
||||||
return signed_file_content
|
return signed_file_content
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def double_up_to_eight(cls, value):
|
||||||
|
# return max 8 digits in DoubleUpToEightDecimalType
|
||||||
|
_TOTAL_DIGITS = 8
|
||||||
|
def digits_decimal(value):
|
||||||
|
num_str = str(value)
|
||||||
|
if '.' in num_str:
|
||||||
|
num_digits = num_str[::-1].find('.')
|
||||||
|
else:
|
||||||
|
num_digits = 0
|
||||||
|
|
||||||
|
return num_digits
|
||||||
|
|
||||||
|
if digits_decimal(value) > _TOTAL_DIGITS:
|
||||||
|
precision = 10 ** -_TOTAL_DIGITS
|
||||||
|
return math.floor(float(value) / precision) * precision
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class InvoiceLine(metaclass=PoolMeta):
|
class InvoiceLine(metaclass=PoolMeta):
|
||||||
__name__ = 'account.invoice.line'
|
__name__ = 'account.invoice.line'
|
||||||
|
|
|
@ -161,7 +161,7 @@
|
||||||
<InvoiceCurrencyCode>{{ invoice.currency.code.upper() }}</InvoiceCurrencyCode>
|
<InvoiceCurrencyCode>{{ invoice.currency.code.upper() }}</InvoiceCurrencyCode>
|
||||||
{% if invoice.currency != euro %}
|
{% if invoice.currency != euro %}
|
||||||
<ExchangeRateDetails>
|
<ExchangeRateDetails>
|
||||||
<ExchangeRate>{{ Currency.compute(invoice.currency, exchange_rate, euro) }}</ExchangeRate>
|
<ExchangeRate>{{ Invoice.double_up_to_eight(exchange_rate) }}</ExchangeRate>
|
||||||
<ExchangeRateDate>{{ exchange_rate_date }}</ExchangeRateDate>
|
<ExchangeRateDate>{{ exchange_rate_date }}</ExchangeRateDate>
|
||||||
</ExchangeRateDetails>
|
</ExchangeRateDetails>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -173,15 +173,15 @@
|
||||||
{% for invoice_tax in invoice.taxes_outputs %}
|
{% for invoice_tax in invoice.taxes_outputs %}
|
||||||
<Tax>
|
<Tax>
|
||||||
<TaxTypeCode>{{ invoice_tax.tax.report_type }}</TaxTypeCode>
|
<TaxTypeCode>{{ invoice_tax.tax.report_type }}</TaxTypeCode>
|
||||||
<TaxRate>{{ Currency.compute(invoice.currency, invoice_tax.tax.rate * 100, euro) }}</TaxRate>
|
<TaxRate>{{ Invoice.double_up_to_eight(invoice_tax.tax.rate * 100) }}</TaxRate>
|
||||||
<TaxableBase>
|
<TaxableBase>
|
||||||
<TotalAmount>{{ Currency.compute(invoice.currency, invoice_tax.base, euro) }}</TotalAmount>
|
<TotalAmount>{{ Invoice.double_up_to_eight(invoice_tax.base) }}</TotalAmount>
|
||||||
{% if invoice.currency != euro %}
|
{% if invoice.currency != euro %}
|
||||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.base, euro) }}</EquivalentInEuros>
|
<EquivalentInEuros>{{ Invoice.double_up_to_eight(invoice_tax.base) }}</EquivalentInEuros>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</TaxableBase>
|
</TaxableBase>
|
||||||
<TaxAmount>
|
<TaxAmount>
|
||||||
<TotalAmount>{{ Currency.compute(invoice.currency, invoice_tax.amount, euro) }}</TotalAmount>
|
<TotalAmount>{{ Invoice.double_up_to_eight(invoice_tax.amount) }}</TotalAmount>
|
||||||
{% if invoice.currency != euro %}
|
{% if invoice.currency != euro %}
|
||||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.amount, euro) }}</EquivalentInEuros>
|
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.amount, euro) }}</EquivalentInEuros>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -208,7 +208,7 @@
|
||||||
{% for invoice_tax in invoice.taxes_withheld %}
|
{% for invoice_tax in invoice.taxes_withheld %}
|
||||||
<Tax>
|
<Tax>
|
||||||
<TaxTypeCode>{{ invoice_tax.tax.report_type }}</TaxTypeCode>
|
<TaxTypeCode>{{ invoice_tax.tax.report_type }}</TaxTypeCode>
|
||||||
<TaxRate>{{ Currency.compute(invoice.currency, invoice_tax.tax.rate * 100, euro) }}</TaxRate>
|
<TaxRate>{{ Invoice.double_up_to_eight(invoice_tax.tax.rate * 100) }}</TaxRate>
|
||||||
<TaxableBase>
|
<TaxableBase>
|
||||||
<TotalAmount>{{ Currency.compute(invoice.currency, invoice_tax.base, euro) }}</TotalAmount>
|
<TotalAmount>{{ Currency.compute(invoice.currency, invoice_tax.base, euro) }}</TotalAmount>
|
||||||
{% if invoice.currency != euro %}
|
{% if invoice.currency != euro %}
|
||||||
|
@ -226,13 +226,13 @@
|
||||||
</TaxesWithheld>
|
</TaxesWithheld>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<InvoiceTotals>
|
<InvoiceTotals>
|
||||||
<TotalGrossAmount>{{ Currency.compute(invoice.currency, invoice.untaxed_amount, euro) }}</TotalGrossAmount>
|
<TotalGrossAmount>{{ Invoice.double_up_to_eight(invoice.untaxed_amount) }}</TotalGrossAmount>
|
||||||
{# TODO: GeneralDiscounts and TotalGeneralDiscounts (account_invoice_discount_global) not supported #}
|
{# TODO: GeneralDiscounts and TotalGeneralDiscounts (account_invoice_discount_global) not supported #}
|
||||||
{# TODO: GeneralSurcharges and TotalGeneralSurcharges not supported #}
|
{# TODO: GeneralSurcharges and TotalGeneralSurcharges not supported #}
|
||||||
<TotalGrossAmountBeforeTaxes>{{ Currency.compute(invoice.currency, invoice.untaxed_amount, euro) }}</TotalGrossAmountBeforeTaxes>
|
<TotalGrossAmountBeforeTaxes>{{ Invoice.double_up_to_eight(invoice.untaxed_amount) }}</TotalGrossAmountBeforeTaxes>
|
||||||
<TotalTaxOutputs>{{ Currency.compute(invoice.currency, invoice.taxes_outputs | sum(attribute='amount', start=Decimal(0)), euro) }}</TotalTaxOutputs>
|
<TotalTaxOutputs>{{ Invoice.double_up_to_eight(invoice.taxes_outputs | sum(attribute='amount', start=Decimal(0))) }}</TotalTaxOutputs>
|
||||||
<TotalTaxesWithheld>{{ Currency.compute(invoice.currency, invoice.taxes_withheld | sum(attribute='amount', start=Decimal(0)), euro) }}</TotalTaxesWithheld>
|
<TotalTaxesWithheld>{{ Invoice.double_up_to_eight(invoice.taxes_withheld | sum(attribute='amount', start=Decimal(0))) }}</TotalTaxesWithheld>
|
||||||
<InvoiceTotal>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</InvoiceTotal>
|
<InvoiceTotal>{{ Invoice.double_up_to_eight(invoice.total_amount) }}</InvoiceTotal>
|
||||||
{# TODO: optional, not supported
|
{# TODO: optional, not supported
|
||||||
- Subsidies
|
- Subsidies
|
||||||
- PaymentsOnAccount, TotalPaymentsOnAccount
|
- PaymentsOnAccount, TotalPaymentsOnAccount
|
||||||
|
@ -240,8 +240,8 @@
|
||||||
- TotalFinancialExpenses (account_payment_type_cost?)
|
- TotalFinancialExpenses (account_payment_type_cost?)
|
||||||
- AmountsWithheld
|
- AmountsWithheld
|
||||||
#}
|
#}
|
||||||
<TotalOutstandingAmount>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</TotalOutstandingAmount>
|
<TotalOutstandingAmount>{{ Invoice.double_up_to_eight(invoice.total_amount) }}</TotalOutstandingAmount>
|
||||||
<TotalExecutableAmount>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</TotalExecutableAmount>
|
<TotalExecutableAmount>{{ Invoice.double_up_to_eight(invoice.total_amount) }}</TotalExecutableAmount>
|
||||||
</InvoiceTotals>
|
</InvoiceTotals>
|
||||||
<Items>
|
<Items>
|
||||||
{% for line in invoice.lines if line.type == 'line' %}
|
{% for line in invoice.lines if line.type == 'line' %}
|
||||||
|
@ -258,19 +258,19 @@
|
||||||
<ItemDescription>{{ line.facturae_item_description }}</ItemDescription>
|
<ItemDescription>{{ line.facturae_item_description }}</ItemDescription>
|
||||||
<Quantity>{{ line.quantity }}</Quantity>
|
<Quantity>{{ line.quantity }}</Quantity>
|
||||||
<UnitOfMeasure>{{ UOM_CODE2TYPE.get(line.unit.symbol, '05') if line.unit else '05' }}</UnitOfMeasure>
|
<UnitOfMeasure>{{ UOM_CODE2TYPE.get(line.unit.symbol, '05') if line.unit else '05' }}</UnitOfMeasure>
|
||||||
<UnitPriceWithoutTax>{{ Currency.compute(invoice.currency, line.unit_price, euro) }}</UnitPriceWithoutTax>
|
<UnitPriceWithoutTax>{{ Invoice.double_up_to_eight(line.unit_price) }}</UnitPriceWithoutTax>
|
||||||
<TotalCost>{{ Currency.compute(invoice.currency, line.amount, euro) }}</TotalCost>
|
<TotalCost>{{ Invoice.double_up_to_eight(line.amount) }}</TotalCost>
|
||||||
{# TODO: optional, not supported
|
{# TODO: optional, not supported
|
||||||
- DiscountsAndRebates (account_invoice_discount)
|
- DiscountsAndRebates (account_invoice_discount)
|
||||||
- Charges
|
- Charges
|
||||||
#}
|
#}
|
||||||
<GrossAmount>{{ Currency.compute(invoice.currency, line.amount, euro) }}</GrossAmount>
|
<GrossAmount>{{ Invoice.double_up_to_eight(line.amount) }}</GrossAmount>
|
||||||
{% if line.taxes_withheld %}
|
{% if line.taxes_withheld %}
|
||||||
<TaxesWithheld>
|
<TaxesWithheld>
|
||||||
{% for line_tax in invoice.taxes_withheld %}
|
{% for line_tax in invoice.taxes_withheld %}
|
||||||
<Tax>
|
<Tax>
|
||||||
<TaxTypeCode>{{ line_tax.tax.report_type }}</TaxTypeCode>
|
<TaxTypeCode>{{ line_tax.tax.report_type }}</TaxTypeCode>
|
||||||
<TaxRate>{{ Currency.compute(invoice.currency, line_tax.tax.rate * 100, euro) }}</TaxRate>
|
<TaxRate>{{ Invoice.double_up_to_eight(line_tax.tax.rate * 100) }}</TaxRate>
|
||||||
<TaxableBase>
|
<TaxableBase>
|
||||||
<TotalAmount>{{ Currency.compute(invoice.currency, line.amount, euro) }}</TotalAmount>
|
<TotalAmount>{{ Currency.compute(invoice.currency, line.amount, euro) }}</TotalAmount>
|
||||||
{% if invoice.currency != euro %}
|
{% if invoice.currency != euro %}
|
||||||
|
|
Loading…
Reference in New Issue