diff --git a/odoo-bringout-oca-ocb-account/account/migrations/16.1.0.0/__init__.py b/odoo-bringout-oca-ocb-account/account/migrations/16.1.0.0/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/odoo-bringout-oca-ocb-account/account/migrations/16.1.0.0/post-migration.py b/odoo-bringout-oca-ocb-account/account/migrations/16.1.0.0/post-migration.py new file mode 100644 index 0000000..7176ead --- /dev/null +++ b/odoo-bringout-oca-ocb-account/account/migrations/16.1.0.0/post-migration.py @@ -0,0 +1,63 @@ +from odoo import api, SUPERUSER_ID + + +def _table_has_column(cr, table, column): + cr.execute( + """ + SELECT 1 + FROM information_schema.columns + WHERE table_name = %s AND column_name = %s + """, + (table, column), + ) + return bool(cr.fetchone()) + + +def migrate(cr, version): + if not version: + return + + env = api.Environment(cr, SUPERUSER_ID, {}) + + # Initialise new company lock fields using existing lock dates. + companies = env['res.company'].with_context(active_test=False).search([]) + for company in companies: + vals = {} + if not company.sale_lock_date and company.period_lock_date: + vals['sale_lock_date'] = company.period_lock_date + if not company.purchase_lock_date and company.period_lock_date: + vals['purchase_lock_date'] = company.period_lock_date + if not company.hard_lock_date and company.fiscalyear_lock_date: + vals['hard_lock_date'] = company.fiscalyear_lock_date + if vals: + company.sudo().write(vals) + + # If account_move_export is installed, migrate configuration defaults. + if env.registry.get('account.move.export.config'): + # Ensure new boolean fields are not left NULL and join_char has a value. + cr.execute( + """ + UPDATE account_move_export_config + SET group_lines = COALESCE(group_lines, FALSE), + lock_tax = COALESCE(lock_tax, FALSE), + lock_sale = COALESCE(lock_sale, FALSE), + lock_purchase = COALESCE(lock_purchase, FALSE), + lock_fiscalyear = COALESCE(lock_fiscalyear, FALSE), + lock_hard = COALESCE(lock_hard, FALSE), + join_char = COALESCE(NULLIF(join_char, ''), '-') + """ + ) + + if _table_has_column(cr, 'account_move_export_config', 'lock'): + cr.execute( + """ + UPDATE account_move_export_config + SET lock_tax = lock_tax OR lock IN ('tax', 'period', 'fiscalyear'), + lock_sale = lock_sale OR lock IN ('period', 'fiscalyear'), + lock_purchase = lock_purchase OR lock IN ('period', 'fiscalyear'), + lock_fiscalyear = lock_fiscalyear OR lock = 'fiscalyear', + lock_hard = lock_hard OR lock = 'fiscalyear' + """ + ) + # Optionally drop the legacy column to avoid confusion. + cr.execute("ALTER TABLE account_move_export_config DROP COLUMN lock") diff --git a/odoo-bringout-oca-ocb-account/account/models/account_account.py b/odoo-bringout-oca-ocb-account/account/models/account_account.py index 83e6e60..76c304d 100644 --- a/odoo-bringout-oca-ocb-account/account/models/account_account.py +++ b/odoo-bringout-oca-ocb-account/account/models/account_account.py @@ -38,6 +38,13 @@ class AccountAccount(models.Model): currency_id = fields.Many2one('res.currency', string='Account Currency', tracking=True, help="Forces all journal items in this account to have a specific currency (i.e. bank journals). If no currency is set, entries can use any currency.") company_currency_id = fields.Many2one(related='company_id.currency_id') + company_ids = fields.Many2many( + 'res.company', + compute='_compute_company_ids', + search='_search_company_ids', + string='Companies', + compute_sudo=True, + ) code = fields.Char(size=64, required=True, tracking=True, unaccent=False) deprecated = fields.Boolean(default=False, tracking=True) used = fields.Boolean(compute='_compute_used', search='_search_used') @@ -344,6 +351,23 @@ class AccountAccount(models.Model): for record in self: record.used = record.id in ids + def _compute_company_ids(self): + for account in self: + account.company_ids = account.company_id + + def _search_company_ids(self, operator, value): + if operator in ('in', 'not in'): + if isinstance(value, (list, tuple, set)): + values = list(value) + elif hasattr(value, 'ids'): + values = value.ids + else: + values = [value] + return [('company_id', operator, values)] + if hasattr(value, 'id'): + value = value.id + return [('company_id', operator, value)] + @api.model def _search_new_account_code(self, company, digits, prefix): for num in range(1, 10000): diff --git a/odoo-bringout-oca-ocb-account/account/models/company.py b/odoo-bringout-oca-ocb-account/account/models/company.py index 5fbf667..dcfe122 100644 --- a/odoo-bringout-oca-ocb-account/account/models/company.py +++ b/odoo-bringout-oca-ocb-account/account/models/company.py @@ -57,6 +57,21 @@ class ResCompany(models.Model): string="Tax Return Lock Date", tracking=True, help="No users can edit journal entries related to a tax prior and inclusive of this date.") + sale_lock_date = fields.Date( + string="Sales Lock Date", + tracking=True, + help="No users can post or modify customer invoices prior to and inclusive of this date." + ) + purchase_lock_date = fields.Date( + string="Purchases Lock Date", + tracking=True, + help="No users can post or modify vendor bills prior to and inclusive of this date." + ) + hard_lock_date = fields.Date( + string="Hard Lock Date", + tracking=True, + help="No users can post or modify any journal entries prior to and inclusive of this date." + ) transfer_account_id = fields.Many2one('account.account', domain="[('reconcile', '=', True), ('account_type', '=', 'asset_current'), ('deprecated', '=', False)]", string="Inter-Banks Transfer Account", help="Intermediary account used when moving money from a liqity account to another") expects_chart_of_accounts = fields.Boolean(string='Expects a Chart of Accounts', default=True) @@ -375,25 +390,41 @@ class ResCompany(models.Model): return lock_date def write(self, values): - #restrict the closing of FY if there are still unposted entries + # Restrict the closing of FY if there are still unposted entries self._validate_fiscalyear_lock(values) - # Reflect the change on accounts + result = True for company in self: - if values.get('bank_account_code_prefix'): - new_bank_code = values.get('bank_account_code_prefix') or company.bank_account_code_prefix - company.reflect_code_prefix_change(company.bank_account_code_prefix, new_bank_code) + company_vals = values.copy() + old_bank_prefix = company.bank_account_code_prefix + old_cash_prefix = company.cash_account_code_prefix - if values.get('cash_account_code_prefix'): - new_cash_code = values.get('cash_account_code_prefix') or company.cash_account_code_prefix - company.reflect_code_prefix_change(company.cash_account_code_prefix, new_cash_code) - - #forbid the change of currency_id if there are already some accounting entries existing - if 'currency_id' in values and values['currency_id'] != company.currency_id.id: - if self.env['account.move.line'].sudo().search([('company_id', '=', company.id)]): + # Forbid currency change when entries already exist. + if 'currency_id' in company_vals and company_vals['currency_id'] != company.currency_id.id: + if self.env['account.move.line'].sudo().search([('company_id', '=', company.id)], limit=1): raise UserError(_('You cannot change the currency of the company since some journal items already exist')) - return super(ResCompany, self).write(values) + sync_vals = {} + if 'period_lock_date' in company_vals and 'sale_lock_date' not in company_vals: + if not company.sale_lock_date or company.sale_lock_date == company.period_lock_date: + sync_vals['sale_lock_date'] = company_vals['period_lock_date'] + if not company.purchase_lock_date or company.purchase_lock_date == company.period_lock_date: + sync_vals['purchase_lock_date'] = company_vals['period_lock_date'] + if 'fiscalyear_lock_date' in company_vals and 'hard_lock_date' not in company_vals: + if not company.hard_lock_date or company.hard_lock_date == company.fiscalyear_lock_date: + sync_vals['hard_lock_date'] = company_vals['fiscalyear_lock_date'] + if sync_vals: + company_vals.update(sync_vals) + + result &= super(ResCompany, company).write(company_vals) + + if 'bank_account_code_prefix' in company_vals and company.bank_account_code_prefix != old_bank_prefix: + company.reflect_code_prefix_change(old_bank_prefix, company.bank_account_code_prefix or company_vals.get('bank_account_code_prefix')) + + if 'cash_account_code_prefix' in company_vals and company.cash_account_code_prefix != old_cash_prefix: + company.reflect_code_prefix_change(old_cash_prefix, company.cash_account_code_prefix or company_vals.get('cash_account_code_prefix')) + + return result @api.model def setting_init_bank_account_action(self): diff --git a/odoo-bringout-oca-ocb-account/account/models/res_config_settings.py b/odoo-bringout-oca-ocb-account/account/models/res_config_settings.py index c6798f3..28f5fca 100644 --- a/odoo-bringout-oca-ocb-account/account/models/res_config_settings.py +++ b/odoo-bringout-oca-ocb-account/account/models/res_config_settings.py @@ -179,6 +179,12 @@ class ResConfigSettings(models.TransientModel): related='company_id.account_journal_early_pay_discount_gain_account_id', domain="[('deprecated', '=', False), ('company_id', '=', company_id), ('account_type', 'in', ('income', 'income_other', 'expense'))]", ) + period_lock_date = fields.Date(related='company_id.period_lock_date', readonly=False) + fiscalyear_lock_date = fields.Date(related='company_id.fiscalyear_lock_date', readonly=False) + tax_lock_date = fields.Date(related='company_id.tax_lock_date', readonly=False) + sale_lock_date = fields.Date(related='company_id.sale_lock_date', readonly=False) + purchase_lock_date = fields.Date(related='company_id.purchase_lock_date', readonly=False) + hard_lock_date = fields.Date(related='company_id.hard_lock_date', readonly=False) def set_values(self): super().set_values() diff --git a/odoo-bringout-oca-ocb-account/account/views/res_config_settings_views.xml b/odoo-bringout-oca-ocb-account/account/views/res_config_settings_views.xml index c32ea2d..a07c7f6 100644 --- a/odoo-bringout-oca-ocb-account/account/views/res_config_settings_views.xml +++ b/odoo-bringout-oca-ocb-account/account/views/res_config_settings_views.xml @@ -77,11 +77,59 @@
How total tax amount is computed in orders and invoices
-
+
+
+
+
+ Lock Dates + +
+ Prevent posting moves before the selected cut-off dates. +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+