Initial commit
This commit is contained in:
414
Fusion Accounting/models/res_config_settings.py
Normal file
414
Fusion Accounting/models/res_config_settings.py
Normal file
@@ -0,0 +1,414 @@
|
||||
# Fusion Accounting - Configuration Settings
|
||||
# Extends res.config.settings with accounting-specific options
|
||||
# including fiscal year, deferrals, tax periodicity, and stock accounts.
|
||||
|
||||
from datetime import date
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tools import date_utils
|
||||
from odoo.tools.misc import format_date
|
||||
|
||||
# Shared domain for stock-related account fields
|
||||
_ACCOUNT_FILTER_DOMAIN = [
|
||||
('account_type', 'not in', (
|
||||
'asset_receivable', 'liability_payable',
|
||||
'asset_cash', 'liability_credit_card', 'off_balance',
|
||||
)),
|
||||
]
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
# =====================================================================
|
||||
# Fiscal Year
|
||||
# =====================================================================
|
||||
|
||||
fiscalyear_last_day = fields.Integer(
|
||||
related='company_id.fiscalyear_last_day',
|
||||
required=True,
|
||||
readonly=False,
|
||||
)
|
||||
fiscalyear_last_month = fields.Selection(
|
||||
related='company_id.fiscalyear_last_month',
|
||||
required=True,
|
||||
readonly=False,
|
||||
)
|
||||
group_fiscal_year = fields.Boolean(
|
||||
string='Fiscal Years',
|
||||
implied_group='fusion_accounting.group_fiscal_year',
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# General Accounting Options
|
||||
# =====================================================================
|
||||
|
||||
use_anglo_saxon = fields.Boolean(
|
||||
string='Anglo-Saxon Accounting',
|
||||
related='company_id.anglo_saxon_accounting',
|
||||
readonly=False,
|
||||
)
|
||||
invoicing_switch_threshold = fields.Date(
|
||||
string="Invoicing Switch Threshold",
|
||||
related='company_id.invoicing_switch_threshold',
|
||||
readonly=False,
|
||||
)
|
||||
predict_bill_product = fields.Boolean(
|
||||
string="Predict Bill Product",
|
||||
related='company_id.predict_bill_product',
|
||||
readonly=False,
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Inter-Company Invoice Sync
|
||||
# =====================================================================
|
||||
|
||||
fusion_intercompany_invoice_enabled = fields.Boolean(
|
||||
string="Inter-Company Invoice Sync",
|
||||
related='company_id.fusion_intercompany_invoice_enabled',
|
||||
readonly=False,
|
||||
help="Automatically create matching bills/invoices between companies.",
|
||||
)
|
||||
fusion_intercompany_invoice_journal_id = fields.Many2one(
|
||||
comodel_name='account.journal',
|
||||
string="Inter-Company Journal",
|
||||
related='company_id.fusion_intercompany_invoice_journal_id',
|
||||
readonly=False,
|
||||
help="Default journal for inter-company counter-documents.",
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Invoice Signing
|
||||
# =====================================================================
|
||||
|
||||
sign_invoice = fields.Boolean(
|
||||
string='Authorized Signatory on invoice',
|
||||
related='company_id.sign_invoice',
|
||||
readonly=False,
|
||||
)
|
||||
signing_user = fields.Many2one(
|
||||
comodel_name='res.users',
|
||||
string="Signature used to sign all the invoice",
|
||||
readonly=False,
|
||||
related='company_id.signing_user',
|
||||
help="Override every invoice signature with this user's signature.",
|
||||
)
|
||||
module_sign = fields.Boolean(
|
||||
string='Sign',
|
||||
compute='_compute_module_sign_status',
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Deferred Expenses
|
||||
# =====================================================================
|
||||
|
||||
deferred_expense_journal_id = fields.Many2one(
|
||||
comodel_name='account.journal',
|
||||
help='Journal for deferred expense entries.',
|
||||
readonly=False,
|
||||
related='company_id.deferred_expense_journal_id',
|
||||
)
|
||||
deferred_expense_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
help='Account for deferred expense balances.',
|
||||
readonly=False,
|
||||
related='company_id.deferred_expense_account_id',
|
||||
)
|
||||
generate_deferred_expense_entries_method = fields.Selection(
|
||||
related='company_id.generate_deferred_expense_entries_method',
|
||||
readonly=False,
|
||||
required=True,
|
||||
help='When to generate deferred expense entries.',
|
||||
)
|
||||
deferred_expense_amount_computation_method = fields.Selection(
|
||||
related='company_id.deferred_expense_amount_computation_method',
|
||||
readonly=False,
|
||||
required=True,
|
||||
help='How to prorate deferred expense amounts.',
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Deferred Revenue
|
||||
# =====================================================================
|
||||
|
||||
deferred_revenue_journal_id = fields.Many2one(
|
||||
comodel_name='account.journal',
|
||||
help='Journal for deferred revenue entries.',
|
||||
readonly=False,
|
||||
related='company_id.deferred_revenue_journal_id',
|
||||
)
|
||||
deferred_revenue_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
help='Account for deferred revenue balances.',
|
||||
readonly=False,
|
||||
related='company_id.deferred_revenue_account_id',
|
||||
)
|
||||
generate_deferred_revenue_entries_method = fields.Selection(
|
||||
related='company_id.generate_deferred_revenue_entries_method',
|
||||
readonly=False,
|
||||
required=True,
|
||||
help='When to generate deferred revenue entries.',
|
||||
)
|
||||
deferred_revenue_amount_computation_method = fields.Selection(
|
||||
related='company_id.deferred_revenue_amount_computation_method',
|
||||
readonly=False,
|
||||
required=True,
|
||||
help='How to prorate deferred revenue amounts.',
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Reporting & Tax Periodicity
|
||||
# =====================================================================
|
||||
|
||||
totals_below_sections = fields.Boolean(
|
||||
related='company_id.totals_below_sections',
|
||||
string='Add totals below sections',
|
||||
readonly=False,
|
||||
help='Display totals and subtotals beneath report sections.',
|
||||
)
|
||||
account_tax_periodicity = fields.Selection(
|
||||
related='company_id.account_tax_periodicity',
|
||||
string='Periodicity',
|
||||
readonly=False,
|
||||
required=True,
|
||||
)
|
||||
account_tax_periodicity_reminder_day = fields.Integer(
|
||||
related='company_id.account_tax_periodicity_reminder_day',
|
||||
string='Reminder',
|
||||
readonly=False,
|
||||
required=True,
|
||||
)
|
||||
account_tax_periodicity_journal_id = fields.Many2one(
|
||||
related='company_id.account_tax_periodicity_journal_id',
|
||||
string='Journal',
|
||||
readonly=False,
|
||||
)
|
||||
account_reports_show_per_company_setting = fields.Boolean(
|
||||
compute="_compute_account_reports_show_per_company_setting",
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Stock Valuation Accounts (Product Category Defaults)
|
||||
# =====================================================================
|
||||
|
||||
property_stock_journal = fields.Many2one(
|
||||
comodel_name='account.journal',
|
||||
string="Stock Journal",
|
||||
check_company=True,
|
||||
compute='_compute_property_stock_account',
|
||||
inverse='_set_property_stock_journal',
|
||||
)
|
||||
property_account_income_categ_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Income Account",
|
||||
check_company=True,
|
||||
domain=_ACCOUNT_FILTER_DOMAIN,
|
||||
compute='_compute_property_stock_account',
|
||||
inverse='_set_property_account_income_categ_id',
|
||||
)
|
||||
property_account_expense_categ_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Expense Account",
|
||||
check_company=True,
|
||||
domain=_ACCOUNT_FILTER_DOMAIN,
|
||||
compute='_compute_property_stock_account',
|
||||
inverse='_set_property_account_expense_categ_id',
|
||||
)
|
||||
property_stock_valuation_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Stock Valuation Account",
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
compute='_compute_property_stock_account',
|
||||
inverse='_set_property_stock_valuation_account_id',
|
||||
)
|
||||
property_stock_account_input_categ_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Stock Input Account",
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
compute='_compute_property_stock_account',
|
||||
inverse='_set_property_stock_account_input_categ_id',
|
||||
)
|
||||
property_stock_account_output_categ_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Stock Output Account",
|
||||
check_company=True,
|
||||
domain="[]",
|
||||
compute='_compute_property_stock_account',
|
||||
inverse='_set_property_stock_account_output_categ_id',
|
||||
)
|
||||
|
||||
# =====================================================================
|
||||
# Compute Methods
|
||||
# =====================================================================
|
||||
|
||||
@api.depends('sign_invoice')
|
||||
def _compute_module_sign_status(self):
|
||||
"""Check whether the Sign module is installed or sign is enabled."""
|
||||
is_sign_installed = 'sign' in self.env['ir.module.module']._installed()
|
||||
for cfg in self:
|
||||
cfg.module_sign = is_sign_installed or cfg.company_id.sign_invoice
|
||||
|
||||
@api.depends('company_id')
|
||||
def _compute_account_reports_show_per_company_setting(self):
|
||||
"""Show per-company tax report start date settings when the
|
||||
company operates in countries with custom start dates."""
|
||||
custom_codes = self._get_country_codes_with_another_tax_closing_start_date()
|
||||
relevant_countries = (
|
||||
self.env['account.fiscal.position'].search([
|
||||
('company_id', '=', self.env.company.id),
|
||||
('foreign_vat', '!=', False),
|
||||
]).mapped('country_id')
|
||||
+ self.env.company.account_fiscal_country_id
|
||||
)
|
||||
for cfg in self:
|
||||
cfg.account_reports_show_per_company_setting = bool(
|
||||
set(relevant_countries.mapped('code')) & custom_codes
|
||||
)
|
||||
|
||||
@api.depends('company_id')
|
||||
def _compute_property_stock_account(self):
|
||||
"""Load stock account defaults from product.category properties."""
|
||||
prop_names = self._get_account_stock_properties_names()
|
||||
ProdCat = self.env['product.category']
|
||||
for cfg in self:
|
||||
scoped = cfg.with_company(cfg.company_id)
|
||||
for prop_name in prop_names:
|
||||
fld = ProdCat._fields[prop_name]
|
||||
scoped[prop_name] = fld.get_company_dependent_fallback(ProdCat)
|
||||
|
||||
# =====================================================================
|
||||
# Constraints
|
||||
# =====================================================================
|
||||
|
||||
@api.constrains('fiscalyear_last_day', 'fiscalyear_last_month')
|
||||
def _check_fiscalyear(self):
|
||||
"""Validate that the fiscal year end date is a real calendar date."""
|
||||
for cfg in self:
|
||||
try:
|
||||
date(2020, int(cfg.fiscalyear_last_month), cfg.fiscalyear_last_day)
|
||||
except ValueError:
|
||||
raise ValidationError(_(
|
||||
'Invalid fiscal year date: day %(day)s is out of range '
|
||||
'for month %(month)s.',
|
||||
month=cfg.fiscalyear_last_month,
|
||||
day=cfg.fiscalyear_last_day,
|
||||
))
|
||||
|
||||
# =====================================================================
|
||||
# Create Override
|
||||
# =====================================================================
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""Write fiscal year settings atomically to the company to
|
||||
avoid intermediate constraint violations from related fields."""
|
||||
for vals in vals_list:
|
||||
fy_day = vals.pop('fiscalyear_last_day', False) or self.env.company.fiscalyear_last_day
|
||||
fy_month = vals.pop('fiscalyear_last_month', False) or self.env.company.fiscalyear_last_month
|
||||
company_updates = {}
|
||||
if fy_day != self.env.company.fiscalyear_last_day:
|
||||
company_updates['fiscalyear_last_day'] = fy_day
|
||||
if fy_month != self.env.company.fiscalyear_last_month:
|
||||
company_updates['fiscalyear_last_month'] = fy_month
|
||||
if company_updates:
|
||||
self.env.company.write(company_updates)
|
||||
return super().create(vals_list)
|
||||
|
||||
# =====================================================================
|
||||
# Actions
|
||||
# =====================================================================
|
||||
|
||||
def open_tax_group_list(self):
|
||||
"""Open the tax group list filtered by the fiscal country."""
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Tax groups',
|
||||
'res_model': 'account.tax.group',
|
||||
'view_mode': 'list',
|
||||
'context': {
|
||||
'default_country_id': self.account_fiscal_country_id.id,
|
||||
'search_default_country_id': self.account_fiscal_country_id.id,
|
||||
},
|
||||
}
|
||||
|
||||
def open_company_dependent_report_settings(self):
|
||||
"""Open the report configuration view for per-company start dates."""
|
||||
self.ensure_one()
|
||||
base_report = self.env.ref('account.generic_tax_report')
|
||||
variant_reports = base_report._get_variants(base_report.id)
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Configure your start dates'),
|
||||
'res_model': 'account.report',
|
||||
'domain': [('id', 'in', variant_reports.ids)],
|
||||
'views': [(
|
||||
self.env.ref(
|
||||
'fusion_accounting.account_report_tree_configure_start_dates',
|
||||
).id,
|
||||
'list',
|
||||
)],
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# Hooks
|
||||
# =====================================================================
|
||||
|
||||
def _get_country_codes_with_another_tax_closing_start_date(self):
|
||||
"""Hook for localization modules to declare countries with
|
||||
custom tax closing start date support.
|
||||
|
||||
:return: Set of country code strings.
|
||||
"""
|
||||
return set()
|
||||
|
||||
# =====================================================================
|
||||
# Stock Property Setters
|
||||
# =====================================================================
|
||||
|
||||
def _set_property_stock_journal(self):
|
||||
for cfg in self:
|
||||
cfg._persist_product_category_default('property_stock_journal')
|
||||
|
||||
def _set_property_account_income_categ_id(self):
|
||||
for cfg in self:
|
||||
cfg._persist_product_category_default('property_account_income_categ_id')
|
||||
|
||||
def _set_property_account_expense_categ_id(self):
|
||||
for cfg in self:
|
||||
cfg._persist_product_category_default('property_account_expense_categ_id')
|
||||
|
||||
def _set_property_stock_valuation_account_id(self):
|
||||
for cfg in self:
|
||||
cfg._persist_product_category_default('property_stock_valuation_account_id')
|
||||
|
||||
def _set_property_stock_account_input_categ_id(self):
|
||||
for cfg in self:
|
||||
cfg._persist_product_category_default('property_stock_account_input_categ_id')
|
||||
|
||||
def _set_property_stock_account_output_categ_id(self):
|
||||
for cfg in self:
|
||||
cfg._persist_product_category_default('property_stock_account_output_categ_id')
|
||||
|
||||
def _persist_product_category_default(self, field_name):
|
||||
"""Save a product category default value via ir.default."""
|
||||
self.env['ir.default'].set(
|
||||
'product.category', field_name,
|
||||
self[field_name].id,
|
||||
company_id=self.company_id.id,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _get_account_stock_properties_names(self):
|
||||
"""Return the list of stock-related property field names."""
|
||||
return [
|
||||
'property_stock_journal',
|
||||
'property_account_income_categ_id',
|
||||
'property_account_expense_categ_id',
|
||||
'property_stock_valuation_account_id',
|
||||
'property_stock_account_input_categ_id',
|
||||
'property_stock_account_output_categ_id',
|
||||
]
|
||||
Reference in New Issue
Block a user