diff --git a/CHANGELOG b/CHANGELOG index b285ff27d3..8c8c2fbab0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add Spanish VAT list and EC Operation List * Add amount to compensate from previous periods in 303 report * Update model 303 to new format diff --git a/__init__.py b/__init__.py index 61a7b99e32..3ba6f55df8 100644 --- a/__init__.py +++ b/__init__.py @@ -2,6 +2,7 @@ # this repository contains the full copyright notices and license terms. from trytond.pool import Pool from . import account +from . import party from . import reporting_tax @@ -10,11 +11,20 @@ def register(): reporting_tax.PrintAEATStart, account.TaxCodeTemplate, account.TaxCode, + account.TaxTemplate, + account.Tax, + party.Party, + reporting_tax.ESVATList, + reporting_tax.ESVATListContext, + reporting_tax.ECOperationList, + reporting_tax.ECOperationListContext, module='account_es', type_='model') Pool.register( reporting_tax.AEAT111, reporting_tax.AEAT115, reporting_tax.AEAT303, + reporting_tax.AEAT347, + reporting_tax.AEAT349, module='account_es', type_='report') Pool.register( reporting_tax.PrintAEAT, diff --git a/account.py b/account.py index c217d76ba3..b756667fe3 100644 --- a/account.py +++ b/account.py @@ -4,7 +4,7 @@ from trytond.model import fields from trytond.pool import PoolMeta from trytond.pyson import Bool, Eval -__all__ = ['TaxCodeTemplate', 'TaxCode'] +__all__ = ['TaxCodeTemplate', 'TaxCode', 'TaxTemplate', 'Tax'] class TaxCodeTemplate(metaclass=PoolMeta): @@ -37,3 +37,34 @@ class TaxCode(metaclass=PoolMeta): & ~Eval('template_override', False)), }, depends=['template', 'template_override']) + + +class TaxTemplate(metaclass=PoolMeta): + __name__ = 'account.tax.template' + + es_vat_list_code = fields.Char("Spanish VAT List Code") + es_ec_purchases_list_code = fields.Char("Spanish EC Purchase List Code") + + def _get_tax_value(self, tax=None): + value = super()._get_tax_value(tax=tax) + for name in ['es_vat_list_code', 'es_ec_purchases_list_code']: + if not tax or getattr(tax, name) != getattr(self, name): + value[name] = getattr(self, name) + return value + + +class Tax(metaclass=PoolMeta): + __name__ = 'account.tax' + + es_vat_list_code = fields.Char("Spanish VAT List Code", + states={ + 'readonly': (Bool(Eval('template', -1)) + & ~Eval('template_override', False)), + }, + depends=['template', 'template_override']) + es_ec_purchases_list_code = fields.Char("Spanish EC Purchases List Code", + states={ + 'readonly': (Bool(Eval('template', -1)) + & ~Eval('template_override', False)), + }, + depends=['template', 'template_override']) diff --git a/reporting_tax.py b/reporting_tax.py index 10e4ff7740..04313aa34d 100644 --- a/reporting_tax.py +++ b/reporting_tax.py @@ -1,26 +1,31 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. +import unicodedata from collections import defaultdict from decimal import Decimal from operator import attrgetter from sql import Cast, Null, Literal -from sql.aggregate import Count +from sql.aggregate import Count, Max, Min, Sum from sql.conditionals import Case -from sql.functions import Substring, Position +from sql.functions import Substring, Position, Extract from trytond.i18n import gettext -from trytond.model import ModelView, fields +from trytond.model import ModelSQL, ModelView, fields from trytond.model.modelsql import convert_from from trytond.pool import Pool +from trytond.pyson import Eval from trytond.report import Report from trytond.transaction import Transaction from trytond.wizard import Wizard, StateView, StateTransition, StateReport, \ Button +from trytond.modules.account_eu.account import ECSalesList, ECSalesListContext from .exceptions import PrintError -__all__ = ['AEAT111', 'AEAT115', 'AEAT303', 'PrintAEATStart', 'PrintAEAT'] +__all__ = ['AEAT111', 'AEAT115', 'AEAT303', 'PrintAEATStart', 'PrintAEAT', + 'ESVATList', 'ESVATListContext', 'AEAT347', 'ECOperationList', + 'ECOperationListContext', 'AEAT349'] # XXX fix: https://genshi.edgewall.org/ticket/582 @@ -63,6 +68,26 @@ def format_percentage(n, size=5): return ('{0:.2f}'.format(n)).replace('.', '').rjust(size, '0') +def identifier_code(identifier): + if identifier: + return identifier.code[2:] + return '' + + +def country_code(record): + code = None + if record.party_tax_identifier: + code = record.party_tax_identifier.code[:2] + if code is None or code == 'ES': + return '' + return code + + +def strip_accents(s): + return ''.join(c for c in unicodedata.normalize('NFD', s) + if unicodedata.category(c) != 'Mn') + + class AEATReport(Report): @classmethod @@ -348,3 +373,271 @@ class PrintAEAT(Wizard): if len(set(p.fiscalyear for p in self.start.periods)) > 1: raise PrintError( gettext('account_es.msg_report_same_fiscalyear')) + + +class ESVATList(ModelSQL, ModelView): + "Spanish VAT List" + __name__ = 'account.reporting.vat_list_es' + + company_tax_identifier = fields.Many2One( + 'party.identifier', "Company Tax Identifier") + party_tax_identifier = fields.Many2One( + 'party.identifier', "Party Tax Identifier") + party = fields.Many2One('party.party', "Party") + province_code = fields.Function(fields.Char("Province Code"), + 'get_province_code', searcher='search_province_code') + code = fields.Char("Code") + amount = fields.Numeric( + "Amount", digits=(16, Eval('currency_digits', 2)), + depends=['currency_digits']) + first_period_amount = fields.Numeric( + "First Period Amount", digits=(16, Eval('currency_digits', 2)), + depends=['currency_digits']) + second_period_amount = fields.Numeric( + "Second Period Amount", digits=(16, Eval('currency_digits', 2)), + depends=['currency_digits']) + third_period_amount = fields.Numeric( + "Third Period Amount", digits=(16, Eval('currency_digits', 2)), + depends=['currency_digits']) + fourth_period_amount = fields.Numeric( + "Fourth Period Amount", digits=(16, Eval('currency_digits', 2)), + depends=['currency_digits']) + currency = fields.Many2One('currency.currency', "Currency") + currency_digits = fields.Function( + fields.Integer("Currency Digits"), 'get_currency_digits') + + def get_currency_digits(self, name): + return self.currency.digits + + @classmethod + def get_province_code(cls, records, name): + return {r.id: r.party.es_province_code or '' if r.party else '' + for r in records} + + @classmethod + def search_province_code(cls, name, clause): + return [(('party.es_province_code',) + tuple(clause[1:]))] + + @classmethod + def table_query(cls): + pool = Pool() + Invoice = pool.get('account.invoice') + InvoiceTax = pool.get('account.invoice.tax') + Tax = pool.get('account.tax') + Date = pool.get('ir.date') + context = Transaction().context + invoice = Invoice.__table__() + invoice_tax = InvoiceTax.__table__() + tax = Tax.__table__() + + amount = invoice_tax.base + invoice_tax.amount + month = Extract('MONTH', invoice.invoice_date) + + where = ((invoice.company == context.get('company')) + & (invoice.state.in_(['posted', 'paid'])) + & (tax.es_vat_list_code != Null) + & (Extract('year', invoice.invoice_date) + == context.get('date', Date.today()).year)) + return (invoice_tax + .join(invoice, + condition=invoice_tax.invoice == invoice.id) + .join(tax, condition=invoice_tax.tax == tax.id) + .select( + Max(invoice_tax.id).as_('id'), + Literal(0).as_('create_uid'), + Min(invoice_tax.create_date).as_('create_date'), + Literal(0).as_('write_uid'), + Max(invoice_tax.write_date).as_('write_date'), + invoice.tax_identifier.as_('company_tax_identifier'), + invoice.party.as_('party'), + invoice.party_tax_identifier.as_('party_tax_identifier'), + tax.es_vat_list_code.as_('code'), + Sum(amount).as_('amount'), + Sum(amount, filter_=month <= Literal(3)).as_( + 'first_period_amount'), + Sum(amount, filter_=( + (month > Literal(3)) & (month <= Literal(6)))).as_( + 'second_period_amount'), + Sum(amount, filter_=( + (month > Literal(6)) & (month <= Literal(9)))).as_( + 'third_period_amount'), + Sum(amount, filter_=( + (month > Literal(9)) & (month <= Literal(12)))).as_( + 'fourth_period_amount'), + invoice.currency.as_('currency'), + where=where, + group_by=[ + invoice.tax_identifier, + invoice.type, + invoice.party, + invoice.party_tax_identifier, + invoice.currency, + tax.es_vat_list_code, + ])) + + +class ESVATListContext(ModelView): + "Spanish VAT List Context" + __name__ = 'account.reporting.vat_list_es.context' + + company = fields.Many2One('company.company', "Company", required=True) + date = fields.Date("Date", required=True, + context={'date_format': '%Y'}) + + @classmethod + def default_company(cls): + return Transaction().context.get('company') + + @classmethod + def default_date(cls): + pool = Pool() + Date = pool.get('ir.date') + return Date.today() + + +class AEAT347(Report): + __name__ = 'account.reporting.aeat347' + + @classmethod + def get_context(cls, records, data): + pool = Pool() + Company = pool.get('company.company') + t_context = Transaction().context + + context = super().get_context(records, data) + + context['year'] = str(t_context['date'].year) + context['company'] = Company(t_context['company']) + context['records_amount'] = sum( + (r.amount for r in records), Decimal(0)) + + context['justify'] = justify + + def format_decimal(n): + if not isinstance(n, Decimal): + n = Decimal(n) + sign = 'N' if n < 0 else ' ' + return sign + ('{0:.2f}'.format(abs(n))).replace('.', '').rjust( + 15, '0') + context['format_decimal'] = format_decimal + context['format_integer'] = format_integer + context['identifier_code'] = identifier_code + context['country_code'] = country_code + context['strip_accents'] = strip_accents + + return context + + +class ECOperationList(ECSalesList): + "EC Operation List" + __name__ = 'account.reporting.es_ec_operation_list' + + @classmethod + def table_query(cls): + pool = Pool() + Invoice = pool.get('account.invoice') + InvoiceTax = pool.get('account.invoice.tax') + Move = pool.get('account.move') + Period = pool.get('account.period') + Tax = pool.get('account.tax') + context = Transaction().context + invoice = Invoice.__table__() + invoice_tax = InvoiceTax.__table__() + move = Move.__table__() + period = Period.__table__() + tax = Tax.__table__() + + sales = super().table_query() + + where = ((invoice.company == context.get('company')) + & (period.fiscalyear == context.get('fiscalyear'))) + if context.get('period'): + where &= (period.id == context.get('period')) + where &= ((tax.es_ec_purchases_list_code != Null) + & (tax.es_ec_purchases_list_code != '')) + where &= invoice.type == 'in' + purchases = (invoice_tax + .join(invoice, + condition=invoice_tax.invoice == invoice.id) + .join(tax, condition=invoice_tax.tax == tax.id) + .join(move, condition=invoice.move == move.id) + .join(period, condition=move.period == period.id) + .select( + Max(invoice_tax.id).as_('id'), + Literal(0).as_('create_uid'), + Min(invoice_tax.create_date).as_('create_date'), + Literal(0).as_('write_uid'), + Max(invoice_tax.write_date).as_('write_date'), + invoice.tax_identifier.as_('company_tax_identifier'), + invoice.party.as_('party'), + invoice.party_tax_identifier.as_('party_tax_identifier'), + tax.es_ec_purchases_list_code.as_('code'), + Sum(invoice_tax.base).as_('amount'), + invoice.currency.as_('currency'), + where=where, + group_by=[ + invoice.tax_identifier, + invoice.party, + invoice.party_tax_identifier, + tax.es_ec_purchases_list_code, + invoice.currency, + ])) + return sales | purchases + + +class ECOperationListContext(ECSalesListContext): + "EC Operation List Context" + __name__ = 'account.reporting.es_ec_operation_list.context' + + +class AEAT349(Report): + __name__ = 'account.reporting.aeat349' + + @classmethod + def get_context(cls, records, data): + pool = Pool() + Period = pool.get('account.period') + Fiscalyear = pool.get('account.fiscalyear') + t_context = Transaction().context + + context = super().get_context(records, data) + + fiscalyear = Fiscalyear(t_context['fiscalyear']) + context['year'] = str(fiscalyear.start_date.year) + context['company'] = fiscalyear.company + context['records_amount'] = sum( + (r.amount for r in records), Decimal(0)) + + period_id = t_context.get('period') + if not period_id: + # Yearly + context['period'] = '0A' + context['period_number'] = '99' + else: + period = Period(period_id) + start_month = period.start_date.month + end_month = period.end_date.month + if end_month - start_month > 0: + context['period'] = str(end_month // 3) + 'T' + context['period_number'] = str(20 + (end_month // 3)) + else: + context['period'] = str(start_month).rjust(2, '0') + context['period_number'] = str(start_month).rjust(2, '0') + + context['justify'] = justify + context['format_integer'] = format_integer + context['format_percentage'] = format_percentage + context['records_amount'] = sum( + (r.amount for r in records), Decimal(0)) + + context['justify'] = justify + context['identifier_code'] = identifier_code + + def format_decimal(n, digits=13): + if not isinstance(n, Decimal): + n = Decimal(n) + return ('{0:.2f}'.format(abs(n))).replace('.', '').rjust( + digits, '0') + context['format_decimal'] = format_decimal + + return context diff --git a/reporting_tax.xml b/reporting_tax.xml index 1e26dd4053..00bbbcbcfc 100644 --- a/reporting_tax.xml +++ b/reporting_tax.xml @@ -63,5 +63,114 @@ this repository contains the full copyright notices and license terms. --> + + account.reporting.vat_list_es + tree + vat_list_list + + + + Spanish VAT List + account.reporting.vat_list_es + account.reporting.vat_list_es.context + + + + + + + + + + account.reporting.vat_list_es.context + form + vat_list_context_form + + + + + + + + + + + + + + + + + + + + AEAT Model 347 + account.reporting.aeat347 + account_es/aeat347.txt + txt + + + + + + + + + + + + form_print + account.reporting.vat_list_es,-1 + + + + + account.reporting.es_ec_operation_list + tree + es_ec_operation_list + + + + EC Operation List + account.reporting.es_ec_operation_list + account.reporting.es_ec_operation_list.context + + + + + + + + + + account.reporting.es_ec_operation_list.context + form + es_ec_operation_list_context_form + + + + AEAT Model 349 + account.reporting.aeat349 + account_es/aeat349.txt + txt + + + + + + + + + + + + form_print + account.reporting.es_ec_operation_list,-1 + + diff --git a/setup.py b/setup.py index c0349321eb..180044a2d5 100755 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ if minor_version % 2: 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % ( name[8:], name, version)) -requires = [] +requires = ['python-sql'] for dep in info.get('depends', []): if not re.match(r'(ir|res)(\W|$)', dep): requires.append(get_require_version('trytond_%s' % dep)) diff --git a/tax.xml b/tax.xml index d980fd5c8b..0aabb447d6 100644 --- a/tax.xml +++ b/tax.xml @@ -12,6 +12,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA 10% @@ -22,6 +23,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA 4% @@ -32,6 +34,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA Exento @@ -117,6 +120,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 10% (operaciones corrientes) @@ -127,6 +131,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 4% (operaciones corrientes) @@ -137,6 +142,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Exento (operaciones corrientes) @@ -157,6 +163,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 10% (bienes de inversión) @@ -167,6 +174,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 4% (bienes de inversión) @@ -177,6 +185,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Exento (bienes de inversión) @@ -319,6 +328,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Intracomunitario. Operaciones corrientes (2) @@ -341,6 +351,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Intracomunitario. Bienes inversión (2) diff --git a/tax_normal.xml b/tax_normal.xml index d2c77b5485..9c1c0a1f97 100644 --- a/tax_normal.xml +++ b/tax_normal.xml @@ -12,6 +12,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA 10% @@ -22,6 +23,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA 4% @@ -32,6 +34,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA Exento @@ -117,6 +120,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 10% (operaciones corrientes) @@ -127,6 +131,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 4% (operaciones corrientes) @@ -137,6 +142,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Exento (operaciones corrientes) @@ -157,6 +163,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 10% (bienes de inversión) @@ -167,6 +174,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 4% (bienes de inversión) @@ -177,6 +185,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Exento (bienes de inversión) @@ -319,6 +328,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Intracomunitario. Operaciones corrientes (2) @@ -341,6 +351,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Intracomunitario. Bienes inversión (2) diff --git a/tax_pyme.xml b/tax_pyme.xml index 4f3874efab..0a63699844 100644 --- a/tax_pyme.xml +++ b/tax_pyme.xml @@ -12,6 +12,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA 10% @@ -22,6 +23,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA 4% @@ -32,6 +34,7 @@ this repository contains the full copyright notices and license terms. --> + B IVA Exento @@ -117,6 +120,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 10% (operaciones corrientes) @@ -127,6 +131,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 4% (operaciones corrientes) @@ -137,6 +142,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Exento (operaciones corrientes) @@ -157,6 +163,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 10% (bienes de inversión) @@ -167,6 +174,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA 4% (bienes de inversión) @@ -177,6 +185,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Exento (bienes de inversión) @@ -319,6 +328,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Intracomunitario. Operaciones corrientes (2) @@ -341,6 +351,7 @@ this repository contains the full copyright notices and license terms. --> + A IVA Intracomunitario. Bienes inversión (2) diff --git a/tests/303.txt b/tests/303.txt index 93e2235b04..684374e452 100644 --- a/tests/303.txt +++ b/tests/303.txt @@ -1 +1 @@ - IB01000009DUNDER MIFFLIN 2018012322 2222000000000000000000040000000000000000000000000000000000000100000000000000000000000000000000200000210000000000000004200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000004200000000000000100000000000000000210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002100000000000000021000220 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210010000000000000000000002100000000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000002100 0 0 0 0 0 0 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + IB01000009DUNDER MIFFLIN 2018012322 2222000000000000000000040000000000000000000000000000000000000100000000000000000000000000000000200000210000000000000004200000000000000100000000000000000210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000006300000000000000100000000000000000210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000021000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004200000000000000021000220 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210010000000000000000000002100000000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000002100 0 0 0 0 0 0 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/tests/scenario_reporting.rst b/tests/scenario_reporting.rst index d60abb1061..4226896836 100644 --- a/tests/scenario_reporting.rst +++ b/tests/scenario_reporting.rst @@ -6,7 +6,7 @@ Imports:: >>> import datetime >>> from decimal import Decimal - >>> from proteus import Model, Wizard + >>> from proteus import Model, Wizard, Report >>> from trytond.tests.tools import activate_modules >>> from trytond.tools import file_open >>> from trytond.modules.company.tests.tools import create_company, \ @@ -65,9 +65,20 @@ Create chart of accounts:: Create parties:: + >>> Country = Model.get('country.country') + >>> spain = Country(name='Spain', code='ES') + >>> spain.save() >>> Party = Model.get('party.party') >>> TaxRule = Model.get('account.tax.rule') >>> party = Party(name='Party') + >>> tax_identifier = party.identifiers.new() + >>> tax_identifier.type = 'eu_vat' + >>> tax_identifier.code = 'ES00000000T' + >>> address, = party.addresses + >>> address.country = spain + >>> address.zip = '25001' + >>> party.es_province_code + '25' >>> party.save() >>> tax_rule, = TaxRule.find([ ... ('company', '=', company.id), @@ -76,7 +87,22 @@ Create parties:: ... ]) >>> supplier = Party(name='Supplier') >>> supplier.supplier_tax_rule = tax_rule + >>> tax_identifier = supplier.identifiers.new() + >>> tax_identifier.type = 'eu_vat' + >>> tax_identifier.code = 'ES00000001R' + >>> supplier.es_province_code = '08' >>> supplier.save() + >>> tax_rule, = TaxRule.find([ + ... ('company', '=', company.id), + ... ('kind', '=', 'purchase'), + ... ('name', '=', 'Compras Intracomunitarias'), + ... ]) + >>> ec_supplier = Party(name='Intracomunitary Supplier') + >>> ec_supplier.supplier_tax_rule = tax_rule + >>> tax_identifier = ec_supplier.identifiers.new() + >>> tax_identifier.type = 'eu_vat' + >>> tax_identifier.code = 'BE0897290877' + >>> ec_supplier.save() Create account category:: @@ -136,6 +162,17 @@ Create invoices:: >>> invoice.click('post') >>> invoice.total_amount Decimal('106.00') + >>> invoice = Invoice() + >>> invoice.type = 'in' + >>> invoice.party = ec_supplier + >>> invoice.invoice_date = period.start_date + >>> line = invoice.lines.new() + >>> line.product = product + >>> line.quantity = 5 + >>> line.unit_price = Decimal('20') + >>> invoice.click('post') + >>> invoice.total_amount + Decimal('100.00') Generate aeat reports:: @@ -179,3 +216,37 @@ Generate aeat reports:: True >>> name 'AEAT Model 303' + + >>> VatList = Model.get('account.reporting.vat_list_es') + >>> context = { + ... 'company': company.id, + ... 'date': period.end_date, + ... } + >>> with config.set_context(context): + ... vat_list_records = VatList.find([]) + ... report = Report('account.reporting.aeat347') + ... extension, content, _, name = report.execute(vat_list_records) + >>> extension + 'txt' + >>> with file_open('account_es/tests/347.txt') as f: + ... content == f.read() + True + >>> name + 'AEAT Model 347' + + >>> ECOperationList = Model.get('account.reporting.es_ec_operation_list') + >>> context = { + ... 'company': company.id, + ... 'fiscalyear': fiscalyear.id, + ... } + >>> with config.set_context(context): + ... records = ECOperationList.find([]) + ... report = Report('account.reporting.aeat349') + ... extension, content, _, name = report.execute(records) + >>> extension + 'txt' + >>> with file_open('account_es/tests/349.txt') as f: + ... content == f.read() + True + >>> name + 'AEAT Model 349' diff --git a/tryton.cfg b/tryton.cfg index 3169a28aa2..1f1d15d36c 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -4,6 +4,8 @@ depends: ir account account_eu + account_invoice + party xml: tax_groups.xml account_normal.xml @@ -13,3 +15,4 @@ xml: view.xml reporting_tax.xml message.xml + party.xml diff --git a/view.xml b/view.xml index 9ec9fb4736..f2771a1835 100644 --- a/view.xml +++ b/view.xml @@ -14,5 +14,17 @@ this repository contains the full copyright notices and license terms. --> tax_code_form + + + account.tax.template + + tax_template_form + + + + account.tax + + tax_form +