# Part of the odoo-at-payroll project. License: LGPL-3. """PV-Agent-Review-Wizard (D25/M4.1 Pilot): Plausibilitätsprüfung einer geplanten einmaligen Auszahlung. Workflow: Draft-Lohnzettel mit ATP_PRAMIE-Eingabe rechnen → Wizard öffnen → „Prüfung starten“ → Odoo baut den minimierten Kontext und ruft den Agenten (mode=review) → Verdict + belegte Antwort werden im Dialog angezeigt. Odoo bleibt autoritativ für Zahlen; der Agent korrigiert nichts stillschweigend. """ import uuid from odoo import _, fields, models REVIEW_QUESTION_DEFAULT = ( "Prüfe die geplante Auszahlung gegen die Regeln der Wissensbasis." ) class PvAgentReviewWizard(models.TransientModel): _name = "pv.agent.review.wizard" _description = "PV-Agent: Plausibilitätsprüfung" _order = "id desc" payslip_id = fields.Many2one( "hr.payslip", string="Lohnzettel (Draft)", required=True, domain="[('state', '=', 'draft')]", help="Gerechneter Draft-Lohnzettel mit einer ATP_PRAMIE-Eingabe " "(geplante Auszahlung).") question = fields.Text( string="Frage an den Agenten", required=True, default=REVIEW_QUESTION_DEFAULT) answer = fields.Text(string="Agent-Antwort (belegt)", readonly=True) verdict = fields.Selection( [("plausible", "Plausibel"), ("implausible", "Nicht plausibel"), ("not_checkable", "Nicht prüfbar")], string="Verdict", readonly=True) checks = fields.Text(string="Prüfpunkte", readonly=True) request_id = fields.Char(string="Request-ID", readonly=True) def action_l10n_at_pv_review(self): self.ensure_one() context = self.env["pv.agent.context.builder"].l10n_at_pv_build_payout_context( self.payslip_id) request_id = "odoo-" + uuid.uuid4().hex[:12] body = self.env["pv.agent.client"].l10n_at_pv_ask_review( self.question, context, request_id) plausibility = body.get("plausibility") or {} self.write({ "answer": body.get("answer", ""), "verdict": plausibility.get("verdict") or "not_checkable", "checks": self._l10n_at_pv_render_checks(plausibility), "request_id": body.get("request_id") or request_id, }) return { "type": "ir.actions.act_window", "res_model": self._name, "res_id": self.id, "view_mode": "form", "target": "new", "name": _("PV-Agent Prüfung"), } @staticmethod def _l10n_at_pv_render_checks(plausibility): lines = [] for check in plausibility.get("checks", []): label = {"ok": "OK", "warn": "WARN ⚠", "open": "OFFEN"}.get( check.get("status"), check.get("status", "")) ids = ", ".join(check.get("source_ids", [])) lines.append( f"[{label}] {check.get('aspect', '')} — {check.get('detail', '')}" + (f" ({ids})" if ids else "")) return "\n".join(lines)