Objective
- Expose a structured payment condition (payment type + lifecycle state) that action flows, inspection worklists, and automations can branch on.
- Let companies target specific situations — Pay at Close pending agreement, signed / due at closing, funded, backup-card / exception paths, card/ACH pending vs settled, unpaid, etc. — instead of relying only on coarse fields like Paid.
- Provide a reliable foundation for collection emails, reminders, worklist views, and downstream automations that today misfire when Paid is false or Paid is true does not mean what staff expect.
Background
- Action flow conditions today expose inspection-level payment fields such as Paid (boolean), Remaining Balance, and Total Paid via
attributePathResolverand the condition builder (templatingData.ts). Inspection worklists use the same attribute keys for MongoDB filtering (worklist.ts→buildMongoCondition). - Payment-specific condition keys are not enabled —
payment: paymentTemplateKeys.filter(...)is commented out inconditionalKeys, andpaymentTemplateKeysonly includes a Payment List template string (not branchable states). - Paid collapses many states. After ATT-1718 (Done),
inspection.paidintentionally treats some in-flight payments as paid for report/access semantics — e.g. pending ACH and signed PAC before funding can setpaid: truewhiletotalPaidremains 0. Flows that use Paid is false for “send collection email” cannot distinguish unsigned PAC, signed-but-unfunded PAC, pending ACH, and truly unpaid jobs. - Rich PAC/ISN status logic already exists for payments processing and client display (
pacIsnFlexFundStatuses.ts, FlexFund webhooks, client payment helpers) — pending signature, signed, funded, backup-card retry buckets, terminal failures, canceled — but it is not surfaced as a condition attribute automations or worklists can evaluate. - This issue is intentionally separate from client-facing Pay at Close copy and status wording (ATT-1818). The goal here is operator-facing branching, not portal labels.
Product Decisions
Locked
- Problem type — Feature gap. Structured payment condition for action flows does not exist today.
- Primary surfaces — Action flows condition builder and backend condition evaluation (
conditionsResolver,attributePathResolver) on inspection-triggered flows, plus inspection-related worklists (same condition attribute for list filtering). Not quote flows. - First-step scope — Ship a reliable condition attribute automations and worklists can branch on; do not bundle client UI copy changes (ATT-1818) into this issue.
- Source of truth — Derive condition values from existing payment records on the inspection (including
payment.type,payment.status, and PACisn.orderStatus/ funded signals), reusing buckets already defined for PAC inpacIsnFlexFundStatuses.tswhere possible. - Relationship to Paid — Keep existing Paid condition; add payment condition as a separate, more specific attribute rather than breaking current flows in v1.
- Attribute shape — Single inspection-level primary payment condition enum (not multiple concurrent values per job).
- v1 enum catalog — Ship the full set of lifecycle values (using values that will be understandable to internal users) in v1:
unpaidpending_agreement(PAC unsigned)due_at_closing(PAC signed, not yet funded)funded/collectedcard_pendingandcard_settled(distinct values)ach_pendingandach_settled(distinct values)backup_card_path/closing_fell_throughkicked_back/ terminal failurecanceledrefunded
- Operator-facing labels — Condition picker and worklist filter labels stay internal/operator-facing; do not wait on or align with client portal PAC wording (ATT-1818).
Open
- Partial payments — How should the primary payment condition resolve when the job has a partial card payment plus remaining balance?
- Condition builder UX — New dedicated attribute (e.g. Payment condition) vs re-enabling commented
paymentkeys inconditionalKeys— which pattern should the builder use? - Triggers vs conditions — ATT-86 (Done) added PAC-specific event triggers (
pac_agreement_signed, etc.). Confirm this issue covers state conditions only and does not duplicate trigger work.
Scope
Backend (attik-backend)
- Condition evaluation —
src/util/functions/actionFlows/attributePathResolver.tsandconditionsResolver.ts: add resolver for primary payment condition derived from populated inspection payments. - Worklist filtering —
src/routes/worklist.ts(buildMongoCondition): register the new attribute and map it to a queryable field (or derived filter strategy) alongside existingpaid,totalPaid,remainingBalance. - PAC status buckets —
src/util/functions/payments/pacIsnFlexFundStatuses.ts(PAC_PENDING_STATUSES,PAC_SUCCESS_STATUSES,PAC_BACKUP_CARD_OR_CHARGE_FAILURE_STATUSES,PAC_BUSINESS_UNWIND_FAILED_STATUSES,PAC_CANCELED_STATUSES,mapPACToStatus) as reference for mapping ISN states to condition values. - Paid semantics context —
syncTotalsOnInspection/inspection.paidbehavior documented intests/integration/inspection.paidSemantics.test.ts(ATT-1718); new attribute must not assumepaidequals collectible state. - Flow population — Ensure
FullPopulatedDataForFlowincludes payment fields needed for evaluation when flows run.
Frontend (attik-frontend)
- Condition builder —
src/components/conditions/templatingData.ts: register new payment-condition attribute ininspectionTemplateKeys/conditionalKeys(and backend mirror inbackendTemplatingData.tsif required for parity). - Worklist conditions — Expose the same attribute in worklist condition UI (
Conditions.tsx/ worklist builder) for inspection worklists. - Operator labels — Use clear staff-facing labels for each enum value (internal wording, not client portal copy).
Out of scope (unless product expands)
- Quote flows and quote worklists.
- Client-facing PAC status/fee wording (ATT-1818).
- New PAC webhook event types or email templates (ATT-86 pattern).
- Changing
inspection.paidsemantics again (ATT-1718 — Done). - To be invoiced condition (ATT-1694) — related but separate attribute.
References
- Paid semantics (Done): ATT-1718
- PAC client copy (separate): ATT-1818
- PAC flow triggers (Done): ATT-86
- Key files:
attik-backend/src/util/functions/actionFlows/attributePathResolver.ts,attik-backend/src/routes/worklist.ts,attik-backend/src/util/functions/payments/pacIsnFlexFundStatuses.ts,attik-frontend/src/components/conditions/templatingData.ts