- New fl.conflict.check model: screens petitioner/respondent/party_ids names against parties on other open cases (exact partner match + difflib fuzzy match at 0.85 threshold); skips folded/closed stages - Runs automatically as the first action in fl.case.create; logs conflicts to chatter with matched-case detail and never silently passes - fl.case gains conflict_check_passed/conflict_check_id/conflict_check_ids; write() blocks advancing stage_id past Intake until the check passes - Admin-only action_override requires a written justification, stamps user/date, and flips conflict_check_passed True with a chatter audit entry - Add conflict check form/tree/search views, action, Cases sub-menu item, case form banner + Run Conflict Check button, and Kanban conflict badge - ACL entries for fl.conflict.check (admin full, paralegal no-delete) - Finish Claude migration cleanup in fl_analysis.py (model_used default, docstring/help text) - Add .gitignore for Python artifacts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
from odoo import fields, models
|
|
|
|
|
|
class FlAnalysis(models.Model):
|
|
"""AI case analysis record. Written by the Claude API engine (fl.ai.engine)."""
|
|
_name = 'fl.analysis'
|
|
_description = 'AI Case Analysis Result'
|
|
_order = 'create_date desc'
|
|
|
|
case_id = fields.Many2one(
|
|
'fl.case', ondelete='cascade', index=True
|
|
)
|
|
analysis_date = fields.Datetime(
|
|
string='Analysis Date',
|
|
default=fields.Datetime.now
|
|
)
|
|
model_used = fields.Char(
|
|
string='AI Model',
|
|
default='claude-sonnet-4-20250514'
|
|
)
|
|
|
|
# ── Results (referenced by fl_case related fields) ─────────────────────
|
|
attorney_referral_flag = fields.Boolean(
|
|
string='Attorney Referral Recommended',
|
|
default=False
|
|
)
|
|
attorney_referral_reason = fields.Text(
|
|
string='Attorney Referral Reason'
|
|
)
|
|
plain_english_summary = fields.Text(
|
|
string='Plain English Summary (EN)',
|
|
help='3-5 sentence summary of case analysis — no legal jargon'
|
|
)
|
|
plain_english_summary_es = fields.Text(
|
|
string='Plain English Summary (ES)',
|
|
help='Resumen en español — sin jerga legal'
|
|
)
|
|
|
|
# ── Analysis Detail (Phase 5) ──────────────────────────────────────────
|
|
petitioner_arguments = fields.Text(
|
|
string='Petitioner Arguments (JSON)'
|
|
)
|
|
respondent_counterarguments = fields.Text(
|
|
string='Respondent Counter-Arguments (JSON)'
|
|
)
|
|
procedural_risks = fields.Text(
|
|
string='Procedural Risks (JSON)'
|
|
)
|
|
matched_caselaw_ids = fields.Many2many(
|
|
'fl.caselaw',
|
|
'fl_analysis_caselaw_rel',
|
|
'analysis_id', 'caselaw_id',
|
|
string='Matched Case Law'
|
|
)
|
|
confidence_level = fields.Selection([
|
|
('high', 'High'),
|
|
('medium', 'Medium'),
|
|
('low', 'Low'),
|
|
], string='Confidence Level')
|
|
case_complexity = fields.Selection([
|
|
('simple', 'Simple'),
|
|
('moderate', 'Moderate'),
|
|
('complex', 'Complex'),
|
|
], string='Case Complexity')
|
|
raw_response = fields.Text(
|
|
string='Raw AI Response',
|
|
help='Full JSON response from the Claude API — for debugging'
|
|
)
|
|
error_message = fields.Text(
|
|
string='Error (if analysis failed)'
|
|
)
|
|
state = fields.Selection([
|
|
('pending', 'Pending'),
|
|
('complete', 'Complete'),
|
|
('failed', 'Failed'),
|
|
], string='Status', default='pending')
|