104 lines
4.1 KiB
Python
104 lines
4.1 KiB
Python
# Fusion Accounting - Move Line Extensions
|
|
# Bank-line exclusion flag, tax-closing safeguards, and report shadowing
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError
|
|
from odoo.tools import SQL
|
|
|
|
|
|
class FusionAccountMoveLine(models.Model):
|
|
"""Extends journal items with a computed bank-line exclusion flag,
|
|
guards against tax manipulation on closing entries, and provides
|
|
utilities for building temporary shadow tables used by analytic
|
|
and budget reports."""
|
|
|
|
_name = "account.move.line"
|
|
_inherit = "account.move.line"
|
|
|
|
# ---- Fields ----
|
|
exclude_bank_lines = fields.Boolean(
|
|
compute='_compute_exclude_bank_lines',
|
|
store=True,
|
|
)
|
|
|
|
# ---- Computed ----
|
|
@api.depends('journal_id')
|
|
def _compute_exclude_bank_lines(self):
|
|
"""Flag lines whose account differs from their journal's
|
|
default account, used to filter non-bank entries in bank
|
|
journal views."""
|
|
for ml in self:
|
|
ml.exclude_bank_lines = (
|
|
ml.account_id != ml.journal_id.default_account_id
|
|
)
|
|
|
|
# ---- Constraints ----
|
|
@api.constrains('tax_ids', 'tax_tag_ids')
|
|
def _check_taxes_on_closing_entries(self):
|
|
"""Prevent taxes from being added to tax-closing move lines."""
|
|
for ml in self:
|
|
if ml.move_id.tax_closing_report_id and (ml.tax_ids or ml.tax_tag_ids):
|
|
raise UserError(
|
|
_("Tax lines are not permitted on tax-closing entries.")
|
|
)
|
|
|
|
# ---- Tax Computation Override ----
|
|
@api.depends('product_id', 'product_uom_id', 'move_id.tax_closing_report_id')
|
|
def _compute_tax_ids(self):
|
|
"""Skip automatic tax computation for lines on tax-closing
|
|
moves, which might otherwise trigger the constraint above."""
|
|
non_closing_lines = self.filtered(
|
|
lambda ln: not ln.move_id.tax_closing_report_id
|
|
)
|
|
(self - non_closing_lines).tax_ids = False
|
|
super(FusionAccountMoveLine, non_closing_lines)._compute_tax_ids()
|
|
|
|
# ---- Report Shadow Table Utility ----
|
|
@api.model
|
|
def _prepare_aml_shadowing_for_report(self, change_equivalence_dict):
|
|
"""Build SQL fragments for creating a temporary table that
|
|
mirrors ``account_move_line`` but substitutes selected columns
|
|
with alternative expressions (e.g. analytic or budget data).
|
|
|
|
:param change_equivalence_dict:
|
|
Mapping ``{field_name: sql_expression}`` where each value
|
|
replaces the corresponding column in the shadow table.
|
|
:returns:
|
|
A tuple ``(insert_columns, select_expressions)`` of SQL
|
|
objects suitable for ``INSERT INTO ... SELECT ...``.
|
|
"""
|
|
field_metadata = self.env['account.move.line'].fields_get()
|
|
self.env.cr.execute(
|
|
"SELECT column_name FROM information_schema.columns "
|
|
"WHERE table_name='account_move_line'"
|
|
)
|
|
db_columns = {
|
|
row[0] for row in self.env.cr.fetchall() if row[0] in field_metadata
|
|
}
|
|
|
|
select_parts = []
|
|
for col_name in db_columns:
|
|
if col_name in change_equivalence_dict:
|
|
select_parts.append(SQL(
|
|
"%(src)s AS %(alias)s",
|
|
src=change_equivalence_dict[col_name],
|
|
alias=SQL('"account_move_line.%s"', SQL(col_name)),
|
|
))
|
|
else:
|
|
col_meta = field_metadata[col_name]
|
|
if col_meta.get("translate"):
|
|
pg_type = SQL('jsonb')
|
|
else:
|
|
pg_type = SQL(
|
|
self.env['account.move.line']._fields[col_name].column_type[0]
|
|
)
|
|
select_parts.append(SQL(
|
|
"CAST(NULL AS %(pg_type)s) AS %(alias)s",
|
|
pg_type=pg_type,
|
|
alias=SQL('"account_move_line.%s"', SQL(col_name)),
|
|
))
|
|
|
|
insert_cols = SQL(', ').join(SQL.identifier(c) for c in db_columns)
|
|
select_clause = SQL(', ').join(select_parts)
|
|
return insert_cols, select_clause
|