dodil/erp-brick-ar

DODIL ERP brick: accounts receivable

src/brick_ar/domain/readiness.py

"""Readiness (shared.yaml conventions.readiness): every gate of a transition as {gate, met, reason, fix}.

`met` is computed at read time; `reason` says why not in the customer's words; `fix` names the action (and who can take it).
"""
from dataclasses import asdict, dataclass

from brick_ar.domain.errors import RuleBroken


@dataclass(frozen=True)
class Gate:
    gate: str
    met: bool
    reason: str
    fix: str

    def as_dict(self) -> dict:
        return asdict(self)


def met(gate: str) -> Gate:
    return Gate(gate, True, "", "")


def unmet(gate: str, reason: str, fix: str) -> Gate:
    return Gate(gate, False, reason, fix)


class GatesUnmet(RuleBroken):
    """A transition refused because gates are unmet: the words are the gates' own, the list is kept for the screen."""

    def __init__(self, what: str, gates):
        self.gates = [g.as_dict() for g in gates if not g.met]
        super().__init__(f"cannot {what}: " + "; ".join(f"[{g['gate']}] {g['reason']} (fix: {g['fix']})" for g in self.gates))


def require(what: str, gates) -> None:
    if any(not g.met for g in gates):
        raise GatesUnmet(what, gates)