P1 batch — webhooks advance state, crons, commerce vertical

Featurekamolos
Shipped
28 Mei 2026, 21:01 UTC
Author
Kamo
Commit
0c59054

Money movement (the core P1): - LoanPaymentPostingService: markSucceededAndPost / markFailed / markReturnedAndReverse / markDisbursementSucceeded / markDrawDisbursed. Allocation order locked: fees → interest → principal. Status auto-advances DELINQUENT ↔ ACTIVE ↔ PAID_OFF based on resulting balance. - StripeWebhookService is no longer log-only: payment_intent.succeeded / payment_failed / charge.refunded (ACH return) / dispute.created+closed / payout.paid+failed all advance the ledger via PostingService. - NachaReturnCode + RetryScheduler: NACHA-compliant R-code routing — R01/R09 retry up to 2× / 5 days apart, R07/R10/R29 revoke the mandate, exhausted retries flip LoanPaymentMethod → REQUIRES_REVERIFY. Commerce-vertical materialization: - **************** now creates Engagement (PERSONAL_LOANS, COMMITTED), Commitment (ACTIVE, with pricing+terms JSON snapshots), Order (AUTHORIZED, subtotal=principal), and threads their IDs back onto Loan.commitmentUid / engagementUid / originatingOrderUid in the same transaction. Cron jobs (real logic, not stubs): - CoolingOffAdvanceJob: enqueues a PENDING DISBURSEMENT_OUT payment for every PENDING_DISBURSEMENT loan whose cooling-off elapsed. - InterestAccrualJob: daily simple-interest accrual on principalBalance for ACTIVE + DELINQUENT loans. - StatementGenerationJob: installment per-due-date statement, LOC per-cycle statement with ADB approximation + annual fee assessment + auto-pay scheduling. - AutoDebitRunJob: fires PENDING auto-debits + DISBURSEMENT_OUT payouts + NACHA retries via StripeConnectService with idempotency keys. - ReconciliationJob: nightly re-sum of fees/principal/balance from the ledger; drift correction logged + audited. - ReminderDispatchJob: pulls SCHEDULED notifications past their scheduledFor and delivers via NotificationDispatchService. Notifications: - **************** real HTTP POST to EmailService (/api/email/transactional/send) and VOIPService (/api/voip/sms/send, /api/voip/voice/send), templateKey = "loan.{kind_lowercase}". Validation: - LoanProductValidationService: enforces APR ≤ state cap (per kind), prohibited-kind checks, min/max-principal sanity. Hooked into LoanProductService.create + update. Charge-off: - LoanChargeOffService.queue() lists D120 loans; .confirm() flips status to CHARGED_OFF and writes a CHARGE_OFF_RECORDED audit event. - LoanChargeOffController exposes **************** Audit browse: - LoanAuditEventController exposes ****************

All changes

Je, unaona nini kuhusu usafiri?

Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.

Kuwa Huru MileleMtazamo wa bei