Add extra dependency of aeat_349 to consider cost invoice as ammendment in 349 report.

This commit refs #26881
This commit is contained in:
ramon.vidal 2023-09-20 19:50:20 +02:00 committed by Sergio Morillo
parent c4a41da4c0
commit f904d51495
9 changed files with 481 additions and 2 deletions

View File

@ -25,3 +25,8 @@ def register():
intrastat.InvoiceLine,
module='sale_cost_apply_invoice', type_='model',
depends=['intrastat'])
Pool.register(
sale_cost.CostType349,
invoice.InvoiceLine349,
module='sale_cost_apply_invoice', type_='model',
depends=['aeat_349'])

View File

@ -90,3 +90,27 @@ class InvoiceLineSaleInfo(metaclass=PoolMeta):
attributes.remove(attribute)
return attributes
class InvoiceLine349(metaclass=PoolMeta):
__name__ = 'account.invoice.line'
def _get_aeat_349_ammendment_line(self):
pool = Pool()
SaleLine = pool.get('sale.line')
SaleCost = pool.get('sale.cost')
if (self.origin
and isinstance(self.origin, SaleCost)
and self.origin.type_.aeat_349_ammendment
and self.origin.sale.invoices):
for line in self.origin.sale.invoices[0].lines:
if (line.type == 'line'
and line.origin
and isinstance(line.origin, SaleLine)
and line.origin.sale == self.origin.sale):
return line
else:
return
return super()._get_aeat_349_ammendment_line()

View File

@ -58,4 +58,8 @@ msgstr "Todo"
msgctxt "field:sale.cost.type,declare_intrastat:"
msgid "Declare Intrastat"
msgstr "Declarar en Intrastat"
msgstr "Declarar en Intrastat"
msgctxt "field:sale.cost.type,aeat_349_ammendment:"
msgid "AEAT 349 ammendment"
msgstr "Rectificación en AEAT 349"

View File

@ -2,7 +2,7 @@
# copyright notices and license terms.
from trytond.pool import PoolMeta
from trytond.model import fields
from trytond.pyson import Eval, Not, And, In
from trytond.pyson import Eval, Not, And, In, Equal
from trytond.modules.document_cost_apply_invoice.cost import (
ApplyMethodCostMixin, ApplyMethodCostDocumentMixin,
ApplyInvoiceAccountMixin
@ -96,3 +96,12 @@ class SaleCostDiscount(metaclass=PoolMeta):
line.discount = 0
line.gross_unit_price = line.unit_price
return lines
class CostType349(metaclass=PoolMeta):
__name__ = 'sale.cost.type'
aeat_349_ammendment = fields.Boolean('AEAT 349 ammendment',
states={
'invisible': Not(Equal(Eval('apply_method', ''), 'invoice_out'))
}, depends=['apply_method'])

View File

@ -94,4 +94,11 @@
<field name="group" ref="sale_cost.group_sale_cost"/>
</record>
</data>
<data depends="aeat_349">
<record model="ir.ui.view" id="cost_type_349_view_form">
<field name="model">sale.cost.type</field>
<field name="inherit" ref="sale_cost.cost_type_view_form"/>
<field name="name">cost_type_349_form</field>
</record>
</data>
</tryton>

View File

@ -0,0 +1,378 @@
================================
Sale Cost Apply Invoice Scenario
================================
Imports::
>>> import datetime
>>> from trytond.tests.tools import activate_modules
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
>>> from operator import attrgetter
>>> from proteus import Model, Wizard, Report
>>> from trytond.modules.company.tests.tools import create_company, \
... get_company
>>> from trytond.modules.account.tests.tools import create_fiscalyear, \
... create_chart, get_accounts, create_tax, create_tax_code
>>> from trytond.modules.account_invoice.tests.tools import \
... set_fiscalyear_invoice_sequences, create_payment_term
>>> from trytond.modules.currency.tests.tools import get_currency
Install sale_cost_apply_invoice::
>>> config = activate_modules(['sale_cost_apply_invoice', 'aeat_349'])
Get Models::
>>> A349Type = Model.get('aeat.349.type')
>>> CostTemplate = Model.get('sale.cost.template')
>>> CostType = Model.get('sale.cost.type')
>>> Party = Model.get('party.party')
>>> Product = Model.get('product.product')
>>> ProductCategory = Model.get('product.category')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> Report = Model.get('aeat.349.report')
>>> Sale = Model.get('sale.sale')
>>> SaleCost = Model.get('sale.cost')
>>> Tax = Model.get('account.tax')
>>> TaxCode = Model.get('account.tax.code')
>>> InvoiceLine = Model.get('account.invoice.line')
>>> Invoice = Model.get('account.invoice')
Create company::
>>> eur = get_currency('EUR')
>>> _ = create_company(currency=eur)
>>> company = get_company()
Create fiscal year::
>>> fiscalyear = set_fiscalyear_invoice_sequences(
... create_fiscalyear(company))
>>> fiscalyear.click('create_period')
>>> today = datetime.date.today()
Create chart of accounts::
>>> _ = create_chart(company)
>>> accounts = get_accounts(company)
>>> receivable = accounts['receivable']
>>> revenue = accounts['revenue']
>>> expense = accounts['expense']
>>> account_tax = accounts['tax']
Create AEAT 349::
>>> operation_key_e, = A349Type.find([('operation_key', '=', 'E')])
>>> operation_key_a, = A349Type.find([('operation_key', '=', 'A')])
>>> operation_key_a_e, = A349Type.find([('operation_key', '=', 'A-E')])
Create tax::
>>> tax = create_tax(Decimal('.10'))
>>> tax.aeat349_operation_keys.append(operation_key_e)
>>> tax.aeat349_operation_keys.append(operation_key_a)
>>> tax.aeat349_operation_keys.append(operation_key_a_e)
>>> tax.aeat349_default_out_operation_key = operation_key_e
>>> tax.aeat349_default_in_operation_key = operation_key_a
>>> tax.aeat349_default_out_ammendment_key = operation_key_a_e
>>> tax.save()
>>> invoice_base_code = create_tax_code(tax, 'base', 'invoice')
>>> invoice_base_code.save()
>>> invoice_tax_code = create_tax_code(tax, 'tax', 'invoice')
>>> invoice_tax_code.save()
>>> credit_note_base_code = create_tax_code(tax, 'base', 'credit')
>>> credit_note_base_code.save()
>>> credit_note_tax_code = create_tax_code(tax, 'tax', 'credit')
>>> credit_note_tax_code.save()
Create account categories::
>>> account_category = ProductCategory(name="Account Category")
>>> account_category.accounting = True
>>> account_category.account_expense = expense
>>> account_category.account_revenue = revenue
>>> account_category.save()
>>> account_category_tax, = account_category.duplicate()
>>> account_category_tax.customer_taxes.append(tax)
>>> account_category_tax.save()
Create parties::
>>> customer = Party(name='Customer')
>>> customer.save()
>>> address = customer.addresses.new()
>>> address.name = 'Address 2'
>>> customer.save()
Create product::
>>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
>>> gram, = ProductUom.find([('name', '=', 'Gram')])
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> template = ProductTemplate()
>>> template.name = 'product 1'
>>> template.default_uom = kg
>>> template.type = 'goods'
>>> template.salable = True
>>> template.list_price = Decimal('10')
>>> template.cost_price = Decimal('5')
>>> template.cost_price_method = 'fixed'
>>> template.account_category = account_category_tax
>>> template.save()
>>> product1 = template.products[0]
>>> template = ProductTemplate()
>>> template.name = 'product 2'
>>> template.default_uom = kg
>>> template.type = 'goods'
>>> template.salable = True
>>> template.list_price = Decimal('30')
>>> template.cost_price = Decimal('10')
>>> template.cost_price_method = 'fixed'
>>> template.account_category = account_category_tax
>>> template.save()
>>> product2 = template.products[0]
>>> template = ProductTemplate()
>>> template.name = 'service'
>>> template.default_uom = unit
>>> template.type = 'service'
>>> template.salable = True
>>> template.list_price = Decimal('50')
>>> template.cost_price = Decimal('20')
>>> template.cost_price_method = 'fixed'
>>> template.account_category = account_category_tax
>>> template.save()
>>> service = template.products[0]
Create payment term::
>>> payment_term = create_payment_term()
>>> payment_term.save()
Create cost type invoice out::
>>> cost_type_invoice_out = CostType(name='Invoice out')
>>> cost_type_invoice_out.product = service
>>> cost_type_invoice_out.apply_method = 'invoice_out'
>>> cost_type_invoice_out.formula = '0.3*untaxed_amount'
>>> cost_type_invoice_out.aeat_349_ammendment = True
>>> cost_type_invoice_out.invoice_party = customer
>>> cost_type_invoice_out.manual = True
>>> cost_type_invoice_out.save()
Sale 2 products::
>>> sale = Sale()
>>> sale.party = customer
>>> sale.payment_term = payment_term
>>> sale.invoice_method = 'order'
>>> sale_line = sale.lines.new()
>>> sale_line.product = product1
>>> sale_line.quantity = 2.0
>>> sale_line = sale.lines.new()
>>> sale_line.product = product2
>>> sale_line.quantity = 300.0
>>> sale_line.unit = gram
>>> cost = sale.costs.new()
>>> cost.type_ = cost_type_invoice_out
>>> sale.click('distribute_costs')
>>> sale.click('quote')
>>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
(Decimal('29.00'), Decimal('2.90'), Decimal('31.90'))
>>> sale.click('confirm')
Get invoice::
>>> sale.reload()
>>> invoice, = sale.invoices
>>> invoice.invoice_date = today
>>> invoice.click('post')
Create invoice cost::
>>> invoice_cost_line, = InvoiceLine.find([
... ('origin', 'like', 'sale.cost%'),
... ('invoice', '=', None)])
>>> invoice_cost_line.amount
Decimal('-8.70')
>>> invoice_cost_line.aeat349_operation_key == operation_key_a_e
True
>>> invoice_cost = Invoice()
>>> invoice_cost.invoice_date = today
>>> invoice_cost.party = customer
>>> invoice_cost.payment_term = payment_term
>>> invoice_cost.lines.append(invoice_cost_line)
>>> invoice_cost.save()
>>> invoice_cost_line, = invoice_cost.lines
>>> invoice_cost.click('post')
Generate 349 Report::
>>> report = Report()
>>> report.year = today.year
>>> report.period = "%02d" % (today.month)
>>> report.company_vat = '123456789'
>>> report.contact_name = 'Guido van Rosum'
>>> report.contact_phone = '987654321'
>>> report.representative_vat = '22334455'
>>> report.click('calculate')
>>> report.operation_amount
Decimal('20.30')
>>> report.ammendment_amount
Decimal('0.0')
>>> len(report.operations)
1
>>> len(report.ammendments)
0
Refund invoice::
>>> credit = Wizard('account.invoice.credit', [invoice])
>>> credit.form.with_refund = True
>>> credit.form.invoice_date = today
>>> credit.execute('credit')
Recompute 349 Report::
>>> report.click('draft')
>>> report.click('calculate')
>>> report.operation_amount
Decimal('-8.70')
>>> report.ammendment_amount
Decimal('0.0')
>>> len(report.operations)
1
>>> len(report.ammendments)
0
Sale2 2 products::
>>> sale2 = Sale()
>>> sale2.party = customer
>>> sale2.payment_term = payment_term
>>> sale2.invoice_method = 'order'
>>> sale_line = sale2.lines.new()
>>> sale_line.product = product1
>>> sale_line.quantity = 2.0
>>> sale_line = sale2.lines.new()
>>> sale_line.product = product2
>>> sale_line.quantity = 300.0
>>> sale_line.unit = gram
>>> cost = sale2.costs.new()
>>> cost.type_ = cost_type_invoice_out
>>> sale2.click('distribute_costs')
>>> sale2.click('quote')
>>> sale2.click('confirm')
>>> sale2.untaxed_amount
Decimal('29.00')
Get invoice2::
>>> sale2.reload()
>>> invoice2, = sale2.invoices
>>> invoice2.invoice_date = today
>>> invoice2.click('post')
Create invoice cost::
>>> invoice_date = today + relativedelta(months=1)
>>> invoice_cost_line, = InvoiceLine.find([
... ('origin', 'like', 'sale.cost%'),
... ('invoice', '=', None)])
>>> invoice_cost_line.amount
Decimal('-8.70')
>>> invoice_cost2 = Invoice()
>>> invoice_cost2.invoice_date = invoice_date
>>> invoice_cost2.party = customer
>>> invoice_cost2.payment_term = payment_term
>>> invoice_cost2.lines.append(invoice_cost_line)
>>> invoice_cost2.click('post')
Recompute 349 Report::
>>> report.click('draft')
>>> report.click('calculate')
>>> report.operation_amount
Decimal('20.30')
>>> report.ammendment_amount
Decimal('0.0')
>>> len(report.operations)
1
>>> len(report.ammendments)
0
Generate 349 Report next month::
>>> report2 = Report()
>>> report2.year = invoice_date.year
>>> report2.period = "%02d" % (invoice_date.month)
>>> report2.company_vat = '123456789'
>>> report2.contact_name = 'Guido van Rosum'
>>> report2.contact_phone = '987654321'
>>> report2.representative_vat = '22334455'
>>> report2.click('calculate')
>>> report2.operation_amount
Decimal('0.0')
>>> report2.ammendment_amount
Decimal('8.70')
>>> len(report2.operations)
0
>>> len(report2.ammendments)
1
Refund invoice (today + 1 month)::
>>> credit = Wizard('account.invoice.credit', [invoice2])
>>> credit.form.with_refund = True
>>> credit.form.invoice_date = invoice_date
>>> credit.execute('credit')
Generate 349 Report (today + 1 month)::
>>> report2.click('draft')
>>> report2.click('calculate')
>>> report2.operation_amount
Decimal('0.0')
>>> report2.ammendment_amount
Decimal('37.70')
>>> len(report2.operations)
0
>>> len(report2.ammendments)
1
>>> len(report2.ammendments[0].invoice_lines)
3

View File

@ -0,0 +1,42 @@
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
import unittest
import doctest
from trytond.tests.test_tryton import ModuleTestCase
from trytond.tests.test_tryton import suite as test_suite
from trytond.tests.test_tryton import doctest_teardown
from trytond.tests.test_tryton import doctest_checker
class SaleCostApplyInvoiceTestCase(ModuleTestCase):
"""Test Sale Cost Apply Invoice module"""
module = 'sale_cost_apply_invoice'
def suite():
suite = test_suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
SaleCostApplyInvoiceTestCase))
suite.addTests(doctest.DocFileSuite(
'scenario_sale_cost_apply_invoice.rst',
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite(
'scenario_sale_cost_apply_invoice_account.rst',
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite(
'scenario_sale_cost_intrastat.rst',
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite(
'scenario_sale_cost_apply_invoice_349.rst',
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite

View File

@ -10,6 +10,7 @@ extras_depend:
account_invoice_line_sale_info
account_invoice_discount
intrastat
aeat_349
xml:
sale_cost.xml

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<data>
<xpath expr="/form/group[@id='checkboxes']" position="inside">
<label name="aeat_349_ammendment"/>
<field name="aeat_349_ammendment" xexpand="0" width="100"/>
</xpath>
</data>