2301 lines
88 KiB
Python
2301 lines
88 KiB
Python
# 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 datetime
|
|
from decimal import Decimal
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from trytond.exceptions import UserError
|
|
from trytond.model.exceptions import SQLConstraintError
|
|
from trytond.modules.account.exceptions import PeriodDatesError
|
|
from trytond.modules.account.tax import TaxableMixin
|
|
from trytond.modules.company.tests import (
|
|
CompanyTestMixin, PartyCompanyCheckEraseMixin, create_company, set_company)
|
|
from trytond.modules.currency.tests import create_currency
|
|
from trytond.modules.party.tests import PartyCheckReplaceMixin
|
|
from trytond.pool import Pool
|
|
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
|
from trytond.transaction import Transaction, inactive_records
|
|
|
|
|
|
def create_chart(company, tax=False, chart='account.account_template_root_en'):
|
|
pool = Pool()
|
|
AccountTemplate = pool.get('account.account.template')
|
|
TaxTemplate = pool.get('account.tax.template')
|
|
TaxCodeTemplate = pool.get('account.tax.code.template')
|
|
ModelData = pool.get('ir.model.data')
|
|
CreateChart = pool.get('account.create_chart', type='wizard')
|
|
Account = pool.get('account.account')
|
|
|
|
module, xml_id = chart.split('.')
|
|
template = AccountTemplate(ModelData.get_id(module, xml_id))
|
|
if tax:
|
|
tax_account = AccountTemplate(ModelData.get_id(
|
|
'account', 'account_template_6_3_4_en'))
|
|
with Transaction().set_user(0):
|
|
tax = TaxTemplate()
|
|
tax.name = tax.description = '20% VAT'
|
|
tax.type = 'percentage'
|
|
tax.rate = Decimal('0.2')
|
|
tax.account = template
|
|
tax.invoice_account = tax_account
|
|
tax.credit_note_account = tax_account
|
|
tax.save()
|
|
|
|
TaxCodeTemplate.create([{
|
|
'name': 'Tax Code',
|
|
'account': template,
|
|
'lines': [('create', [{
|
|
'operator': '+',
|
|
'type': 'invoice',
|
|
'amount': 'tax',
|
|
'tax': tax.id,
|
|
}])],
|
|
}, {
|
|
'name': 'Base Code',
|
|
'account': template,
|
|
'lines': [('create', [{
|
|
'operator': '+',
|
|
'type': 'invoice',
|
|
'amount': 'base',
|
|
'tax': tax.id,
|
|
}])],
|
|
}])
|
|
|
|
session_id, _, _ = CreateChart.create()
|
|
create_chart = CreateChart(session_id)
|
|
create_chart.account.account_template = template
|
|
create_chart.account.company = company
|
|
create_chart.transition_create_account()
|
|
properties_state = create_chart.states['properties']
|
|
for name, value in properties_state.get_defaults(
|
|
create_chart, 'properties',
|
|
list(create_chart.properties._fields.keys())).items():
|
|
if name in create_chart.properties._fields:
|
|
setattr(create_chart.properties, name, value)
|
|
if not create_chart.properties.account_receivable:
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('party_required', '=', True),
|
|
('company', '=', company.id),
|
|
], limit=1)
|
|
create_chart.properties.account_receivable = receivable
|
|
if not create_chart.properties.account_payable:
|
|
payable, = Account.search([
|
|
('type.payable', '=', True),
|
|
('party_required', '=', True),
|
|
('company', '=', company.id),
|
|
], limit=1)
|
|
create_chart.properties.account_payable = payable
|
|
create_chart.transition_create_properties()
|
|
|
|
|
|
def get_fiscalyear(company, today=None, start_date=None, end_date=None):
|
|
pool = Pool()
|
|
Sequence = pool.get('ir.sequence.strict')
|
|
SequenceType = pool.get('ir.sequence.type')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
|
|
if not today:
|
|
today = datetime.date.today()
|
|
if not start_date:
|
|
start_date = today.replace(month=1, day=1)
|
|
if not end_date:
|
|
end_date = today.replace(month=12, day=31)
|
|
|
|
sequence_type, = SequenceType.search([
|
|
('name', '=', "Account Move"),
|
|
], limit=1)
|
|
sequence, = Sequence.create([{
|
|
'name': '%s' % today.year,
|
|
'sequence_type': sequence_type.id,
|
|
'company': company.id,
|
|
}])
|
|
fiscalyear = FiscalYear(name='%s' % today.year, company=company)
|
|
fiscalyear.start_date = start_date
|
|
fiscalyear.end_date = end_date
|
|
fiscalyear.move_sequence = sequence
|
|
return fiscalyear
|
|
|
|
|
|
def close_fiscalyear(fiscalyear):
|
|
pool = Pool()
|
|
Journal = pool.get('account.journal')
|
|
Period = pool.get('account.period')
|
|
Account = pool.get('account.account')
|
|
Move = pool.get('account.move')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
BalanceNonDeferral = pool.get(
|
|
'account.fiscalyear.balance_non_deferral', type='wizard')
|
|
|
|
# Balance non-deferral
|
|
journal_closing, = Journal.create([{
|
|
'name': 'Closing',
|
|
'code': 'CLO',
|
|
'type': 'situation',
|
|
}])
|
|
period_closing, = Period.create([{
|
|
'name': 'Closing',
|
|
'start_date': fiscalyear.end_date,
|
|
'end_date': fiscalyear.end_date,
|
|
'fiscalyear': fiscalyear.id,
|
|
'type': 'adjustment',
|
|
}])
|
|
account_pl, = Account.search([
|
|
('code', '=', '3.2.1'),
|
|
])
|
|
|
|
session_id = BalanceNonDeferral.create()[0]
|
|
balance_non_deferral = BalanceNonDeferral(session_id)
|
|
|
|
balance_non_deferral.start.fiscalyear = fiscalyear
|
|
balance_non_deferral.start.journal = journal_closing
|
|
balance_non_deferral.start.period = period_closing
|
|
balance_non_deferral.start.credit_account = account_pl
|
|
balance_non_deferral.start.debit_account = account_pl
|
|
|
|
balance_non_deferral._execute('balance')
|
|
|
|
moves = Move.search([
|
|
('state', '=', 'draft'),
|
|
('period.fiscalyear', '=', fiscalyear.id),
|
|
])
|
|
Move.post(moves)
|
|
|
|
# Close fiscalyear
|
|
FiscalYear.close([fiscalyear])
|
|
|
|
|
|
class AccountTestCase(
|
|
PartyCompanyCheckEraseMixin, PartyCheckReplaceMixin, CompanyTestMixin,
|
|
ModuleTestCase):
|
|
'Test Account module'
|
|
module = 'account'
|
|
maxDiff = None
|
|
|
|
@with_transaction()
|
|
def test_account_chart(self):
|
|
'Test creation and update of minimal chart of accounts'
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
UpdateChart = pool.get('account.update_chart', type='wizard')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
root, = Account.search([('parent', '=', None)])
|
|
|
|
# Create an account and tax without template
|
|
|
|
cash, = Account.search([('code', '=', '1.1.1')])
|
|
Account.copy([cash.id])
|
|
|
|
tax, = Tax.search([])
|
|
Tax.copy([tax.id])
|
|
|
|
session_id, _, _ = UpdateChart.create()
|
|
update_chart = UpdateChart(session_id)
|
|
update_chart.start.account = root
|
|
update_chart.transition_update()
|
|
|
|
@with_transaction()
|
|
def test_account_chart_many_companies(self):
|
|
"Test creation of chart of accounts for many companies"
|
|
company1 = create_company()
|
|
with set_company(company1):
|
|
create_chart(company1, tax=True)
|
|
|
|
company2 = create_company()
|
|
with set_company(company2):
|
|
create_chart(company2, tax=True)
|
|
|
|
@with_transaction()
|
|
def test_fiscalyear(self):
|
|
'Test fiscalyear'
|
|
pool = Pool()
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
company = create_company()
|
|
with set_company(company):
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
self.assertEqual(len(fiscalyear.periods), 12)
|
|
|
|
@with_transaction()
|
|
def test_fiscalyear_create_periods(self):
|
|
'Test fiscalyear create periods'
|
|
FiscalYear = Pool().get('account.fiscalyear')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
year = datetime.date.today().year
|
|
date = datetime.date
|
|
for start_date, end_date, interval, end_day, num_periods in [
|
|
(date(year, 1, 1), date(year, 12, 31), 1, 31, 12),
|
|
(date(year + 1, 1, 1), date(year + 1, 12, 31), 3, 31, 4),
|
|
(date(year + 2, 1, 1), date(year + 2, 12, 31), 5, 31, 3),
|
|
(date(year + 3, 4, 6), date(year + 4, 4, 5), 1, 5, 12),
|
|
(date(year + 4, 4, 6), date(year + 5, 4, 5), 3, 5, 4),
|
|
(date(year + 5, 4, 6), date(year + 6, 4, 5), 5, 5, 3),
|
|
(date(year + 6, 6, 6), date(year + 6, 12, 31), 1, 29, 8),
|
|
(date(year + 7, 7, 7), date(year + 7, 12, 31), 3, 29, 3),
|
|
(date(year + 8, 1, 1), date(year + 9, 8, 7), 1, 29, 20),
|
|
(date(year + 9, 9, 9), date(year + 10, 11, 12), 3, 29, 5),
|
|
]:
|
|
fiscalyear = get_fiscalyear(
|
|
company, start_date, start_date, end_date)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear], interval, end_day)
|
|
|
|
self.assertEqual(len(fiscalyear.periods), num_periods)
|
|
|
|
self.assertEqual(fiscalyear.periods[-1].end_date, end_date)
|
|
self.assertTrue(all(
|
|
p.end_date == p.end_date + relativedelta(day=end_day)
|
|
for p in fiscalyear.periods[:-1]))
|
|
|
|
self.assertEqual(fiscalyear.periods[0].start_date, start_date)
|
|
self.assertTrue(all(
|
|
p1.end_date + relativedelta(days=1) == p2.start_date
|
|
for p1, p2 in zip(
|
|
fiscalyear.periods[:-1], fiscalyear.periods[1:])))
|
|
|
|
@with_transaction()
|
|
def test_open_fiscalyear_before_open(self):
|
|
"Test create open fiscal year before an open one"
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
fiscalyear = get_fiscalyear(
|
|
company,
|
|
start_date=datetime.date(2022, 1, 1),
|
|
end_date=datetime.date(2022, 12, 31))
|
|
fiscalyear.save()
|
|
|
|
earlier_fiscalyear = get_fiscalyear(
|
|
company,
|
|
start_date=datetime.date(2021, 1, 1),
|
|
end_date=datetime.date(2021, 12, 31))
|
|
earlier_fiscalyear.save()
|
|
|
|
@with_transaction()
|
|
def test_open_fiscalyear_before_close(self):
|
|
"Test create open fiscal year before a close one"
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
fiscalyear = get_fiscalyear(
|
|
company,
|
|
start_date=datetime.date(2022, 1, 1),
|
|
end_date=datetime.date(2022, 12, 31))
|
|
fiscalyear.save()
|
|
close_fiscalyear(fiscalyear)
|
|
|
|
earlier_fiscalyear = get_fiscalyear(
|
|
company,
|
|
start_date=datetime.date(2021, 1, 1),
|
|
end_date=datetime.date(2021, 12, 31))
|
|
with self.assertRaises(SQLConstraintError):
|
|
earlier_fiscalyear.save()
|
|
|
|
@with_transaction()
|
|
def test_change_fiscalyear_dates_with_periods(self):
|
|
"Test change fiscal year dates"
|
|
company = create_company()
|
|
with set_company(company):
|
|
fiscalyear = get_fiscalyear(
|
|
company,
|
|
start_date=datetime.date(2023, 1, 1),
|
|
end_date=datetime.date(2023, 12, 31))
|
|
fiscalyear.save()
|
|
fiscalyear.create_period([fiscalyear])
|
|
|
|
# Extend
|
|
fiscalyear.end_date = datetime.date(2024, 5, 31)
|
|
fiscalyear.save()
|
|
|
|
# Shorten
|
|
with self.assertRaises(PeriodDatesError):
|
|
fiscalyear.end_date = datetime.date(2023, 5, 31)
|
|
fiscalyear.save()
|
|
|
|
@with_transaction()
|
|
def test_change_period_dates_with_move(self):
|
|
"Test change period dates"
|
|
pool = Pool()
|
|
Period = pool.get('account.period')
|
|
Move = pool.get('account.move')
|
|
Journal = pool.get('account.journal')
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
|
|
period = Period(
|
|
fiscalyear=fiscalyear,
|
|
type='adjustment',
|
|
name="Period",
|
|
start_date=fiscalyear.start_date,
|
|
end_date=fiscalyear.start_date)
|
|
period.save()
|
|
|
|
journal, = Journal.search([], limit=1)
|
|
|
|
move, = Move.create([{
|
|
'period': period.id,
|
|
'journal': journal.id,
|
|
'date': period.start_date,
|
|
}])
|
|
|
|
# Extend
|
|
period.end_date = fiscalyear.end_date
|
|
period.save()
|
|
|
|
# Shorten
|
|
with self.assertRaises(PeriodDatesError):
|
|
period.start_date = fiscalyear.end_date
|
|
period.save()
|
|
|
|
@with_transaction()
|
|
def test_account_debit_credit(self):
|
|
'Test account debit/credit'
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Journal = pool.get('account.journal')
|
|
Account = pool.get('account.account')
|
|
Move = pool.get('account.move')
|
|
|
|
party = Party(name='Party')
|
|
party.save()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
period = fiscalyear.periods[0]
|
|
create_chart(company)
|
|
|
|
sec_cur = create_currency('sec')
|
|
|
|
journal_revenue, = Journal.search([
|
|
('code', '=', 'REV'),
|
|
])
|
|
journal_expense, = Journal.search([
|
|
('code', '=', 'EXP'),
|
|
])
|
|
revenue, = Account.search([
|
|
('type.revenue', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
expense, = Account.search([
|
|
('type.expense', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
payable, = Account.search([
|
|
('type.payable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
cash, = Account.search([
|
|
('code', '=', '1.1.1'),
|
|
])
|
|
cash_cur, = Account.copy([cash], default={
|
|
'second_currency': sec_cur.id,
|
|
})
|
|
# Create some moves
|
|
vlist = [
|
|
{
|
|
'period': period.id,
|
|
'journal': journal_revenue.id,
|
|
'date': period.start_date,
|
|
'lines': [
|
|
('create', [{
|
|
'account': revenue.id,
|
|
'credit': Decimal(100),
|
|
}, {
|
|
'account': receivable.id,
|
|
'debit': Decimal(100),
|
|
'party': party.id,
|
|
}]),
|
|
],
|
|
},
|
|
{
|
|
'period': period.id,
|
|
'journal': journal_revenue.id,
|
|
'date': period.start_date,
|
|
'lines': [
|
|
('create', [{
|
|
'account': receivable.id,
|
|
'credit': Decimal(80),
|
|
'second_currency': sec_cur.id,
|
|
'amount_second_currency': -Decimal(50),
|
|
'party': party.id,
|
|
}, {
|
|
'account': cash_cur.id,
|
|
'debit': Decimal(80),
|
|
'second_currency': sec_cur.id,
|
|
'amount_second_currency': Decimal(50),
|
|
}]),
|
|
],
|
|
},
|
|
{
|
|
'period': period.id,
|
|
'journal': journal_expense.id,
|
|
'date': period.start_date,
|
|
'lines': [
|
|
('create', [{
|
|
'account': expense.id,
|
|
'debit': Decimal(30),
|
|
}, {
|
|
'account': payable.id,
|
|
'credit': Decimal(30),
|
|
'party': party.id,
|
|
}]),
|
|
],
|
|
},
|
|
]
|
|
Move.create(vlist)
|
|
|
|
# Test debit/credit
|
|
self.assertEqual((revenue.debit, revenue.credit),
|
|
(Decimal(0), Decimal(100)))
|
|
self.assertEqual(revenue.balance, Decimal(-100))
|
|
|
|
self.assertEqual((cash_cur.debit, cash_cur.credit),
|
|
(Decimal(80), Decimal(0)))
|
|
self.assertEqual(
|
|
cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
# Use next fiscalyear
|
|
today = datetime.date.today()
|
|
next_fiscalyear = get_fiscalyear(company,
|
|
today=today + relativedelta(years=1))
|
|
next_fiscalyear.save()
|
|
FiscalYear.create_period([next_fiscalyear])
|
|
|
|
# Test debit/credit for next year
|
|
with Transaction().set_context(fiscalyear=next_fiscalyear.id):
|
|
revenue = Account(revenue.id)
|
|
self.assertEqual((revenue.debit, revenue.credit),
|
|
(Decimal(0), Decimal(0)))
|
|
self.assertEqual(revenue.balance, Decimal(-100))
|
|
|
|
cash_cur = Account(cash_cur.id)
|
|
self.assertEqual(
|
|
cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
# Test debit/credit cumulate for next year
|
|
with Transaction().set_context(fiscalyear=next_fiscalyear.id,
|
|
cumulate=True):
|
|
revenue = Account(revenue.id)
|
|
self.assertEqual((revenue.debit, revenue.credit),
|
|
(Decimal(0), Decimal(100)))
|
|
self.assertEqual(revenue.balance, Decimal(-100))
|
|
|
|
cash_cur = Account(cash_cur.id)
|
|
self.assertEqual(
|
|
cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
close_fiscalyear(fiscalyear)
|
|
|
|
# Check deferral
|
|
self.assertEqual(revenue.deferrals, ())
|
|
|
|
deferral_receivable, = receivable.deferrals
|
|
self.assertEqual(
|
|
(deferral_receivable.debit, deferral_receivable.credit),
|
|
(Decimal(100), Decimal(80)))
|
|
self.assertEqual(deferral_receivable.fiscalyear, fiscalyear)
|
|
|
|
cash_cur = Account(cash_cur.id)
|
|
deferral_cash_cur, = cash_cur.deferrals
|
|
self.assertEqual(
|
|
deferral_cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
# Test debit/credit
|
|
with Transaction().set_context(fiscalyear=fiscalyear.id):
|
|
revenue = Account(revenue.id)
|
|
self.assertEqual((revenue.debit, revenue.credit),
|
|
(Decimal(100), Decimal(100)))
|
|
self.assertEqual(revenue.balance, Decimal(0))
|
|
|
|
receivable = Account(receivable.id)
|
|
self.assertEqual((receivable.debit, receivable.credit),
|
|
(Decimal(100), Decimal(80)))
|
|
self.assertEqual(receivable.balance, Decimal(20))
|
|
|
|
cash_cur = Account(cash_cur.id)
|
|
self.assertEqual(
|
|
cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
# Test debit/credit for next year
|
|
with Transaction().set_context(fiscalyear=next_fiscalyear.id):
|
|
revenue = Account(revenue.id)
|
|
self.assertEqual((revenue.debit, revenue.credit),
|
|
(Decimal(0), Decimal(0)))
|
|
self.assertEqual(revenue.balance, Decimal(0))
|
|
|
|
receivable = Account(receivable.id)
|
|
self.assertEqual((receivable.debit, receivable.credit),
|
|
(Decimal(0), Decimal(0)))
|
|
self.assertEqual(receivable.balance, Decimal(20))
|
|
|
|
cash_cur = Account(cash_cur.id)
|
|
self.assertEqual(
|
|
cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
# Test debit/credit cumulate for next year
|
|
with Transaction().set_context(fiscalyear=next_fiscalyear.id,
|
|
cumulate=True):
|
|
revenue = Account(revenue.id)
|
|
self.assertEqual((revenue.debit, revenue.credit),
|
|
(Decimal(0), Decimal(0)))
|
|
self.assertEqual(revenue.balance, Decimal(0))
|
|
|
|
receivable = Account(receivable.id)
|
|
self.assertEqual((receivable.debit, receivable.credit),
|
|
(Decimal(100), Decimal(80)))
|
|
self.assertEqual(receivable.balance, Decimal(20))
|
|
|
|
cash_cur = Account(cash_cur.id)
|
|
self.assertEqual(
|
|
cash_cur.amount_second_currency, Decimal(50))
|
|
|
|
@with_transaction()
|
|
def test_account_type_amount(self):
|
|
"Test account type amount"
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Journal = pool.get('account.journal')
|
|
Account = pool.get('account.account')
|
|
Move = pool.get('account.move')
|
|
Type = pool.get('account.account.type')
|
|
|
|
party = Party(name='Party')
|
|
party.save()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
period = fiscalyear.periods[0]
|
|
create_chart(company)
|
|
|
|
journal_revenue, = Journal.search([
|
|
('code', '=', 'REV'),
|
|
])
|
|
revenue, = Account.search([
|
|
('type.revenue', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
|
|
Move.create([{
|
|
'period': period.id,
|
|
'journal': journal_revenue.id,
|
|
'date': period.start_date,
|
|
'lines': [
|
|
('create', [{
|
|
'account': revenue.id,
|
|
'credit': Decimal(100),
|
|
}, {
|
|
'account': receivable.id,
|
|
'debit': Decimal(100),
|
|
'party': party.id,
|
|
}]),
|
|
],
|
|
}])
|
|
|
|
with Transaction().set_context(fiscalyear=fiscalyear.id):
|
|
revenue_type = Type(revenue.type)
|
|
receivable_type = Type(receivable.type)
|
|
|
|
# Test type amount
|
|
self.assertEqual(revenue_type.amount, Decimal(100))
|
|
self.assertEqual(receivable_type.amount, Decimal(100))
|
|
|
|
# Set a debit type on receivable
|
|
with Transaction().set_context(fiscalyear=fiscalyear.id):
|
|
debit_receivable_type, = Type.copy([receivable_type])
|
|
receivable.debit_type = debit_receivable_type
|
|
receivable.credit_type = None
|
|
receivable.save()
|
|
self.assertEqual(receivable_type.amount, Decimal(0))
|
|
self.assertEqual(debit_receivable_type.amount, Decimal(100))
|
|
|
|
# Set a debit type on revenue
|
|
with Transaction().set_context(fiscalyear=fiscalyear.id):
|
|
debit_revenue_type, = Type.copy([revenue_type])
|
|
revenue.debit_type = debit_revenue_type
|
|
revenue.credit_type = None
|
|
revenue.save()
|
|
self.assertEqual(revenue_type.amount, Decimal(100))
|
|
self.assertEqual(debit_revenue_type.amount, Decimal(0))
|
|
|
|
# Set a credit type on revenue
|
|
with Transaction().set_context(fiscalyear=fiscalyear.id):
|
|
credit_revenue_type, = Type.copy([revenue_type])
|
|
revenue.credit_type = credit_revenue_type
|
|
revenue.debit_type = None
|
|
revenue.save()
|
|
self.assertEqual(revenue_type.amount, Decimal(0))
|
|
self.assertEqual(credit_revenue_type.amount, Decimal(100))
|
|
|
|
# Set a credit type on receivable
|
|
with Transaction().set_context(fiscalyear=fiscalyear.id):
|
|
credit_receivable_type, = Type.copy([receivable_type])
|
|
receivable.credit_type = credit_receivable_type
|
|
receivable.debit_type = None
|
|
receivable.save()
|
|
self.assertEqual(receivable_type.amount, Decimal(100))
|
|
self.assertEqual(credit_receivable_type.amount, Decimal(0))
|
|
|
|
@with_transaction()
|
|
def test_move_post(self):
|
|
"Test posting move"
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Journal = pool.get('account.journal')
|
|
Account = pool.get('account.account')
|
|
Move = pool.get('account.move')
|
|
Line = pool.get('account.move.line')
|
|
Period = pool.get('account.period')
|
|
|
|
party = Party(name='Party')
|
|
party.save()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
period = fiscalyear.periods[0]
|
|
create_chart(company)
|
|
|
|
journal_revenue, = Journal.search([
|
|
('code', '=', 'REV'),
|
|
])
|
|
revenue, = Account.search([
|
|
('type.revenue', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
|
|
move = Move()
|
|
move.period = period
|
|
move.journal = journal_revenue
|
|
move.date = period.start_date
|
|
move.lines = [
|
|
Line(account=revenue, credit=Decimal(100)),
|
|
Line(account=receivable, debit=Decimal(100), party=party),
|
|
]
|
|
move.save()
|
|
Move.post([move])
|
|
move_id = move.id
|
|
|
|
self.assertEqual(move.state, 'posted')
|
|
|
|
# Move lines with debit = credit = 0 are automatically reconciled
|
|
receivable_no_party, = Account.copy([receivable], default={
|
|
'party_required': False,
|
|
})
|
|
move = Move()
|
|
move.period = period
|
|
move.journal = journal_revenue
|
|
move.date = period.start_date
|
|
move.lines = [
|
|
Line(account=receivable_no_party, credit=Decimal(0)),
|
|
Line(account=receivable, debit=Decimal(0), party=party),
|
|
]
|
|
move.save()
|
|
Move.post([move])
|
|
|
|
lines = Line.browse([l.id for l in move.lines
|
|
if l.account.reconcile])
|
|
self.assertTrue(all(bool(l.reconciliation) for l in lines))
|
|
|
|
# Can not post an empty move
|
|
with self.assertRaises(UserError):
|
|
move = Move()
|
|
move.period = period
|
|
move.journal = journal_revenue
|
|
move.date = period.start_date
|
|
move.save()
|
|
Move.post([move])
|
|
Move.delete([move])
|
|
|
|
# Can not modify posted move
|
|
with self.assertRaises(UserError):
|
|
move = Move(move_id)
|
|
move.date = period.end_date
|
|
move.save()
|
|
|
|
# Can not go back to draft
|
|
with self.assertRaises(UserError):
|
|
move = Move(move_id)
|
|
move.state = 'draft'
|
|
move.save()
|
|
|
|
Period.close([period])
|
|
|
|
# Can not create move with lines on closed period
|
|
with self.assertRaises(UserError):
|
|
move = Move()
|
|
move.period = period
|
|
move.journal = journal_revenue
|
|
move.date = period.start_date
|
|
move.lines = [
|
|
Line(account=revenue, credit=Decimal(100)),
|
|
Line(account=receivable, debit=Decimal(100), party=party),
|
|
]
|
|
move.save()
|
|
|
|
@with_transaction()
|
|
def test_find_best_reconciliation(self):
|
|
"Test find best reconciliation"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Journal = pool.get('account.journal')
|
|
Line = pool.get('account.move.line')
|
|
Move = pool.get('account.move')
|
|
Party = pool.get('party.party')
|
|
|
|
party = Party(name='Party')
|
|
party.save()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
period = fiscalyear.periods[0]
|
|
journal_revenue, = Journal.search([
|
|
('code', '=', 'REV'),
|
|
])
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
currency = company.currency
|
|
|
|
move = Move()
|
|
move.period = period
|
|
move.journal = journal_revenue
|
|
move.date = period.start_date
|
|
move.save()
|
|
|
|
line1 = Line(
|
|
move=move, party=party,
|
|
debit=Decimal(10), credit=0,
|
|
account=receivable,
|
|
maturity_date=datetime.date(2024, 1, 1))
|
|
line2 = Line(
|
|
move=move, party=party,
|
|
debit=0, credit=Decimal(10),
|
|
account=receivable,
|
|
maturity_date=datetime.date(2024, 1, 2))
|
|
line3 = Line(
|
|
move=move, party=party,
|
|
debit=0, credit=Decimal(5),
|
|
account=receivable,
|
|
maturity_date=datetime.date(2024, 1, 3))
|
|
Line.save([line1, line2, line3])
|
|
|
|
for (lines, amount, best, remaining) in [
|
|
([line1], 0, [line1], Decimal('10')),
|
|
([line1], Decimal(10), [line1], Decimal(0)),
|
|
([line1], Decimal(3), [line1], Decimal(7)),
|
|
([line1, line2], 0, [line1, line2], Decimal(0)),
|
|
([line1, line2], Decimal(10), [line1], Decimal(0)),
|
|
([line1, line2], Decimal(-10), [line2], Decimal(0)),
|
|
([line1, line2], Decimal(20), [line1], Decimal(-10)),
|
|
([line1, line2], Decimal(-3), [line1, line2], Decimal(3)),
|
|
([line1, line2], Decimal(-9), [line2], Decimal(-1)),
|
|
([line1, line3], 0, [line1, line3], Decimal(5)),
|
|
([line1, line2, line3], 0, [line1, line2], Decimal(0)),
|
|
]:
|
|
with self.subTest(lines=lines, amount=amount):
|
|
self.assertEqual(
|
|
Line.find_best_reconciliation(lines, currency, amount),
|
|
(best, remaining))
|
|
|
|
@with_transaction()
|
|
def test_find_best_reconciliation_currency(self):
|
|
"Test find best reconciliation with different currencies"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Journal = pool.get('account.journal')
|
|
Line = pool.get('account.move.line')
|
|
Move = pool.get('account.move')
|
|
Party = pool.get('party.party')
|
|
|
|
currency1 = create_currency('USD')
|
|
currency2 = create_currency('EUR')
|
|
|
|
party = Party(name='Party')
|
|
party.save()
|
|
|
|
company = create_company(currency=currency1)
|
|
with set_company(company):
|
|
create_chart(company)
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
period = fiscalyear.periods[0]
|
|
journal_revenue, = Journal.search([
|
|
('code', '=', 'REV'),
|
|
])
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
|
|
move = Move()
|
|
move.period = period
|
|
move.journal = journal_revenue
|
|
move.date = period.start_date
|
|
move.save()
|
|
|
|
line1 = Line(
|
|
move=move, party=party,
|
|
debit=Decimal(10), credit=0,
|
|
second_currency=currency2,
|
|
amount_second_currency=Decimal(10),
|
|
account=receivable,
|
|
maturity_date=datetime.date(2024, 1, 1))
|
|
line2 = Line(
|
|
move=move, party=party,
|
|
debit=0, credit=Decimal(20),
|
|
second_currency=currency2,
|
|
amount_second_currency=Decimal('-10'),
|
|
account=receivable, maturity_date=datetime.date(2024, 1, 1))
|
|
line3 = Line(
|
|
move=move, party=party,
|
|
debit=0, credit=Decimal(5),
|
|
second_currency=None, account=receivable,
|
|
maturity_date=datetime.date(2024, 1, 3))
|
|
Line.save([line1, line2, line3])
|
|
|
|
self.assertEqual(
|
|
Line.find_best_reconciliation(
|
|
[line1, line2, line3], currency2),
|
|
([line1, line2], Decimal(0)))
|
|
|
|
@with_transaction()
|
|
def test_tax_compute(self):
|
|
'Test tax compute/reverse_compute'
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
today = datetime.date.today()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
tax = Tax()
|
|
tax.name = tax.description = 'Test'
|
|
tax.type = 'none'
|
|
tax.invoice_account = tax_account
|
|
tax.credit_note_account = tax_account
|
|
|
|
child1 = Tax()
|
|
child1.name = child1.description = 'Child 1'
|
|
child1.type = 'percentage'
|
|
child1.rate = Decimal('0.2')
|
|
child1.invoice_account = tax_account
|
|
child1.credit_note_account = tax_account
|
|
child1.save()
|
|
|
|
child2 = Tax()
|
|
child2.name = child2.description = 'Child 1'
|
|
child2.type = 'fixed'
|
|
child2.amount = Decimal('10')
|
|
child2.invoice_account = tax_account
|
|
child2.credit_note_account = tax_account
|
|
child2.save()
|
|
|
|
tax.childs = [child1, child2]
|
|
tax.save()
|
|
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2, today),
|
|
[{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('40.0'),
|
|
'tax': child1,
|
|
}, {
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('130'), [tax], today),
|
|
Decimal('100'))
|
|
|
|
child1.end_date = today + relativedelta(days=5)
|
|
child1.save()
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2, today),
|
|
[{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('40.0'),
|
|
'tax': child1,
|
|
}, {
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('130'), [tax], today),
|
|
Decimal('100'))
|
|
|
|
child1.start_date = today + relativedelta(days=1)
|
|
child1.save()
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2, today),
|
|
[{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('110'), [tax], today),
|
|
Decimal('100'))
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2,
|
|
today + relativedelta(days=1)), [{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('40.0'),
|
|
'tax': child1,
|
|
}, {
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal('130'), [tax], today + relativedelta(days=1)),
|
|
Decimal('100'))
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2,
|
|
today + relativedelta(days=5)), [{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('40.0'),
|
|
'tax': child1,
|
|
}, {
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('130'), [tax],
|
|
today + relativedelta(days=5)),
|
|
Decimal('100'))
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2,
|
|
today + relativedelta(days=6)), [{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('110'), [tax],
|
|
today + relativedelta(days=6)),
|
|
Decimal('100'))
|
|
|
|
child1.end_date = None
|
|
child1.save()
|
|
self.assertEqual(Tax.compute([tax], Decimal('100'), 2,
|
|
today + relativedelta(days=6)), [{
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('40.0'),
|
|
'tax': child1,
|
|
}, {
|
|
'base': Decimal('200'),
|
|
'amount': Decimal('20'),
|
|
'tax': child2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('130'), [tax],
|
|
today + relativedelta(days=6)),
|
|
Decimal('100'))
|
|
|
|
ecotax1 = Tax()
|
|
ecotax1.name = ecotax1.description = 'EcoTax 1'
|
|
ecotax1.type = 'fixed'
|
|
ecotax1.amount = Decimal(5)
|
|
ecotax1.invoice_account = tax_account
|
|
ecotax1.credit_note_account = tax_account
|
|
ecotax1.sequence = 10
|
|
ecotax1.save()
|
|
|
|
vat0 = Tax()
|
|
vat0.name = vat0.description = 'VAT0'
|
|
vat0.type = 'percentage'
|
|
vat0.rate = Decimal('0.1')
|
|
vat0.invoice_account = tax_account
|
|
vat0.credit_note_account = tax_account
|
|
vat0.sequence = 5
|
|
vat0.save()
|
|
|
|
vat1 = Tax()
|
|
vat1.name = vat1.description = 'VAT1'
|
|
vat1.type = 'percentage'
|
|
vat1.rate = Decimal('0.2')
|
|
vat1.invoice_account = tax_account
|
|
vat1.credit_note_account = tax_account
|
|
vat1.sequence = 20
|
|
vat1.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([vat0, ecotax1, vat1], Decimal(100), 1, today),
|
|
[{
|
|
'base': Decimal(100),
|
|
'amount': Decimal(10),
|
|
'tax': vat0,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(5),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(20),
|
|
'tax': vat1,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal(135), [vat0, ecotax1, vat1], today),
|
|
Decimal(100))
|
|
|
|
@with_transaction()
|
|
def test_tax_compute_with_update_unit_price(self):
|
|
'Test tax compute with unit_price modifying tax'
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Date = pool.get('ir.date')
|
|
Tax = pool.get('account.tax')
|
|
today = Date.today()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
ecotax1 = Tax()
|
|
ecotax1.name = ecotax1.description = 'EcoTax 1'
|
|
ecotax1.type = 'fixed'
|
|
ecotax1.amount = Decimal(5)
|
|
ecotax1.invoice_account = tax_account
|
|
ecotax1.credit_note_account = tax_account
|
|
ecotax1.update_unit_price = True
|
|
ecotax1.sequence = 10
|
|
ecotax1.save()
|
|
|
|
vat1 = Tax()
|
|
vat1.name = vat1.description = 'VAT1'
|
|
vat1.type = 'percentage'
|
|
vat1.rate = Decimal('0.2')
|
|
vat1.invoice_account = tax_account
|
|
vat1.credit_note_account = tax_account
|
|
vat1.sequence = 20
|
|
vat1.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([ecotax1, vat1], Decimal(100), 5, today),
|
|
[{
|
|
'base': Decimal(500),
|
|
'amount': Decimal(25),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(525),
|
|
'amount': Decimal(105),
|
|
'tax': vat1,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal(126), [ecotax1, vat1], today),
|
|
Decimal(100))
|
|
|
|
ecotax2 = Tax()
|
|
ecotax2.name = ecotax2.description = 'EcoTax 2'
|
|
ecotax2.type = 'percentage'
|
|
ecotax2.rate = Decimal('0.5')
|
|
ecotax2.invoice_account = tax_account
|
|
ecotax2.credit_note_account = tax_account
|
|
ecotax2.update_unit_price = True
|
|
ecotax2.sequence = 10
|
|
ecotax2.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([ecotax1, ecotax2, vat1], Decimal(100), 1, today),
|
|
[{
|
|
'base': Decimal(100),
|
|
'amount': Decimal(5),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(50),
|
|
'tax': ecotax2,
|
|
}, {
|
|
'base': Decimal(155),
|
|
'amount': Decimal(31),
|
|
'tax': vat1,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal(186), [ecotax1, ecotax2, vat1], today),
|
|
Decimal(100))
|
|
|
|
vat0 = Tax()
|
|
vat0.name = vat0.description = 'VAT0'
|
|
vat0.type = 'percentage'
|
|
vat0.rate = Decimal('0.1')
|
|
vat0.invoice_account = tax_account
|
|
vat0.credit_note_account = tax_account
|
|
vat0.sequence = 5
|
|
vat0.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([vat0, ecotax1, vat1], Decimal(100), 1, today),
|
|
[{
|
|
'base': Decimal(100),
|
|
'amount': Decimal(10),
|
|
'tax': vat0,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(5),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(105),
|
|
'amount': Decimal(21),
|
|
'tax': vat1,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal(136), [vat0, ecotax1, vat1], today),
|
|
Decimal(100))
|
|
|
|
self.assertEqual(
|
|
Tax.compute([vat0, ecotax1, ecotax2, vat1],
|
|
Decimal(100), 1, today),
|
|
[{
|
|
'base': Decimal(100),
|
|
'amount': Decimal(10),
|
|
'tax': vat0,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(5),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(50),
|
|
'tax': ecotax2,
|
|
}, {
|
|
'base': Decimal(155),
|
|
'amount': Decimal(31),
|
|
'tax': vat1,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal(196), [vat0, ecotax1, ecotax2, vat1], today),
|
|
Decimal(100))
|
|
|
|
vat2 = Tax()
|
|
vat2.name = vat2.description = 'VAT2'
|
|
vat2.type = 'percentage'
|
|
vat2.rate = Decimal('0.3')
|
|
vat2.invoice_account = tax_account
|
|
vat2.credit_note_account = tax_account
|
|
vat2.sequence = 30
|
|
vat2.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([vat0, ecotax1, vat1, vat2],
|
|
Decimal(100), 1, today),
|
|
[{
|
|
'base': Decimal(100),
|
|
'amount': Decimal(10),
|
|
'tax': vat0,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(5),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(105),
|
|
'amount': Decimal(21),
|
|
'tax': vat1,
|
|
}, {
|
|
'base': Decimal(105),
|
|
'amount': Decimal('31.5'),
|
|
'tax': vat2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal('167.5'), [vat0, ecotax1, vat1, vat2], today),
|
|
Decimal(100))
|
|
|
|
ecotax3 = Tax()
|
|
ecotax3.name = ecotax3.description = 'ECOTAX3'
|
|
ecotax3.type = 'percentage'
|
|
ecotax3.rate = Decimal('0.4')
|
|
ecotax3.invoice_account = tax_account
|
|
ecotax3.credit_note_account = tax_account
|
|
ecotax3.update_unit_price = True
|
|
ecotax3.sequence = 25
|
|
ecotax3.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([vat0, ecotax1, vat1, ecotax3, vat2],
|
|
Decimal(100), 1, today),
|
|
[{
|
|
'base': Decimal(100),
|
|
'amount': Decimal(10),
|
|
'tax': vat0,
|
|
}, {
|
|
'base': Decimal(100),
|
|
'amount': Decimal(5),
|
|
'tax': ecotax1,
|
|
}, {
|
|
'base': Decimal(105),
|
|
'amount': Decimal(21),
|
|
'tax': vat1,
|
|
}, {
|
|
'base': Decimal(105),
|
|
'amount': Decimal('42'),
|
|
'tax': ecotax3,
|
|
}, {
|
|
'base': Decimal(147),
|
|
'amount': Decimal('44.1'),
|
|
'tax': vat2
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(
|
|
Decimal('222.1'),
|
|
[vat0, ecotax1, vat1, ecotax3, vat2],
|
|
today),
|
|
Decimal(100))
|
|
|
|
class Taxable(TaxableMixin):
|
|
__slots__ = ('currency', 'taxable_lines', 'company')
|
|
|
|
def __init__(self, currency=None, taxable_lines=None, company=None):
|
|
super().__init__()
|
|
self.currency = currency
|
|
self.taxable_lines = taxable_lines
|
|
self.company = company
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_line(self):
|
|
"Test TaxableMixin with rounding on line"
|
|
pool = Pool()
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'line'
|
|
config.save()
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax], Decimal('1.001'), 1, None),
|
|
] * 100,
|
|
company=company)
|
|
|
|
taxes = taxable._get_taxes().values()
|
|
|
|
tax, = taxes
|
|
self.assertEqual(tax.base, Decimal('100.00'))
|
|
self.assertEqual(tax.amount, Decimal('20.00'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_line2(self):
|
|
"Test TaxableMixin with rounding on line"
|
|
pool = Pool()
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
tax.rate = 1
|
|
tax.save()
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'line'
|
|
config.save()
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax], Decimal('1.070'), 1, None),
|
|
([tax], Decimal('1.005'), 1, None),
|
|
],
|
|
company=company)
|
|
|
|
taxes = taxable._get_taxes().values()
|
|
|
|
tax, = taxes
|
|
self.assertEqual(tax.base, Decimal('2.07'))
|
|
self.assertEqual(tax.amount, Decimal('2.07'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_document(self):
|
|
"Test TaxableMixin with rounding on document"
|
|
pool = Pool()
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'document'
|
|
config.save()
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax], Decimal('1.001'), 1, None),
|
|
] * 100,
|
|
company=company)
|
|
|
|
taxes = taxable._get_taxes().values()
|
|
|
|
tax, = taxes
|
|
self.assertEqual(tax.base, Decimal('100.00'))
|
|
self.assertEqual(tax.amount, Decimal('20.02'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_many_taxable_lines(self):
|
|
"Test TaxableMixin with many taxable lines"
|
|
pool = Pool()
|
|
Tax = pool.get('account.tax')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax2, = Tax.search([])
|
|
tax1, = Tax.copy([tax2], default={'rate': Decimal('0.1')})
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax1], Decimal('10'), 1, None),
|
|
([tax1, tax2], Decimal('20'), 1, None),
|
|
],
|
|
company=company)
|
|
|
|
taxes = taxable._get_taxes().values()
|
|
|
|
self.assertEqual(len(taxes), 2)
|
|
tax_line1, = [t for t in taxes if t.tax == tax1]
|
|
tax_line2, = [t for t in taxes if t.tax == tax2]
|
|
self.assertEqual(tax_line1.base, Decimal('30.00'))
|
|
self.assertEqual(tax_line1.amount, Decimal('3.00'))
|
|
self.assertEqual(tax_line2.base, Decimal('20.00'))
|
|
self.assertEqual(tax_line2.amount, Decimal('4.00'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_tax_residual_rounding(self):
|
|
"Test TaxableMixin for rounding with residual amount"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'line'
|
|
config.save()
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
|
|
tax1 = Tax()
|
|
tax1.name = tax1.description = "Tax 1"
|
|
tax1.type = 'percentage'
|
|
tax1.rate = Decimal('.1')
|
|
tax1.invoice_account = tax_account
|
|
tax1.credit_note_account = tax_account
|
|
tax1.save()
|
|
tax2 = Tax()
|
|
tax2.name = tax2.description = "Tax 2"
|
|
tax2.type = 'percentage'
|
|
tax2.rate = Decimal('.1')
|
|
tax2.invoice_account = tax_account
|
|
tax2.credit_note_account = tax_account
|
|
tax2.save()
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax1, tax2], Decimal('1.0417'), 1, None),
|
|
],
|
|
company=company)
|
|
|
|
taxline_1, taxline_2 = taxable._get_taxes().values()
|
|
self.assertEqual(taxline_1.base, Decimal('1.04'))
|
|
self.assertEqual(taxline_1.amount, Decimal('.11'))
|
|
self.assertEqual(taxline_2.base, Decimal('1.04'))
|
|
self.assertEqual(taxline_2.amount, Decimal('.10'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_tax_residual_rounding_with_0(self):
|
|
"Test TaxableMixin for rounding with residual amount and tax 0"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'line'
|
|
config.save()
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
|
|
tax0 = Tax()
|
|
tax0.name = tax0.description = "Tax 0"
|
|
tax0.type = 'percentage'
|
|
tax0.rate = Decimal('0')
|
|
tax0.invoice_account = tax_account
|
|
tax0.credit_note_account = tax_account
|
|
tax0.save()
|
|
tax1 = Tax()
|
|
tax1.name = tax1.description = "Tax 1"
|
|
tax1.type = 'percentage'
|
|
tax1.rate = Decimal('.1')
|
|
tax1.invoice_account = tax_account
|
|
tax1.credit_note_account = tax_account
|
|
tax1.save()
|
|
tax2 = Tax()
|
|
tax2.name = tax2.description = "Tax 2"
|
|
tax2.type = 'percentage'
|
|
tax2.rate = Decimal('.1')
|
|
tax2.invoice_account = tax_account
|
|
tax2.credit_note_account = tax_account
|
|
tax2.save()
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax0, tax1, tax2], Decimal('1.0417'), 1, None),
|
|
],
|
|
company=company)
|
|
|
|
taxline_0, taxline_1, taxline_2 = taxable._get_taxes().values()
|
|
self.assertEqual(taxline_0.base, Decimal('1.04'))
|
|
self.assertEqual(taxline_0.amount, Decimal('0'))
|
|
self.assertEqual(taxline_1.base, Decimal('1.04'))
|
|
self.assertEqual(taxline_1.amount, Decimal('.11'))
|
|
self.assertEqual(taxline_2.base, Decimal('1.04'))
|
|
self.assertEqual(taxline_2.amount, Decimal('.10'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_tax_residual_rounding_negative_residual(self):
|
|
"Test TaxableMixin for rounding with negative residual amount"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'line'
|
|
config.save()
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
|
|
tax1 = Tax()
|
|
tax1.name = tax1.description = "Tax 1"
|
|
tax1.type = 'percentage'
|
|
tax1.rate = Decimal('.1')
|
|
tax1.invoice_account = tax_account
|
|
tax1.credit_note_account = tax_account
|
|
tax1.save()
|
|
tax2 = Tax()
|
|
tax2.name = tax2.description = "Tax 2"
|
|
tax2.type = 'percentage'
|
|
tax2.rate = Decimal('.1')
|
|
tax2.invoice_account = tax_account
|
|
tax2.credit_note_account = tax_account
|
|
tax2.save()
|
|
|
|
# -2.95 is the unit price of -3.54 with 20% tax included
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax1], Decimal('30.00'), 1, None),
|
|
([tax1, tax2], Decimal('-2.95'), 1, None),
|
|
],
|
|
company=company)
|
|
|
|
taxline_1, taxline_2, taxline_3 = taxable._get_taxes().values()
|
|
self.assertEqual(taxline_1.base, Decimal('30.00'))
|
|
self.assertEqual(taxline_1.amount, Decimal('3.00'))
|
|
self.assertEqual(taxline_2.base, Decimal('-2.95'))
|
|
self.assertEqual(taxline_2.amount, Decimal('-0.29'))
|
|
self.assertEqual(taxline_3.base, Decimal('-2.95'))
|
|
self.assertEqual(taxline_3.amount, Decimal('-0.30'))
|
|
|
|
@with_transaction()
|
|
def test_taxable_mixin_tax_residual_rounding_per_same_taxes(self):
|
|
"""Test TaxableMixin for rounding with residual amount only for same
|
|
taxes"""
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
Configuration = pool.get('account.configuration')
|
|
currency = create_currency('cur')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
config = Configuration(1)
|
|
config.tax_rounding = 'document'
|
|
config.save()
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
|
|
tax = Tax()
|
|
tax.name = tax.description = "Tax"
|
|
tax.type = 'percentage'
|
|
tax.rate = Decimal('.06')
|
|
tax.invoice_account = tax_account
|
|
tax.credit_note_account = tax_account
|
|
tax.save()
|
|
|
|
taxable = self.Taxable(
|
|
currency=currency,
|
|
taxable_lines=[
|
|
([tax], Decimal('11.2736'), 1.04, None),
|
|
([tax], Decimal('0.4529'), -1, None),
|
|
],
|
|
company=company)
|
|
|
|
taxline_1, taxline_2 = taxable._get_taxes().values()
|
|
self.assertEqual(taxline_1.base, Decimal('11.72'))
|
|
self.assertEqual(taxline_1.amount, Decimal('0.7'))
|
|
self.assertEqual(taxline_2.base, Decimal('-0.45'))
|
|
self.assertEqual(taxline_2.amount, Decimal('-0.03'))
|
|
|
|
@with_transaction()
|
|
def test_tax_compute_with_children_update_unit_price(self):
|
|
"Test tax compute with children taxes modifying unit_price"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
Date = pool.get('ir.date')
|
|
Tax = pool.get('account.tax')
|
|
today = Date.today()
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
|
|
tax_account, = Account.search([
|
|
('code', '=', '6.3.6'),
|
|
])
|
|
|
|
tax1 = Tax()
|
|
tax1.name = tax1.description = "Tax 1"
|
|
tax1.type = 'none'
|
|
tax1.update_unit_price = True
|
|
tax1.sequence = 1
|
|
tax1.save()
|
|
child1 = Tax()
|
|
child1.name = child1.description = "Child 1"
|
|
child1.type = 'percentage'
|
|
child1.rate = Decimal('0.1')
|
|
child1.invoice_account = tax_account
|
|
child1.credit_note_account = tax_account
|
|
child1.parent = tax1
|
|
child1.save()
|
|
|
|
tax2 = Tax()
|
|
tax2.name = tax2.description = "Tax 2"
|
|
tax2.type = 'fixed'
|
|
tax2.amount = Decimal('10')
|
|
tax2.invoice_account = tax_account
|
|
tax2.credit_note_account = tax_account
|
|
tax2.sequence = 2
|
|
tax2.save()
|
|
|
|
self.assertEqual(
|
|
Tax.compute([tax1, tax2], Decimal(100), 2, today), [{
|
|
'base': Decimal(200),
|
|
'amount': Decimal(20),
|
|
'tax': child1,
|
|
}, {
|
|
'base': Decimal('220'),
|
|
'amount': Decimal('20'),
|
|
'tax': tax2,
|
|
}])
|
|
self.assertEqual(
|
|
Tax.reverse_compute(Decimal('120'), [tax1, tax2], today),
|
|
Decimal('100'))
|
|
|
|
@with_transaction()
|
|
def test_receivable_payable(self):
|
|
'Test party receivable payable'
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
Party = pool.get('party.party')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Journal = pool.get('account.journal')
|
|
Account = pool.get('account.account')
|
|
Move = pool.get('account.move')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
fiscalyear = get_fiscalyear(company)
|
|
fiscalyear.save()
|
|
FiscalYear.create_period([fiscalyear])
|
|
period = fiscalyear.periods[0]
|
|
journal_revenue, = Journal.search([
|
|
('code', '=', 'REV'),
|
|
])
|
|
journal_expense, = Journal.search([
|
|
('code', '=', 'EXP'),
|
|
])
|
|
revenue, = Account.search([
|
|
('type.revenue', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
expense, = Account.search([
|
|
('type.expense', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
payable, = Account.search([
|
|
('type.payable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
party, = Party.create([{
|
|
'name': 'Receivable/Payable party',
|
|
}])
|
|
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
|
|
|
|
def get_move(journal, amount, credit_account, debit_account, party,
|
|
maturity_date=None):
|
|
return {
|
|
'period': period.id,
|
|
'journal': journal.id,
|
|
'date': period.start_date,
|
|
'lines': [
|
|
('create', [{
|
|
'account': credit_account.id,
|
|
'credit': amount,
|
|
}, {
|
|
'account': debit_account.id,
|
|
'debit': amount,
|
|
'party': party.id,
|
|
'maturity_date': maturity_date,
|
|
}]),
|
|
],
|
|
}
|
|
vlist = [
|
|
get_move(journal_revenue, Decimal(100), revenue, receivable,
|
|
party),
|
|
get_move(journal_expense, Decimal(30), expense, payable,
|
|
party),
|
|
get_move(journal_revenue, Decimal(200), revenue, receivable,
|
|
party, tomorrow),
|
|
get_move(journal_revenue, Decimal(60), expense, payable,
|
|
party, tomorrow),
|
|
]
|
|
moves = Move.create(vlist)
|
|
Move.post(moves)
|
|
|
|
def check_fields():
|
|
party_test = Party(party.id)
|
|
company_test = Company(company.id)
|
|
|
|
for record, Model in [
|
|
(party_test, Party),
|
|
(company_test, Company),
|
|
]:
|
|
for field, value in [
|
|
('receivable', Decimal('300')),
|
|
('receivable_today', Decimal('100')),
|
|
('payable', Decimal('90')),
|
|
('payable_today', Decimal('30')),
|
|
]:
|
|
with self.subTest(
|
|
record=record, field=field, value=value):
|
|
self.assertEqual(
|
|
getattr(record, field), value)
|
|
self.assertEqual(
|
|
Model.search([(field, '=', value)]),
|
|
[record])
|
|
self.assertEqual(
|
|
Model.search([(field, 'in', [value])]),
|
|
[record])
|
|
self.assertEqual(
|
|
Model.search([(field, '!=', value)]),
|
|
[])
|
|
self.assertEqual(
|
|
Model.search([(field, 'not in', [value])]),
|
|
[])
|
|
|
|
check_fields()
|
|
close_fiscalyear(fiscalyear)
|
|
check_fields()
|
|
|
|
@with_transaction()
|
|
def test_sort_taxes(self):
|
|
"Test sort_taxes"
|
|
pool = Pool()
|
|
Tax = pool.get('account.tax')
|
|
|
|
tax1 = Tax(sequence=None, id=-3)
|
|
tax2 = Tax(sequence=None, id=-2)
|
|
tax3 = Tax(sequence=1, id=-1)
|
|
self.assertSequenceEqual(
|
|
Tax.sort_taxes([tax3, tax2, tax1]), [tax1, tax2, tax3])
|
|
|
|
@with_transaction()
|
|
def test_configuration_accounts_on_party(self):
|
|
'Test configuration accounts are used as fallback on party'
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
Account = pool.get('account.account')
|
|
|
|
party = Party(name='Party')
|
|
party.save()
|
|
|
|
self.assertIsNone(party.account_payable)
|
|
self.assertIsNone(party.account_receivable)
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company)
|
|
receivable, = Account.search([
|
|
('type.receivable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
payable, = Account.search([
|
|
('type.payable', '=', True),
|
|
('closed', '=', False),
|
|
], limit=1)
|
|
|
|
party = Party(party.id)
|
|
|
|
self.assertEqual(party.account_payable_used, payable)
|
|
self.assertEqual(party.account_receivable_used, receivable)
|
|
|
|
@with_transaction()
|
|
def test_tax_rule(self):
|
|
"Test tax rule"
|
|
pool = Pool()
|
|
TaxRule = pool.get('account.tax.rule')
|
|
Tax = pool.get('account.tax')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
target_tax, = Tax.copy([tax])
|
|
|
|
tax_rule, = TaxRule.create([{
|
|
'name': 'Test',
|
|
'kind': 'both',
|
|
'lines': [('create', [{
|
|
'origin_tax': tax.id,
|
|
'tax': target_tax.id,
|
|
}])],
|
|
}])
|
|
self.assertListEqual(tax_rule.apply(tax, {}), [target_tax.id])
|
|
|
|
@with_transaction()
|
|
def test_tax_rule_start_date(self):
|
|
"Test tax rule start date"
|
|
pool = Pool()
|
|
TaxRule = pool.get('account.tax.rule')
|
|
Tax = pool.get('account.tax')
|
|
Date = pool.get('ir.date')
|
|
|
|
today = Date.today()
|
|
yesterday = today - datetime.timedelta(days=1)
|
|
tomorrow = today + datetime.timedelta(days=1)
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
target_tax, = Tax.copy([tax])
|
|
|
|
tax_rule, = TaxRule.create([{
|
|
'name': "Test",
|
|
'kind': 'both',
|
|
'lines': [('create', [{
|
|
'start_date': today,
|
|
'tax': target_tax.id,
|
|
}])],
|
|
}])
|
|
|
|
self.assertListEqual(tax_rule.apply(tax, {}), [target_tax.id])
|
|
self.assertListEqual(
|
|
tax_rule.apply(tax, {'date': yesterday}), [tax.id])
|
|
self.assertListEqual(
|
|
tax_rule.apply(tax, {'date': tomorrow}), [target_tax.id])
|
|
|
|
@with_transaction()
|
|
def test_tax_rule_end_date(self):
|
|
"Test tax rule end date"
|
|
pool = Pool()
|
|
TaxRule = pool.get('account.tax.rule')
|
|
Tax = pool.get('account.tax')
|
|
Date = pool.get('ir.date')
|
|
|
|
today = Date.today()
|
|
yesterday = today - datetime.timedelta(days=1)
|
|
tomorrow = today + datetime.timedelta(days=1)
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
target_tax, = Tax.copy([tax])
|
|
|
|
tax_rule, = TaxRule.create([{
|
|
'name': "Test",
|
|
'kind': 'both',
|
|
'lines': [('create', [{
|
|
'end_date': today,
|
|
'tax': target_tax.id,
|
|
}])],
|
|
}])
|
|
|
|
self.assertListEqual(tax_rule.apply(tax, {}), [target_tax.id])
|
|
self.assertListEqual(
|
|
tax_rule.apply(tax, {'date': yesterday}), [target_tax.id])
|
|
self.assertListEqual(
|
|
tax_rule.apply(tax, {'date': tomorrow}), [tax.id])
|
|
|
|
@with_transaction()
|
|
def test_tax_rule_keep_origin(self):
|
|
"Test tax rule keeps origin"
|
|
pool = Pool()
|
|
TaxRule = pool.get('account.tax.rule')
|
|
Tax = pool.get('account.tax')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
tax, = Tax.search([])
|
|
target_tax, = Tax.copy([tax])
|
|
|
|
tax_rule, = TaxRule.create([{
|
|
'name': 'Test',
|
|
'kind': 'both',
|
|
'lines': [('create', [{
|
|
'origin_tax': tax.id,
|
|
'tax': target_tax.id,
|
|
'keep_origin': True,
|
|
}])],
|
|
}])
|
|
self.assertListEqual(
|
|
tax_rule.apply(tax, {}), [target_tax.id, tax.id])
|
|
|
|
@with_transaction()
|
|
def test_update_chart(self):
|
|
'Test all template models are updated when updating chart'
|
|
pool = Pool()
|
|
TypeTemplate = pool.get('account.account.type.template')
|
|
AccountTemplate = pool.get('account.account.template')
|
|
TaxTemplate = pool.get('account.tax.template')
|
|
TaxCodeTemplate = pool.get('account.tax.code.template')
|
|
ModelData = pool.get('ir.model.data')
|
|
UpdateChart = pool.get('account.update_chart', type='wizard')
|
|
Type = pool.get('account.account.type')
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
TaxCode = pool.get('account.tax.code')
|
|
|
|
def check():
|
|
for type_ in Type.search([]):
|
|
self.assertEqual(type_.name, type_.template.name)
|
|
self.assertEqual(
|
|
type_.statement, type_.template.statement)
|
|
if type_.template.parent:
|
|
self.assertEqual(
|
|
type_.parent.name, type_.template.parent.name)
|
|
else:
|
|
self.assertEqual(type_.parent, None)
|
|
|
|
for account in Account.search([]):
|
|
self.assertEqual(account.name, account.template.name)
|
|
self.assertEqual(account.code, account.template.code)
|
|
self.assertEqual(
|
|
account.type.template if account.type else None,
|
|
account.template.type)
|
|
self.assertEqual(account.reconcile, account.template.reconcile)
|
|
self.assertEqual(
|
|
account.start_date, account.template.start_date)
|
|
self.assertEqual(account.end_date, account.template.end_date)
|
|
self.assertEqual(
|
|
account.party_required, account.template.party_required)
|
|
self.assertEqual(
|
|
account.general_ledger_balance,
|
|
account.template.general_ledger_balance)
|
|
self.assertEqual(
|
|
set(t.template for t in account.taxes),
|
|
set(t for t in account.template.taxes))
|
|
if account.template.parent:
|
|
self.assertEqual(
|
|
account.parent.name, account.template.parent.name)
|
|
else:
|
|
self.assertEqual(account.parent, None)
|
|
if account.template.replaced_by:
|
|
self.assertEqual(
|
|
account.replaced_by.name,
|
|
account.template.replaced_by.name)
|
|
else:
|
|
self.assertEqual(account.replaced_by, None)
|
|
|
|
for tax_code in TaxCode.search([]):
|
|
self.assertEqual(tax_code.name, tax_code.template.name)
|
|
self.assertEqual(tax_code.code, tax_code.template.code)
|
|
for line in tax_code.lines:
|
|
self.assertEqual(line.code.template, line.template.code)
|
|
self.assertEqual(line.operator, line.template.operator)
|
|
self.assertEqual(line.type, line.template.type)
|
|
self.assertEqual(line.tax.template, line.template.tax)
|
|
|
|
for tax in Tax.search([]):
|
|
self.assertEqual(tax.name, tax.template.name)
|
|
self.assertEqual(tax.description, tax.template.description)
|
|
self.assertEqual(tax.type, tax.template.type)
|
|
self.assertEqual(tax.rate, tax.template.rate)
|
|
self.assertEqual(tax.amount, tax.template.amount)
|
|
self.assertEqual(
|
|
tax.update_unit_price, tax.template.update_unit_price)
|
|
self.assertEqual(
|
|
tax.start_date, tax.template.start_date)
|
|
self.assertEqual(tax.end_date, tax.template.end_date)
|
|
self.assertEqual(
|
|
tax.invoice_account.template, tax.template.invoice_account)
|
|
self.assertEqual(
|
|
tax.credit_note_account.template,
|
|
tax.template.credit_note_account)
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, True)
|
|
|
|
with inactive_records():
|
|
self.assertEqual(Type.search([], count=True), 46)
|
|
self.assertEqual(Account.search([], count=True), 135)
|
|
self.assertEqual(Tax.search([], count=True), 1)
|
|
|
|
check()
|
|
|
|
with Transaction().set_user(0):
|
|
root_type = TypeTemplate(ModelData.get_id(
|
|
'account', 'account_type_template_root_en'))
|
|
root_type.name = "Updated " + root_type.name
|
|
root_type.save()
|
|
chart = AccountTemplate(ModelData.get_id(
|
|
'account', 'account_template_root_en'))
|
|
new_type = TypeTemplate()
|
|
new_type.name = 'New Type'
|
|
new_type.parent = root_type
|
|
new_type.statement = 'balance'
|
|
new_type.save()
|
|
updated_tax_type, = TypeTemplate.search([
|
|
('name', '=', "Liabilities and assets for current tax"),
|
|
])
|
|
updated_tax_type.parent = updated_tax_type.parent.parent
|
|
updated_tax_type.save()
|
|
new_account = AccountTemplate()
|
|
new_account.name = 'New Account'
|
|
new_account.parent = chart
|
|
new_account.type = new_type
|
|
new_account.save()
|
|
updated_tax, = TaxTemplate.search([])
|
|
updated_tax.name = 'VAT'
|
|
updated_tax.invoice_account = new_account
|
|
updated_tax.save()
|
|
# Can only change type which is compatible with previous parent
|
|
updated_account = AccountTemplate(ModelData.get_id(
|
|
'account', 'account_template_1_1_1_en'))
|
|
updated_account.code = 'REV'
|
|
updated_account.name = 'Updated Account'
|
|
updated_account.parent = new_account
|
|
updated_account.type = new_type
|
|
updated_account.reconcile = True
|
|
updated_account.end_date = datetime.date.today()
|
|
updated_account.taxes = [updated_tax]
|
|
updated_account.save()
|
|
inactive_account = AccountTemplate(ModelData.get_id(
|
|
'account', 'account_template_5_1_1_en'))
|
|
inactive_account.end_date = datetime.date.min
|
|
inactive_account.replaced_by = new_account
|
|
inactive_account.save()
|
|
new_tax = TaxTemplate()
|
|
new_tax.name = new_tax.description = '10% VAT'
|
|
new_tax.type = 'percentage'
|
|
new_tax.rate = Decimal('0.1')
|
|
new_tax.account = chart
|
|
new_tax.invoice_account = new_account
|
|
new_tax.credit_note_account = new_account
|
|
new_tax.save()
|
|
updated_tax_code, = TaxCodeTemplate.search([
|
|
('name', '=', 'Tax Code'),
|
|
])
|
|
updated_tax_code.name = 'Updated Tax Code'
|
|
updated_tax_code.save()
|
|
updated_tax_code_line, = updated_tax_code.lines
|
|
updated_tax_code_line.operator = '-'
|
|
updated_tax_code_line.save()
|
|
|
|
with set_company(company):
|
|
account, = Account.search([('parent', '=', None)])
|
|
session_id, _, _ = UpdateChart.create()
|
|
update_chart = UpdateChart(session_id)
|
|
update_chart.start.account = account
|
|
update_chart.transition_update()
|
|
|
|
with inactive_records():
|
|
self.assertEqual(Type.search([], count=True), 47)
|
|
self.assertEqual(Account.search([], count=True), 136)
|
|
self.assertEqual(Tax.search([], count=True), 2)
|
|
|
|
check()
|
|
|
|
@with_transaction()
|
|
def test_update_override(self):
|
|
"Test all models are not updated when template override is True"
|
|
pool = Pool()
|
|
ModelData = pool.get('ir.model.data')
|
|
TypeTemplate = pool.get('account.account.type.template')
|
|
AccountTemplate = pool.get('account.account.template')
|
|
TaxTemplate = pool.get('account.tax.template')
|
|
TaxCodeTemplate = pool.get('account.tax.code.template')
|
|
TaxCodeTemplateLine = pool.get('account.tax.code.line.template')
|
|
UpdateChart = pool.get('account.update_chart', type='wizard')
|
|
Type = pool.get('account.account.type')
|
|
Account = pool.get('account.account')
|
|
Tax = pool.get('account.tax')
|
|
TaxCode = pool.get('account.tax.code')
|
|
TaxCodeLine = pool.get('account.tax.code.line')
|
|
|
|
new_name = "Updated"
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, True)
|
|
|
|
type_count = Type.search([], count=True)
|
|
account_count = Account.search([], count=True)
|
|
tax_count = Tax.search([], count=True)
|
|
tax_code_count = TaxCode.search([], count=True)
|
|
tax_code_line_count = TaxCodeLine.search([], count=True)
|
|
|
|
with Transaction().set_user(0):
|
|
root = AccountTemplate(ModelData.get_id(
|
|
'account', 'account_template_root_en'))
|
|
|
|
template_type, = TypeTemplate.search([
|
|
('parent', '!=', None),
|
|
('parent', 'child_of', [root.type.id]),
|
|
], limit=1)
|
|
template_type.name = new_name
|
|
template_type.save()
|
|
type_, = Type.search([('template', '=', template_type.id)])
|
|
type_.template_override = True
|
|
type_.save()
|
|
|
|
template_account, = AccountTemplate.search([
|
|
('parent', '!=', None),
|
|
('parent', 'child_of', [root.id]),
|
|
], limit=1)
|
|
template_account.name = new_name
|
|
template_account.save()
|
|
account, = Account.search([('template', '=', template_account.id)])
|
|
account.template_override = True
|
|
account.save()
|
|
|
|
template_tax, = TaxTemplate.search([])
|
|
template_tax.name = new_name
|
|
template_tax.save()
|
|
tax, = Tax.search([('template', '=', template_tax.id)])
|
|
tax.template_override = True
|
|
tax.save()
|
|
|
|
template_tax_code, = TaxCodeTemplate.search([], limit=1)
|
|
template_tax_code.name = new_name
|
|
template_tax_code.save()
|
|
tax_code, = TaxCode.search(
|
|
[('template', '=', template_tax_code.id)])
|
|
tax_code.template_override = True
|
|
tax_code.save()
|
|
|
|
template_tax_code_line, = TaxCodeTemplateLine.search([], limit=1)
|
|
tax_code_line, = TaxCodeLine.search(
|
|
[('template', '=', template_tax_code_line.id)])
|
|
tax_code_line.template_override = True
|
|
tax_code_line.save()
|
|
|
|
with set_company(company):
|
|
account, = Account.search([('parent', '=', None)])
|
|
session_id, _, _ = UpdateChart.create()
|
|
update_chart = UpdateChart(session_id)
|
|
update_chart.start.account = account
|
|
update_chart.transition_update()
|
|
|
|
self.assertEqual(Type.search([], count=True), type_count)
|
|
self.assertEqual(Account.search([], count=True), account_count)
|
|
self.assertEqual(Tax.search([], count=True), tax_count)
|
|
self.assertEqual(
|
|
TaxCode.search([], count=True), tax_code_count)
|
|
self.assertEqual(
|
|
TaxCodeLine.search([], count=True), tax_code_line_count)
|
|
|
|
for Model in [Type, Account, Tax, TaxCode]:
|
|
for record in Model.search([]):
|
|
self.assertNotEqual(record.name, new_name)
|
|
|
|
@with_transaction()
|
|
def test_update_inactive(self):
|
|
"Test update chart of accounts with inactive account"
|
|
pool = Pool()
|
|
Account = pool.get('account.account')
|
|
UpdateChart = pool.get('account.update_chart', type='wizard')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, tax=True)
|
|
root, = Account.search([('parent', '=', None)])
|
|
|
|
cash, = Account.search([('code', '=', '1.1.1')])
|
|
cash.template_override = True
|
|
cash.end_date = datetime.date.min
|
|
cash.save()
|
|
self.assertFalse(cash.active)
|
|
|
|
session_id, _, _ = UpdateChart.create()
|
|
update_chart = UpdateChart(session_id)
|
|
update_chart.start.account = root
|
|
update_chart.transition_update()
|
|
|
|
with inactive_records():
|
|
self.assertEqual(
|
|
Account.search([('code', '=', '1.1.1')], count=True),
|
|
1)
|
|
|
|
@with_transaction()
|
|
def test_update_chart_new_parent(self):
|
|
"Test update chart of accounts with new parent"
|
|
pool = Pool()
|
|
ModelData = pool.get('ir.model.data')
|
|
TypeTemplate = pool.get('account.account.type.template')
|
|
Type = pool.get('account.account.type')
|
|
AccountTemplate = pool.get('account.account.template')
|
|
Account = pool.get('account.account')
|
|
UpdateChart = pool.get('account.update_chart', type='wizard')
|
|
|
|
company = create_company()
|
|
with set_company(company):
|
|
create_chart(company, True)
|
|
|
|
with Transaction().set_user(0):
|
|
root_type_template = TypeTemplate(ModelData.get_id(
|
|
'account', 'account_type_template_root_en'))
|
|
|
|
type_template, = TypeTemplate.search([
|
|
('parent', '!=', None),
|
|
('parent', 'child_of', [root_type_template.id]),
|
|
], limit=1)
|
|
new_type_template, = TypeTemplate.copy([type_template])
|
|
type_template.parent = new_type_template
|
|
type_template.save()
|
|
|
|
root_template = AccountTemplate(ModelData.get_id(
|
|
'account', 'account_template_root_en'))
|
|
|
|
account_template, = AccountTemplate.search([
|
|
('parent', '!=', None),
|
|
('parent', 'child_of', [root_template.id]),
|
|
], limit=1)
|
|
new_account_template, = AccountTemplate.copy([account_template])
|
|
account_template.parent = new_account_template
|
|
account_template.save()
|
|
|
|
with set_company(company):
|
|
account, = Account.search([('parent', '=', None)])
|
|
session_id, _, _ = UpdateChart.create()
|
|
update_chart = UpdateChart(session_id)
|
|
update_chart.start.account = account
|
|
update_chart.transition_update()
|
|
|
|
new_type, = Type.search(
|
|
[('template', '=', new_type_template.id)])
|
|
type, = Type.search(
|
|
[('template', '=', type_template.id)])
|
|
|
|
self.assertEqual(type.parent, new_type)
|
|
|
|
new_account, = Account.search(
|
|
[('template', '=', new_account_template.id)])
|
|
account, = Account.search(
|
|
[('template', '=', account_template.id)])
|
|
|
|
self.assertEqual(account.parent, new_account)
|
|
|
|
|
|
del ModuleTestCase
|