Subscription Lifecycle
Every subscription carries two independent state machines. They’re deliberately orthogonal — a subscription is routinely “in force” and “not yet paid” at the same time, during its grace period. That’s expected, not an error state.
1. Status — is this period in force?
2. Payment status — has this period been paid for?
Pause / resume — the one contract every trigger follows
Whether a pause is customer-initiated, admin-initiated, or automatic (non-payment), the contract is identical:
No wash is ever silently lost to a pause — it’s either restored or replaced by a makeup slot as part of the top-up.
Incidents — a missed wash always gets a retry
If a cleaner can’t complete a wash (car not found, blocked access, weather, etc.), a makeup wash is automatically created for the next available day (skipping days that already have a wash, and never past the period’s end) — except when the customer explicitly asked to skip that day, which doesn’t trigger a retry.
A wash left SCHEDULED with no cleaner activity past its operating day’s
close (3 PM Cairo the following day) is automatically marked a no-show and
gets the same makeup treatment.