fix test and templates

This commit is contained in:
?ngel ?lvarez 2018-07-08 19:30:21 +02:00
parent 096a933f1a
commit 75b56c5a0d
6 changed files with 136 additions and 59 deletions

View File

@ -12,3 +12,4 @@ class Company:
facturae_certificate = fields.Binary('Factura-e Certificate', facturae_certificate = fields.Binary('Factura-e Certificate',
help='The certificate to generate the XAdES electronic firm for ' help='The certificate to generate the XAdES electronic firm for '
'invoices.') 'invoices.')

View File

@ -18,6 +18,7 @@ from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval from trytond.pyson import Bool, Eval
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.wizard import Wizard, StateView, StateTransition, Button from trytond.wizard import Wizard, StateView, StateTransition, Button
from trytond import backend
__all__ = ['Invoice', 'InvoiceLine', 'CreditInvoiceStart', 'CreditInvoice', __all__ = ['Invoice', 'InvoiceLine', 'CreditInvoiceStart', 'CreditInvoice',
'GenerateFacturaeStart', 'GenerateFacturae'] 'GenerateFacturaeStart', 'GenerateFacturae']
@ -264,8 +265,9 @@ class Invoice:
continue continue
facturae_content = invoice.get_facturae() facturae_content = invoice.get_facturae()
invoice._validate_facturae(facturae_content) invoice._validate_facturae(facturae_content)
invoice.invoice_facturae = invoice._sign_facturae( if backend.name() != 'sqlite':
facturae_content, certificate_password) invoice.invoice_facturae = invoice._sign_facturae(
facturae_content, certificate_password)
to_save.append(invoice) to_save.append(invoice)
if to_save: if to_save:
cls.save(to_save) cls.save(to_save)
@ -301,11 +303,12 @@ class Invoice:
'invoice': self.rec_name, 'invoice': self.rec_name,
'field': field, 'field': field,
}) })
if (not self.company.party.vat_code if (not self.company.party.tax_identifier
or len(self.company.party.vat_code) < 3 or len(self.company.party.tax_identifier.code) < 3
or len(self.company.party.vat_code) > 30): or len(self.company.party.tax_identifier.code) > 30):
self.raise_user_error('company_vat_identifier', self.raise_user_error('company_vat_identifier',
(self.company.party.rec_name,)) (self.company.party.rec_name,))
if (not self.company.party.addresses if (not self.company.party.addresses
or not self.company.party.addresses[0].street or not self.company.party.addresses[0].street
or not self.company.party.addresses[0].zip or not self.company.party.addresses[0].zip
@ -315,9 +318,9 @@ class Invoice:
self.raise_user_error('company_address_fields', self.raise_user_error('company_address_fields',
(self.company.party.rec_name,)) (self.company.party.rec_name,))
if (not self.party.vat_code if (not self.party.tax_identifier
or len(self.party.vat_code) < 3 or len(self.party.tax_identifier.code) < 3
or len(self.party.vat_code) > 30): or len(self.party.tax_identifier.code) > 30):
self.raise_user_error('party_vat_identifier', { self.raise_user_error('party_vat_identifier', {
'party': self.party.rec_name, 'party': self.party.rec_name,
'invoice': self.rec_name, 'invoice': self.rec_name,
@ -408,6 +411,7 @@ class Invoice:
return jinja_template.render({ return jinja_template.render({
'invoice': self, 'invoice': self,
'Decimal': Decimal, 'Decimal': Decimal,
'Currency': Currency,
'euro': euro, 'euro': euro,
'exchange_rate': exchange_rate, 'exchange_rate': exchange_rate,
'exchange_rate_date': exchange_rate_date, 'exchange_rate_date': exchange_rate_date,

View File

@ -49,6 +49,18 @@
<field name="wiz_name">account.invoice.generate_facturae</field> <field name="wiz_name">account.invoice.generate_facturae</field>
<field name="model">account.invoice</field> <field name="model">account.invoice</field>
</record> </record>
<record model="ir.model.button" id="generate_facturae_button">
<field name="name">generate_facturae_wizard</field>
<field name="string">Generate Facturae</field>
<field name="model" search="[('model', '=', 'account.invoice')]"/>
</record>
<record model="ir.model.button-res.group"
id="generate_facturae_button_group_account">
<field name="button" ref="generate_facturae_button"/>
<field name="group" ref="account.group_account"/>
</record>
<!--<record model="ir.action.keyword" id="generate_signed_facturae_keyword"> <!--<record model="ir.action.keyword" id="generate_signed_facturae_keyword">
<field name="keyword">form_action</field> <field name="keyword">form_action</field>
<field name="model">account.invoice,-1</field> <field name="model">account.invoice,-1</field>

View File

@ -7,7 +7,7 @@
<InvoiceIssuerType>EM</InvoiceIssuerType> <InvoiceIssuerType>EM</InvoiceIssuerType>
{# As InvoiceIssuerType != TE, ThirdParty element is not generated #} {# As InvoiceIssuerType != TE, ThirdParty element is not generated #}
<Batch> <Batch>
<BatchIdentifier>{{ ('%s%s' % (invoice.company.party.vat_code, invoice.number))[:70] }}</BatchIdentifier> <BatchIdentifier>{{ ('%s%s' % (invoice.company.party.tax_identifier.code, invoice.number))[:70] }}</BatchIdentifier>
<InvoicesCount>1</InvoicesCount> <InvoicesCount>1</InvoicesCount>
<TotalInvoicesAmount> <TotalInvoicesAmount>
<TotalAmount>{{ invoice.total_amount }}</TotalAmount> <TotalAmount>{{ invoice.total_amount }}</TotalAmount>
@ -29,7 +29,7 @@
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</EquivalentInEuros> <EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</EquivalentInEuros>
{% endif %} {% endif %}
</TotalExecutableAmount> </TotalExecutableAmount>
<InvoiceCurrencyCode>{{ invoice.currency.code }}</InvoiceCurrencyCode> <InvoiceCurrencyCode>{{ invoice.currency.code.upper() }}</InvoiceCurrencyCode>
</Batch> </Batch>
{# FactoryAssignmentData optional: not supported (factoring not supported) #} {# FactoryAssignmentData optional: not supported (factoring not supported) #}
</FileHeader> </FileHeader>
@ -39,7 +39,7 @@
<TaxIdentification> <TaxIdentification>
<PersonTypeCode>{{ invoice.company.party.facturae_person_type }}</PersonTypeCode> <PersonTypeCode>{{ invoice.company.party.facturae_person_type }}</PersonTypeCode>
<ResidenceTypeCode>{{ invoice.company.party.facturae_residence_type }}</ResidenceTypeCode> <ResidenceTypeCode>{{ invoice.company.party.facturae_residence_type }}</ResidenceTypeCode>
<TaxIdentificationNumber>{{ invoice.company.party.vat_code[:30] }}</TaxIdentificationNumber> <TaxIdentificationNumber>{{ invoice.company.party.tax_identifier.code[:30] }}</TaxIdentificationNumber>
</TaxIdentification> </TaxIdentification>
{# Optional. It could be the ID or the code #} {# Optional. It could be the ID or the code #}
{% if invoice.company.party.code and invoice.company.party.code | length < 10 %} {% if invoice.company.party.code and invoice.company.party.code | length < 10 %}
@ -72,7 +72,7 @@
<TaxIdentification> <TaxIdentification>
<PersonTypeCode>{{ invoice.party.facturae_person_type }}</PersonTypeCode> <PersonTypeCode>{{ invoice.party.facturae_person_type }}</PersonTypeCode>
<ResidenceTypeCode>{{ invoice.party.facturae_residence_type }}</ResidenceTypeCode> <ResidenceTypeCode>{{ invoice.party.facturae_residence_type }}</ResidenceTypeCode>
<TaxIdentificationNumber>{{ invoice.party.vat_code[:30] }}</TaxIdentificationNumber> <TaxIdentificationNumber>{{ invoice.party.tax_identifier.code[:30] }}</TaxIdentificationNumber>
</TaxIdentification> </TaxIdentification>
{# Optional. It could be the ID or the code #} {# Optional. It could be the ID or the code #}
{% if invoice.party.code and invoice.party.code | length < 10 %} {% if invoice.party.code and invoice.party.code | length < 10 %}
@ -158,11 +158,11 @@
{# OperationDate required only if is different to IssueDate, but we consider OperatinDate==invoice_date: not supported #} {# OperationDate required only if is different to IssueDate, but we consider OperatinDate==invoice_date: not supported #}
{# PlaceOfIssue optional: not supported #} {# PlaceOfIssue optional: not supported #}
{# InvoicingPeriod required only for Recapitulativas or temporary service: not supported #} {# InvoicingPeriod required only for Recapitulativas or temporary service: not supported #}
<InvoiceCurrencyCode>{{ invoice.currency.code }}</InvoiceCurrencyCode> <InvoiceCurrencyCode>{{ invoice.currency.code.upper() }}</InvoiceCurrencyCode>
{% if invoice.currency != euro %} {% if invoice.currency != euro %}
<ExchangeRateDetails> <ExchangeRateDetails>
<ExchangeRate>{{ exchange_rate_date }}</ExchangeRate> <ExchangeRate>{{ exchange_rate }}</ExchangeRate>
<ExchangeRateDate>{{ exchange_rate_date.isoformat() }}</ExchangeRateDate> <ExchangeRateDate>{{ exchange_rate_date }}</ExchangeRateDate>
</ExchangeRateDetails> </ExchangeRateDetails>
{% endif %} {% endif %}
<TaxCurrencyCode>EUR</TaxCurrencyCode> <TaxCurrencyCode>EUR</TaxCurrencyCode>
@ -255,7 +255,7 @@
- TransactionDate - TransactionDate
- Extensions - Extensions
#} #}
<ItemDescription>{{ line.description[:2500] }}</ItemDescription> <ItemDescription>{{ line.description and line.description[:2500] or '' }}</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>{{ line.unit_price }}</UnitPriceWithoutTax> <UnitPriceWithoutTax>{{ line.unit_price }}</UnitPriceWithoutTax>

View File

@ -29,7 +29,7 @@
{% else %} {% else %}
<OverseasAddress> <OverseasAddress>
<Address>{{ address.street[:80] }}</Address> <Address>{{ address.street[:80] }}</Address>
<PostCodeAndTown>{{ (', '.join(address.zip, address.city))[:50] }}</PostCode> <PostCodeAndTown>{{ (', '.join([address.zip, address.city]))[:50] }}</PostCodeAndTown>
<Province>{{ address.subdivision.name[:20] }}</Province> <Province>{{ address.subdivision.name[:20] }}</Province>
<CountryCode>{{ address.country.code3 }}</CountryCode> <CountryCode>{{ address.country.code3 }}</CountryCode>
</OverseasAddress> </OverseasAddress>

View File

@ -6,12 +6,12 @@ import unittest
from decimal import Decimal from decimal import Decimal
import trytond.tests.test_tryton import trytond.tests.test_tryton
from trytond.pool import Pool from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.tests.test_tryton import ModuleTestCase, with_transaction
from trytond.modules.account.tests import get_fiscalyear from trytond.modules.account.tests import get_fiscalyear, create_chart
from trytond.modules.account_es.tests import create_chart
from trytond.modules.company.tests import create_company, set_company from trytond.modules.company.tests import create_company, set_company
from trytond.modules.account_invoice.tests import set_invoice_sequences from trytond.modules.account_invoice.tests import set_invoice_sequences
from trytond.modules.currency.tests import create_currency, add_currency_rate
CURRENT_PATH = os.path.dirname(os.path.abspath(__file__)) CURRENT_PATH = os.path.dirname(os.path.abspath(__file__))
@ -22,6 +22,7 @@ class TestAccountInvoiceFacturaeCase(ModuleTestCase):
@with_transaction() @with_transaction()
def test_invoice_generation(self): def test_invoice_generation(self):
'Test invoice generation' 'Test invoice generation'
pool = Pool() pool = Pool()
Account = pool.get('account.account') Account = pool.get('account.account')
FiscalYear = pool.get('account.fiscalyear') FiscalYear = pool.get('account.fiscalyear')
@ -29,24 +30,41 @@ class TestAccountInvoiceFacturaeCase(ModuleTestCase):
type='wizard') type='wizard')
Invoice = pool.get('account.invoice') Invoice = pool.get('account.invoice')
InvoiceLine = pool.get('account.invoice.line') InvoiceLine = pool.get('account.invoice.line')
ModelData = pool.get('ir.model.data')
Party = pool.get('party.party') Party = pool.get('party.party')
PaymentTerm = pool.get('account.invoice.payment_term') PaymentTerm = pool.get('account.invoice.payment_term')
ProductUom = pool.get('product.uom') ProductUom = pool.get('product.uom')
ProductTemplate = pool.get('product.template') ProductTemplate = pool.get('product.template')
Product = pool.get('product.product') Product = pool.get('product.product')
Tax = pool.get('account.tax') Tax = pool.get('account.tax')
Address = pool.get('party.address')
PartyIdentifier = pool.get('party.identifier')
Country = pool.get('country.country')
Subdivision = pool.get('country.subdivision')
PaymentType = pool.get('account.payment.type')
revenue_template_id = ModelData.get_id('account_es', 'pgc_7000_child') country = Country(name='Country', code='ES', code3='ESP')
expense_template_id = ModelData.get_id('account_es', 'pgc_600_child') country.save()
vat21_template_id = ModelData.get_id('account_es', 'iva_rep_21') subdivision = Subdivision(
name='Subdivision', country=country, code='SUB', type='area')
subdivision.save()
company = create_company() company = create_company()
currency = create_currency('EUR')
add_currency_rate(currency, 1.0)
tax_identifier = PartyIdentifier()
tax_identifier.type = 'eu_vat'
tax_identifier.code = 'BE0897290877'
company.party.identifiers = [tax_identifier]
company.party.facturae_person_type = 'J'
company.party.facturae_residence_type = 'R'
company.party.save()
company.save()
# Save certificate into company # Save certificate into company
with open(os.path.join( with open(os.path.join(
CURRENT_PATH, 'certificate.pfx'), 'rb') as cert_file: CURRENT_PATH, 'certificate.pfx'), 'rb') as cert_file:
company.facturae_certificate = cert_file.read() company.facturae_certificate = cert_file.read()
company.save()
payment_term, = PaymentTerm.create([{ payment_term, = PaymentTerm.create([{
'name': '20 days, 40 days', 'name': '20 days, 40 days',
@ -79,13 +97,55 @@ class TestAccountInvoiceFacturaeCase(ModuleTestCase):
fiscalyear.save() fiscalyear.save()
FiscalYear.create_period([fiscalyear]) FiscalYear.create_period([fiscalyear])
revenue, = Account.search([('template', '=', revenue_template_id)]) payment_receivable, = PaymentType.create([{
expense, = Account.search([('template', '=', expense_template_id)]) 'name': 'Payment Receivable',
vat21, = Tax.search([('template', '=', vat21_template_id)]) 'kind': 'receivable',
'company': company.id,
'facturae_type': '01',
}])
revenue, = Account.search([('kind', '=', 'revenue')])
expense, = Account.search([('kind', '=', 'expense')])
tax_account, = Account.search([
('name', '=', 'Main Tax'),
])
with Transaction().set_user(0):
vat21 = Tax()
vat21.name = vat21.description = '21% VAT'
vat21.type = 'percentage'
vat21.rate = Decimal('0.21')
vat21.invoice_account = tax_account
vat21.report_type = '05'
vat21.credit_note_account = tax_account
vat21.save()
company_address, = company.party.addresses
company_address.street = 'street'
company_address.zip = '08201'
company_address.city = 'City'
company_address.subdivision = subdivision
company_address.country = country
company_address.save()
party = Party(name='Party') party = Party(name='Party')
party.facturae_person_type = 'J'
party.facturae_residence_type = 'R'
tax_identifier = PartyIdentifier()
tax_identifier.type = 'eu_vat'
tax_identifier.code = 'BE0897290877'
party.identifiers = [tax_identifier]
party.save() party.save()
address_dict = {
'party': party.id,
'street': 'St sample, 15',
'city': 'City',
'zip': '08201',
'subdivision': subdivision.id,
'country': country.id,
}
address, = Address.create([address_dict])
term, = PaymentTerm.create([{ term, = PaymentTerm.create([{
'name': 'Payment term', 'name': 'Payment term',
'lines': [ 'lines': [
@ -116,43 +176,43 @@ class TestAccountInvoiceFacturaeCase(ModuleTestCase):
product.template = template product.template = template
product.save() product.save()
invoice = Invoice() currency = create_currency('Eur')
invoice.type = 'out' add_currency_rate(currency, 1)
invoice.on_change_type()
invoice.party = party
invoice.on_change_party()
invoice.payment_term = term
line1 = InvoiceLine() with Transaction().set_user(0):
line1.product = product invoice = Invoice()
line1.on_change_product() invoice.type = 'out'
line1.on_change_account() invoice.on_change_type()
line1.quantity = 5 invoice.party = party
line1.unit_price = Decimal('40') invoice.on_change_party()
invoice.payment_type = payment_receivable
invoice.payment_term = term
invoice.currency = currency
invoice.company = company
line2 = InvoiceLine() line1 = InvoiceLine()
line2.account = revenue line1.product = product
line2.on_change_account() line1.on_change_product()
line2.description = 'Test' line1.on_change_account()
line2.quantity = 1 line1.quantity = 5
line2.unit_price = Decimal(20) line1.unit_price = Decimal('40')
invoice.lines = [line1, line2] line2 = InvoiceLine()
invoice.on_change_lines() line2.account = revenue
invoice.save() line2.on_change_account()
# invoice.untaxed_amount == Decimal('220.00') line2.product = product
# invoice.tax_amount == Decimal('20.00') line2.on_change_product()
# invoice.total_amount == Decimal('240.00') line2.description = 'Test'
line2.quantity = 1
line2.unit_price = Decimal(20)
Invoice.post([invoice]) invoice.lines = [line1, line2]
invoice.on_change_lines()
session_id, _, _ = GenerateSignedFacturae.create() invoice.save()
generate_signed_facturae = GenerateSignedFacturae(session_id) Invoice.post([invoice])
generate_signed_facturae.account.certificate_password = (
'privatepassword')
generate_signed_facturae.transition_generate()
self.assertIsNotNone(invoice.invoice_facturae) Invoice.generate_facturae_default([invoice], 'privatepassword')
def suite(): def suite():