"""Persistent definition of a Fusion financial report. Each report (P&L, balance sheet, trial balance, GL) has ONE row in fusion.report describing its metadata + line specs. The line specs are stored as a JSON-typed field for flexibility (each line spec includes account_type filter, sub-totaling rules, sign convention).""" from odoo import _, api, fields, models REPORT_TYPES = [ ('pnl', 'Income Statement (P&L)'), ('balance_sheet', 'Balance Sheet'), ('trial_balance', 'Trial Balance'), ('general_ledger', 'General Ledger'), ('aged_receivable', 'Aged Receivable'), ('aged_payable', 'Aged Payable'), ('partner_ledger', 'Partner Ledger'), ] class FusionReport(models.Model): _name = "fusion.report" _description = "Fusion Financial Report Definition" _order = "sequence, id" name = fields.Char(required=True, translate=True) code = fields.Char( required=True, help="Unique technical code (e.g. 'pnl', 'balance_sheet').", ) report_type = fields.Selection(REPORT_TYPES, required=True) sequence = fields.Integer(default=10) description = fields.Text() active = fields.Boolean(default=True) # Layout config - stored as JSON for flexibility per report type. # Example for P&L: # [ # {"label": "Revenue", "account_type_prefix": "income_", "sign": 1}, # {"label": "Cost of Goods Sold", "account_type_prefix": "expense_direct_", "sign": -1}, # {"label": "Gross Profit", "compute": "subtotal", "above": 2}, # ... # ] line_specs = fields.Json(string="Line Specs") show_zero_balances = fields.Boolean(default=False) show_unposted = fields.Boolean(default=False) default_comparison_mode = fields.Selection( [ ('none', 'No comparison'), ('previous_period', 'Previous Period'), ('previous_year', 'Previous Year'), ], default='none', ) company_id = fields.Many2one( 'res.company', default=lambda self: self.env.company, ) _unique_company_code = models.Constraint( 'UNIQUE(company_id, code)', 'Report code must be unique per company.', )