Files
famlaw/activeblue_familylaw/wizard/fl_efiling_wizard.py
tocmo0nlord 6f6129550e Add FL e-Filing Portal integration (assisted submission, Phase 1)
- fl.efiling.submission: generates the 11th Circuit court filename
  ({LastName}_{CaseNumber}_{DocumentType}_{YYYYMMDD}.pdf), validates PDF/A via
  pikepdf (XMP pdfaid + OutputIntents, graceful if pikepdf missing), and tracks
  status (draft → validated → pending_manual → submitted → accepted/rejected/failed)
- Assisted flow: "Open e-Filing Portal" deep-links to eportal.flcourts.org
  (?caseNumber=… when available; base overridable via ir.config_parameter
  fl_efiling.portal_url); confirmation # capture; accepted/rejected mark the
  linked fl.document filed and log to chatter
- Phase 2 API stub (action_submit_api) reads creds/endpoint from ir.config_parameter
  and refuses to call an unconfirmed endpoint — no guessed URLs, no silent failure
- fl.efiling.wizard: pick document/attachment/filing_type, preview the filename,
  create + auto-validate the submission
- Wiring: model + wizard registered, ACL (admin/paralegal), e-filing views, Cases
  menu item, fl.case.efiling_submission_ids + Filings tab + Prepare e-Filing button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 00:42:28 +00:00

83 lines
3.3 KiB
Python

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.addons.activeblue_familylaw.models.fl_efiling import (
DOC_TYPE_TO_FILING_TYPE, FILING_TYPE_TOKEN,
)
class FlEfilingWizard(models.TransientModel):
_name = 'fl.efiling.wizard'
_description = 'Assisted e-Filing Preparation Wizard'
case_id = fields.Many2one('fl.case', string='Case', required=True)
document_id = fields.Many2one(
'fl.document', string='Case Document',
domain="[('case_id', '=', case_id)]"
)
attachment_id = fields.Many2one(
'ir.attachment', string='PDF to File',
help='The PDF to file — use the signed PDF where applicable.'
)
filing_type = fields.Selection([
('petition', 'Petition'),
('supplemental_petition', 'Supplemental Petition'),
('financial_affidavit', 'Financial Affidavit'),
('support_worksheet', 'Child Support Worksheet'),
('motion_to_modify', 'Motion to Modify'),
('motion_to_compel', 'Motion to Compel'),
('motion_default', 'Motion for Default'),
('notice_deposition', 'Notice of Deposition'),
('parenting_plan', 'Parenting Plan'),
('mandatory_disclosure', 'Mandatory Disclosure'),
('fee_waiver', 'Civil Indigent Status'),
('income_withholding', 'Income Withholding'),
('notice_ssn', 'Notice of SSN'),
('other', 'Other'),
], string='Filing Type', default='other', required=True)
court_filename_preview = fields.Char(
string='Court Filename', compute='_compute_filename_preview'
)
@api.depends('case_id', 'filing_type')
def _compute_filename_preview(self):
Submission = self.env['fl.efiling.submission']
for rec in self:
case = rec.case_id
last = Submission._sanitize(
Submission._last_name(case.petitioner_id)) or 'Party'
casenum = Submission._sanitize(case.court_case_number or 'NOCASE')
token = FILING_TYPE_TOKEN.get(rec.filing_type, 'Document')
datestr = fields.Date.context_today(rec).strftime('%Y%m%d')
rec.court_filename_preview = f'{last}_{casenum}_{token}_{datestr}.pdf'
@api.onchange('document_id')
def _onchange_document_id(self):
if not self.document_id:
return
self.filing_type = DOC_TYPE_TO_FILING_TYPE.get(
self.document_id.document_type, 'other')
if self.document_id.attachment_ids:
self.attachment_id = self.document_id.attachment_ids[:1]
def action_create_submission(self):
self.ensure_one()
if not self.attachment_id:
raise UserError(_(
'Select the PDF to file before creating the submission.'))
submission = self.env['fl.efiling.submission'].create({
'case_id': self.case_id.id,
'document_id': self.document_id.id,
'attachment_id': self.attachment_id.id,
'filing_type': self.filing_type,
})
submission.action_validate_pdfa()
return {
'type': 'ir.actions.act_window',
'name': 'e-Filing Submission',
'res_model': 'fl.efiling.submission',
'res_id': submission.id,
'view_mode': 'form',
'target': 'current',
}