Files
Odoo-Modules/fusion_accounting_followup/models/fusion_followup_cron.py
gsinghpal 042dcf8067
Some checks failed
fusion_accounting CI / test (fusion_accounting_ai) (push) Has been cancelled
fusion_accounting CI / test (fusion_accounting_core) (push) Has been cancelled
fusion_accounting CI / test (fusion_accounting_migration) (push) Has been cancelled
feat(fusion_accounting_followup): 2 cron jobs (daily scan + weekly risk refresh)
- fusion.followup.cron AbstractModel with two handlers
- cron_fusion_followup_daily_scan: walks every overdue partner and
  delegates to engine.send_followup_email
- cron_fusion_followup_risk_refresh: weekly refresh of
  fusion_followup_risk_score / risk_band on res.partner
- V19 ir.cron records (no numbercall field)
- 2 smoke tests added (80 total)

Made-with: Cursor
2026-04-19 21:04:37 -04:00

85 lines
3.1 KiB
Python

"""Cron handlers for fusion_accounting_followup.
Two scheduled jobs:
- Daily scan: walk every partner with an open overdue receivable line and
call the engine to send/escalate where appropriate.
- Weekly risk refresh: recompute fusion_followup_risk_score on every
partner with overdue.
"""
import logging
from datetime import date
from odoo import api, models
_logger = logging.getLogger(__name__)
class FusionFollowupCron(models.AbstractModel):
_name = "fusion.followup.cron"
_description = "Fusion Follow-up Cron Handlers"
@api.model
def _cron_daily_scan(self):
"""Scan every partner with overdue and send follow-ups when due."""
engine = self.env['fusion.followup.engine']
Line = self.env['account.move.line'].sudo()
overdue_lines = Line.search([
('parent_state', '=', 'posted'),
('account_id.account_type', '=', 'asset_receivable'),
('reconciled', '=', False),
('amount_residual', '>', 0),
('date_maturity', '<', date.today()),
])
partner_ids = list(set(overdue_lines.mapped('partner_id').ids))
sent = 0
skipped = 0
for pid in partner_ids:
partner = self.env['res.partner'].sudo().browse(pid)
if not partner.exists():
continue
try:
with self.env.cr.savepoint():
result = engine.send_followup_email(partner)
if result.get('status') == 'sent':
sent += 1
else:
skipped += 1
except Exception as e:
_logger.warning(
"Cron daily_scan failed for partner %s: %s", pid, e,
)
skipped += 1
_logger.info(
"Cron: scanned %d partners, sent %d, skipped %d",
len(partner_ids), sent, skipped,
)
@api.model
def _cron_risk_refresh(self):
"""Refresh fusion_followup_risk_score on every partner with overdue."""
Partner = self.env['res.partner'].sudo()
engine = self.env['fusion.followup.engine']
Line = self.env['account.move.line'].sudo()
partner_ids = list(set(Line.search([
('parent_state', '=', 'posted'),
('account_id.account_type', '=', 'asset_receivable'),
('reconciled', '=', False),
('amount_residual', '>', 0),
]).mapped('partner_id').ids))
updated = 0
for pid in partner_ids:
partner = Partner.browse(pid)
try:
overdue = engine.get_overdue_for_partner(partner)
partner.write({
'fusion_followup_risk_score': overdue['risk']['score'],
'fusion_followup_risk_band': overdue['risk']['band'],
})
updated += 1
except Exception as e:
_logger.warning(
"Risk refresh failed for partner %s: %s", pid, e,
)
_logger.info("Cron: refreshed risk on %d partners", updated)