Step 5: mandatory disclosure (Rule 12.285) — checklist + financial affidavit
Three per-proceeding models: - familylaw.disclosure.item: Rule 12.285 checklist; is_mandatory items refuse waiver in code (action_waive raises); non-mandatory can be waived - familylaw.financial.affidavit: form-by-income selection — short 12.902(b) below the $50,000 gross-annual threshold, long 12.902(c) at/above it; 45-day due date (Rule 12.285(e)) with weekend roll; line totals + net worth - familylaw.fin.line: income/expense/asset/liability line items All thresholds/counts flagged "verify current rule" (volatile FL law). proceeding gets disclosure_item_ids + affidavit_ids, Seed Disclosure Checklist button, and Disclosure / Financial Affidavits notebook tabs. Views + menu + ACL. Tests (familylaw_step5): 15 tests — form selection across the threshold boundary (49999 short / 50000 long / 80000 long), recompute on income change, 45-day due with/without weekend roll (fixed dates), mandatory-cannot-waive, non-mandatory waive, totals + net worth, idempotent seeding, per-proceeding isolation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
{
|
{
|
||||||
"name": "Active Blue Family Law",
|
"name": "Active Blue Family Law",
|
||||||
"version": "18.0.4.0.0",
|
"version": "18.0.5.0.0",
|
||||||
"category": "Services/Legal",
|
"category": "Services/Legal",
|
||||||
"summary": "Florida family law case management (Miami-Dade / 11th Judicial Circuit)",
|
"summary": "Florida family law case management (Miami-Dade / 11th Judicial Circuit)",
|
||||||
"description": """
|
"description": """
|
||||||
@@ -32,6 +32,7 @@ Each step adds one vertical, independently testable slice. See BUILD_PLAN.md.
|
|||||||
"views/familylaw_proceeding_views.xml",
|
"views/familylaw_proceeding_views.xml",
|
||||||
"views/familylaw_document_views.xml",
|
"views/familylaw_document_views.xml",
|
||||||
"views/familylaw_deadline_views.xml",
|
"views/familylaw_deadline_views.xml",
|
||||||
|
"views/familylaw_disclosure_views.xml",
|
||||||
"views/familylaw_intake_views.xml",
|
"views/familylaw_intake_views.xml",
|
||||||
"views/familylaw_case_views.xml",
|
"views/familylaw_case_views.xml",
|
||||||
"views/familylaw_menus.xml",
|
"views/familylaw_menus.xml",
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ from . import familylaw_conflict
|
|||||||
from . import familylaw_intake
|
from . import familylaw_intake
|
||||||
from . import familylaw_document
|
from . import familylaw_document
|
||||||
from . import familylaw_deadline
|
from . import familylaw_deadline
|
||||||
|
from . import familylaw_disclosure
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""STEP 5 — Mandatory disclosure (Florida Family Law Rule 12.285).
|
||||||
|
|
||||||
|
Three models, all hanging off a PROCEEDING:
|
||||||
|
|
||||||
|
* familylaw.disclosure.item — the checklist of required disclosure documents
|
||||||
|
* familylaw.financial.affidavit — the financial affidavit, with the form-by-income
|
||||||
|
selection (12.902(b) short vs 12.902(c) long)
|
||||||
|
* familylaw.fin.line — line items (income/expense/asset/liability)
|
||||||
|
|
||||||
|
LEGAL NOTES (verify current rule — these values are volatile):
|
||||||
|
* Mandatory disclosure under Rule 12.285 CANNOT be waived by the parties (with
|
||||||
|
narrow exceptions, e.g. simplified dissolution). Items flagged is_mandatory
|
||||||
|
refuse waiver in code.
|
||||||
|
* The financial affidavit form turns on gross annual income: below the threshold
|
||||||
|
the short form 12.902(b) applies; at or above it the long form 12.902(c) applies.
|
||||||
|
The threshold is currently $50,000 — CONFIRM before relying on it.
|
||||||
|
* The affidavit is due within 45 days of service of the initial pleading
|
||||||
|
(Rule 12.285(e)) — confirm the trigger and count for the matter at hand.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from odoo import api, fields, models, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
# VERIFY CURRENT RULE — do not treat as permanent.
|
||||||
|
DISCLOSURE_INCOME_THRESHOLD = 50000.0 # gross annual income, USD
|
||||||
|
DISCLOSURE_DUE_DAYS = 45 # Rule 12.285(e)
|
||||||
|
|
||||||
|
|
||||||
|
def _roll_forward_weekend(due):
|
||||||
|
while due.weekday() >= 5:
|
||||||
|
due += timedelta(days=1)
|
||||||
|
return due
|
||||||
|
|
||||||
|
|
||||||
|
class FamilyLawDisclosureItem(models.Model):
|
||||||
|
_name = "familylaw.disclosure.item"
|
||||||
|
_description = "Mandatory Disclosure Item"
|
||||||
|
_inherit = ["mail.thread"]
|
||||||
|
_order = "sequence, id"
|
||||||
|
|
||||||
|
sequence = fields.Integer(default=10)
|
||||||
|
proceeding_id = fields.Many2one(
|
||||||
|
"familylaw.proceeding", required=True, ondelete="cascade", index=True,
|
||||||
|
tracking=True,
|
||||||
|
)
|
||||||
|
case_id = fields.Many2one(
|
||||||
|
"familylaw.case", related="proceeding_id.case_id", store=True, index=True,
|
||||||
|
)
|
||||||
|
name = fields.Char(required=True, tracking=True)
|
||||||
|
is_mandatory = fields.Boolean(
|
||||||
|
string="Mandatory (cannot waive)",
|
||||||
|
default=True,
|
||||||
|
help="Rule 12.285 disclosure that the parties cannot waive.",
|
||||||
|
)
|
||||||
|
state = fields.Selection(
|
||||||
|
selection=[
|
||||||
|
("required", "Required"),
|
||||||
|
("provided", "Provided"),
|
||||||
|
("waived", "Waived"),
|
||||||
|
("na", "Not Applicable"),
|
||||||
|
],
|
||||||
|
default="required",
|
||||||
|
required=True,
|
||||||
|
tracking=True,
|
||||||
|
)
|
||||||
|
notes = fields.Text()
|
||||||
|
|
||||||
|
def action_mark_provided(self):
|
||||||
|
for item in self:
|
||||||
|
item.state = "provided"
|
||||||
|
item.message_post(body=_("Disclosure item provided."))
|
||||||
|
return True
|
||||||
|
|
||||||
|
def action_waive(self):
|
||||||
|
for item in self:
|
||||||
|
if item.is_mandatory:
|
||||||
|
raise UserError(
|
||||||
|
_("'%s' is mandatory disclosure under Rule 12.285 and cannot be "
|
||||||
|
"waived by the parties.") % item.name
|
||||||
|
)
|
||||||
|
item.state = "waived"
|
||||||
|
item.message_post(body=_("Disclosure item waived (non-mandatory)."))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class FamilyLawFinancialAffidavit(models.Model):
|
||||||
|
_name = "familylaw.financial.affidavit"
|
||||||
|
_description = "Financial Affidavit (12.902(b)/(c))"
|
||||||
|
_inherit = ["mail.thread"]
|
||||||
|
_order = "create_date desc"
|
||||||
|
|
||||||
|
proceeding_id = fields.Many2one(
|
||||||
|
"familylaw.proceeding", required=True, ondelete="cascade", index=True,
|
||||||
|
tracking=True,
|
||||||
|
)
|
||||||
|
case_id = fields.Many2one(
|
||||||
|
"familylaw.case", related="proceeding_id.case_id", store=True, index=True,
|
||||||
|
)
|
||||||
|
party_id = fields.Many2one("familylaw.party", string="Affiant (party)")
|
||||||
|
name = fields.Char(string="Affiant Name", required=True, tracking=True)
|
||||||
|
|
||||||
|
gross_annual_income = fields.Float(
|
||||||
|
string="Gross Annual Income",
|
||||||
|
tracking=True,
|
||||||
|
help="Drives the form selection. Verify the current threshold.",
|
||||||
|
)
|
||||||
|
form_type = fields.Selection(
|
||||||
|
selection=[
|
||||||
|
("short", "Short Form — 12.902(b)"),
|
||||||
|
("long", "Long Form — 12.902(c)"),
|
||||||
|
],
|
||||||
|
compute="_compute_form_type",
|
||||||
|
store=True,
|
||||||
|
string="Required Form",
|
||||||
|
)
|
||||||
|
form_reference = fields.Char(
|
||||||
|
compute="_compute_form_type", store=True, string="Form #",
|
||||||
|
)
|
||||||
|
|
||||||
|
trigger_date = fields.Date(string="Trigger (service) Date", tracking=True)
|
||||||
|
due_date = fields.Date(
|
||||||
|
compute="_compute_due_date", store=True, tracking=True,
|
||||||
|
help="45 days from the trigger (Rule 12.285(e)), rolled off weekends.",
|
||||||
|
)
|
||||||
|
state = fields.Selection(
|
||||||
|
selection=[
|
||||||
|
("draft", "Draft"),
|
||||||
|
("provided", "Provided"),
|
||||||
|
("filed", "Filed"),
|
||||||
|
],
|
||||||
|
default="draft",
|
||||||
|
required=True,
|
||||||
|
tracking=True,
|
||||||
|
)
|
||||||
|
line_ids = fields.One2many(
|
||||||
|
"familylaw.fin.line", "affidavit_id", string="Line Items",
|
||||||
|
)
|
||||||
|
total_income = fields.Float(compute="_compute_totals", store=True)
|
||||||
|
total_expense = fields.Float(compute="_compute_totals", store=True)
|
||||||
|
total_asset = fields.Float(compute="_compute_totals", store=True)
|
||||||
|
total_liability = fields.Float(compute="_compute_totals", store=True)
|
||||||
|
net_worth = fields.Float(compute="_compute_totals", store=True)
|
||||||
|
|
||||||
|
@api.depends("gross_annual_income")
|
||||||
|
def _compute_form_type(self):
|
||||||
|
for aff in self:
|
||||||
|
if aff.gross_annual_income >= DISCLOSURE_INCOME_THRESHOLD:
|
||||||
|
aff.form_type = "long"
|
||||||
|
aff.form_reference = "12.902(c)"
|
||||||
|
else:
|
||||||
|
aff.form_type = "short"
|
||||||
|
aff.form_reference = "12.902(b)"
|
||||||
|
|
||||||
|
@api.depends("trigger_date")
|
||||||
|
def _compute_due_date(self):
|
||||||
|
for aff in self:
|
||||||
|
if not aff.trigger_date:
|
||||||
|
aff.due_date = False
|
||||||
|
continue
|
||||||
|
raw = aff.trigger_date + timedelta(days=DISCLOSURE_DUE_DAYS)
|
||||||
|
aff.due_date = _roll_forward_weekend(raw)
|
||||||
|
|
||||||
|
@api.depends("line_ids.amount", "line_ids.category")
|
||||||
|
def _compute_totals(self):
|
||||||
|
for aff in self:
|
||||||
|
sums = {"income": 0.0, "expense": 0.0, "asset": 0.0, "liability": 0.0}
|
||||||
|
for line in aff.line_ids:
|
||||||
|
if line.category in sums:
|
||||||
|
sums[line.category] += line.amount
|
||||||
|
aff.total_income = sums["income"]
|
||||||
|
aff.total_expense = sums["expense"]
|
||||||
|
aff.total_asset = sums["asset"]
|
||||||
|
aff.total_liability = sums["liability"]
|
||||||
|
aff.net_worth = sums["asset"] - sums["liability"]
|
||||||
|
|
||||||
|
def action_mark_provided(self):
|
||||||
|
for aff in self:
|
||||||
|
aff.state = "provided"
|
||||||
|
aff.message_post(body=_("Financial affidavit provided."))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class FamilyLawFinLine(models.Model):
|
||||||
|
_name = "familylaw.fin.line"
|
||||||
|
_description = "Financial Affidavit Line"
|
||||||
|
_order = "category, id"
|
||||||
|
|
||||||
|
affidavit_id = fields.Many2one(
|
||||||
|
"familylaw.financial.affidavit", required=True, ondelete="cascade", index=True,
|
||||||
|
)
|
||||||
|
category = fields.Selection(
|
||||||
|
selection=[
|
||||||
|
("income", "Income"),
|
||||||
|
("expense", "Expense"),
|
||||||
|
("asset", "Asset"),
|
||||||
|
("liability", "Liability"),
|
||||||
|
],
|
||||||
|
required=True,
|
||||||
|
default="income",
|
||||||
|
)
|
||||||
|
name = fields.Char(string="Description", required=True)
|
||||||
|
amount = fields.Float()
|
||||||
|
monthly = fields.Boolean(
|
||||||
|
string="Monthly?",
|
||||||
|
help="If set, this is a recurring monthly figure (informational).",
|
||||||
|
)
|
||||||
@@ -60,6 +60,40 @@ class FamilyLawProceeding(models.Model):
|
|||||||
deadline_ids = fields.One2many(
|
deadline_ids = fields.One2many(
|
||||||
"familylaw.deadline", "proceeding_id", string="Deadlines",
|
"familylaw.deadline", "proceeding_id", string="Deadlines",
|
||||||
)
|
)
|
||||||
|
disclosure_item_ids = fields.One2many(
|
||||||
|
"familylaw.disclosure.item", "proceeding_id", string="Disclosure Items",
|
||||||
|
)
|
||||||
|
affidavit_ids = fields.One2many(
|
||||||
|
"familylaw.financial.affidavit", "proceeding_id", string="Financial Affidavits",
|
||||||
|
)
|
||||||
|
|
||||||
|
def action_seed_disclosure_items(self):
|
||||||
|
"""Seed the standard Rule 12.285 mandatory disclosure checklist.
|
||||||
|
VERIFY the current rule's required-document list before relying on it."""
|
||||||
|
Item = self.env["familylaw.disclosure.item"]
|
||||||
|
standard = [
|
||||||
|
"Federal income tax returns (last 3 years)",
|
||||||
|
"IRS forms W-2, 1099, K-1 (last year)",
|
||||||
|
"Pay stubs (last 3 months)",
|
||||||
|
"Loan applications / financial statements (last 12 months)",
|
||||||
|
"Bank / checking / savings statements (last 3 months)",
|
||||||
|
"Deeds, leases, and mortgages on real property",
|
||||||
|
"Credit card and other liability statements (last 3 months)",
|
||||||
|
"Retirement / pension / profit-sharing statements (last 12 months)",
|
||||||
|
]
|
||||||
|
for proc in self:
|
||||||
|
existing = set(proc.disclosure_item_ids.mapped("name"))
|
||||||
|
for seq, label in enumerate(standard, start=1):
|
||||||
|
if label in existing:
|
||||||
|
continue
|
||||||
|
Item.create({
|
||||||
|
"proceeding_id": proc.id,
|
||||||
|
"name": label,
|
||||||
|
"sequence": seq * 10,
|
||||||
|
"is_mandatory": True,
|
||||||
|
})
|
||||||
|
proc.message_post(body="Mandatory disclosure checklist seeded (Rule 12.285).")
|
||||||
|
return True
|
||||||
|
|
||||||
def action_seed_standard_deadlines(self):
|
def action_seed_standard_deadlines(self):
|
||||||
"""Create the common procedural deadlines for this proceeding, dated from
|
"""Create the common procedural deadlines for this proceeding, dated from
|
||||||
|
|||||||
@@ -16,3 +16,9 @@ access_familylaw_document_user,familylaw.document staff,model_familylaw_document
|
|||||||
access_familylaw_document_attorney,familylaw.document attorney,model_familylaw_document,group_familylaw_attorney,1,1,1,1
|
access_familylaw_document_attorney,familylaw.document attorney,model_familylaw_document,group_familylaw_attorney,1,1,1,1
|
||||||
access_familylaw_deadline_user,familylaw.deadline staff,model_familylaw_deadline,group_familylaw_user,1,1,1,0
|
access_familylaw_deadline_user,familylaw.deadline staff,model_familylaw_deadline,group_familylaw_user,1,1,1,0
|
||||||
access_familylaw_deadline_attorney,familylaw.deadline attorney,model_familylaw_deadline,group_familylaw_attorney,1,1,1,1
|
access_familylaw_deadline_attorney,familylaw.deadline attorney,model_familylaw_deadline,group_familylaw_attorney,1,1,1,1
|
||||||
|
access_familylaw_disclosure_item_user,familylaw.disclosure.item staff,model_familylaw_disclosure_item,group_familylaw_user,1,1,1,0
|
||||||
|
access_familylaw_disclosure_item_attorney,familylaw.disclosure.item attorney,model_familylaw_disclosure_item,group_familylaw_attorney,1,1,1,1
|
||||||
|
access_familylaw_affidavit_user,familylaw.financial.affidavit staff,model_familylaw_financial_affidavit,group_familylaw_user,1,1,1,0
|
||||||
|
access_familylaw_affidavit_attorney,familylaw.financial.affidavit attorney,model_familylaw_financial_affidavit,group_familylaw_attorney,1,1,1,1
|
||||||
|
access_familylaw_fin_line_user,familylaw.fin.line staff,model_familylaw_fin_line,group_familylaw_user,1,1,1,0
|
||||||
|
access_familylaw_fin_line_attorney,familylaw.fin.line attorney,model_familylaw_fin_line,group_familylaw_attorney,1,1,1,1
|
||||||
|
|||||||
|
@@ -2,3 +2,4 @@ from . import test_case_lifecycle
|
|||||||
from . import test_step2
|
from . import test_step2
|
||||||
from . import test_step3
|
from . import test_step3
|
||||||
from . import test_step4
|
from . import test_step4
|
||||||
|
from . import test_step5
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""STEP 5 tests — mandatory disclosure (Rule 12.285).
|
||||||
|
|
||||||
|
odoo -d <db> -u activeblue_familylaw --test-enable \
|
||||||
|
--test-tags familylaw_step5 --stop-after-init
|
||||||
|
|
||||||
|
Proves:
|
||||||
|
* form selection 12.902(b) vs 12.902(c) by gross annual income (threshold);
|
||||||
|
* 45-day affidavit due date with weekend roll (fixed dates);
|
||||||
|
* mandatory disclosure cannot be waived; non-mandatory can;
|
||||||
|
* line-item totals and net worth;
|
||||||
|
* per-proceeding isolation + seeding.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
from odoo.tests.common import TransactionCase, tagged
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
|
@tagged("post_install", "-at_install", "familylaw", "familylaw_step5")
|
||||||
|
class TestStep5Disclosure(TransactionCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
cls.partner = cls.env["res.partner"].create({"name": "Disc Client"})
|
||||||
|
cls.case = cls.env["familylaw.case"].create({
|
||||||
|
"name": "Disclosure Matter",
|
||||||
|
"client_id": cls.partner.id,
|
||||||
|
"case_type": "dissolution_children",
|
||||||
|
})
|
||||||
|
cls.proc = cls.case.proceeding_ids[0]
|
||||||
|
cls.Aff = cls.env["familylaw.financial.affidavit"]
|
||||||
|
cls.Item = cls.env["familylaw.disclosure.item"]
|
||||||
|
|
||||||
|
def _aff(self, income, **kw):
|
||||||
|
vals = {
|
||||||
|
"proceeding_id": self.proc.id,
|
||||||
|
"name": "Affiant",
|
||||||
|
"gross_annual_income": income,
|
||||||
|
}
|
||||||
|
vals.update(kw)
|
||||||
|
return self.Aff.create(vals)
|
||||||
|
|
||||||
|
# --- form selection by income -------------------------------------------
|
||||||
|
def test_01_low_income_short_form(self):
|
||||||
|
aff = self._aff(30000.0)
|
||||||
|
self.assertEqual(aff.form_type, "short")
|
||||||
|
self.assertEqual(aff.form_reference, "12.902(b)")
|
||||||
|
|
||||||
|
def test_02_high_income_long_form(self):
|
||||||
|
aff = self._aff(80000.0)
|
||||||
|
self.assertEqual(aff.form_type, "long")
|
||||||
|
self.assertEqual(aff.form_reference, "12.902(c)")
|
||||||
|
|
||||||
|
def test_03_threshold_is_long_form(self):
|
||||||
|
# exactly at threshold (>=) -> long form
|
||||||
|
aff = self._aff(50000.0)
|
||||||
|
self.assertEqual(aff.form_type, "long")
|
||||||
|
|
||||||
|
def test_04_just_below_threshold_short(self):
|
||||||
|
aff = self._aff(49999.0)
|
||||||
|
self.assertEqual(aff.form_type, "short")
|
||||||
|
|
||||||
|
def test_05_form_recomputes_on_income_change(self):
|
||||||
|
aff = self._aff(10000.0)
|
||||||
|
self.assertEqual(aff.form_type, "short")
|
||||||
|
aff.gross_annual_income = 120000.0
|
||||||
|
self.assertEqual(aff.form_type, "long")
|
||||||
|
|
||||||
|
# --- 45-day due date ----------------------------------------------------
|
||||||
|
def test_06_due_date_45_days(self):
|
||||||
|
# 2025-01-01 + 45 = 2025-02-15 (Sat) -> 2025-02-17 (Mon)
|
||||||
|
aff = self._aff(20000.0, trigger_date=date(2025, 1, 1))
|
||||||
|
self.assertEqual(aff.due_date, date(2025, 2, 17))
|
||||||
|
|
||||||
|
def test_07_due_date_no_weekend_roll(self):
|
||||||
|
# 2025-02-03 (Mon) + 45 = 2025-03-20 (Thu)
|
||||||
|
aff = self._aff(20000.0, trigger_date=date(2025, 2, 3))
|
||||||
|
self.assertEqual(aff.due_date, date(2025, 3, 20))
|
||||||
|
|
||||||
|
def test_08_no_trigger_no_due(self):
|
||||||
|
aff = self._aff(20000.0)
|
||||||
|
self.assertFalse(aff.due_date)
|
||||||
|
|
||||||
|
# --- can't waive mandatory ----------------------------------------------
|
||||||
|
def test_09_mandatory_cannot_waive(self):
|
||||||
|
item = self.Item.create({
|
||||||
|
"proceeding_id": self.proc.id,
|
||||||
|
"name": "Tax returns",
|
||||||
|
"is_mandatory": True,
|
||||||
|
})
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
item.action_waive()
|
||||||
|
self.assertEqual(item.state, "required")
|
||||||
|
|
||||||
|
def test_10_non_mandatory_can_waive(self):
|
||||||
|
item = self.Item.create({
|
||||||
|
"proceeding_id": self.proc.id,
|
||||||
|
"name": "Optional extra",
|
||||||
|
"is_mandatory": False,
|
||||||
|
})
|
||||||
|
item.action_waive()
|
||||||
|
self.assertEqual(item.state, "waived")
|
||||||
|
|
||||||
|
def test_11_mark_provided(self):
|
||||||
|
item = self.Item.create({
|
||||||
|
"proceeding_id": self.proc.id,
|
||||||
|
"name": "Pay stubs",
|
||||||
|
"is_mandatory": True,
|
||||||
|
})
|
||||||
|
item.action_mark_provided()
|
||||||
|
self.assertEqual(item.state, "provided")
|
||||||
|
|
||||||
|
# --- totals -------------------------------------------------------------
|
||||||
|
def test_12_totals_and_net_worth(self):
|
||||||
|
aff = self._aff(60000.0)
|
||||||
|
self.env["familylaw.fin.line"].create([
|
||||||
|
{"affidavit_id": aff.id, "category": "income", "name": "Salary", "amount": 5000.0},
|
||||||
|
{"affidavit_id": aff.id, "category": "expense", "name": "Rent", "amount": 2000.0},
|
||||||
|
{"affidavit_id": aff.id, "category": "asset", "name": "Home", "amount": 300000.0},
|
||||||
|
{"affidavit_id": aff.id, "category": "liability", "name": "Mortgage", "amount": 180000.0},
|
||||||
|
])
|
||||||
|
self.assertEqual(aff.total_income, 5000.0)
|
||||||
|
self.assertEqual(aff.total_expense, 2000.0)
|
||||||
|
self.assertEqual(aff.total_asset, 300000.0)
|
||||||
|
self.assertEqual(aff.total_liability, 180000.0)
|
||||||
|
self.assertEqual(aff.net_worth, 120000.0)
|
||||||
|
|
||||||
|
# --- seeding + isolation ------------------------------------------------
|
||||||
|
def test_13_seed_disclosure_checklist(self):
|
||||||
|
self.proc.action_seed_disclosure_items()
|
||||||
|
self.assertTrue(self.proc.disclosure_item_ids)
|
||||||
|
self.assertTrue(all(self.proc.disclosure_item_ids.mapped("is_mandatory")))
|
||||||
|
|
||||||
|
def test_14_seed_is_idempotent(self):
|
||||||
|
self.proc.action_seed_disclosure_items()
|
||||||
|
n1 = len(self.proc.disclosure_item_ids)
|
||||||
|
self.proc.action_seed_disclosure_items()
|
||||||
|
self.assertEqual(len(self.proc.disclosure_item_ids), n1)
|
||||||
|
|
||||||
|
def test_15_affidavit_isolated_per_proceeding(self):
|
||||||
|
proc2 = self.env["familylaw.proceeding"].create({
|
||||||
|
"case_id": self.case.id,
|
||||||
|
"name": "Second",
|
||||||
|
"proceeding_type": "modification",
|
||||||
|
})
|
||||||
|
a1 = self._aff(20000.0)
|
||||||
|
a2 = self.Aff.create({
|
||||||
|
"proceeding_id": proc2.id, "name": "Other", "gross_annual_income": 90000.0,
|
||||||
|
})
|
||||||
|
self.assertIn(a1, self.proc.affidavit_ids)
|
||||||
|
self.assertNotIn(a2, self.proc.affidavit_ids)
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<!-- ===== Disclosure item ===== -->
|
||||||
|
<record id="view_familylaw_disclosure_item_list" model="ir.ui.view">
|
||||||
|
<field name="name">familylaw.disclosure.item.list</field>
|
||||||
|
<field name="model">familylaw.disclosure.item</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Disclosure Items"
|
||||||
|
decoration-success="state == 'provided'"
|
||||||
|
decoration-muted="state in ('waived','na')">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="case_id"/>
|
||||||
|
<field name="is_mandatory"/>
|
||||||
|
<field name="state" widget="badge"
|
||||||
|
decoration-success="state == 'provided'"
|
||||||
|
decoration-info="state == 'required'"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_familylaw_disclosure_item_form" model="ir.ui.view">
|
||||||
|
<field name="name">familylaw.disclosure.item.form</field>
|
||||||
|
<field name="model">familylaw.disclosure.item</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Disclosure Item">
|
||||||
|
<header>
|
||||||
|
<button name="action_mark_provided" type="object"
|
||||||
|
string="Mark Provided" class="btn-primary"
|
||||||
|
invisible="state == 'provided'"/>
|
||||||
|
<button name="action_waive" type="object" string="Waive"
|
||||||
|
invisible="state in ('waived','na') or is_mandatory"/>
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<div class="alert alert-info" role="alert" invisible="not is_mandatory">
|
||||||
|
Mandatory under Rule 12.285 — cannot be waived by the parties.
|
||||||
|
</div>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="is_mandatory"/>
|
||||||
|
<field name="state"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="proceeding_id"/>
|
||||||
|
<field name="case_id" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group string="Notes"><field name="notes" nolabel="1"/></group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- ===== Financial affidavit ===== -->
|
||||||
|
<record id="view_familylaw_affidavit_list" model="ir.ui.view">
|
||||||
|
<field name="name">familylaw.financial.affidavit.list</field>
|
||||||
|
<field name="model">familylaw.financial.affidavit</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Financial Affidavits">
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="case_id"/>
|
||||||
|
<field name="gross_annual_income"/>
|
||||||
|
<field name="form_reference"/>
|
||||||
|
<field name="due_date"/>
|
||||||
|
<field name="state" widget="badge"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_familylaw_affidavit_form" model="ir.ui.view">
|
||||||
|
<field name="name">familylaw.financial.affidavit.form</field>
|
||||||
|
<field name="model">familylaw.financial.affidavit</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Financial Affidavit">
|
||||||
|
<header>
|
||||||
|
<button name="action_mark_provided" type="object"
|
||||||
|
string="Mark Provided" class="btn-primary"
|
||||||
|
invisible="state != 'draft'"/>
|
||||||
|
<field name="state" widget="statusbar"/>
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<div class="oe_title">
|
||||||
|
<label for="name"/>
|
||||||
|
<h1><field name="name" placeholder="Affiant name"/></h1>
|
||||||
|
</div>
|
||||||
|
<group>
|
||||||
|
<group string="Form Selection">
|
||||||
|
<field name="gross_annual_income"/>
|
||||||
|
<field name="form_reference" readonly="1"/>
|
||||||
|
<field name="form_type" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<group string="Matter / Timing">
|
||||||
|
<field name="proceeding_id"/>
|
||||||
|
<field name="case_id" readonly="1"/>
|
||||||
|
<field name="party_id"/>
|
||||||
|
<field name="trigger_date"/>
|
||||||
|
<field name="due_date" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<notebook>
|
||||||
|
<page string="Line Items" name="lines">
|
||||||
|
<field name="line_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="category"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="amount"/>
|
||||||
|
<field name="monthly"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<group class="oe_subtotal_footer">
|
||||||
|
<field name="total_income"/>
|
||||||
|
<field name="total_expense"/>
|
||||||
|
<field name="total_asset"/>
|
||||||
|
<field name="total_liability"/>
|
||||||
|
<field name="net_worth"/>
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</sheet>
|
||||||
|
<div class="oe_chatter">
|
||||||
|
<field name="message_follower_ids"/>
|
||||||
|
<field name="activity_ids"/>
|
||||||
|
<field name="message_ids"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_familylaw_affidavit" model="ir.actions.act_window">
|
||||||
|
<field name="name">Financial Affidavits</field>
|
||||||
|
<field name="res_model">familylaw.financial.affidavit</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
@@ -34,6 +34,13 @@
|
|||||||
action="action_familylaw_deadline"
|
action="action_familylaw_deadline"
|
||||||
sequence="30"/>
|
sequence="30"/>
|
||||||
|
|
||||||
|
<!-- Financial Affidavits -->
|
||||||
|
<menuitem id="menu_familylaw_affidavits"
|
||||||
|
name="Financial Affidavits"
|
||||||
|
parent="menu_familylaw_root"
|
||||||
|
action="action_familylaw_affidavit"
|
||||||
|
sequence="40"/>
|
||||||
|
|
||||||
<!-- Configuration placeholder (populated in later steps) -->
|
<!-- Configuration placeholder (populated in later steps) -->
|
||||||
<menuitem id="menu_familylaw_config"
|
<menuitem id="menu_familylaw_config"
|
||||||
name="Configuration"
|
name="Configuration"
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
<header>
|
<header>
|
||||||
<button name="action_seed_standard_deadlines" type="object"
|
<button name="action_seed_standard_deadlines" type="object"
|
||||||
string="Seed Standard Deadlines"/>
|
string="Seed Standard Deadlines"/>
|
||||||
|
<button name="action_seed_disclosure_items" type="object"
|
||||||
|
string="Seed Disclosure Checklist"/>
|
||||||
<button name="action_close_proceeding" type="object"
|
<button name="action_close_proceeding" type="object"
|
||||||
string="Close Proceeding"
|
string="Close Proceeding"
|
||||||
invisible="state == 'closed'"/>
|
invisible="state == 'closed'"/>
|
||||||
@@ -82,6 +84,31 @@
|
|||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
|
<page string="Disclosure" name="disclosure">
|
||||||
|
<field name="disclosure_item_ids"
|
||||||
|
context="{'default_proceeding_id': id}">
|
||||||
|
<list editable="bottom"
|
||||||
|
decoration-success="state == 'provided'"
|
||||||
|
decoration-muted="state in ('waived','na')">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="is_mandatory"/>
|
||||||
|
<field name="state" widget="badge"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="Financial Affidavits" name="affidavits">
|
||||||
|
<field name="affidavit_ids"
|
||||||
|
context="{'default_proceeding_id': id}">
|
||||||
|
<list>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="gross_annual_income"/>
|
||||||
|
<field name="form_reference"/>
|
||||||
|
<field name="due_date"/>
|
||||||
|
<field name="state" widget="badge"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter">
|
<div class="oe_chatter">
|
||||||
|
|||||||
Reference in New Issue
Block a user