"""Discount-approval review specimen, NOT an installable Odoo module.

Run: python3 approval-review-model.py
Python standard library only. No Odoo, database, network or AI model call.
Both implementations and all invented business rules were written for this article.
"""
from copy import deepcopy
from decimal import Decimal
import json


class Rejected(Exception):
    pass


class InjectedAuditFailure(Exception):
    pass


def initial_store(second_company=None):
    def quote(key, company):
        return dict(key=key, company=company, revision=3, discount="5.00",
                    lifecycle="draft", approval="pending",
                    approved_revision=None, approved_by=None)
    rows = {"Q-17": quote("Q-17", "A")}
    if second_company:
        rows["Q-18"] = quote("Q-18", second_company)
    return dict(quotes=rows, audits=[])


def flawed_approve(store, quote_ids, actor, expected_revisions,
                   claimed_approver=None, fail_audit_for=None):
    for key in quote_ids:
        quote = store["quotes"][key]
        # A: business preconditions and current authority are not checked.
        quote["approval"] = "approved"
        quote["approved_revision"] = expected_revisions[key]
        # B: caller-supplied identity is trusted.
        quote["approved_by"] = claimed_approver or actor["uid"]
        # C: failure now leaves a partial business change.
        if key == fail_audit_for:
            raise InjectedAuditFailure(key)
        # D: every repeated call appends another effect.
        store["audits"].append(dict(quote=key, revision=expected_revisions[key],
                                    actor=quote["approved_by"]))


def corrected_approve(store, quote_ids, actor, expected_revisions,
                      claimed_approver=None, fail_audit_for=None):
    if not actor["can_approve"]:
        raise Rejected("approval role required")
    staged = deepcopy(store)
    pending = []
    for key in dict.fromkeys(quote_ids):
        quote = staged["quotes"][key]
        if quote["company"] not in actor["companies"]:
            raise Rejected("company outside authority")
        if quote["revision"] != expected_revisions[key]:
            raise Rejected("stale approval revision")
        if quote["lifecycle"] != "draft":
            raise Rejected("quotation is not a draft")
        percentage = Decimal(quote["discount"])
        if not Decimal("0") <= percentage <= Decimal("10.00"):
            raise Rejected("outside illustrative approval limit")
        if quote["approval"] == "approved":
            if quote["approved_revision"] != quote["revision"]:
                raise Rejected("approval does not match current revision")
            continue
        if quote["approval"] != "pending":
            raise Rejected("unexpected approval state")
        pending.append(key)
    for key in pending:
        quote = staged["quotes"][key]
        quote["approval"] = "approved"
        quote["approved_revision"] = quote["revision"]
        # Authenticated fixture actor, never the untrusted claimed label.
        quote["approved_by"] = actor["uid"]
        if key == fail_audit_for:
            raise InjectedAuditFailure(key)
        staged["audits"].append(dict(quote=key, revision=quote["revision"],
                                     actor=actor["uid"]))
    # A staged-copy swap models the required all-or-nothing outcome only.
    # It is not evidence of a real Odoo/PostgreSQL transaction.
    store.clear()
    store.update(staged)


def observed_state(store, error):
    return dict(error=error,
                approvals={k: q["approval"] for k, q in store["quotes"].items()},
                approved_revisions={k: q["approved_revision"] for k, q in store["quotes"].items()},
                approvers={k: q["approved_by"] for k, q in store["quotes"].items()},
                lifecycles={k: q["lifecycle"] for k, q in store["quotes"].items()},
                audit_count=len(store["audits"]))


def expected_state(keys, approved=False, error=False, cancelled=False):
    # Explicit business-contract expectations, independent of either implementation.
    return dict(error=error,
                approvals={k: "approved" if approved else "pending" for k in keys},
                approved_revisions={k: 3 if approved else None for k in keys},
                approvers={k: 7 if approved else None for k in keys},
                lifecycles={k: "cancelled" if cancelled else "draft" for k in keys},
                audit_count=len(keys) if approved else 0)


def scenarios():
    return [
        dict(name="ordinary_5_percent_approval", expected=expected_state(["Q-17"], approved=True)),
        dict(name="exact_10_percent_boundary", discount="10.00",
             expected=expected_state(["Q-17"], approved=True)),
        dict(name="10_01_percent_requires_another_decision", discount="10.01",
             expected=expected_state(["Q-17"], error=True)),
        dict(name="actor_without_approval_role", can_approve=False,
             expected=expected_state(["Q-17"], error=True)),
        dict(name="record_in_unauthorized_company", company="B",
             expected=expected_state(["Q-17"], error=True)),
        dict(name="reviewed_revision_is_stale", revision=4,
             expected=expected_state(["Q-17"], error=True)),
        dict(name="cancelled_quotation", lifecycle="cancelled",
             expected=expected_state(["Q-17"], error=True, cancelled=True)),
        dict(name="duplicate_selection_in_one_request", duplicate_selection=True,
             expected=expected_state(["Q-17"], approved=True)),
        dict(name="repeat_same_approval", repeats=2,
             expected=expected_state(["Q-17"], approved=True)),
        dict(name="caller_supplies_false_approver", claimed_approver=99,
             expected=expected_state(["Q-17"], approved=True)),
        dict(name="audit_failure_after_state_assignment", fail_audit_for="Q-17",
             expected=expected_state(["Q-17"], error=True)),
        dict(name="batch_second_company_is_unauthorized", second_company="B",
             expected=expected_state(["Q-17", "Q-18"], error=True)),
        dict(name="batch_second_audit_write_fails", second_company="A",
             fail_audit_for="Q-18",
             expected=expected_state(["Q-17", "Q-18"], error=True)),
    ]


def run_case(implementation, case):
    store = initial_store(case.get("second_company"))
    first = store["quotes"]["Q-17"]
    for field in ("discount", "company", "revision", "lifecycle"):
        if field in case:
            first[field] = case[field]
    actor = dict(uid=7, companies=["A"], can_approve=case.get("can_approve", True))
    keys = list(store["quotes"])
    if case.get("duplicate_selection"):
        keys = keys + keys
    expected_revisions = {key: 3 for key in keys}
    error = False
    try:
        for _ in range(case.get("repeats", 1)):
            implementation(store, keys, actor, expected_revisions,
                           case.get("claimed_approver"), case.get("fail_audit_for"))
    except (Rejected, InjectedAuditFailure):
        error = True
    observed = observed_state(store, error)
    return dict(contract_passed=observed == case["expected"], observed=observed)


def main():
    results = []
    for case in scenarios():
        bad = run_case(flawed_approve, case)
        good = run_case(corrected_approve, case)
        assert good["contract_passed"], (case["name"], good)
        results.append(dict(case=case["name"], expected=case["expected"],
                            flawed=bad, corrected=good))
    failed = sum(not r["flawed"]["contract_passed"] for r in results)
    assert len(results) == 13 and failed == 11
    output = dict(kind="executed synthetic approval-contract review",
                  run_on="2026-11-05", runtime="Python standard library",
                  case_count=len(results), flawed_contract_failures=failed,
                  corrected_contract_passes=sum(r["corrected"]["contract_passed"] for r in results),
                  cases=results, limits=[
                      "Intentionally flawed and corrected editorial specimens, not client code.",
                      "No live AI output was sampled and no AI quality rate is measured.",
                      "Not an Odoo module; no install, ACL, ORM, native transaction or upgrade ran.",
                      "The 10 percent threshold is an invented policy, not an Odoo default.",
                      "A discount approval does not confirm a quotation or post an invoice.",
                      "Staged Python copies illustrate all-or-nothing intent, not database behavior.",
                      "Real module acceptance remains NOT_RUN.",
                  ])
    print(json.dumps(output, indent=2))


if __name__ == "__main__":
    main()
