Adds Aged Receivable, Aged Payable, and Partner Ledger as fusion.report records using the new compute_partner_grouped engine method. REPORT_TYPES is extended with aged_receivable / aged_payable / partner_ledger so each report has a unique report_type. The HTTP controller dispatches these to engine.compute_partner_grouped with the appropriate account_type via PARTNER_GROUPED_ACCOUNT_TYPE. Output includes per-partner aging buckets: current, 1-30, 31-60, 61-90, 90+ days. Westin total: 4 + 4 + 3 = 11 of Enterprise's 22 standard reports. Made-with: Cursor
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
"""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.',
|
|
)
|