Phase 1: core models, security, seed data, and backend views
Implements full Phase 1 of the activeblue_familylaw Odoo 18 module: - 17 Python models (fl.case, fl.party, fl.child, fl.support.calculation, fl.fee.waiver, fl.income.withholding, fl.deadline, fl.hearing, fl.deposition, fl.discovery, fl.document, fl.caselaw, fl.analysis, fl.ai.engine, fl.argument, fl.statute, fl.issue.tag) + hr.expense extension - 3 wizard stubs (intake, analysis, generate-packet) - Security: 4 groups (admin/paralegal/portal-petitioner/portal-respondent) + record rules scoping portal users to their own cases - Seed data: issue tags, FL statutes, FL DCF support schedule, ir.sequence - 13 backend view XML files with FL 61.30 worksheet, fee waiver eligibility banner, DV safety resources, emancipation alerts - Static CSS/JS stubs for Phase 6 portal Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
165
activeblue_familylaw/models/fl_income_withholding.py
Normal file
165
activeblue_familylaw/models/fl_income_withholding.py
Normal file
@@ -0,0 +1,165 @@
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class FlIncomeWithholding(models.Model):
|
||||
"""
|
||||
FL 61.1301 — Income Deduction (Withholding) Order.
|
||||
|
||||
MANDATORY after every child support or alimony order unless:
|
||||
- Good cause shown, OR
|
||||
- Written agreement between parties for alternative payment method.
|
||||
|
||||
All payments route through Florida State Disbursement Unit (SDU).
|
||||
Employer receives copy and deducts from obligor's paycheck.
|
||||
"""
|
||||
_name = 'fl.income.withholding'
|
||||
_description = 'Income Withholding Order (FL 61.1301)'
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'issued_date desc'
|
||||
|
||||
case_id = fields.Many2one(
|
||||
'fl.case', string='Case',
|
||||
ondelete='cascade', index=True
|
||||
)
|
||||
name = fields.Char(
|
||||
string='Reference',
|
||||
compute='_compute_name', store=True
|
||||
)
|
||||
|
||||
# ── Parties ────────────────────────────────────────────────────────────
|
||||
|
||||
obligor_id = fields.Many2one(
|
||||
'res.partner',
|
||||
string='Obligor (Person Paying)',
|
||||
required=True
|
||||
)
|
||||
obligee_id = fields.Many2one(
|
||||
'res.partner',
|
||||
string='Obligee (Person Receiving)',
|
||||
required=True
|
||||
)
|
||||
employer_id = fields.Many2one(
|
||||
'res.partner',
|
||||
string="Obligor's Employer",
|
||||
help='Employer who will receive and execute the withholding order'
|
||||
)
|
||||
employer_contact = fields.Char(
|
||||
string='Employer HR / Payroll Contact'
|
||||
)
|
||||
|
||||
# ── Amounts ────────────────────────────────────────────────────────────
|
||||
|
||||
monthly_support_amount = fields.Float(
|
||||
string='Monthly Support Amount ($)',
|
||||
required=True,
|
||||
tracking=True
|
||||
)
|
||||
arrears_amount = fields.Float(
|
||||
string='Arrears Amount ($)',
|
||||
help='Total unpaid support owed prior to this order'
|
||||
)
|
||||
arrears_monthly_payment = fields.Float(
|
||||
string='Monthly Arrears Payment ($)',
|
||||
help='Additional monthly amount toward arrears payoff'
|
||||
)
|
||||
total_monthly_withholding = fields.Float(
|
||||
string='Total Monthly Withholding ($)',
|
||||
compute='_compute_total', store=True,
|
||||
help='Support + arrears payment per month'
|
||||
)
|
||||
|
||||
# ── Florida State Disbursement Unit ────────────────────────────────────
|
||||
# ALL payments must go through FL SDU — never directly to the other party
|
||||
|
||||
fl_sdu_case_number = fields.Char(
|
||||
string='FL SDU Case Number',
|
||||
help='Florida State Disbursement Unit case number. '
|
||||
'Obtain from DOR: https://www.floridarevenue.com/childsupport'
|
||||
)
|
||||
fl_sdu_address = fields.Char(
|
||||
string='FL SDU Payment Address',
|
||||
default='Florida State Disbursement Unit, PO Box 8500, Tallahassee, FL 32314-8500',
|
||||
readonly=True
|
||||
)
|
||||
fl_sdu_website = fields.Char(
|
||||
default='https://www.floridarevenue.com/childsupport',
|
||||
readonly=True
|
||||
)
|
||||
|
||||
# ── Dates & Status ────────────────────────────────────────────────────
|
||||
|
||||
issued_date = fields.Date(
|
||||
string='Order Issued Date',
|
||||
tracking=True
|
||||
)
|
||||
served_on_employer_date = fields.Date(
|
||||
string='Served on Employer Date'
|
||||
)
|
||||
first_withholding_date = fields.Date(
|
||||
string='First Withholding Payroll Date',
|
||||
help='Date of first paycheck with withholding applied'
|
||||
)
|
||||
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('issued', 'Issued by Court'),
|
||||
('served', 'Served on Employer'),
|
||||
('active', 'Active — Withholding'),
|
||||
('modified', 'Modified'),
|
||||
('terminated', 'Terminated'),
|
||||
], string='Status', default='draft', tracking=True)
|
||||
|
||||
# ── Exceptions (rare) ─────────────────────────────────────────────────
|
||||
|
||||
good_cause_exception = fields.Boolean(
|
||||
string='Good Cause Exception',
|
||||
help='FL 61.1301(1)(a): Court may waive withholding for good cause shown. '
|
||||
'Must be documented in court order. RARE.'
|
||||
)
|
||||
written_agreement = fields.Boolean(
|
||||
string='Written Agreement Between Parties',
|
||||
help='Parties may agree in writing to an alternative payment method. '
|
||||
'Agreement must be filed with the court.'
|
||||
)
|
||||
exception_reason = fields.Text(
|
||||
string='Exception Reason / Agreement Details'
|
||||
)
|
||||
|
||||
# ── Notes ─────────────────────────────────────────────────────────────
|
||||
|
||||
notes = fields.Text(string='Notes')
|
||||
|
||||
# ── Computed ──────────────────────────────────────────────────────────
|
||||
|
||||
@api.depends('case_id', 'issued_date')
|
||||
def _compute_name(self):
|
||||
for rec in self:
|
||||
case_ref = rec.case_id.name if rec.case_id else 'NEW'
|
||||
date_str = str(rec.issued_date) if rec.issued_date else 'Draft'
|
||||
rec.name = f'IWO — {case_ref} — {date_str}'
|
||||
|
||||
@api.depends('monthly_support_amount', 'arrears_monthly_payment')
|
||||
def _compute_total(self):
|
||||
for rec in self:
|
||||
rec.total_monthly_withholding = (
|
||||
(rec.monthly_support_amount or 0.0)
|
||||
+ (rec.arrears_monthly_payment or 0.0)
|
||||
)
|
||||
|
||||
# ── State Actions ─────────────────────────────────────────────────────
|
||||
|
||||
def action_issue(self):
|
||||
self.state = 'issued'
|
||||
self.issued_date = self.issued_date or fields.Date.today()
|
||||
|
||||
def action_serve(self):
|
||||
self.state = 'served'
|
||||
self.served_on_employer_date = (
|
||||
self.served_on_employer_date or fields.Date.today()
|
||||
)
|
||||
|
||||
def action_activate(self):
|
||||
self.state = 'active'
|
||||
|
||||
def action_terminate(self):
|
||||
self.state = 'terminated'
|
||||
Reference in New Issue
Block a user