"""Cache of AI-generated follow-up text to avoid LLM cost on repeats.""" import hashlib from odoo import _, api, fields, models class FusionFollowupTextCache(models.Model): _name = "fusion.followup.text.cache" _description = "Cache of AI-generated follow-up text" _order = "generated_at desc" partner_id = fields.Many2one('res.partner', required=True, ondelete='cascade') level_id = fields.Many2one('fusion.followup.level', ondelete='cascade') company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company) fingerprint = fields.Char(required=True, index=True, help="SHA-256 of input parameters") subject = fields.Char() body = fields.Text() tone_used = fields.Selection([ ('gentle', 'Gentle'), ('firm', 'Firm'), ('legal', 'Legal'), ]) key_points = fields.Json() generated_at = fields.Datetime(default=fields.Datetime.now, required=True) expires_at = fields.Datetime() use_count = fields.Integer(default=0) provider = fields.Char() @api.model def compute_fingerprint(self, *, partner_id: int, level_id: int, overdue_amount: float, longest_overdue_days: int, invoice_count: int, tone: str) -> str: """Stable hash of the inputs that determine the generated text.""" s = f"{partner_id}|{level_id}|{round(overdue_amount, 2)}|" \ f"{longest_overdue_days}|{invoice_count}|{tone}" return hashlib.sha256(s.encode('utf-8')).hexdigest() @api.model def lookup(self, *, partner_id: int, level_id: int, overdue_amount: float, longest_overdue_days: int, invoice_count: int, tone: str): """Find a cached entry matching these inputs, or empty recordset.""" fp = self.compute_fingerprint( partner_id=partner_id, level_id=level_id, overdue_amount=overdue_amount, longest_overdue_days=longest_overdue_days, invoice_count=invoice_count, tone=tone, ) return self.search([ ('partner_id', '=', partner_id), ('fingerprint', '=', fp), ], limit=1) def action_increment_use(self): for rec in self: rec.use_count += 1