changeset 6c2410dd2382 in modules/account_es:default
details: 
https://hg.tryton.org/modules/account_es?cmd=changeset;node=6c2410dd2382
description:
        Add Spanish VAT list and EC Operation List

        issue7558
        review54281002
diffstat:

 CHANGELOG                    |    1 +
 __init__.py                  |   10 +
 account.py                   |   33 ++++-
 reporting_tax.py             |  301 ++++++++++++++++++++++++++++++++++++++++++-
 reporting_tax.xml            |  109 +++++++++++++++
 setup.py                     |    2 +-
 tax.xml                      |   11 +
 tax_normal.xml               |   11 +
 tax_pyme.xml                 |   11 +
 tests/303.txt                |    2 +-
 tests/scenario_reporting.rst |   73 ++++++++++-
 tryton.cfg                   |    3 +
 view.xml                     |   12 +
 13 files changed, 571 insertions(+), 8 deletions(-)

diffs (984 lines):

diff -r 6bf7b7497654 -r 6c2410dd2382 CHANGELOG
--- a/CHANGELOG Thu Apr 11 15:08:15 2019 +0200
+++ b/CHANGELOG Sun Apr 14 14:21:07 2019 +0200
@@ -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 -r 6bf7b7497654 -r 6c2410dd2382 __init__.py
--- a/__init__.py       Thu Apr 11 15:08:15 2019 +0200
+++ b/__init__.py       Sun Apr 14 14:21:07 2019 +0200
@@ -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 @@
         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 -r 6bf7b7497654 -r 6c2410dd2382 account.py
--- a/account.py        Thu Apr 11 15:08:15 2019 +0200
+++ b/account.py        Sun Apr 14 14:21:07 2019 +0200
@@ -4,7 +4,7 @@
 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 @@
                 & ~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 -r 6bf7b7497654 -r 6c2410dd2382 reporting_tax.py
--- a/reporting_tax.py  Thu Apr 11 15:08:15 2019 +0200
+++ b/reporting_tax.py  Sun Apr 14 14:21:07 2019 +0200
@@ -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 @@
     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 @@
         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 -r 6bf7b7497654 -r 6c2410dd2382 reporting_tax.xml
--- a/reporting_tax.xml Thu Apr 11 15:08:15 2019 +0200
+++ b/reporting_tax.xml Sun Apr 14 14:21:07 2019 +0200
@@ -63,5 +63,114 @@
             <field name="group" ref="account.group_account"/>
         </record>
 
+        <record model="ir.ui.view" id="vat_list_view_list">
+            <field name="model">account.reporting.vat_list_es</field>
+            <field name="type">tree</field>
+            <field name="name">vat_list_list</field>
+        </record>
+
+        <record model="ir.action.act_window" id="act_vat_list_form">
+            <field name="name">Spanish VAT List</field>
+            <field name="res_model">account.reporting.vat_list_es</field>
+            <field 
name="context_model">account.reporting.vat_list_es.context</field>
+        </record>
+        <record model="ir.action.act_window.view"
+            id="act_vat_list_form_view1">
+            <field name="sequence" eval="10"/>
+            <field name="view" ref="vat_list_view_list"/>
+            <field name="act_window" ref="act_vat_list_form"/>
+        </record>
+        <menuitem parent="account.menu_reporting"
+            action="act_vat_list_form" id="menu_vat_list"/>
+
+        <record model="ir.ui.view" id="vat_list_context_view_form">
+            <field name="model">account.reporting.vat_list_es.context</field>
+            <field name="type">form</field>
+            <field name="name">vat_list_context_form</field>
+        </record>
+
+        <record model="ir.model.access" id="access_vat_list">
+            <field name="model" search="[('model', '=', 
'account.reporting.vat_list_es')]"/>
+            <field name="perm_read" eval="False"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
+        <record model="ir.model.access" id="access_vat_list_account">
+            <field name="model" search="[('model', '=', 
'account.reporting.vat_list_es')]"/>
+            <field name="group" ref="account.group_account"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
+
+        <record model="ir.action.report" id="report_aeat_347">
+            <field name="name">AEAT Model 347</field>
+            <field name="report_name">account.reporting.aeat347</field>
+            <field name="report">account_es/aeat347.txt</field>
+            <field name="template_extension">txt</field>
+            <field name="translatable" eval="False"/>
+        </record>
+        <record model="ir.action-res.group" id="report_aeat_347_group_account">
+            <field name="action" ref="report_aeat_347"/>
+            <field name="group" ref="account.group_account"/>
+        </record>
+        <record model="ir.action-res.group" 
id="report_aeat_347_group_account_admin">
+            <field name="action" ref="report_aeat_347"/>
+            <field name="group" ref="account.group_account_admin"/>
+        </record>
+        <record model="ir.action.keyword" id="report_aeat_347_keyword">
+            <field name="keyword">form_print</field>
+            <field name="model">account.reporting.vat_list_es,-1</field>
+            <field name="action" ref="report_aeat_347"/>
+        </record>
+
+        <record model="ir.ui.view" id="es_ec_operation_list_view_list">
+            <field name="model">account.reporting.es_ec_operation_list</field>
+            <field name="type">tree</field>
+            <field name="name">es_ec_operation_list</field>
+        </record>
+
+        <record model="ir.action.act_window" 
id="act_es_ec_operation_list_form">
+            <field name="name">EC Operation List</field>
+            <field 
name="res_model">account.reporting.es_ec_operation_list</field>
+            <field 
name="context_model">account.reporting.es_ec_operation_list.context</field>
+        </record>
+        <record model="ir.action.act_window.view"
+            id="act_es_ec_operation_list_form_view1">
+            <field name="sequence" eval="10"/>
+            <field name="view" ref="es_ec_operation_list_view_list"/>
+            <field name="act_window" ref="act_es_ec_operation_list_form"/>
+        </record>
+        <menuitem parent="account.menu_reporting"
+            action="act_es_ec_operation_list_form" 
id="menu_es_ec_operation_list"/>
+
+        <record model="ir.ui.view" id="es_ec_operation_list_context_view_form">
+            <field 
name="model">account.reporting.es_ec_operation_list.context</field>
+            <field name="type">form</field>
+            <field name="name">es_ec_operation_list_context_form</field>
+        </record>
+
+        <record model="ir.action.report" id="report_aeat_349">
+            <field name="name">AEAT Model 349</field>
+            <field name="report_name">account.reporting.aeat349</field>
+            <field name="report">account_es/aeat349.txt</field>
+            <field name="template_extension">txt</field>
+            <field name="translatable" eval="False"/>
+        </record>
+        <record model="ir.action-res.group" id="report_aeat_349_group_account">
+            <field name="action" ref="report_aeat_349"/>
+            <field name="group" ref="account.group_account"/>
+        </record>
+        <record model="ir.action-res.group" 
id="report_aeat_349_group_account_admin">
+            <field name="action" ref="report_aeat_349"/>
+            <field name="group" ref="account.group_account_admin"/>
+        </record>
+        <record model="ir.action.keyword" id="report_aeat_349_keyword">
+            <field name="keyword">form_print</field>
+            <field 
name="model">account.reporting.es_ec_operation_list,-1</field>
+            <field name="action" ref="report_aeat_349"/>
+        </record>
     </data>
 </tryton>
diff -r 6bf7b7497654 -r 6c2410dd2382 setup.py
--- a/setup.py  Thu Apr 11 15:08:15 2019 +0200
+++ b/setup.py  Sun Apr 14 14:21:07 2019 +0200
@@ -45,7 +45,7 @@
         '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 -r 6bf7b7497654 -r 6c2410dd2382 tax.xml
--- a/tax.xml   Thu Apr 11 15:08:15 2019 +0200
+++ b/tax.xml   Sun Apr 14 14:21:07 2019 +0200
@@ -12,6 +12,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_477"/>
             <field name="credit_note_account" ref="pgc_477"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record model="account.tax.template" id="iva_rep_10">
             <field name="name">IVA 10%</field>
@@ -22,6 +23,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_477"/>
             <field name="credit_note_account" ref="pgc_477"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record model="account.tax.template" id="iva_rep_4">
             <field name="name">IVA 4%</field>
@@ -32,6 +34,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_477"/>
             <field name="credit_note_account" ref="pgc_477"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record model="account.tax.template" id="iva_rep_ex">
             <field name="name">IVA Exento</field>
@@ -117,6 +120,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_10">
             <field name="name">IVA 10% (operaciones corrientes)</field>
@@ -127,6 +131,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_4">
             <field name="name">IVA 4% (operaciones corrientes)</field>
@@ -137,6 +142,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_ex">
             <field name="name">IVA Exento (operaciones corrientes)</field>
@@ -157,6 +163,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_10_inv">
             <field name="name">IVA 10% (bienes de inversión)</field>
@@ -167,6 +174,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_4_inv">
             <field name="name">IVA 4% (bienes de inversión)</field>
@@ -177,6 +185,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_ex_inv">
             <field name="name">IVA Exento (bienes de inversión)</field>
@@ -319,6 +328,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_ec_purchases_list_code">A</field>
         </record>
         <record model="account.tax.template" id="iva_sop_intracomunitario_2">
             <field name="name">IVA Intracomunitario. Operaciones corrientes 
(2)</field>
@@ -341,6 +351,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472"/>
             <field name="credit_note_account" ref="pgc_472"/>
+            <field name="es_ec_purchases_list_code">A</field>
         </record>
         <record model="account.tax.template" 
id="iva_sop_intracomunitario_inv_2">
             <field name="name">IVA Intracomunitario. Bienes inversión 
(2)</field>
diff -r 6bf7b7497654 -r 6c2410dd2382 tax_normal.xml
--- a/tax_normal.xml    Thu Apr 11 15:08:15 2019 +0200
+++ b/tax_normal.xml    Sun Apr 14 14:21:07 2019 +0200
@@ -12,6 +12,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_477_normal"/>
             <field name="credit_note_account" ref="pgc_477_normal"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record id="iva_rep_10_normal" model="account.tax.template">
             <field name="name">IVA 10%</field>
@@ -22,6 +23,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_477_normal"/>
             <field name="credit_note_account" ref="pgc_477_normal"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record id="iva_rep_4_normal" model="account.tax.template">
             <field name="name">IVA 4%</field>
@@ -32,6 +34,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_477_normal"/>
             <field name="credit_note_account" ref="pgc_477_normal"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record id="iva_rep_ex_normal" model="account.tax.template">
             <field name="name">IVA Exento</field>
@@ -117,6 +120,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_10_normal" model="account.tax.template">
             <field name="name">IVA 10% (operaciones corrientes)</field>
@@ -127,6 +131,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_4_normal" model="account.tax.template">
             <field name="name">IVA 4% (operaciones corrientes)</field>
@@ -137,6 +142,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_ex_normal" model="account.tax.template">
             <field name="name">IVA Exento (operaciones corrientes)</field>
@@ -157,6 +163,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_10_inv_normal" model="account.tax.template">
             <field name="name">IVA 10% (bienes de inversión)</field>
@@ -167,6 +174,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_4_inv_normal" model="account.tax.template">
             <field name="name">IVA 4% (bienes de inversión)</field>
@@ -177,6 +185,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_ex_inv_normal" model="account.tax.template">
             <field name="name">IVA Exento (bienes de inversión)</field>
@@ -319,6 +328,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_ec_purchases_list_code">A</field>
         </record>
         <record id="iva_sop_intracomunitario_2_normal" 
model="account.tax.template">
             <field name="name">IVA Intracomunitario. Operaciones corrientes 
(2)</field>
@@ -341,6 +351,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_normal"/>
             <field name="credit_note_account" ref="pgc_472_normal"/>
+            <field name="es_ec_purchases_list_code">A</field>
         </record>
         <record id="iva_sop_intracomunitario_inv_2_normal" 
model="account.tax.template">
             <field name="name">IVA Intracomunitario. Bienes inversión 
(2)</field>
diff -r 6bf7b7497654 -r 6c2410dd2382 tax_pyme.xml
--- a/tax_pyme.xml      Thu Apr 11 15:08:15 2019 +0200
+++ b/tax_pyme.xml      Sun Apr 14 14:21:07 2019 +0200
@@ -12,6 +12,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_477_pyme"/>
             <field name="credit_note_account" ref="pgc_477_pyme"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record id="iva_rep_10_pyme" model="account.tax.template">
             <field name="name">IVA 10%</field>
@@ -22,6 +23,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_477_pyme"/>
             <field name="credit_note_account" ref="pgc_477_pyme"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record id="iva_rep_4_pyme" model="account.tax.template">
             <field name="name">IVA 4%</field>
@@ -32,6 +34,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_477_pyme"/>
             <field name="credit_note_account" ref="pgc_477_pyme"/>
+            <field name="es_vat_list_code">B</field>
         </record>
         <record id="iva_rep_ex_pyme" model="account.tax.template">
             <field name="name">IVA Exento</field>
@@ -117,6 +120,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_10_pyme" model="account.tax.template">
             <field name="name">IVA 10% (operaciones corrientes)</field>
@@ -127,6 +131,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_4_pyme" model="account.tax.template">
             <field name="name">IVA 4% (operaciones corrientes)</field>
@@ -137,6 +142,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_ex_pyme" model="account.tax.template">
             <field name="name">IVA Exento (operaciones corrientes)</field>
@@ -157,6 +163,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_10_inv_pyme" model="account.tax.template">
             <field name="name">IVA 10% (bienes de inversión)</field>
@@ -167,6 +174,7 @@
             <field name="rate" eval="Decimal('0.1')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_4_inv_pyme" model="account.tax.template">
             <field name="name">IVA 4% (bienes de inversión)</field>
@@ -177,6 +185,7 @@
             <field name="rate" eval="Decimal('0.04')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_vat_list_code">A</field>
         </record>
         <record id="iva_sop_ex_inv_pyme" model="account.tax.template">
             <field name="name">IVA Exento (bienes de inversión)</field>
@@ -319,6 +328,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_ec_purchases_list_code">A</field>
         </record>
         <record id="iva_sop_intracomunitario_2_pyme" 
model="account.tax.template">
             <field name="name">IVA Intracomunitario. Operaciones corrientes 
(2)</field>
@@ -341,6 +351,7 @@
             <field name="rate" eval="Decimal('0.21')"/>
             <field name="invoice_account" ref="pgc_472_pyme"/>
             <field name="credit_note_account" ref="pgc_472_pyme"/>
+            <field name="es_ec_purchases_list_code">A</field>
         </record>
         <record id="iva_sop_intracomunitario_inv_2_pyme" 
model="account.tax.template">
             <field name="name">IVA Intracomunitario. Bienes inversión 
(2)</field>
diff -r 6bf7b7497654 -r 6c2410dd2382 tests/303.txt
--- a/tests/303.txt     Thu Apr 11 15:08:15 2019 +0200
+++ b/tests/303.txt     Sun Apr 14 14:21:07 2019 +0200
@@ -1,1 +1,1 @@
-<T30302018010000><AUX>                                                         
                                                                                
                                                                                
                                                                                
   </AUX><T30301000> IB01000009DUNDER MIFFLIN                                   
                               2018012322         
2222000000000000000000040000000000000000000000000000000000000100000000000000000000000000000000200000210000000000000004200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000004200000000000000100000000000000000210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002100000000000000021000220
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                               
</T30301000><T30303000>00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210010000000000000000000002100000000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000002100
                                                            0    0    0    0    
0    0     
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                               
</T30303000></T30302018010000>
+<T30302018010000><AUX>                                                         
                                                                                
                                                                                
                                                                                
   </AUX><T30301000> IB01000009DUNDER MIFFLIN                                   
                               2018012322         
2222000000000000000000040000000000000000000000000000000000000100000000000000000000000000000000200000210000000000000004200000000000000100000000000000000210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000006300000000000000100000000000000000210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000021000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004200000000000000021000220
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                               
</T30301000><T30303000>00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210010000000000000000000002100000000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000002100
                                                            0    0    0    0    
0    0     
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                               
</T30303000></T30302018010000>
diff -r 6bf7b7497654 -r 6c2410dd2382 tests/scenario_reporting.rst
--- a/tests/scenario_reporting.rst      Thu Apr 11 15:08:15 2019 +0200
+++ b/tests/scenario_reporting.rst      Sun Apr 14 14:21:07 2019 +0200
@@ -6,7 +6,7 @@
 
     >>> 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 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 @@
     ...     ])
     >>> 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 @@
     >>> 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 @@
     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 -r 6bf7b7497654 -r 6c2410dd2382 tryton.cfg
--- a/tryton.cfg        Thu Apr 11 15:08:15 2019 +0200
+++ b/tryton.cfg        Sun Apr 14 14:21:07 2019 +0200
@@ -4,6 +4,8 @@
     ir
     account
     account_eu
+    account_invoice
+    party
 xml:
     tax_groups.xml
     account_normal.xml
@@ -13,3 +15,4 @@
     view.xml
     reporting_tax.xml
     message.xml
+    party.xml
diff -r 6bf7b7497654 -r 6c2410dd2382 view.xml
--- a/view.xml  Thu Apr 11 15:08:15 2019 +0200
+++ b/view.xml  Sun Apr 14 14:21:07 2019 +0200
@@ -14,5 +14,17 @@
             <field name="inherit" ref="account.tax_code_view_form"/>
             <field name="name">tax_code_form</field>
         </record>
+
+        <record model="ir.ui.view" id="tax_template_view_form">
+            <field name="model">account.tax.template</field>
+            <field name="inherit" ref="account.tax_template_view_form"/>
+            <field name="name">tax_template_form</field>
+        </record>
+
+        <record model="ir.ui.view" id="tax_view_form">
+            <field name="model">account.tax</field>
+            <field name="inherit" ref="account.tax_view_form"/>
+            <field name="name">tax_form</field>
+        </record>
     </data>
 </tryton>

Reply via email to