feat(fusion_accounting_reports): period picker wizard with common presets
Adds fusion.period.picker.wizard - a guided entry point that lets users pick a report type and a common period preset (this/last month, quarter, YTD, last year, or custom range). The wizard uses the existing date_periods service helpers (month_bounds, quarter_bounds, fiscal_year_bounds) to pre-fill date_from / date_to via @api.onchange. action_open_report returns a client action that launches the OWL reports viewer with default_report_type / default_date_from / default_date_to / default_comparison in the context. Tests: 3 new (test_period_picker.py). Net 111 -> 114. Made-with: Cursor
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
'name': 'Fusion Accounting Reports',
|
'name': 'Fusion Accounting Reports',
|
||||||
'version': '19.0.1.0.31',
|
'version': '19.0.1.0.32',
|
||||||
'category': 'Accounting/Accounting',
|
'category': 'Accounting/Accounting',
|
||||||
'summary': 'AI-augmented financial reports (P&L, balance sheet, trial balance, GL).',
|
'summary': 'AI-augmented financial reports (P&L, balance sheet, trial balance, GL).',
|
||||||
'description': """
|
'description': """
|
||||||
@@ -38,6 +38,7 @@ menu hides; the engine and AI tools remain available for the chat.
|
|||||||
'data/cron.xml',
|
'data/cron.xml',
|
||||||
'reports/report_pdf_template.xml',
|
'reports/report_pdf_template.xml',
|
||||||
'wizards/xlsx_export_wizard_views.xml',
|
'wizards/xlsx_export_wizard_views.xml',
|
||||||
|
'wizards/period_picker_wizard_views.xml',
|
||||||
],
|
],
|
||||||
'external_dependencies': {
|
'external_dependencies': {
|
||||||
'python': ['xlsxwriter'],
|
'python': ['xlsxwriter'],
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ access_fusion_report_admin,fusion.report.admin,model_fusion_report,fusion_accoun
|
|||||||
access_fusion_report_commentary,fusion.report.commentary,model_fusion_report_commentary,base.group_user,1,1,1,0
|
access_fusion_report_commentary,fusion.report.commentary,model_fusion_report_commentary,base.group_user,1,1,1,0
|
||||||
access_fusion_report_anomaly,fusion.report.anomaly,model_fusion_report_anomaly,base.group_user,1,1,1,0
|
access_fusion_report_anomaly,fusion.report.anomaly,model_fusion_report_anomaly,base.group_user,1,1,1,0
|
||||||
access_fusion_xlsx_export_wizard_user,fusion.xlsx.export.wizard.user,model_fusion_xlsx_export_wizard,base.group_user,1,1,1,0
|
access_fusion_xlsx_export_wizard_user,fusion.xlsx.export.wizard.user,model_fusion_xlsx_export_wizard,base.group_user,1,1,1,0
|
||||||
|
access_fusion_period_picker_wizard_user,fusion.period.picker.wizard.user,model_fusion_period_picker_wizard,base.group_user,1,1,1,0
|
||||||
|
|||||||
|
@@ -20,3 +20,4 @@ from . import test_account_balance_mv
|
|||||||
from . import test_cron
|
from . import test_cron
|
||||||
from . import test_pdf_export
|
from . import test_pdf_export
|
||||||
from . import test_xlsx_export
|
from . import test_xlsx_export
|
||||||
|
from . import test_period_picker
|
||||||
|
|||||||
36
fusion_accounting_reports/tests/test_period_picker.py
Normal file
36
fusion_accounting_reports/tests/test_period_picker.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
"""Tests for period picker wizard."""
|
||||||
|
|
||||||
|
from odoo.tests.common import TransactionCase, tagged
|
||||||
|
|
||||||
|
|
||||||
|
@tagged('post_install', '-at_install')
|
||||||
|
class TestPeriodPickerWizard(TransactionCase):
|
||||||
|
|
||||||
|
def test_this_month_preset_fills_dates(self):
|
||||||
|
wizard = self.env['fusion.period.picker.wizard'].create({
|
||||||
|
'report_type': 'pnl',
|
||||||
|
'period_preset': 'this_month',
|
||||||
|
})
|
||||||
|
wizard._onchange_period_preset()
|
||||||
|
self.assertTrue(wizard.date_from)
|
||||||
|
self.assertTrue(wizard.date_to)
|
||||||
|
self.assertEqual(wizard.date_from.day, 1)
|
||||||
|
|
||||||
|
def test_this_year_preset_uses_ytd(self):
|
||||||
|
wizard = self.env['fusion.period.picker.wizard'].create({
|
||||||
|
'report_type': 'pnl',
|
||||||
|
'period_preset': 'this_year',
|
||||||
|
})
|
||||||
|
wizard._onchange_period_preset()
|
||||||
|
self.assertEqual(wizard.date_from.month, 1)
|
||||||
|
self.assertEqual(wizard.date_from.day, 1)
|
||||||
|
|
||||||
|
def test_action_open_report_returns_client_action(self):
|
||||||
|
wizard = self.env['fusion.period.picker.wizard'].create({
|
||||||
|
'report_type': 'pnl',
|
||||||
|
'period_preset': 'this_year',
|
||||||
|
})
|
||||||
|
wizard._onchange_period_preset()
|
||||||
|
action = wizard.action_open_report()
|
||||||
|
self.assertEqual(action['type'], 'ir.actions.client')
|
||||||
|
self.assertEqual(action['tag'], 'fusion_reports')
|
||||||
@@ -1 +1,2 @@
|
|||||||
from . import xlsx_export_wizard
|
from . import xlsx_export_wizard
|
||||||
|
from . import period_picker_wizard
|
||||||
|
|||||||
77
fusion_accounting_reports/wizards/period_picker_wizard.py
Normal file
77
fusion_accounting_reports/wizards/period_picker_wizard.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
"""Period selection + comparison wizard.
|
||||||
|
|
||||||
|
Pre-fills date ranges for common report periods (current month, YTD, etc.)."""
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
from ..services.date_periods import (
|
||||||
|
fiscal_year_bounds, month_bounds, quarter_bounds,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FusionPeriodPickerWizard(models.TransientModel):
|
||||||
|
_name = "fusion.period.picker.wizard"
|
||||||
|
_description = "Period Selection Wizard"
|
||||||
|
|
||||||
|
report_type = fields.Selection([
|
||||||
|
('pnl', 'P&L'),
|
||||||
|
('balance_sheet', 'Balance Sheet'),
|
||||||
|
('trial_balance', 'Trial Balance'),
|
||||||
|
('general_ledger', 'General Ledger'),
|
||||||
|
], required=True, default='pnl')
|
||||||
|
period_preset = fields.Selection([
|
||||||
|
('this_month', 'This Month'),
|
||||||
|
('last_month', 'Last Month'),
|
||||||
|
('this_quarter', 'This Quarter'),
|
||||||
|
('last_quarter', 'Last Quarter'),
|
||||||
|
('this_year', 'This Year (YTD)'),
|
||||||
|
('last_year', 'Last Year'),
|
||||||
|
('custom', 'Custom Range'),
|
||||||
|
], default='this_month', required=True)
|
||||||
|
date_from = fields.Date()
|
||||||
|
date_to = fields.Date()
|
||||||
|
comparison = fields.Selection([
|
||||||
|
('none', 'No Comparison'),
|
||||||
|
('previous_period', 'Previous Period'),
|
||||||
|
('previous_year', 'Previous Year'),
|
||||||
|
], default='none')
|
||||||
|
|
||||||
|
@api.onchange('period_preset')
|
||||||
|
def _onchange_period_preset(self):
|
||||||
|
today = fields.Date.today()
|
||||||
|
if self.period_preset == 'this_month':
|
||||||
|
p = month_bounds(today)
|
||||||
|
self.date_from, self.date_to = p.date_from, p.date_to
|
||||||
|
elif self.period_preset == 'last_month':
|
||||||
|
p = month_bounds(today.replace(day=1) - timedelta(days=1))
|
||||||
|
self.date_from, self.date_to = p.date_from, p.date_to
|
||||||
|
elif self.period_preset == 'this_quarter':
|
||||||
|
p = quarter_bounds(today)
|
||||||
|
self.date_from, self.date_to = p.date_from, p.date_to
|
||||||
|
elif self.period_preset == 'last_quarter':
|
||||||
|
this_q = quarter_bounds(today)
|
||||||
|
p = quarter_bounds(this_q.date_from - timedelta(days=1))
|
||||||
|
self.date_from, self.date_to = p.date_from, p.date_to
|
||||||
|
elif self.period_preset == 'this_year':
|
||||||
|
p = fiscal_year_bounds(today)
|
||||||
|
self.date_from, self.date_to = p.date_from, today
|
||||||
|
elif self.period_preset == 'last_year':
|
||||||
|
last_year = today.replace(year=today.year - 1)
|
||||||
|
p = fiscal_year_bounds(last_year)
|
||||||
|
self.date_from, self.date_to = p.date_from, p.date_to
|
||||||
|
|
||||||
|
def action_open_report(self):
|
||||||
|
"""Open the fusion reports viewer pre-filled with selected period."""
|
||||||
|
self.ensure_one()
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'fusion_reports',
|
||||||
|
'context': {
|
||||||
|
'default_report_type': self.report_type,
|
||||||
|
'default_date_from': str(self.date_from),
|
||||||
|
'default_date_to': str(self.date_to),
|
||||||
|
'default_comparison': self.comparison,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_fusion_period_picker_wizard_form" model="ir.ui.view">
|
||||||
|
<field name="name">fusion.period.picker.wizard.form</field>
|
||||||
|
<field name="model">fusion.period.picker.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Pick Reporting Period">
|
||||||
|
<group>
|
||||||
|
<field name="report_type"/>
|
||||||
|
<field name="period_preset"/>
|
||||||
|
<field name="date_from" invisible="period_preset != 'custom'"
|
||||||
|
required="period_preset == 'custom'"/>
|
||||||
|
<field name="date_to" invisible="period_preset != 'custom'"
|
||||||
|
required="period_preset == 'custom'"/>
|
||||||
|
<field name="comparison"/>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button name="action_open_report" type="object" string="Open Report"
|
||||||
|
class="btn-primary"/>
|
||||||
|
<button special="cancel" string="Cancel"/>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_fusion_period_picker_wizard" model="ir.actions.act_window">
|
||||||
|
<field name="name">Open Financial Report</field>
|
||||||
|
<field name="res_model">fusion.period.picker.wizard</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user