forked from Mapan/odoo17e
1536 lines
79 KiB
Python
1536 lines
79 KiB
Python
# -*- coding: utf-8 -*-
|
|
# pylint: disable=C0326
|
|
from odoo.addons.account_reports.tests.common import TestAccountReportsCommon
|
|
from odoo import fields, Command
|
|
from odoo.exceptions import UserError
|
|
from odoo.tests import tagged, HttpCase, Form
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestDeferredReports(TestAccountReportsCommon, HttpCase):
|
|
@classmethod
|
|
def setUpClass(cls, chart_template_ref=None):
|
|
super().setUpClass(chart_template_ref=chart_template_ref)
|
|
cls.deferred_expense_report = cls.env.ref('account_reports.deferred_expense_report')
|
|
cls.deferred_revenue_report = cls.env.ref('account_reports.deferred_revenue_report')
|
|
cls.handler = cls.env['account.deferred.expense.report.handler']
|
|
|
|
cls.expense_accounts = [cls.env['account.account'].create({
|
|
'name': f'Expense {i}',
|
|
'code': f'EXP{i}',
|
|
'account_type': 'expense',
|
|
}) for i in range(10)]
|
|
cls.revenue_accounts = [cls.env['account.account'].create({
|
|
'name': f'Revenue {i}',
|
|
'code': f'REV{i}',
|
|
'account_type': 'income',
|
|
}) for i in range(3)]
|
|
|
|
cls.company = cls.company_data['company']
|
|
cls.deferral_account = cls.company_data['default_account_deferred_expense']
|
|
cls.company.deferred_journal_id = cls.company_data['default_journal_misc'].id
|
|
cls.company.deferred_expense_account_id = cls.company_data['default_account_deferred_expense'].id
|
|
cls.company.deferred_revenue_account_id = cls.company_data['default_account_deferred_revenue'].id
|
|
|
|
cls.expense_lines = [
|
|
[cls.expense_accounts[0], 1000, '2023-01-01', '2023-04-30'], # 4 full months (=250/month)
|
|
[cls.expense_accounts[0], 1050, '2023-01-16', '2023-04-30'], # 3 full months + 15 days (=300/month)
|
|
[cls.expense_accounts[1], 1225, '2023-01-01', '2023-04-15'], # 3 full months + 15 days (=350/month)
|
|
[cls.expense_accounts[2], 1680, '2023-01-21', '2023-04-14'], # 2 full months + 10 days + 14 days (=600/month)
|
|
[cls.expense_accounts[2], 225, '2023-04-01', '2023-04-15'], # 15 days (=450/month)
|
|
]
|
|
cls.revenue_lines = [
|
|
[cls.revenue_accounts[0], 1000, '2023-01-01', '2023-04-30'], # 4 full months (=250/month)
|
|
[cls.revenue_accounts[0], 1050, '2023-01-16', '2023-04-30'], # 3 full months + 15 days (=300/month)
|
|
[cls.revenue_accounts[1], 1225, '2023-01-01', '2023-04-15'], # 3 full months + 15 days (=350/month)
|
|
[cls.revenue_accounts[2], 1680, '2023-01-21', '2023-04-14'], # 2 full months + 10 days + 14 days (=600/month)
|
|
[cls.revenue_accounts[2], 225, '2023-04-01', '2023-04-15'], # 15 days (=450/month)
|
|
]
|
|
|
|
def create_invoice(self, invoice_lines, move_type='in_invoice', invoice_date='2023-01-01', post=True):
|
|
journal = self.company_data['default_journal_sale']
|
|
if move_type.startswith('in_'):
|
|
journal = self.company_data['default_journal_purchase']
|
|
move = self.env['account.move'].create({
|
|
'move_type': move_type,
|
|
'partner_id': self.partner_a.id,
|
|
'date': invoice_date,
|
|
'invoice_date': invoice_date,
|
|
'journal_id': journal.id,
|
|
'invoice_line_ids': [
|
|
Command.create({
|
|
'product_id': self.product_a.id,
|
|
'quantity': 1,
|
|
'account_id': invoice_line[0].id,
|
|
'price_unit': invoice_line[1],
|
|
'deferred_start_date': invoice_line[2],
|
|
'deferred_end_date': invoice_line[3],
|
|
}) for invoice_line in invoice_lines
|
|
]
|
|
})
|
|
if post:
|
|
move.action_post()
|
|
return move
|
|
|
|
def get_options(self, from_date, to_date, report=None):
|
|
report = report or self.deferred_expense_report
|
|
return self._generate_options(report, from_date, to_date)
|
|
|
|
def test_deferred_expense_report_months(self):
|
|
"""
|
|
Test the deferred expense report with the 'month' method.
|
|
We use multiple report months/quarters/years to check that the computation is correct.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.create_invoice(self.expense_lines)
|
|
|
|
# December 2022
|
|
options = self.get_options('2022-12-01', '2022-12-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# January 2023
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 0, 250 + 150, 750 + 900 ),
|
|
('EXP1 Expense 1', 1225, 0, 0, 350, 875 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 0, 600 * (10/30) + 0, 600 * (2 + 14/30) + 225 ),
|
|
('Total', 5180, 225, 0, 950, 4230 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# February 2023
|
|
options = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 250 + 150, 250 + 300, 500 + 600 ),
|
|
('EXP1 Expense 1', 1225, 0, 350, 350, 525 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 600 * (10/30) + 0, 600 + 0, 600 * (1 + 14/30) + 225 ),
|
|
('Total', 5180, 225, 950, 1500, 2730 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# April 2023
|
|
options = self.get_options('2023-04-01', '2023-04-30')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 750 + 750, 250 + 300, 0 ),
|
|
('EXP1 Expense 1', 1225, 0, 1050, 175, 0 ),
|
|
('EXP2 Expense 2', 1680 + 225, 0, 600 * (2 + 10/30), 600 * (14/30)+ 225, 0 ),
|
|
('Total', 5180, 0, 3950, 1230, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# May 2023
|
|
options = self.get_options('2023-05-01', '2023-05-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# Q1 2023
|
|
options = self.get_options('2023-01-01', '2023-03-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 0, 750 + 750, 550 ),
|
|
('EXP1 Expense 1', 1225, 0, 0, 1050, 175 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 0, 600 * (2 + 10/30) + 0, 280 + 225 ),
|
|
('Total', 5180, 225, 0, 3950, 1230 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Q2 2023
|
|
options = self.get_options('2023-04-01', '2023-06-30')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 750 + 750, 250 + 300, 0 ),
|
|
('EXP1 Expense 1', 1225, 0, 1050, 175, 0 ),
|
|
('EXP2 Expense 2', 1680 + 225, 0, 600 * (2 + 10/30), 600 * (14/30)+ 225, 0 ),
|
|
('Total', 5180, 0, 3950, 1230, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# 2022
|
|
options = self.get_options('2022-01-01', '2022-12-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# 2023, nothing to show as all the moves have been deferred by the end of the year 2023
|
|
options = self.get_options('2023-01-01', '2023-12-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_revenue_report(self):
|
|
"""
|
|
Test the deferred revenue report with the 'month' method.
|
|
We use multiple report months/quarters/years to check that the computation is correct.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.create_invoice(self.revenue_lines, 'out_invoice')
|
|
|
|
# December 2022
|
|
options = self.get_options('2022-12-01', '2022-12-31', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# January 2023
|
|
options = self.get_options('2023-01-01', '2023-01-31', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('REV0 Revenue 0', 1000 + 1050, 0, 0, 250 + 150, 750 + 900 ),
|
|
('REV1 Revenue 1', 1225, 0, 0, 350, 875 ),
|
|
('REV2 Revenue 2', 1680 + 225, 225, 0, 600 * (10/30) + 0, 600 * (2 + 14/30) + 225 ),
|
|
('Total', 5180, 225, 0, 950, 4230 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# February 2023
|
|
options = self.get_options('2023-02-01', '2023-02-28', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('REV0 Revenue 0', 1000 + 1050, 0, 250 + 150, 250 + 300, 500 + 600 ),
|
|
('REV1 Revenue 1', 1225, 0, 350, 350, 525 ),
|
|
('REV2 Revenue 2', 1680 + 225, 225, 600 * (10/30) + 0, 600 + 0, 600 * (1 + 14/30) + 225 ),
|
|
('Total', 5180, 225, 950, 1500, 2730 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# April 2023
|
|
options = self.get_options('2023-04-01', '2023-04-30', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('REV0 Revenue 0', 1000 + 1050, 0, 750 + 750, 250 + 300, 0 ),
|
|
('REV1 Revenue 1', 1225, 0, 1050, 175, 0 ),
|
|
('REV2 Revenue 2', 1680 + 225, 0, 600 * (2 + 10/30), 600 * (14/30)+ 225, 0 ),
|
|
('Total', 5180, 0, 3950, 1230, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# May 2023
|
|
options = self.get_options('2023-05-01', '2023-05-31', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# Q1 2023
|
|
options = self.get_options('2023-01-01', '2023-03-31', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('REV0 Revenue 0', 1000 + 1050, 0, 0, 750 + 750, 550 ),
|
|
('REV1 Revenue 1', 1225, 0, 0, 1050, 175 ),
|
|
('REV2 Revenue 2', 1680 + 225, 225, 0, 600 * (2 + 10/30) + 0, 280 + 225 ),
|
|
('Total', 5180, 225, 0, 3950, 1230 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Q2 2023
|
|
options = self.get_options('2023-04-01', '2023-06-30', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('REV0 Revenue 0', 1000 + 1050, 0, 750 + 750, 250 + 300, 0 ),
|
|
('REV1 Revenue 1', 1225, 0, 1050, 175, 0 ),
|
|
('REV2 Revenue 2', 1680 + 225, 0, 600 * (2 + 10/30), 600 * (14/30)+ 225, 0 ),
|
|
('Total', 5180, 0, 3950, 1230, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# 2022
|
|
options = self.get_options('2022-01-01', '2022-12-31', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# 2023: nothing to show since all the invoices are deferred
|
|
options = self.get_options('2023-01-01', '2023-12-31', self.deferred_revenue_report)
|
|
lines = self.deferred_revenue_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_report_days(self):
|
|
"""
|
|
Test the deferred expense report with the 'day' method.
|
|
We use multiple report months/quarters/years to check that the computation is correct.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'day'
|
|
self.create_invoice(self.expense_lines)
|
|
|
|
# December 2022
|
|
options = self.get_options('2022-12-01', '2022-12-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
# January 2023
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 0, 418.33, 1631.67 ),
|
|
('EXP1 Expense 1', 1225, 0, 0, 361.67, 863.33 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 0, 220, 1460 + 225 ),
|
|
('Total', 5180, 225, 0, 1000, 4180 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# February 2023
|
|
options = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 418.33, 513.33, 1118.33 ),
|
|
('EXP1 Expense 1', 1225, 0, 361.67, 326.67, 536.67 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 220, 560, 900 + 225 ),
|
|
('Total', 5180, 225, 1000, 1400, 2780 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# April 2023
|
|
options = self.get_options('2023-04-01', '2023-04-30')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
|
|
# ruff: noqa: E202
|
|
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 1500, 550, 0 ),
|
|
('EXP1 Expense 1', 1225, 0, 1050, 175, 0 ),
|
|
('EXP2 Expense 2', 1680 + 225, 0, 1400, 505, 0 ),
|
|
('Total', 5180, 0, 3950, 1230, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Q1 2023
|
|
options = self.get_options('2023-01-01', '2023-03-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 0, 1500, 550 ),
|
|
('EXP1 Expense 1', 1225, 0, 0, 1050, 175 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 0, 1400, 280 + 225 ),
|
|
('Total', 5180, 225, 0, 3950, 1230 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_report_filter_all_entries(self):
|
|
"""
|
|
Test the 'All entries' option on the deferred expense report.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'day'
|
|
self.create_invoice(self.expense_lines, post=True)
|
|
self.create_invoice(self.expense_lines, post=False)
|
|
|
|
# Only posted entries
|
|
options = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000 + 1050, 0, 418.33, 513.33, 1118.33 ),
|
|
('EXP1 Expense 1', 1225, 0, 361.67, 326.67, 536.67 ),
|
|
('EXP2 Expense 2', 1680 + 225, 225, 220, 560, 900 + 225 ),
|
|
('Total', 5180, 225, 1000, 1400, 2780 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# All non-cancelled entries
|
|
options = self._generate_options(self.deferred_expense_report, fields.Date.from_string('2023-02-01'), fields.Date.from_string('2023-02-28'), {
|
|
'all_entries': True,
|
|
})
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 2000 + 2100, 0, 836.67, 1026.67, 2236.67 ),
|
|
('EXP1 Expense 1', 2450, 0, 723.33, 653.33, 1073.33 ),
|
|
('EXP2 Expense 2', 3360 + 450, 450, 440, 1120, 1800 + 450 ),
|
|
('Total', 10360, 450, 2000, 2800, 5560 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_report_comparison(self):
|
|
"""
|
|
Test the the comparison tool on the deferred expense report.
|
|
For instance, we select April 2023 and compare it with the last 4 months
|
|
"""
|
|
self.create_invoice(self.expense_lines)
|
|
|
|
# April 2023 + period comparison of last 4 months
|
|
options = self.get_options('2023-04-01', '2023-04-30')
|
|
options = self._update_comparison_filter(options, self.deferred_expense_report, 'previous_period', 4)
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Dec 2022 Jan 2023 Feb 2023 Mar 2023 Apr 2023 (Current) Later
|
|
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
|
|
[
|
|
('EXP0 Expense 0', 2050, 0, 0, 0, 400, 550, 550, 550, 0 ),
|
|
('EXP1 Expense 1', 1225, 0, 0, 0, 350, 350, 350, 175, 0 ),
|
|
('EXP2 Expense 2', 1905, 0, 0, 0, 200, 600, 600, 505, 0 ),
|
|
('Total', 5180, 0, 0, 0, 950, 1500, 1500, 1230, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_report_partially_deductible_tax(self):
|
|
"""
|
|
Test the deferred expense report with partially deductible tax.
|
|
If we have 50% deductible tax, half of the invoice line amount should also be deferred.
|
|
Here, for an invoice line of 1000, and a tax of 40% partially deductible (50%) on 3 months, we will have:
|
|
- 1400 for the total amount, tax included
|
|
- 1200 for the total amount to be deferred (1000 + 400/2)
|
|
- 400 for the deferred amount for each of the 3 months
|
|
"""
|
|
partially_deductible_tax = self.env['account.tax'].create({
|
|
'name': 'Partially deductible Tax',
|
|
'amount': 40,
|
|
'amount_type': 'percent',
|
|
'type_tax_use': 'purchase',
|
|
'invoice_repartition_line_ids': [
|
|
Command.create({'repartition_type': 'base'}),
|
|
Command.create({
|
|
'factor_percent': 50,
|
|
'repartition_type': 'tax',
|
|
'use_in_tax_closing': False
|
|
}),
|
|
Command.create({
|
|
'factor_percent': 50,
|
|
'repartition_type': 'tax',
|
|
'account_id': self.company_data['default_account_tax_purchase'].id,
|
|
'use_in_tax_closing': True
|
|
}),
|
|
],
|
|
'refund_repartition_line_ids': [
|
|
Command.create({'repartition_type': 'base'}),
|
|
Command.create({
|
|
'factor_percent': 50,
|
|
'repartition_type': 'tax',
|
|
'use_in_tax_closing': False
|
|
}),
|
|
Command.create({
|
|
'factor_percent': 50,
|
|
'repartition_type': 'tax',
|
|
'account_id': self.company_data['default_account_tax_purchase'].id,
|
|
'use_in_tax_closing': True
|
|
}),
|
|
],
|
|
})
|
|
|
|
# Create invoice with 3 cars to be depreciated on different periods
|
|
# to make sure the deferred dates are correctly copied on the right lines
|
|
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
|
move_form.partner_id = self.partner_a
|
|
move_form.invoice_date = fields.Date.from_string('2022-01-01')
|
|
for year in (2022, 2023, 2023):
|
|
with move_form.invoice_line_ids.new() as line_form:
|
|
line_form.name = f"Car {year}"
|
|
line_form.quantity = 1
|
|
line_form.price_unit = 1000
|
|
line_form.deferred_start_date = f'{year}-01-01'
|
|
line_form.deferred_end_date = f'{year}-03-31'
|
|
line_form.tax_ids.add(partially_deductible_tax)
|
|
line_form.account_id = self.expense_accounts[0]
|
|
move = move_form.save()
|
|
move.action_post()
|
|
|
|
# Taxes for 2023 should be aggregated into one because we have the same deferred dates.
|
|
# Taxes for 2022 should not be aggregated with 2023 because we have different deferred dates.
|
|
# Therefore we have 4 lines:
|
|
# - 3 for the cars
|
|
# - 1 for the tax of 2022
|
|
# - 1 for the aggregated taxes of 2023
|
|
self.assertEqual(len(move.line_ids.filtered(lambda l: l.account_id == self.expense_accounts[0])), 5)
|
|
|
|
# 2 cars (not 3) should appear with this date range
|
|
options = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 2400, 0, 800, 800, 800 ),
|
|
('Total', 2400, 0, 800, 800, 800 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_report_credit_notes(self):
|
|
"""
|
|
Test the credit notes on the deferred expense report.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'day'
|
|
self.create_invoice(self.expense_lines, move_type='in_refund')
|
|
|
|
options = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', -1000 - 1050, 0, -418.33, -513.33, -1118.33 ),
|
|
('EXP1 Expense 1', -1225, 0, -361.67, -326.67, -536.67 ),
|
|
('EXP2 Expense 2', -1680 - 225, -225, -220, -560, -900 - 225 ),
|
|
('Total', -5180, -225, -1000, -1400, -2780 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_report_compute_method_full_months(self):
|
|
"""
|
|
Test the full_months method on the deferred expense report.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'full_months'
|
|
self.create_invoice([[self.expense_accounts[0], 1200, '2023-02-01', '2023-03-31']])
|
|
self.create_invoice([[self.expense_accounts[1], 1200, '2023-02-01', '2023-03-16']])
|
|
self.create_invoice([[self.expense_accounts[2], 1200, '2023-02-05', '2023-03-16']])
|
|
self.create_invoice([[self.expense_accounts[3], 1200, '2023-02-05', '2023-03-31']])
|
|
self.create_invoice([[self.expense_accounts[4], 1200, '2023-02-13', '2023-04-30']])
|
|
self.create_invoice([[self.expense_accounts[5], 1200, '2023-03-01', '2023-06-18']])
|
|
self.create_invoice([[self.expense_accounts[6], 1200, '2023-03-05', '2023-06-30']])
|
|
self.create_invoice([[self.expense_accounts[7], 1200, '2023-03-13', '2024-03-12']])
|
|
self.create_invoice([[self.expense_accounts[8], 1200, '2023-03-14', '2023-03-18']])
|
|
|
|
options = self.get_options('2023-03-01', '2023-03-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[0, 1, 2, 3, 4, 5],
|
|
[
|
|
('EXP0 Expense 0', 1200, 0, 600, 600, 0),
|
|
('EXP1 Expense 1', 1200, 0, 1200, 0, 0),
|
|
('EXP2 Expense 2', 1200, 0, 1200, 0, 0),
|
|
('EXP3 Expense 3', 1200, 0, 600, 600, 0),
|
|
('EXP4 Expense 4', 1200, 0, 400, 400, 400),
|
|
('EXP5 Expense 5', 1200, 0, 0, 400, 800),
|
|
('EXP6 Expense 6', 1200, 0, 0, 300, 900),
|
|
('EXP7 Expense 7', 1200, 0, 0, 100, 1100),
|
|
('EXP8 Expense 8', 1200, 0, 0, 1200, 0),
|
|
('Total', 10800, 0, 4000, 3600, 3200),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def assert_invoice_lines(self, deferred_move, expected_values):
|
|
for line, expected_value in zip(deferred_move.line_ids, expected_values):
|
|
expected_account, expected_debit, expected_credit = expected_value
|
|
self.assertRecordValues(line, [{
|
|
'account_id': expected_account.id,
|
|
'debit': expected_debit,
|
|
'credit': expected_credit,
|
|
}])
|
|
|
|
def test_deferred_expense_report_accounting_date(self):
|
|
"""
|
|
Test that the accounting date is taken into account for the deferred expense report.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.create_invoice([self.expense_lines[0]], invoice_date='2023-02-15')
|
|
|
|
# In january, the move is not accounted yet (accounting date is in 15 Feb), so nothing should be displayed.
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
# Nothing should be generated either.
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options)
|
|
|
|
# In Feb, the move is accounted, so it should be displayed.
|
|
options = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 0, 250, 250, 500 ),
|
|
('Total', 1000, 0, 250, 250, 500 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Same in March.
|
|
options = self.get_options('2023-03-01', '2023-03-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 0, 500, 250, 250 ),
|
|
('Total', 1000, 0, 500, 250, 250 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Same in April.
|
|
options = self.get_options('2023-04-01', '2023-04-30')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 0, 750, 250, 0 ),
|
|
('Total', 1000, 0, 750, 250, 0 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# In May, the move is accounted and fully deferred, so it should not be displayed.
|
|
options = self.get_options('2023-05-01', '2023-05-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[],
|
|
options,
|
|
)
|
|
|
|
def test_deferred_expense_generate_grouped_entries_method(self):
|
|
"""
|
|
Test the Generate entries button on the deferred expense report.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options)
|
|
|
|
# Create 3 different invoices (instead of one with 3 lines)
|
|
for expense_line in self.expense_lines[:3]:
|
|
self.create_invoice([expense_line])
|
|
|
|
# Check that no deferred move has been created
|
|
self.assertEqual(self.env['account.move.line'].search_count([('account_id', '=', self.deferral_account.id)]), 0)
|
|
|
|
# Generate the grouped deferred entries
|
|
generated_entries_january = self.handler._generate_deferral_entry(options)
|
|
|
|
deferred_move_january = generated_entries_january[0]
|
|
self.assertRecordValues(deferred_move_january, [{
|
|
'state': 'posted',
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-01-31'),
|
|
}])
|
|
expected_values_january = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 1000 + 1050],
|
|
[self.expense_accounts[0], 250 + 150, 0],
|
|
[self.expense_accounts[1], 0, 1225],
|
|
[self.expense_accounts[1], 350, 0],
|
|
[self.deferral_account, 1000 + 1050 + 1225 - 250 - 150 - 350, 0]
|
|
]
|
|
self.assert_invoice_lines(deferred_move_january, expected_values_january)
|
|
|
|
deferred_inverse_january = generated_entries_january[1]
|
|
self.assertEqual(deferred_inverse_january.move_type, 'entry')
|
|
self.assertEqual(deferred_inverse_january.state, 'posted') # Posted because the date is before today
|
|
self.assertEqual(deferred_inverse_january.date, fields.Date.from_string('2023-02-01'))
|
|
|
|
# Don't re-generate entries for the same period if they already exist for all move lines
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options)
|
|
|
|
# Generate the grouped deferred entries for the next period
|
|
generated_entries_february = self.handler._generate_deferral_entry(self.get_options('2023-02-01', '2023-02-28'))
|
|
deferred_move_february = generated_entries_february[0]
|
|
expected_values_february = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 1000 + 1050],
|
|
[self.expense_accounts[0], 500 + 450, 0],
|
|
[self.expense_accounts[1], 0, 1225],
|
|
[self.expense_accounts[1], 700, 0],
|
|
[self.deferral_account, 1000 + 1050 + 1225 - 500 - 450 - 700, 0]
|
|
]
|
|
self.assert_invoice_lines(deferred_move_february, expected_values_february)
|
|
|
|
def test_deferred_expense_generate_future_deferrals_grouped(self):
|
|
"""
|
|
Test the Generate entries button when we have a deferral starting after the invoice period.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.create_invoice([[self.expense_accounts[0], 750, '2023-03-01', '2023-04-15']])
|
|
|
|
# JANUARY
|
|
generated_entries_january = self.handler._generate_deferral_entry(self.get_options('2023-01-01', '2023-01-31'))
|
|
|
|
# January Deferral
|
|
deferred_move_january = generated_entries_january[0]
|
|
self.assertRecordValues(deferred_move_january, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-01-31'),
|
|
}])
|
|
expected_values_january = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 750],
|
|
[self.deferral_account, 750, 0],
|
|
]
|
|
self.assert_invoice_lines(deferred_move_january, expected_values_january)
|
|
|
|
# January Reversal
|
|
deferred_inverse_january = generated_entries_january[1]
|
|
self.assertRecordValues(deferred_inverse_january, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-02-01'),
|
|
}])
|
|
expected_values_inverse_january = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 750, 0],
|
|
[self.deferral_account, 0, 750],
|
|
]
|
|
self.assert_invoice_lines(deferred_inverse_january, expected_values_inverse_january)
|
|
|
|
# FEBRUARY
|
|
generated_entries_february = self.handler._generate_deferral_entry(self.get_options('2023-02-01', '2023-02-28'))
|
|
|
|
# February Deferral
|
|
deferred_move_february = generated_entries_february[0]
|
|
self.assertRecordValues(deferred_move_february, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-02-28'),
|
|
}])
|
|
expected_values_february = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 750],
|
|
[self.deferral_account, 750, 0],
|
|
]
|
|
self.assert_invoice_lines(deferred_move_february, expected_values_february)
|
|
|
|
# February Reversal
|
|
deferred_inverse_february = generated_entries_february[1]
|
|
self.assertRecordValues(deferred_inverse_february, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-03-01'),
|
|
}])
|
|
expected_values_inverse_february = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 750, 0],
|
|
[self.deferral_account, 0, 750],
|
|
]
|
|
self.assert_invoice_lines(deferred_inverse_february, expected_values_inverse_february)
|
|
|
|
# MARCH
|
|
generated_entries_march = self.handler._generate_deferral_entry(self.get_options('2023-03-01', '2023-03-31'))
|
|
|
|
# March Deferral
|
|
deferred_move_march = generated_entries_march[0]
|
|
self.assertRecordValues(deferred_move_march, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-03-31'),
|
|
}])
|
|
expected_values_march = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 750],
|
|
[self.expense_accounts[0], 500, 0],
|
|
[self.deferral_account, 250, 0],
|
|
]
|
|
self.assert_invoice_lines(deferred_move_march, expected_values_march)
|
|
|
|
# March Reversal
|
|
deferred_inverse_march = generated_entries_march[1]
|
|
self.assertRecordValues(deferred_inverse_march, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-04-01'),
|
|
}])
|
|
expected_values_inverse_march = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 750, 0],
|
|
[self.expense_accounts[0], 0, 500],
|
|
[self.deferral_account, 0, 250],
|
|
]
|
|
self.assert_invoice_lines(deferred_inverse_march, expected_values_inverse_march)
|
|
|
|
# APRIL
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
# No entry should be generated, since everything has been deferred.
|
|
self.handler._generate_deferral_entry(self.get_options('2023-04-01', '2023-04-30'))
|
|
|
|
def test_deferred_revenue_generate_grouped_without_taxes(self):
|
|
"""
|
|
Test the default taxes on accounts are ignored when generating a grouped deferral entry.
|
|
"""
|
|
self.company.generate_deferred_revenue_entries_method = 'manual'
|
|
deferral_account = self.company_data['default_account_deferred_revenue']
|
|
revenue_account_with_taxes = self.env['account.account'].create({
|
|
'name': 'Revenue with Taxes',
|
|
'code': 'REVWTAXES',
|
|
'account_type': 'income',
|
|
'tax_ids': [Command.set(self.tax_sale_a.ids)]
|
|
})
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
revenue_handler = self.env['account.deferred.revenue.report.handler']
|
|
|
|
self.create_invoice([[revenue_account_with_taxes, 1000, '2023-01-01', '2023-04-30']], move_type='out_invoice')
|
|
|
|
# Check that no deferred move has been created
|
|
self.assertEqual(self.env['account.move.line'].search_count([('account_id', '=', deferral_account.id)]), 0)
|
|
|
|
# Generate the grouped deferred entries
|
|
generated_entries_january = revenue_handler._generate_deferral_entry(options)
|
|
|
|
deferred_move_january = generated_entries_january[0]
|
|
self.assertRecordValues(deferred_move_january, [{
|
|
'state': 'posted',
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-01-31'),
|
|
}])
|
|
expected_values_january = [
|
|
# Account Debit Credit
|
|
[revenue_account_with_taxes, 1000, 0],
|
|
[revenue_account_with_taxes, 0, 250],
|
|
[deferral_account, 0, 750],
|
|
]
|
|
self.assert_invoice_lines(deferred_move_january, expected_values_january)
|
|
# There are no extra (tax) lines besides the three lines we checked before
|
|
self.assertFalse(deferred_move_january.line_ids.tax_line_id)
|
|
|
|
def test_deferred_values_rounding(self):
|
|
"""
|
|
When using the manually & grouped method, we might have some rounding issues
|
|
when aggregating multiple deferred entries. This test ensures that the rounding
|
|
is done correctly.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.company.deferred_amount_computation_method = 'day'
|
|
self.create_invoice([[self.expense_accounts[0], 600, '2023-04-04', '2023-05-25']])
|
|
self.create_invoice([[self.expense_accounts[1], 600, '2023-04-05', '2023-05-16']])
|
|
self.create_invoice([[self.expense_accounts[0], 600, '2023-04-04', '2023-05-08']])
|
|
|
|
# This shouldn't raise an error like this 'The total of debits equals $1,800.01 and the total of credits equals $1,800.00.'
|
|
self.handler._generate_deferral_entry(self.get_options('2023-04-01', '2023-04-30'))
|
|
|
|
def test_deferred_single_rounding(self):
|
|
"""
|
|
When using the manually & grouped method, we might have some rounding issues
|
|
due to rounding in different places. This test ensures that the a balance line is created
|
|
automatically for the difference.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.create_invoice([[self.expense_accounts[0], 4.95, '2023-01-01', '2023-10-31']])
|
|
|
|
# This shouldn't raise an error like this 'The total of debits equals $4.96 and the total of credits equals $4.95.'
|
|
generated_entries = self.handler._generate_deferral_entry(self.get_options('2023-01-01', '2023-01-31'))
|
|
|
|
deferral_move = generated_entries[0]
|
|
expected_values = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 4.95],
|
|
[self.expense_accounts[0], 0.50, 0],
|
|
[self.deferral_account, 4.46, 0],
|
|
[self.deferral_account, 0, 0.01],
|
|
]
|
|
# The balance line was added for the rounding error
|
|
self.assert_invoice_lines(deferral_move, expected_values)
|
|
|
|
def test_deferred_fully_inside_report_period(self):
|
|
"""
|
|
If the invoice is fully inside the report period, nothing should be generated.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
|
|
# The report should be empty because the invoice date, and the deferred dates are all in inside the report period
|
|
# Nothing should be reversed, displayed or generated because the invoice is already in the correct period
|
|
move1 = self.create_invoice([[self.expense_accounts[0], 600, '2023-01-15', '2023-01-30']], invoice_date='2023-01-15')
|
|
options_january = self.get_options('2023-01-01', '2023-01-31')
|
|
lines = self.deferred_expense_report._get_lines(options_january)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Before Current Later
|
|
[ 0, 1, 2, 3, 4 ],
|
|
[],
|
|
options_january,
|
|
)
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options_january)
|
|
|
|
move1.button_cancel()
|
|
|
|
# The report should be NOT empty because the invoice date is prior the report date (even if
|
|
# the deferred dates are all in inside the report period) because we need to be able to
|
|
# reverse the invoice in january and account for it in the correct period (in february here).
|
|
self.create_invoice([[self.expense_accounts[0], 1000, '2023-02-10', '2023-02-28']], invoice_date='2023-01-01')
|
|
|
|
# In january, the invoice exists, and the 'To defer' (Later) column should not be empty
|
|
lines = self.deferred_expense_report._get_lines(options_january)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 1000, 0, 0, 1000 ),
|
|
('Total', 1000, 1000, 0, 0, 1000 ),
|
|
],
|
|
options_january,
|
|
)
|
|
|
|
# The invoice should be reversed in january so that it can be accounted for in february
|
|
generated_entries = self.handler._generate_deferral_entry(options_january)
|
|
|
|
deferral_move_january = generated_entries[0]
|
|
self.assertEqual(deferral_move_january.date, fields.Date.to_date('2023-01-31'))
|
|
expected_values_january = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 1000],
|
|
[self.deferral_account, 1000, 0],
|
|
]
|
|
self.assert_invoice_lines(deferral_move_january, expected_values_january)
|
|
|
|
# In february, the invoice exists, and is being accounted for (Current column)
|
|
options_february = self.get_options('2023-02-01', '2023-02-28')
|
|
lines = self.deferred_expense_report._get_lines(options_february)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 0, 0, 1000, 0 ),
|
|
('Total', 1000, 0, 0, 1000, 0 ),
|
|
],
|
|
options_february,
|
|
)
|
|
|
|
# The invoice is now accounted for in february, so nothing should be generated
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options_february)
|
|
|
|
def test_deferred_same_date(self):
|
|
"""
|
|
A bug has been found where having an invoice with a start and end date on the last day
|
|
of the month would cause a division by zero error. This test ensures that this bug is fixed.
|
|
Here, the deferred dates are not inside the report period.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.create_invoice([[self.expense_accounts[0], 1000, '2023-10-30', '2023-10-30']])
|
|
|
|
options_sept = self.get_options('2023-09-01', '2023-09-30')
|
|
lines = self.deferred_expense_report._get_lines(options_sept)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 1000, 0, 0, 1000 ),
|
|
('Total', 1000, 1000, 0, 0, 1000 ),
|
|
],
|
|
options_sept,
|
|
)
|
|
|
|
generated_entries = self.handler._generate_deferral_entry(options_sept)
|
|
|
|
deferral_move = generated_entries[0]
|
|
self.assertEqual(deferral_move.date, fields.Date.to_date('2023-09-30'))
|
|
expected_values = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 1000],
|
|
[self.deferral_account, 1000, 0],
|
|
]
|
|
self.assert_invoice_lines(deferral_move, expected_values)
|
|
|
|
def test_deferred_expense_change_grouped_entries_method(self):
|
|
"""
|
|
Test the change of the deferred expense method from on_validation to manual
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'on_validation'
|
|
|
|
self.create_invoice([self.expense_lines[0]])
|
|
self.assertEqual(self.env['account.move.line'].search_count([('account_id', '=', self.deferral_account.id)]), 5) # 4 months + 1 for the initial deferred invoice
|
|
|
|
# When changing the method to manual, the deferred entries should not be re-generated
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(self.get_options('2023-02-01', '2023-02-28'))
|
|
|
|
def test_deferred_expense_manual_generation_totally_deferred(self):
|
|
"""
|
|
In manual mode generation, if the lines are totally deferred,
|
|
then no entry should be generated.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
self.create_invoice([[self.expense_accounts[0], 1000, '2023-01-01', '2023-04-30']])
|
|
self.handler._generate_deferral_entry(self.get_options('2023-03-01', '2023-03-31'))
|
|
self.assertEqual(self.env['account.move.line'].search_count([('account_id', '=', self.deferral_account.id)]), 2)
|
|
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(self.get_options('2023-04-01', '2023-04-30'))
|
|
|
|
move2 = self.create_invoice([[self.expense_accounts[1], 1000, '2023-01-01', '2023-05-31']])
|
|
generated_entry = self.handler._generate_deferral_entry(self.get_options('2023-04-01', '2023-04-30'))[0]
|
|
self.assertEqual(len(generated_entry.line_ids), 3) # 3 lines, not 6 because move1 is totally deferred
|
|
self.assertEqual(generated_entry.deferred_original_move_ids, move2) # not move1
|
|
|
|
def test_deferred_expense_manual_generation_only_posted(self):
|
|
"""
|
|
In manual mode generation, even if the filter shows draft moves,
|
|
then no entry should be generated for draft moves.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
self.create_invoice([self.expense_lines[0]], post=False)
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
options['all_entries'] = True
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options)
|
|
|
|
def test_deferred_expense_manual_generation_after_on_validation(self):
|
|
"""
|
|
In manual mode, you should still be able to generate an deferral entry for a period
|
|
when there already exists a deferral entry from a former on_validation mode on the same date,
|
|
and that entry should not defer the already deferred amount from the automatic entry in that
|
|
same period.
|
|
"""
|
|
# First post an invoice with the on_validation method, creating deferrals
|
|
move = self.create_invoice([self.expense_lines[0]])
|
|
# Check that the deferral moves have been created (1 + 4)
|
|
self.assertEqual(len(move.deferred_move_ids), 5)
|
|
|
|
# Switch to manual mode
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.create_invoice([self.expense_lines[0]])
|
|
|
|
options = self.get_options('2023-01-01', '2023-01-31')
|
|
generated_entries_jan = self.handler._generate_deferral_entry(options)
|
|
|
|
deferred_move_jan = generated_entries_jan[0]
|
|
self.assertRecordValues(deferred_move_jan, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-01-31'),
|
|
}])
|
|
expected_values_jan = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 1000],
|
|
[self.expense_accounts[0], 250, 0],
|
|
[self.deferral_account, 750, 0],
|
|
]
|
|
self.assert_invoice_lines(deferred_move_jan, expected_values_jan)
|
|
|
|
# Reversal
|
|
deferred_inverse_jan = generated_entries_jan[1]
|
|
self.assertRecordValues(deferred_inverse_jan, [{
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-02-01'),
|
|
}])
|
|
expected_values_inverse_jan = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 1000, 0],
|
|
[self.expense_accounts[0], 0, 250],
|
|
[self.deferral_account, 0, 750],
|
|
]
|
|
self.assert_invoice_lines(deferred_inverse_jan, expected_values_inverse_jan)
|
|
|
|
def test_deferred_expense_manual_generation_old_moves(self):
|
|
"""Test that old moves are not taken into account when generating deferred entries."""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
|
|
self.create_invoice([(self.expense_accounts[0], 1200, '2022-01-01', '2022-12-31')])
|
|
self.create_invoice([(self.expense_accounts[0], 1200, '2023-01-01', '2023-12-31')])
|
|
|
|
options = self.get_options('2023-03-01', '2023-03-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1200, 0, 200, 100, 900 ),
|
|
('Total', 1200, 0, 200, 100, 900 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
expected_values = (
|
|
# Account Debit Credit
|
|
(self.expense_accounts[0], 0, 1200),
|
|
(self.expense_accounts[0], 300, 0),
|
|
(self.deferral_account, 900, 0),
|
|
)
|
|
deferral = self.handler._generate_deferral_entry(options)[0]
|
|
self.assert_invoice_lines(deferral, expected_values)
|
|
|
|
def test_deferred_expense_manual_generation_deprecated_account(self):
|
|
"""Test that deferred on deprecated accounts are still visible in the report, but cannot be generated."""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
|
|
self.create_invoice([self.expense_lines[0]])
|
|
self.expense_accounts[0].deprecated = True
|
|
|
|
options = self.get_options('2023-03-01', '2023-03-31')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 0, 500, 250, 250 ),
|
|
('Total', 1000, 0, 500, 250, 250 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Shouldn't raise
|
|
# 'The account ... is deprecated.'
|
|
# or 'A line of this move is using a deprecated account, you cannot post it.'
|
|
entries = self.handler._generate_deferral_entry(options)
|
|
expected_values = [
|
|
# Account Debit Credit
|
|
[self.expense_accounts[0], 0, 1000],
|
|
[self.expense_accounts[0], 750, 0],
|
|
[self.deferral_account, 250, 0],
|
|
]
|
|
self.assert_invoice_lines(entries[0], expected_values)
|
|
|
|
def test_deferred_expense_manual_generation_go_backwards_in_time(self):
|
|
"""
|
|
In manual mode generation, if we generate the deferral entries for
|
|
a given month, we should still be able to generate the entries for
|
|
the months prior to this one.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
# No entries yet for August
|
|
options_august = self.get_options('2023-08-01', '2023-08-31')
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options_august)
|
|
|
|
self.create_invoice([[self.expense_accounts[0], 600, '2023-07-01', '2023-09-30']])
|
|
|
|
# Check that no deferred move has been created yet
|
|
self.assertEqual(self.env['account.move.line'].search_count([('account_id', '=', self.deferral_account.id)]), 0)
|
|
|
|
# Generate the grouped deferred entries for August (before doing it for July)
|
|
generated_entries_august = self.handler._generate_deferral_entry(options_august)
|
|
deferred_move_august = generated_entries_august[0]
|
|
expected_values_august = (
|
|
# Account Debit Credit
|
|
(self.expense_accounts[0], 0, 600),
|
|
(self.expense_accounts[0], 400, 0),
|
|
(self.deferral_account, 200, 0),
|
|
)
|
|
self.assert_invoice_lines(deferred_move_august, expected_values_august)
|
|
|
|
# Don't re-generate entries for the same period if they already exist for all move lines
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options_august)
|
|
|
|
# Generate the grouped deferred entries for July
|
|
options_july = self.get_options('2023-07-01', '2023-07-31')
|
|
generated_entries_july = self.handler._generate_deferral_entry(options_july)
|
|
self.assertRecordValues(generated_entries_july, [{
|
|
'state': 'posted',
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-07-31'),
|
|
}, {
|
|
'state': 'posted',
|
|
'move_type': 'entry',
|
|
'date': fields.Date.to_date('2023-08-01'),
|
|
}])
|
|
deferred_move_july, reversed_deferred_move_july = generated_entries_july
|
|
expected_values_july = (
|
|
# Account Debit Credit
|
|
(self.expense_accounts[0], 0, 600),
|
|
(self.expense_accounts[0], 200, 0),
|
|
(self.deferral_account, 400, 0),
|
|
)
|
|
expected_values_july_reversed = (
|
|
# Account Debit Credit
|
|
(self.expense_accounts[0], 600, 0),
|
|
(self.expense_accounts[0], 0, 200),
|
|
(self.deferral_account, 0, 400),
|
|
)
|
|
self.assert_invoice_lines(deferred_move_july, expected_values_july)
|
|
self.assert_invoice_lines(reversed_deferred_move_july, expected_values_july_reversed)
|
|
|
|
# Don't re-generate entries for the same period if they already exist for all move lines
|
|
with self.assertRaisesRegex(UserError, 'No entry to generate.'):
|
|
self.handler._generate_deferral_entry(options_july)
|
|
|
|
def test_deferred_expense_manual_generation_single_period(self):
|
|
"""
|
|
If we have an invoice covering only one period, we should only avoid creating deferral entries when the invoice
|
|
date is the same as the period for the deferral. Otherwise we should still generate a deferral entry.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
self.create_invoice([[self.expense_accounts[0], 1000, '2023-02-01', '2023-02-28']])
|
|
|
|
self.handler._generate_deferral_entry(self.get_options('2023-01-01', '2023-01-31'))
|
|
self.assertEqual(self.env['account.move.line'].search_count([('account_id', '=', self.deferral_account.id)]), 2)
|
|
|
|
def test_deferred_expense_generation_lock_date(self):
|
|
"""
|
|
Test that we cannot generate entries for a period that is locked.
|
|
"""
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
move = self.create_invoice([[self.expense_accounts[0], 1000, '2023-01-01', '2023-04-30']])
|
|
|
|
move.company_id.fiscalyear_lock_date = fields.Date.to_date('2023-02-28')
|
|
|
|
with self.assertRaisesRegex(UserError, 'You cannot generate entries for a period that is locked.'):
|
|
self.handler._generate_deferral_entry(self.get_options('2023-01-01', '2023-01-31'))
|
|
|
|
def test_deferred_expense_manual_generation_reset_to_draft(self):
|
|
"""Test that the deferred entries cannot be deleted in the manual mode"""
|
|
|
|
# On validation, we can reset to draft
|
|
self.company.deferred_amount_computation_method = 'month'
|
|
move = self.create_invoice([(self.expense_accounts[0], 1680, '2023-01-21', '2023-04-14')])
|
|
self.assertEqual(len(move.deferred_move_ids), 5)
|
|
move.button_draft()
|
|
self.assertFalse(move.deferred_move_ids)
|
|
move.action_post() # Repost
|
|
|
|
# Let's switch to manual mode
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
# We should still be able to reset to draft a move that was created with the on_validation mode
|
|
move.button_draft()
|
|
self.assertFalse(move.deferred_move_ids)
|
|
|
|
# If the grouped deferral entry is the aggregation of only one invoice, we can reset the invoice to draft
|
|
move3 = self.create_invoice([(self.expense_accounts[0], 1680, '2023-03-21', '2023-06-14')])
|
|
self.handler._generate_deferral_entry(self.get_options('2023-03-01', '2023-03-31'))
|
|
move3.button_draft()
|
|
self.assertFalse(move.deferred_move_ids)
|
|
|
|
# If the grouped deferral entry is the aggregation of more than one invoice, we cannot reset to draft any of those to draft
|
|
move4 = self.create_invoice([(self.expense_accounts[0], 1680, '2023-03-21', '2023-06-14')])
|
|
move5 = self.create_invoice([(self.expense_accounts[0], 1680, '2023-03-21', '2023-06-14')])
|
|
self.handler._generate_deferral_entry(self.get_options('2023-03-01', '2023-03-31'))
|
|
with self.assertRaisesRegex(UserError, 'You cannot reset to draft an invoice that is grouped in deferral entry. You can create a credit note instead.'):
|
|
move4.button_draft()
|
|
with self.assertRaisesRegex(UserError, 'You cannot reset to draft an invoice that is grouped in deferral entry. You can create a credit note instead.'):
|
|
move5.button_draft()
|
|
|
|
def test_deferred_expense_on_validation_generation_analytic_distribution(self):
|
|
"""Test that the analytic distribution of the invoice is transferred the deferred entries generated on validation."""
|
|
|
|
analytic_plan_a = self.env['account.analytic.plan'].create({
|
|
'name': 'Plan A',
|
|
})
|
|
aa_a1 = self.env['account.analytic.account'].create({
|
|
'name': 'Account A1',
|
|
'plan_id': analytic_plan_a.id
|
|
})
|
|
aa_a2 = self.env['account.analytic.account'].create({
|
|
'name': 'Account A2',
|
|
'plan_id': analytic_plan_a.id
|
|
})
|
|
move = self.create_invoice([self.expense_lines[0]], post=False)
|
|
move.write({'invoice_line_ids': [
|
|
Command.update(move.invoice_line_ids.id, {'analytic_distribution': {str(aa_a1.id): 60.0, str(aa_a2.id): 40.0}}),
|
|
]})
|
|
self.env['account.move.line'].flush_model()
|
|
move.action_post()
|
|
expected_analytic_distribution = {str(aa_a1.id): 60.0, str(aa_a2.id): 40.0}
|
|
for line in move.deferred_move_ids.line_ids:
|
|
self.assertEqual(line.analytic_distribution, expected_analytic_distribution)
|
|
|
|
def test_deferred_expense_manual_generation_analytic_distribution(self):
|
|
"""
|
|
When using the manually & grouped method, the analytic distribution of the deferred entries
|
|
should be computed according to the proportion between the deferred amount of each account
|
|
and the total deferred amount.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
|
|
analytic_plan_a = self.env['account.analytic.plan'].create({
|
|
'name': 'Plan A',
|
|
})
|
|
analytic_plan_b = self.env['account.analytic.plan'].create({
|
|
'name': 'Plan B',
|
|
})
|
|
aa_a1 = self.env['account.analytic.account'].create({
|
|
'name': 'Account A1',
|
|
'plan_id': analytic_plan_a.id
|
|
})
|
|
aa_a2 = self.env['account.analytic.account'].create({
|
|
'name': 'Account A2',
|
|
'plan_id': analytic_plan_a.id
|
|
})
|
|
aa_a3 = self.env['account.analytic.account'].create({
|
|
'name': 'Account A3',
|
|
'plan_id': analytic_plan_a.id
|
|
})
|
|
aa_b1 = self.env['account.analytic.account'].create({
|
|
'name': 'Account B1',
|
|
'plan_id': analytic_plan_b.id
|
|
})
|
|
aa_b2 = self.env['account.analytic.account'].create({
|
|
'name': 'Account B2',
|
|
'plan_id': analytic_plan_b.id
|
|
})
|
|
# Test the account move lines with the following analytic distribution:
|
|
#
|
|
# # | Expense Account | Amount | Analytic Distribution
|
|
# ------------------------------------------------------------------------
|
|
# 1 | Expense 0 | 1200 | {A1: 60%, A2: 40%, B1: 50%, B2: 50%}
|
|
# 2 | Expense 0 | 2400 | {A1: 100%}
|
|
# 3 | Expense 1 | 1200 | {A1: 50%, A3: 50%}
|
|
# 4 | Expense 1 | 1200 | NULL
|
|
|
|
invoice_lines = [
|
|
[self.expense_accounts[0], 1200, '2023-01-01', '2023-12-31'],
|
|
[self.expense_accounts[0], 2400, '2023-01-01', '2023-12-31'],
|
|
[self.expense_accounts[1], 1200, '2023-01-01', '2023-12-31'],
|
|
[self.expense_accounts[1], 1200, '2023-01-01', '2023-12-31'],
|
|
]
|
|
move = self.create_invoice(invoice_lines, post=False)
|
|
move.write({'invoice_line_ids': [
|
|
Command.update(move.invoice_line_ids[0].id,
|
|
{'analytic_distribution': {str(aa_a1.id): 60.0, str(aa_a2.id): 40.0, str(aa_b1.id): 50.0, str(aa_b2.id): 50.0}}
|
|
),
|
|
Command.update(move.invoice_line_ids[1].id,{'analytic_distribution': {str(aa_a1.id): 100.0}}),
|
|
Command.update(move.invoice_line_ids[2].id, {'analytic_distribution': {str(aa_a1.id): 50.0, str(aa_a3.id): 50.0}}),
|
|
]})
|
|
self.env['account.move.line'].flush_model()
|
|
move.action_post()
|
|
|
|
# Generate the grouped deferred entries
|
|
generated_entries = self.handler._generate_deferral_entry(self.get_options('2023-01-01', '2023-08-31'))
|
|
|
|
# Details of the computation:
|
|
# Total Amount (Deferral Account): 1200 + 2400 + 1200 + 1200 = 6000
|
|
# Amount for Expense 0: 1200 + 2400 = 3600
|
|
# Amount for Expense 1: 1200 + 1200 = 2400
|
|
# ___________________________________________________________________________________________________________________
|
|
# | | | | Distribution by expense (*) | Deferral distribution (**)
|
|
# # | Amount | Expense ratio | Total ratio | (distribution / expense ratio) | (distribution / total ratio)
|
|
# -------------------------------------------------------------------------------------------------------------------
|
|
# 1 | 1200 | 1200 / 3600 = 0.33 | 1200 / 6000 = 0.2 | A1 = 60% * 0.33 = 20% | A1 = 60% * 0.2 = 12%
|
|
# | | (0.33333333333...) | | A2 = 40% * 0.33 = 13.33% | A2 = 40% * 0.2 = 8%
|
|
# | | | | B1, B2 = 50% * 0.33 = 16.67% | B1, B2 = 50% * 0.2 = 10%
|
|
# -------------------------------------------------------------------------------------------------------------------
|
|
# 2 | 1200 | 2400 / 3600 = 0.67 | 2400 / 6000 = 0.4 | A1 = 100% * 0.67 = 66.67% | A1 = 100% * 0.4 = 40%
|
|
# -------------------------------------------------------------------------------------------------------------------
|
|
# 3 | 1200 | 1200 / 2400 = 0.5 | 1200 / 6000 = 0.2 | A1, A3 = 50% * 0.5 = 25% | A1, A3 = 50% * 0.2 = 10%
|
|
# -------------------------------------------------------------------------------------------------------------------
|
|
# 4 | 1200 | 1200 / 2400 = 0.5 | 1200 / 6000 = 0.2 | NULL | NULL
|
|
#
|
|
# The analytic distribution of the deferred entries should be:
|
|
# - Expense 0: {A1: 86.67%, A2: 13.33%, B1: 16.67%, B2: 16.67%} [Sum of column (*) of line #1 and #2]
|
|
# - Expense 1: {A1: 25%, A3: 25%} [Sum of column (*) of line #3 and #4]
|
|
# - Deferral Account: {A1: 62%, A2: 8%, B1: 10%, B2: 10%, A3: 10%} [Sum of column (**) of all 4 lines]
|
|
#
|
|
# The 2 generated entries should be the "Grouped Deferral Entry of Aug 2023" and its reversal.
|
|
#
|
|
# "Grouped Deferral Entry of Aug 2023":
|
|
#
|
|
# Account | Analytic Distribution | Debit | Credit
|
|
# -------------------------------------------------------------------------------------
|
|
# Expense 0 | {A1: 86.67%, A2: 13.33%, B1: 16.67%, B2: 16.67%} | 3600 | 0
|
|
# Expense 0 | {A1: 86.67%, A2: 13.33%, B1: 16.67%, B2: 16.67%} | 0 | 2400
|
|
# Expense 1 | {A1: 25%, A3: 25%} | 2400 | 0
|
|
# Expense 1 | {A1: 25%, A3: 25%} | 0 | 1600
|
|
# Deferral Account | {A1: 62%, A2: 8%, B1: 10%, B2: 10%, A3: 10%} | 0 | 2000
|
|
# -------------------------------------------------------------------------------------
|
|
# | 6000 | 6000
|
|
expected_analytic_distribution = {
|
|
self.expense_accounts[0].id: {str(aa_a1.id): 86.67, str(aa_a2.id): 13.33, str(aa_b1.id): 16.67, str(aa_b2.id): 16.67},
|
|
self.expense_accounts[1].id: {str(aa_a1.id): 25.0, str(aa_a3.id): 25.0},
|
|
self.deferral_account.id: {str(aa_a1.id): 62.0, str(aa_a2.id): 8.0, str(aa_b1.id): 10.0, str(aa_b2.id): 10.0, str(aa_a3.id): 10.0},
|
|
}
|
|
expected_analytic_amount = [{
|
|
aa_a1.id: (3120.12, 0.00), # 3600 * 86.67%
|
|
aa_a2.id: ( 479.88, 0.00), # 3600 * 13.33%
|
|
aa_b1.id: ( 0.00, 600.12), # 3600 * 16.67%
|
|
aa_b2.id: ( 0.00, 600.12), # 3600 * 16.67%
|
|
}, {
|
|
aa_a1.id: (-2080.08, 0.00), # -2400 * 86.67%
|
|
aa_a2.id: ( -319.92, 0.00), # -2400 * 13.33%
|
|
aa_b1.id: ( 0.00, -400.08), # -2400 * 16.67%
|
|
aa_b2.id: ( 0.00, -400.08), # -2400 * 16.67%
|
|
},{
|
|
aa_a1.id: ( 600.00, 0.00), # 2400 * 25%
|
|
aa_a3.id: ( 600.00, 0.00), # 2400 * 25%
|
|
},{
|
|
aa_a1.id: ( -400.00, 0.00), # -1600 * 25%
|
|
aa_a3.id: ( -400.00, 0.00), # -1600 * 25%
|
|
}, {
|
|
aa_a1.id: (-1240.00, 0.00), # -2000 * 62%
|
|
aa_a2.id: ( -160.00, 0.00), # -2000 * 8%
|
|
aa_a3.id: ( -200.00, 0.00), # -2000 * 10%
|
|
aa_b1.id: ( 0.00, -200.00), # -2000 * 10%
|
|
aa_b2.id: ( 0.00, -200.00), # -2000 * 10%
|
|
}]
|
|
# testing the amount of the analytic lines for the "Grouped Deferral Entry of Aug 2023"
|
|
for index, line in enumerate(generated_entries[0].line_ids):
|
|
self.assertEqual(line.analytic_distribution, expected_analytic_distribution[line.account_id.id])
|
|
for al in line.analytic_line_ids:
|
|
fname_a = analytic_plan_a._column_name()
|
|
fname_b = analytic_plan_b._column_name()
|
|
fname, idx = (fname_a, 0) if al[fname_a] else (fname_b, 1)
|
|
self.assertAlmostEqual(al.amount, expected_analytic_amount[index][al[fname].id][idx])
|
|
# testing the amount of the analytic lines for the "Reversal of Grouped Deferral Entry of Aug 2023"
|
|
# the values should be the opposite of the "Grouped Deferral Entry of Aug 2023"
|
|
for index, line in enumerate(generated_entries[1].line_ids):
|
|
self.assertEqual(line.analytic_distribution, expected_analytic_distribution[line.account_id.id])
|
|
for al in line.analytic_line_ids:
|
|
fname_a = analytic_plan_a._column_name()
|
|
fname_b = analytic_plan_b._column_name()
|
|
fname, idx = (fname_a, 0) if al[fname_a] else (fname_b, 1)
|
|
self.assertAlmostEqual(al.amount, -expected_analytic_amount[index][al[fname].id][idx])
|
|
|
|
def test_deferred_expense_report_invalid_period(self):
|
|
"""
|
|
Only periods that start on the first day of a month and end on the last day of a month are allowed.
|
|
"""
|
|
self.company.generate_deferred_expense_entries_method = 'manual'
|
|
self.create_invoice([self.expense_lines[0]])
|
|
|
|
options = self.get_options('2023-03-01', '2023-03-15')
|
|
lines = self.deferred_expense_report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Total Not Started Before Current Later
|
|
[ 0, 1, 2, 3, 4, 5 ],
|
|
[
|
|
('EXP0 Expense 0', 1000, 0, 500, 125, 375 ),
|
|
('Total', 1000, 0, 500, 125, 375 ),
|
|
],
|
|
options,
|
|
)
|
|
|
|
with self.assertRaisesRegex(UserError, 'You cannot generate entries for a period that does not end at the end of the month.'):
|
|
self.handler._generate_deferral_entry(options)
|