Update to 4.7

This commit is contained in:
Cédric Krier 2018-01-18 17:08:54 +01:00
parent d06f9affa6
commit 325df0acd8
10 changed files with 186 additions and 96 deletions

49
.drone.yml Normal file
View File

@ -0,0 +1,49 @@
clone:
hg:
image: plugins/hg
pipeline:
tox:
image: ${IMAGE}
environment:
- CFLAGS=-O0
- DB_CACHE=/cache
- TOX_TESTENV_PASSENV=CFLAGS DB_CACHE
- POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
commands:
- pip install tox
- tox -e "${TOXENV}-${DATABASE}"
services:
postgresql:
image: postgres
when:
matrix:
DATABASE: postgresql
matrix:
include:
- IMAGE: python:2.7
TOXENV: py27
DATABASE: sqlite
- IMAGE: python:2.7
TOXENV: py27
DATABASE: postgresql
- IMAGE: python:3.4
TOXENV: py34
DATABASE: sqlite
- IMAGE: python:3.4
TOXENV: py34
DATABASE: postgresql
- IMAGE: python:3.5
TOXENV: py35
DATABASE: sqlite
- IMAGE: python:3.5
TOXENV: py35
DATABASE: postgresql
- IMAGE: python:3.6
TOXENV: py36
DATABASE: sqlite
- IMAGE: python:3.6
TOXENV: py36
DATABASE: postgresql

View File

@ -1,13 +1,10 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from trytond.model import ModelSQL, ModelView, fields
from trytond.wizard import Wizard, StateView, StateTransition, Button
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, And, Bool
from trytond.transaction import Transaction
from .aeat import (OPERATION_KEY, BOOK_KEY, SEND_SPECIAL_REGIME_KEY,
RECEIVE_SPECIAL_REGIME_KEY, AEAT_INVOICE_STATE, IVA_SUBJECTED,
EXCEMPTION_CAUSE, INTRACOMUNITARY_TYPE)
from trytond.model import fields
from trytond.pool import PoolMeta
from .aeat import (BOOK_KEY, SEND_SPECIAL_REGIME_KEY,
RECEIVE_SPECIAL_REGIME_KEY, IVA_SUBJECTED, EXCEMPTION_CAUSE,
INTRACOMUNITARY_TYPE)
__all__ = ['TemplateTax', 'Tax']

112
aeat.py
View File

@ -28,6 +28,7 @@ _ZERO = Decimal('0.0')
# AEAT SII test
SII_TEST = config.getboolean('aeat', 'sii_test', default=True)
def _decimal(x):
return Decimal(x) if x is not None else None
@ -46,7 +47,7 @@ COMMUNICATION_TYPE = [ # L0
# ('A4', 'Amendment of Invoice for Travellers'), # Not suported
('C0', 'Query Invoices'), # Not in L0
('D0', 'Delete Invoices'), # Not In L0
]
]
BOOK_KEY = [
(None, ''),
@ -54,13 +55,14 @@ BOOK_KEY = [
('I', 'Investment Goods'),
('R', 'Received Invoices'),
('U', 'Particular Intracommunity Operations'),
]
]
OPERATION_KEY = [ # L2_EMI - L2_RECI
(None, ''),
('F1', 'Invoice'),
('F2', 'Simplified Invoice (ticket)'),
('R1', 'Corrected Invoice (Art 80.1, 80.2 and 80.6 and error grounded in law)'),
('R1', 'Corrected Invoice '
'(Art 80.1, 80.2 and 80.6 and error grounded in law)'),
('R2', 'Corrected Invoice (Art. 80.3)'),
('R3', 'Credit Note (Art 80.4)'),
('R4', 'Corrected Invoice (Other)'),
@ -69,19 +71,18 @@ OPERATION_KEY = [ # L2_EMI - L2_RECI
('F4', 'Invoice summary entry'),
('F5', 'Import (DUA)'),
('F6', 'Other accounting documents'),
]
]
PARTY_IDENTIFIER_TYPE = [
(None, ''),
('02', 'NIF-VAT'),
('03', 'Passport'),
('04', 'Official identification document issued by the country '
'or region of residence'),
'or region of residence'),
('05', 'Residence certificate'),
('06', 'Other supporting document'),
('07', 'Not registered'),
]
]
SEND_SPECIAL_REGIME_KEY = [ # L3.1
@ -89,58 +90,58 @@ SEND_SPECIAL_REGIME_KEY = [ # L3.1
('01', 'General tax regime activity'),
('02', 'Export'),
('03', 'Activities to which the special scheme of used goods, '
'works of art, antiquities and collectables (135-139 of the VAT Law)'),
'works of art, antiquities and collectables (135-139 of the VAT Law)'),
('04', 'Special scheme for investment gold'),
('05', 'Special scheme for travel agencies'),
('06', 'Special scheme applicable to groups of entities, VAT (Advanced)'),
('07', 'Special cash basis scheme'),
('08', 'Activities subject to Canary Islands General Indirect Tax/Tax on '
'Production, Services and Imports'),
'Production, Services and Imports'),
('09', 'Invoicing of the provision of travel agency services acting as '
'intermediaries in the name of and on behalf of other persons '
'(Additional Provision 4, Royal Decree 1619/2012)'),
'intermediaries in the name of and on behalf of other persons '
'(Additional Provision 4, Royal Decree 1619/2012)'),
('10', 'Collections on behalf of third parties of professional fees or '
'industrial property, copyright or other such rights by partners, '
'associates or members undertaken by companies, associations, '
'professional organisations or other entities that, amongst their '
'functions, undertake collections'),
'industrial property, copyright or other such rights by partners, '
'associates or members undertaken by companies, associations, '
'professional organisations or other entities that, amongst their '
'functions, undertake collections'),
('11', 'Business premises lease activities subject to withholding'),
('12', 'Business premises lease activities not subject to withholding'),
('13', 'Business premises lease activities subject and not subject '
'to withholding'),
'to withholding'),
('14', 'Invoice with VAT pending accrual (work certifications with Public '
'Administration recipients)'),
'Administration recipients)'),
('15', 'Invoice with VAT pending accrual - '
'operations of successive tract'),
'operations of successive tract'),
('16', 'First semester 2017'),
]
]
RECEIVE_SPECIAL_REGIME_KEY = [
(None, ''),
('01', 'General tax regime activity'),
('02', 'Activities through which businesses pay compensation for special '
'VAT arrangements for agriculture and fisheries'),
('03', 'Activities to which the special scheme of used goods, works of art, '
'antiquities and collectables (135-139 of the VAT Law)'),
'VAT arrangements for agriculture and fisheries'),
('03', 'Activities to which the special scheme of used goods, '
'works of art, antiquities and collectables (135-139 of the VAT Law)'),
('04', 'Special scheme for investment gold'),
('05', 'Special scheme for travel agencies'),
('06', 'Special scheme applicable to groups of entities, VAT (Advanced)'),
('07', 'Special cash basis scheme'),
('08', 'Activities subject to Canary Islands General Indirect Tax/Tax '
'on Production, Services and Imports'),
'on Production, Services and Imports'),
('09', 'Intra-Community acquisition of assets and provisions of services'),
('12', 'Business premises lease activities'),
('13', 'Invoice corresponding to an import '
'(reported without been associated with a DUA)'),
'(reported without been associated with a DUA)'),
('14', 'First semester 2017'),
]
]
AEAT_COMMUNICATION_STATE = [
(None, ''),
('Correcto', 'Accepted'),
('ParcialmenteCorrecto', 'Partially Accepted'),
('Incorrecto', 'Rejected')
]
]
AEAT_INVOICE_STATE = [
(None, ''),
@ -156,13 +157,13 @@ AEAT_INVOICE_STATE = [
PROPERTY_STATE = [ # L6
('0', ''),
('1', '1. Property with a land register reference located in any part '
'of Spain, with the exception of the Basque Country and Navarre'),
'of Spain, with the exception of the Basque Country and Navarre'),
('2', '2. Property located in the Autonomous Community of the Basque '
'Country or the Chartered Community of Navarre.'),
('3', '3. Property in any of the foregoing locations with no land register '
'reference'),
'Country or the Chartered Community of Navarre.'),
('3', '3. Property in any of the foregoing locations '
'with no land register reference'),
('4', '4. Property located abroad'),
]
]
# L7 - Iva Subjected
@ -171,8 +172,8 @@ IVA_SUBJECTED = [
('S1', 'Subject - Not exempt. Non VAT reverse charge'),
('S2', 'Subject - Not exempt. VAT reverse charge'),
('S3', 'Subject - Not exempt. Both non VAT reverse charge '
'and VAT reverse charge')
]
'and VAT reverse charge')
]
# L9 - Excemption cause
EXCEMPTION_CAUSE = [
@ -183,26 +184,26 @@ EXCEMPTION_CAUSE = [
('E4', 'Exempt on account of Article 23 and Article 24'),
('E5', 'Exempt on account of Article 25'),
('E6', 'Exempt on other grounds'),
]
]
# L11 Payment Type
PAYMENT_TYPE = [
('01', 'Transfer'),
('02', 'Cheque'),
('03', 'Not to be collected/paid (deadline for accrual/forced accrual '
'as part of insolvency proceedings)'),
'as part of insolvency proceedings)'),
('04', 'Other methods of collection/payment')
]
]
# L12
INTRACOMUNITARY_TYPE = [
(None, ''),
('A', 'The transmission or receipt of goods to undertake partial reports '
'or works stipulated in Article 70, section one, Number 7 '
'of the Tax Law (Law 37/1992)'),
'or works stipulated in Article 70, section one, Number 7 '
'of the Tax Law (Law 37/1992)'),
('B', 'Transfers of goods or intra-Community acquisitions of goods listed '
'in Article 9.3 and Article 16.2 of the Tax Law (Law 37/1992)'),
]
'in Article 9.3 and Article 16.2 of the Tax Law (Law 37/1992)'),
]
def remove_accents(unicode_string):
@ -241,10 +242,12 @@ class SIIReport(Workflow, ModelSQL, ModelView):
states={
'readonly': Eval('state') != 'draft',
}, depends=['state'])
company_vat = fields.Char('VAT', size=9, states={
company_vat = fields.Char('VAT', size=9,
states={
'required': Eval('state').in_(['confirmed', 'done']),
'readonly': ~Eval('state').in_(['draft', 'confirmed']),
}, depends=['state'])
},
depends=['state'])
currency = fields.Function(fields.Many2One('currency.currency',
'Currency'), 'on_change_with_currency')
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
@ -275,21 +278,21 @@ class SIIReport(Workflow, ModelSQL, ModelView):
('done', 'Done'),
('cancelled', 'Cancelled'),
('sent', 'Sent'),
], 'State', readonly=True)
], 'State', readonly=True)
communication_state = fields.Selection(AEAT_COMMUNICATION_STATE,
'Communication State', readonly=True)
csv = fields.Char('CSV', readonly=True)
version = fields.Selection([
('0.7', '0.7'),
('1.0', '1.0'),
], 'Version', required=True,
('1.0', '1.0'),
], 'Version', required=True,
states={
'readonly': Eval('state') != 'draft',
},
},
depends=['state'])
lines = fields.One2Many('aeat.sii.report.lines', 'report',
'Lines', states={
'readonly': Eval('state') != 'draft',
'readonly': Eval('state') != 'draft',
}, depends=['state'])
# TODO crash GTK client 4.x with widget date in XML view and attribute
# readonly = True. At the moment, use PYSON to readonly field in XML views.
@ -567,8 +570,10 @@ class SIIReport(Workflow, ModelSQL, ModelView):
base=_decimal(detail.BaseImponible),
rate=_decimal(detail.TipoImpositivo),
amount=_decimal(detail.CuotaRepercutida),
surcharge_rate=_decimal(detail.TipoRecargoEquivalencia),
surcharge_amount=_decimal(detail.CuotaRecargoEquivalencia),
surcharge_rate=_decimal(
detail.TipoRecargoEquivalencia),
surcharge_amount=_decimal(
detail.CuotaRecargoEquivalencia),
)
for detail in reg.DatosFacturaEmitida.TipoDesglose.
DesgloseFactura.Sujeta.NoExenta.DesgloseIVA.DetalleIVA
@ -706,10 +711,13 @@ class SIIReport(Workflow, ModelSQL, ModelView):
base=_decimal(detail.BaseImponible),
rate=_decimal(detail.TipoImpositivo),
amount=_decimal(detail.CuotaSoportada),
surcharge_rate=_decimal(detail.TipoRecargoEquivalencia),
surcharge_amount=_decimal(detail.CuotaRecargoEquivalencia),
surcharge_rate=_decimal(
detail.TipoRecargoEquivalencia),
surcharge_amount=_decimal(
detail.CuotaRecargoEquivalencia),
reagyp_rate=_decimal(detail.PorcentCompensacionREAGYP),
reagyp_amount=_decimal(detail.ImporteCompensacionREAGYP),
reagyp_amount=_decimal(
detail.ImporteCompensacionREAGYP),
)
for detail in reg.DatosFacturaRecibida.
DesgloseFactura.DesgloseIVA.DetalleIVA

View File

@ -3,9 +3,10 @@
from decimal import Decimal
from trytond.model import ModelView, fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
from trytond.pyson import Eval, Bool
from trytond.transaction import Transaction
from sql import Null
from sql.aggregate import Max
from .aeat import (
@ -35,7 +36,7 @@ class Invoice:
sii_received_key = fields.Selection(RECEIVE_SPECIAL_REGIME_KEY,
'SII Recived Key',
states={
'invisible': ~Eval('sii_book_key').in_(['R']),
'invisible': ~Eval('sii_book_key').in_(['R']),
}, depends=['sii_book_key'])
sii_subjected_key = fields.Selection(IVA_SUBJECTED, 'Subjected')
sii_excemption_key = fields.Selection(EXCEMPTION_CAUSE,
@ -62,7 +63,7 @@ class Invoice:
cls._check_modify_exclude += sii_fields
cls._buttons.update({
'reset_sii_keys': {
'invisible': Eval('sii_state', None) != None,
'invisible': Bool(Eval('sii_state', None)),
'icon': 'tryton-executable'}
})
if hasattr(cls, '_intercompany_excluded_fields'):
@ -101,16 +102,17 @@ class Invoice:
c.remove(None)
c0 = []
if clause[-1] == None or is_none:
if clause[-1] is None or is_none:
c0 = [('id', 'not in', invoices)]
clause2 = [tuple(('state',)) + tuple(clause[1:])] + \
[('id', 'in', lines)]
clause2 = [tuple(('state',)) + tuple(clause[1:]),
('id', 'in', lines)]
res_lines = SIILines.search(clause2)
if is_none:
return ['OR', c0, [('id', 'in', [x.invoice.id for x in res_lines])]]
return ['OR', c0, [
('id', 'in', [x.invoice.id for x in res_lines])]]
else:
return [('id', 'in', [x.invoice.id for x in res_lines])]
@ -132,7 +134,7 @@ class Invoice:
cursor.execute(*table.select(Max(table.id), table.invoice,
where=(table.invoice.in_([x.id for x in invoices]) &
(table.state != None)),
(table.state != Null)),
group_by=table.invoice))
lines = [a[0] for a in cursor.fetchall()]
@ -140,7 +142,7 @@ class Invoice:
if lines:
cursor.execute(*join.select(table.state, report.operation_type,
table.invoice,
where=((table.id.in_(lines)) & (table.state != None) &
where=((table.id.in_(lines)) & (table.state != Null) &
(table.company == report.company))))
for state, op, inv in cursor.fetchall():

View File

@ -4,17 +4,21 @@
from setuptools import setup
import re
import os
import ConfigParser
import io
try:
from configparser import ConfigParser
except ImportError:
from ConfigParser import ConfigParser
MODULE = 'aeat_sii'
PREFIX = 'trytonspain'
MODULE2PREFIX = {
'account_es': 'trytonspain'
}
MODULE2PREFIX = {}
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
return io.open(
os.path.join(os.path.dirname(__file__), fname),
'r', encoding='utf-8').read()
def get_require_version(name):
@ -26,7 +30,7 @@ def get_require_version(name):
major_version, minor_version + 1)
return require
config = ConfigParser.ConfigParser()
config = ConfigParser()
config.readfp(open('tryton.cfg'))
info = dict(config.items('tryton'))
for key in ('depends', 'extras_depend', 'xml'):
@ -41,17 +45,20 @@ minor_version = int(minor_version)
requires = [
'cryptography',
'pyOpenSSL',
'pyAEATsii>=0.2.4'
]
'pyAEATsii>=0.2.4',
'python-sql',
]
for dep in info.get('depends', []):
if not re.match(r'(ir|res|webdav)(\W|$)', dep):
if not re.match(r'(ir|res)(\W|$)', dep):
prefix = MODULE2PREFIX.get(dep, 'trytond')
requires.append('%s_%s >= %s.%s, < %s.%s' %
(prefix, dep, major_version, minor_version,
major_version, minor_version + 1))
requires.append(get_require_version('%s_%s' % (prefix, dep)))
requires.append(get_require_version('trytond'))
tests_require = [get_require_version('proteus')]
dependency_links = []
if minor_version % 2:
# Add development index for testing with proteus
dependency_links.append('https://trydevpi.tryton.org/')
setup(name='%s_%s' % (PREFIX, MODULE),
version=version,
@ -68,7 +75,7 @@ setup(name='%s_%s' % (PREFIX, MODULE),
],
package_data={
'trytond.modules.%s' % MODULE: (info.get('xml', [])
+ ['tryton.cfg', 'locale/*.po', 'tests/*.rst', 'view/*.xml']),
+ ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
},
classifiers=[
'Development Status :: 5 - Production/Stable',
@ -88,12 +95,17 @@ setup(name='%s_%s' % (PREFIX, MODULE),
'Natural Language :: Russian',
'Natural Language :: Spanish',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Office/Business',
],
license='GPL-3',
install_requires=requires,
dependency_links=dependency_links,
zip_safe=False,
entry_points="""
[trytond.modules]
@ -102,4 +114,8 @@ setup(name='%s_%s' % (PREFIX, MODULE),
test_suite='tests',
test_loader='trytond.test_loader:Loader',
tests_require=tests_require,
use_2to3=True,
convert_2to3_doctests=[
'tests/scenario_aeat_sii.rst',
],
)

View File

@ -1,3 +1,8 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from .test_aeat_sii import suite
try:
from trytond.modules.aeat_sii.tests.test_aeat_sii import suite
except ImportError:
from .test_aeat_sii import suite
__all__ = ['suite']

View File

@ -13,15 +13,10 @@ Imports::
... get_company
>>> from trytond.modules.account.tests.tools import create_fiscalyear, \
... create_chart, get_accounts, create_tax, set_tax_code
>>> from.trytond.modules.account_invoice.tests.tools import \
>>> from trytond.modules.account_invoice.tests.tools import \
... set_fiscalyear_invoice_sequences
>>> today = datetime.date.today()
Create database::
>>> config = config.set_trytond()
>>> config.pool.test = True
Install account_sii::
>>> config = activate_modules('aeat_sii')

View File

@ -3,18 +3,18 @@
# copyright notices and license terms.
import unicodedata
src_chars = """"/*+?¿!$[]{}@#`^:;<>=~%\\"""
src_chars = unicode(src_chars, 'iso-8859-1')
dst_chars = """________________________"""
dst_chars = unicode(dst_chars, 'iso-8859-1')
src_chars = u"/*+?¿!$[]{}@#`^:;<>=~%\\"
dst_chars = u"________________________"
def normalize(text):
if isinstance(text, unicode):
text = text.encode('utf-8')
return text
def unaccent(text):
if isinstance(text, str):
if isinstance(text, bytes):
text = unicode(text, 'utf-8')
output = text
for c in xrange(len(src_chars)):

18
tox.ini Normal file
View File

@ -0,0 +1,18 @@
[tox]
envlist = {py27,py34,py35,py36}-{sqlite,postgresql,mysql},pypy-{sqlite,postgresql}
[testenv]
commands = {envpython} setup.py test
deps =
{py27,py34,py35,py36}-postgresql: psycopg2 >= 2.5
pypy-postgresql: psycopg2cffi >= 2.5
mysql: MySQL-python
sqlite: sqlitebck
setenv =
sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
mysql: TRYTOND_DATABASE_URI={env:MYSQL_URI:mysql://}
sqlite: DB_NAME={env:SQLITE_NAME::memory:}
postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
mysql: DB_NAME={env:MYSQL_NAME:test}
install_command = pip install --pre --process-dependency-links {opts} {packages}

View File

@ -1,5 +1,5 @@
[tryton]
version=4.3.0
version=4.7.0
depends:
account_invoice
extras_depend: