[ADD] new module account_subsequence_fiscal_year

Co-authored-by: Saran @ Ecosoft <saranl@ecosoft.co.th>
This commit is contained in:
Sylvain LE GAL
2020-05-30 14:50:27 +02:00
parent c7eea57f24
commit 1ef9c7ead8
18 changed files with 463 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
========================================
Accounting Subsequences per Fiscal Years
========================================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,27 @@
# Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Accounting Subsequences per Fiscal Years",
"summary": "Allow to create sub sequences for account moves number, based"
" on the fiscal years settings",
"version": "12.0.1.0.0",
"category": "Accounting",
"author": "GRAP,Odoo Community Association (OCA)",
"maintainers": ["legalsylvain"],
"website": "http://www.github.com/OCA/account-financial-tools",
"license": "AGPL-3",
"depends": [
"account",
],
"data": [
"views/view_res_config_settings.xml",
],
"demo": [
"demo/res_groups.xml",
],
"images": [
"static/description/res_config_setting.png",
],
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="account.group_account_user" model="res.groups">
<field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
</odoo>

View File

@@ -0,0 +1,79 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_subsequence_fiscal_year
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-30 17:11+0000\n"
"PO-Revision-Date: 2020-05-30 17:11+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_subsequence_fiscal_year
#: model_terms:ir.ui.view,arch_db:account_subsequence_fiscal_year.view_res_config_settings_form
msgid "<span class=\"o_form_label\">Accounting Subsequences Method</span>"
msgstr "<span class=\"o_form_label\">Méthode pour les sous-séquences comptables</span>"
#. module: account_subsequence_fiscal_year
#: model:ir.model.fields,field_description:account_subsequence_fiscal_year.field_res_company__account_subsequence_method
#: model:ir.model.fields,field_description:account_subsequence_fiscal_year.field_res_config_settings__account_subsequence_method
msgid "Accounting Subsequences Method"
msgstr "Méthode pour les sous-séquences comptables"
#. module: account_subsequence_fiscal_year
#: model:ir.model,name:account_subsequence_fiscal_year.model_account_bank_statement
msgid "Bank Statement"
msgstr "Relevé bancaire"
#. module: account_subsequence_fiscal_year
#: selection:res.company,account_subsequence_method:0
msgid "Based on Company Settings"
msgstr "Basé sur les paramètres de la société"
#. module: account_subsequence_fiscal_year
#: selection:res.company,account_subsequence_method:0
msgid "Based on Fiscal Years Settings"
msgstr "Basés sur les exercices comptables"
#. module: account_subsequence_fiscal_year
#: model:ir.model,name:account_subsequence_fiscal_year.model_res_company
msgid "Companies"
msgstr "Sociétés"
#. module: account_subsequence_fiscal_year
#: model:ir.model,name:account_subsequence_fiscal_year.model_res_config_settings
msgid "Config Settings"
msgstr "Paramètres de config"
#. module: account_subsequence_fiscal_year
#: model_terms:ir.ui.view,arch_db:account_subsequence_fiscal_year.view_res_config_settings_form
msgid "Define how accounting subsequences are generated"
msgstr "Définit comment les sous-séquences comptables sont générées"
#. module: account_subsequence_fiscal_year
#: model_terms:ir.ui.view,arch_db:account_subsequence_fiscal_year.view_res_config_settings_form
msgid "Generation Method"
msgstr "Méthode de génération"
#. module: account_subsequence_fiscal_year
#: model:ir.model,name:account_subsequence_fiscal_year.model_account_move
msgid "Journal Entries"
msgstr "Pièces comptables"
#. module: account_subsequence_fiscal_year
#: model:ir.model,name:account_subsequence_fiscal_year.model_ir_sequence
msgid "Sequence"
msgstr "Séquence"
#. module: account_subsequence_fiscal_year
#: code:addons/account_subsequence_fiscal_year/models/ir_sequence.py:45
#, python-format
msgid "You can not post an accounting entry for the date %s because there is no fiscal year defined at this date."
msgstr "Vous ne pouvez pas valider une pièce comptable pour la date du %s car aucun exercice comptable n'est défini à cette date."

View File

@@ -0,0 +1,5 @@
from . import account_bank_statement
from . import account_move
from . import ir_sequence
from . import res_company
from . import res_config_settings

View File

@@ -0,0 +1,14 @@
# Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
class AccountBankStatement(models.Model):
_inherit = "account.bank.statement"
@api.multi
def button_open(self):
return super(
AccountBankStatement, self.with_context(account_sequence=True)
).button_open()

View File

@@ -0,0 +1,14 @@
# Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
class AccountMove(models.Model):
_inherit = "account.move"
@api.multi
def post(self, invoice=False):
return super(
AccountMove, self.with_context(account_sequence=True)
).post(invoice=invoice)

View File

@@ -0,0 +1,59 @@
# Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import datetime
from dateutil.relativedelta import relativedelta
from odoo import _, fields, models
from odoo.exceptions import ValidationError
class IrSequence(models.Model):
_inherit = "ir.sequence"
def _create_date_range_seq(self, date):
AccountFiscalYear = self.env["account.fiscal.year"]
IrSequenceDateRange = self.env["ir.sequence.date_range"]
if self._context.get("account_sequence", False)\
and self.company_id\
and self.company_id.account_subsequence_method:
method = self.company_id.account_subsequence_method
object_date = fields.Date.from_string(date)
if method == "company_setting":
base_date = datetime.date(
object_date.year,
int(self.company_id.fiscalyear_last_month),
int(self.company_id.fiscalyear_last_day),
)
if object_date <= base_date:
date_from = base_date + relativedelta(years=-1, days=1)
date_to = base_date
else:
date_from = base_date + relativedelta(days=1)
date_to = base_date + relativedelta(years=1)
elif method == "fiscal_year_setting":
fiscal_years = AccountFiscalYear.search(
[("date_to", ">=", object_date.strftime("%Y-%m-%d"))],
order="date_from desc",
limit=1
)
if not fiscal_years or fiscal_years[0].date_from > object_date:
raise ValidationError(_(
"You can not post an accounting entry for the"
" date %s because there is no fiscal year defined at"
" this date.") % (date))
date_from = fiscal_years[0].date_from
date_to = fiscal_years[0].date_to
# Create and return new sequence
return IrSequenceDateRange.sudo().create({
'sequence_id': self.id,
'date_from': date_from,
'date_to': date_to,
})
return super()._create_date_range_seq(date)

View File

@@ -0,0 +1,16 @@
# Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = "res.company"
account_subsequence_method = fields.Selection(
string="Accounting Subsequences Method",
selection=[
("company_setting", "Based on Company Settings"),
("fiscal_year_setting", "Based on Fiscal Years Settings"),
])

View File

@@ -0,0 +1,13 @@
# Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
account_subsequence_method = fields.Selection(
related="company_id.account_subsequence_method",
readonly=False,
)

View File

@@ -0,0 +1,27 @@
To configure this module, you need to:
* Add your users to the group 'Technical Settings / Show Full Accounting Features'
* Go to Invoicing > Configuration / Settings
* configure your accounting settings
.. figure:: ../static/description/res_config_setting.png
Depending on what you want, 3 options are available.
Given the following example:
- an account move with a date set to 2030-06-01
- a company set with ``fiscalyear_last_day = 1`` and ``fiscalyear_last_month = 10``
* 'empty' (default value):
the subsequence will be created "normaly", with ``date_from = 2030-01-01`` and ``date_to = 2030-12-31``
* 'Based on Company Settings':
the subsequence will be created depending on the values of ``fiscalyear_last_day``
and ``fiscalyear_last_month``, so ``date_from = 2029-10-01`` and ``date_to = 2030-09-30``
* 'Based on Fiscal Years Settings':
the subsequence will be created with the values defined in the according fiscal year.
Note that if no fiscal year is found, the generation will fail.

View File

@@ -0,0 +1 @@
* Sylvain LE GAL <https://twitter.com/legalsylvain>

View File

@@ -0,0 +1,9 @@
This module extends the functionality of Accounting Odoo module, to
generate custom sub sequences for accounting entries, if fiscal years are not "classic".
(ie: last day = 31 / last month = 12)
without this module, in such cases (for example, for fiscal year from 01 April 2020 to 31 May 2021)
accounting moves of the same fiscal year will not have the same numbering: Some entries will
have ``BILL/2020/`` prefix and other will have ``BILL/2021/``, that is not allowed in many countries.
That modules fixes this problem.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1 @@
from . import test_module

View File

@@ -0,0 +1,142 @@
# Copyright 2020 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
from datetime import date
class TestModule(TransactionCase):
def setUp(self):
super().setUp()
self.AccountFiscalYear = self.env["account.fiscal.year"]
self.company = self.env.ref("base.main_company")
self.account_type_receivable = self.env["account.account.type"].create(
{"name": "Test Receivable", "type": "receivable"}
)
self.account_receivable = self.env["account.account"].create(
{
"name": "Test Receivable",
"code": "TEST_AR",
"user_type_id": self.account_type_receivable.id,
"reconcile": True,
}
)
self.sale_journal = self.env["account.journal"].search(
[("type", "=", "sale"), ("company_id", "=", self.company.id)]
)[0]
self.sequence = self.sale_journal.sequence_id
self.sequence.use_date_range = True
self.account_move = self.env["account.move"].create({
"journal_id": self.sale_journal.id,
"company_id": self.company.id,
"line_ids": [(0, 0, {
"account_id": self.account_receivable.id,
"debit": 100,
}), (0, 0, {
"account_id": self.account_receivable.id,
"credit": 100,
})]
})
self.existing_subsequence_ids =\
self.env["ir.sequence.date_range"].search([
("sequence_id", "=", self.sequence.id)]).ids
def _get_new_subsequence(self):
return self.env["ir.sequence.date_range"].search([
("sequence_id", "=", self.sequence.id),
("id", "not in", self.existing_subsequence_ids),
])
def test_method_normal(self):
"""Non Regression Test"""
self.company.account_subsequence_method = False
self.account_move.date = "2100-06-01"
self.account_move.post()
new_subsequences = self._get_new_subsequence()
self.assertEqual(len(new_subsequences), 1)
self.assertEqual(
new_subsequences[0].date_from,
date(2100, 1, 1)
)
self.assertEqual(
new_subsequences[0].date_to,
date(2100, 12, 31)
)
def test_method_company_setting_before(self):
self.company.account_subsequence_method = 'company_setting'
self.company.fiscalyear_last_day = 31
self.company.fiscalyear_last_month = 3
self.account_move.date = "2100-03-15"
self.account_move.post()
new_subsequences = self._get_new_subsequence()
self.assertEqual(len(new_subsequences), 1)
self.assertEqual(
new_subsequences[0].date_from,
date(2099, 4, 1)
)
self.assertEqual(
new_subsequences[0].date_to,
date(2100, 3, 31)
)
def test_method_company_setting_after(self):
self.company.account_subsequence_method = 'company_setting'
self.company.fiscalyear_last_day = 31
self.company.fiscalyear_last_month = 3
self.account_move.date = "2100-05-15"
self.account_move.post()
new_subsequences = self._get_new_subsequence()
self.assertEqual(len(new_subsequences), 1)
self.assertEqual(
new_subsequences[0].date_from,
date(2100, 4, 1)
)
self.assertEqual(
new_subsequences[0].date_to,
date(2101, 3, 31)
)
def test_method_fiscal_year_setting(self):
self.company.account_subsequence_method = 'fiscal_year_setting'
with self.assertRaises(ValidationError):
self.account_move.date = "2100-06-01"
self.account_move.post()
# create a Fiscal Year
self.AccountFiscalYear.create({
"name": "2100 FY April to March",
"company_id": self.company.id,
"date_from": "2100-04-01",
"date_to": "2101-03-31",
})
# Try to post out the date range
with self.assertRaises(ValidationError):
self.account_move.date = "2100-03-31"
self.account_move.post()
with self.assertRaises(ValidationError):
self.account_move.date = "2101-04-01"
self.account_move.post()
# Post in the range should succeed
self.account_move.date = "2100-06-01"
self.account_move.post()
new_subsequences = self._get_new_subsequence()
self.assertEqual(len(new_subsequences), 1)
self.assertEqual(
new_subsequences[0].date_from,
date(2100, 4, 1)
)
self.assertEqual(
new_subsequences[0].date_to,
date(2101, 3, 31)
)

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="view_res_config_settings_form" model="ir.ui.view">
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="account.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='accounting_reports']" position="inside">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<span class="o_form_label">Accounting Subsequences Method</span>
<div class="text-muted">
Define how accounting subsequences are generated
</div>
<div class="content-group">
<div class="row mt16">
<label string="Generation Method" for="account_subsequence_method" class="col-lg-3 o_light_label"/>
<field name="account_subsequence_method"/>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>