Objective
- Stop clients from receiving unpaid / "No Pay" SMS and other automations tied to Paid is false when the work order already shows Pay at Close (PAC) and staff expect payment to be arranged.
- Align action flow behavior with how teams interpret PAC on the payments list vs the job-level Paid flag used by conditions.
Background
- Production example (FHI): Inspection 1008591123 — payment shows PAC, but the client received "No Pay" texts/notifications.
- Symptom: Work order Payments shows Pay at Close (often Paid / Signed on the PAC row from ISN status), while automations keyed on Paid → is false ("order not paid") still run (SMS, email, reminders).
- Root cause (code review):
- Action flow condition Paid is false maps to
inspection.paid(attributePathResolver.ts,conditionsResolver.ts, builder intemplatingData.ts). inspection.paidis set insyncTotalsOnInspection(syncTotalsOnInspections.ts) only when balance ≤ $0.01; pendingpay_at_closepayments contribute $0 tototalPaid.- On inspection payments changes,
inspectionStream.tscallssyncTotalsOnInspectionwithoutawait, then immediatelyflowEventTriggerer('payment_created', …)— flows can evaluatepaid: falseeven right after PAC activity. payment_createdfires when a pending PAC row is created (isnPayments.ts), not only when the job is fully paid.- UI mismatch:
ServicesPayments.tsxcan show PAC as Paid/Signed from payment/ISN status whileinspection.paidremains false; client portal shows Pending Payment untilinspection.paidis true (JobAccordion.tsx).
Steps to reproduce
- Configure an action flow on Payment created (or follow-up/reminders) with condition Paid → is false (unpaid / "No Pay" SMS or email).
- On a job, client selects Pay at Close (FlexFund/ISN) so the work order shows a Pay at Close payment line.
- Observe the flow still runs while
inspection.paidis false (common when PAC is pending, or due to sync timing right after PAC create/complete).
Narrower repro: Client starts PAC → pending payment created → payment_created fires immediately → Paid is false passes → unpaid SMS sent while staff see PAC on the WO.
Scope
Backend (required)
attik-backend/src/events/streamHandlers/inspectionStream.ts— awaitsyncTotalsOnInspectionbefore enqueueingpayment_created(or re-fetch inspection after sync in the flow worker beforeevaluateConditions).attik-backend/src/util/functions/forecast/syncTotalsOnInspections.ts—paid/totalPaidrules for pending vs completed PAC.attik-backend/src/routes/isnPayments.ts— PAC create (pending payment).attik-backend/src/routes/webhooks/flexfund/flexfundWebhook.ts— PAC complete (awaits sync today; stream may still race).attik-backend/src/util/functions/isn/isnPayAtCloseOrderTotal.ts— PAC amount towardtotalPaidwhen completed.attik-backend/src/util/functions/actionFlows/handleEventTriggerdByBull.ts— condition evaluation timing vs populated inspection snapshot.- Product decision needed: Treat pending PAC as "payment arranged" for some conditions (new attribute) or do not fire
payment_createdon pending PAC create — use an event when PAC completes / wheninspection.paidbecomes true. - Tests:
tests/unit/payment.pac.test.tsand flow condition tests — completed PAC →inspection.paid === true→ Paid is false actions filtered; pending PAC behavior matches chosen product rule.
Frontend (supporting / clarity)
attik-frontend/src/components/conditions/templatingData.ts— Paid boolean condition labeling (clarify vs PAC row status).attik-frontend/src/app/tools/inspections/[id]/components/ServicesPayments.tsx— PAC display vs job Paid flag.attik-frontend/src/app/client/job/[slug]/components/JobAccordion.tsx— portal Pending Payment vs Paid chip.
Investigation outcomes (acceptance)
- [ ] On 1008591123 (or clone): confirm PAC pending vs completed,
inspection.paid,remainingBalance, and which flow action (event + Paid is false) sent the "No Pay" SMS. - [ ] Fix: After completed PAC with $0 balance,
inspection.paidis true beforepayment_createdactions evaluate (or those actions do not run for settled PAC). - [ ] Fix: Product rule documented for pending PAC (no unpaid harassment vs intentional reminders).
- [ ] Regression test(s) committed.
References
- Example inspection 1008591123 (FHI)
attik-backend/src/events/streamHandlers/inspectionStream.tsattik-backend/src/util/functions/forecast/syncTotalsOnInspections.tsattik-backend/src/util/functions/actionFlows/attributePathResolver.tsattik-backend/src/routes/isnPayments.tsattik-backend/src/routes/webhooks/flexfund/flexfundWebhook.tsattik-frontend/src/components/conditions/templatingData.ts