Files
baya-monorepo/product/business-requirements.md
T
2026-06-21 00:05:07 +03:30

48 KiB
Raw Blame History

Balinyaar — Business Requirements

Purpose. This document specifies the business requirements for Balinyaar, an MVP home-nursing marketplace in Iran where independent, individually-verified nurses list configurable services, families search and request a nurse, the nurse accepts, the family pays through the platform, the platform holds the money as an internal escrow ledger state, the nurse performs one or more visits with Electronic Visit Verification (EVV) check-in/out, and the platform pays the nurse weekly minus a commission. It is grounded in the verified payment/settlement research, the adversarial fact-checks, the database-model critiques, and the market/legal/verification research. It is written to be an MVP that is decisive but not naive about Iranian payment law, tax, and the realities of caring for vulnerable people at home. All monetary values are in IRR (Rials); Toman is a display concern only and is converted to/from Rials solely at an external provider's API boundary.

Date: 2026-06-20


How to read this document

Each section covers one business area and states, in order:

  • (a) Business requirements — what the platform must do.
  • (b) Iran-specific considerations — the local legal, fiscal, cultural, and infrastructural realities that shape the requirement.
  • (c) MVP vs DEFERRED — an explicit callout of what ships at launch and what is intentionally postponed.
  • (d) Supporting database entities — the entities (using the final names from the refined data model) that implement the requirement.

Cross-cutting ground truths (true in every section):

  1. Balinyaar cannot legally custody customer cash. Under Iranian rules a پرداخت‌یار (payment facilitator) is forbidden from holding deposits, running wallets, or moving money between merchants. Money always flows card → licensed PSP → Shaparak settlement → bank-registered IBANs. "Escrow" is therefore an internal ledger state over funds custodied at a licensed provider/partner bank — never a Balinyaar-owned cash balance. (ledger_entries)
  2. VAT is 10%, not 9% — it rose from 9% to 10% in 1403 (7% government + 3% municipal) and is treated as a configurable rate.
  3. BNPL is full-upfront. A BNPL provider settles one full-amount lump (net of its commission) to the merchant-of-record, bears 100% of customer-default risk, and owns the customer's installment repayment entirely. A BNPL order behaves in Balinyaar's books exactly like a card payment landing net-of-fee. (bnpl_transactions)
  4. The nurse is paid by Balinyaar, weekly, on Balinyaar's own schedule — gated on EVV completion and a closed dispute window — regardless of how the family paid.

1. Actors & Onboarding

(a) Business requirements

  • Three actor types: customer (the family member / payer), nurse (the independent caregiver / seller), and admin (Balinyaar back-office staff: support, finance, moderation, super-admin).
  • Phone number is the primary login credential. Authentication is phone-OTP (one-time code by SMS). Email is optional/secondary (required only for admin accounts).
  • The patient (care recipient) is a first-class entity distinct from the customer, because the payer (an adult child, a spouse) is frequently not the patient (an elderly parent, a newborn, a post-surgical adult). A customer may register multiple patients.
  • KYC timing is role- and risk-staged, not up-front-for-everyone:
    • A customer can register and browse with only a verified phone (OTP). National-ID KYC for customers is anti-fraud only and is deferred at launch.
    • A nurse must complete the full verification pipeline (Section 2) before any of their service variants become bookable. national_id is populated only after the identity step passes.
    • An admin is provisioned internally with RBAC roles.
  • Each successful login creates a refresh-token session that can be revoked (logout, stolen-token detection).

(b) Iran-specific considerations

  • Phone-OTP is the dominant Iranian login norm and is also the anchor for Shahkar SIM↔national-ID binding (Section 2).
  • Storing national_id only post-KYC matches the reality that identity is verified through gated vendor APIs, not collected casually at signup.
  • Cultural reality: the booking flow must let a family member act on behalf of a patient who cannot self-advocate (infant, dementia, post-anesthesia). The customer/patient split is essential, not cosmetic.

(c) MVP vs DEFERRED

  • MVP: phone-OTP login; customer/nurse/admin roles; customer→patient (1:N); session management; admin RBAC; nurse onboarding gated on verification.
  • DEFERRED: customer national-ID KYC (customer_profiles.national_id_verified_at exists but is optional/unused at launch); push notifications; social login; nursing-company (organization) self-onboarding.

(d) Supporting database entities

users, user_sessions, roles, user_roles, nurse_profiles, customer_profiles, patients, customer_addresses.


2. Nurse Verification & Credentials

(a) Business requirements

Verified trust is the entire brand. Vetting is platform-owned, non-optional, and performed at the authoritative source — never delegated to families, and never marketed as a check the platform does not actually perform. A nurse is bookable only after all required verification steps pass.

The pipeline is data-driven: the set of steps lives as rows in verification_step_types (not a code enum), so a new regulatory requirement (e.g., professional liability insurance) is one INSERT, not a migration. Each step can be automated (a KYC vendor API call) or manual (admin reviews an uploaded document). The aggregate nurse_verifications record rolls the step outcomes into a single status; nurse_profiles.is_verified flips to true only inside the same transaction that confirms every required step is passed.

The verification steps:

  1. Identity (KYC) — automated. Match person ↔ کد ملی (national ID) ↔ phone ↔ face via one Iranian KYC vendor: national-ID validity/name match + photo/video liveness against the national-card / civil-registry (ثبت احوال) photo. Binds the profile to a real identity and a liveness selfie to defeat the stolen-identity / alias fraud pattern.
  2. Shahkar phone↔national-id binding — automated. Confirm the login SIM is registered to the nurse's own کد ملی. The binding result (when, which vendor, the reference) is recorded, and re-verification is triggered on phone change. The shared-SIM failure mode (a SIM owned by a family member) is an explicit, handled state, not an undefined edge case.
  3. MoH پروانه صلاحیت حرفه‌ای (professional-competency license) — the single most important credential. It is the MoH-mandated license for in-home nursing and already bundles the criminal-record (سوء پیشینه) screen plus scientific/ethical/health vetting. Verified against the MoH source (Rn.behdasht.gov.ir). No public B2B API exists, so the realistic method at launch is nurse-uploaded document + manual admin verification against the official record.
  4. نظام پرستاری (Iranian Nursing Organization / INO) membership — cross-check. The INO membership number is captured and cross-checked (ino.ir) as a second source. Manual at launch.
  5. عدم سوء پیشینه (criminal-record certificate). Consent-gated to the individual (obtained by the nurse via adliran.ir / their own ثنا password); no company/employer API exists. The nurse uploads it; it is time-limited — on expiry the step reverts to pending and a support alert is raised. Partly covered already by credential #3.
  6. IBAN ownership verification. The payout IBAN (Sheba) must be proven to belong to the verified nurse — the account-holder national ID must equal the verified nurse national ID. Done via automated IBAN-ownership inquiry (استعلام شبا) where available, gating the first payout, not merely an admin eyeballing the number. Prevents paying a nurse's earnings into a third party's account (money-mule risk).

Structured credential registry. Beyond opaque uploaded files, the actual license numbers, issuing authority, holder-name-as-printed, and issue/expiry dates are stored as typed, queryable rows in nurse_credentials. This powers renewal/expiry alerts, the public "verified" trust badge, cross-checking against official portals, and audit defensibility — and survives the future arrival of an MoH/INO API.

Continuous monitoring, not one-and-done: license validity and the criminal-record certificate are periodically re-verified; Shahkar is re-run on phone change. Expiring credentials raise support_alerts.

(b) Iran-specific considerations

  • The license layer is fragmented across regulators (MoH vs INO) and has no public B2B API — manual verification against the official portal is the realistic MVP method; the structured registry makes that defensible and renewable.
  • The criminal-record check is consent-gated to the person and cannot be pulled by a company — hence nurse-uploaded + re-requested periodically, leaning on the MoH license which already embeds it.
  • Identity (Shahkar, liveness, national-ID match) is the easy layer because a competitive market of Iranian e-KYC vendors (Finnotech, U-ID, Jibbit, Farashensa, Verify, Kavoshak) already holds the regulator-gated upstream agreements. Buy this, don't build it.
  • Document forgery is the documented attack (the "imposter nurse" pattern): verify at source, bind to national ID + liveness, never trust an uploaded PDF alone.

(c) MVP vs DEFERRED

  • MVP: all six steps; data-driven verification_step_types; structured nurse_credentials registry; manual MoH/INO verification; nurse-uploaded عدم سوء پیشینه with expiry; automated identity + Shahkar + IBAN-ownership via one KYC vendor; expiry-driven re-verification alerts; transactional is_verified.
  • DEFERRED: automated MoH/INO license lookup (pending a B2B API); ML-driven fraud scoring (fraud_flags is modeled but inactive); professional-liability-insurance step (addable as a row when required).

(d) Supporting database entities

nurse_verifications, verification_step_types, verification_steps, verification_documents, nurse_credentials (structured license registry), nurse_bank_accounts (IBAN ownership), support_alerts (expiry/renewal), audit_logs.


3. Service Catalog & Pricing

(a) Business requirements

  • Admin defines the catalog skeleton: top-level service categories (e.g., مراقبت از سالمند / Elderly Care, مراقبت پس از جراحی / Post-Surgery Recovery, مراقبت از نوزاد / Infant Care, مدیریت بیماری مزمن / Chronic Illness Management) and configurable option dimensions as admin-managed option groups (e.g., تعداد بیمار / patient count, نوع شیفت / shift type) each with concrete option values (e.g., ۱ نفر, ۲ نفر, شبانه‌روزی). Admin can add new dimensions without a schema change.
  • Each nurse defines their own offerings as variants. A variant is the atomic bookable unit: a category + a chosen combination of option values + the nurse's own price and price unit. A nurse may have many variants per category, one per combination they choose to offer and price independently.
  • Price units must support the real shapes of home nursing: per_hour, per_session, per_half_day, per_day, and per_24h (شبانه‌روزی / live-in). For hourly variants an estimated duration helps the customer estimate total cost.
  • The variant display_name auto-generates from option labels but is nurse-editable. Nurses can deactivate (not delete) a variant; deactivated variants cannot be booked.
  • Catalog and prices are snapshotted onto the booking at booking time (variant_snapshot_json) so historical records survive later edits.

(b) Iran-specific considerations

  • Iranian competitors sell exactly these shapes — hourly / daily / 24-hour (شبانه‌روزی) shifts and multi-day packages — so per_24h and per_day are first-class, not edge cases.
  • Competitor pricing is opaque and "توافقی" (negotiable); transparent, upfront, nurse-set pricing is a deliberate differentiator families value.
  • All catalog tables carry name_fa / name_en pairs (Persian primary).

(c) MVP vs DEFERRED

  • MVP: admin categories + option groups/values; nurse variants with own price + price unit across all five units; activate/deactivate; snapshotting.
  • DEFERRED: holiday/surge pricing rules; a lighter "companionship / daily-living" tier (modeled as a future category); dynamic/tiered commission per category.

(d) Supporting database entities

service_categories, service_option_groups, service_option_values, nurse_service_variants (carries price, price_unit), nurse_service_variant_options.


4. Search & Matching

(a) Business requirements

  • Families search by service category, geography (city, and optionally district), price, and availability, with results sortable by rating.
  • Geography is driven by nurse-declared service areas: a nurse covers one or more cities, optionally specific districts; a city-level row (no district) means the whole city.
  • Search must be cheap from day one. The naive query joins nurse profile (verified + accepting) → variants (category/price) → variant options → service areas → rating across 4+ tables. Instead a denormalized nurse_search_index holds one flat row per active, bookable variant with all search-relevant fields, maintained on write. A row exists only when the nurse is is_verified and not suspended and the variant is_active. This is far cheaper than introducing Elasticsearch at MVP stage.
  • Same-gender caregiver matching is a first-class filter and a near-hard requirement: in Iranian bodily-care (bathing, toileting, intimate post-surgical care) same-gender caregiving is culturally decisive, not optional. The customer specifies a required caregiver gender on the booking request (required_caregiver_gender), and nurse gender is an exposed search filter so families can narrow to same-gender caregivers up front. The patient's gender (patients.gender) and the nurse's gender support this matching.

(b) Iran-specific considerations

  • District granularity varies: in Tehran, districts map to the 22 official municipal مناطق; in smaller cities they are major neighborhoods. Districts are optional.
  • Same-gender matching is the single most Iran-specific matching constraint — every real elder/post-surgical bodily-care request implies it. It must be surfaced before booking, not discovered after.
  • White-space opportunity: incumbents concentrate ~99% in Tehran/Karaj; the search/area model must work for under-served second-tier cities (Mashhad, Isfahan, Shiraz, Tabriz, Ahvaz, Qom).

(c) MVP vs DEFERRED

  • MVP: category + city/district geo search; nurse_search_index denormalization; same-gender filter via required_caregiver_gender; rating sort.
  • DEFERRED: map-based discovery; availability-window filtering as a hard constraint (availability slots are soft guidance at launch); algorithmic ranking beyond rating; continuity-of-carer "preferred nurse" suggestions.

(d) Supporting database entities

nurse_service_areas, cities, districts, nurse_search_index, nurse_service_variants, nurse_profiles (rating, gender via users), patients.gender; booking_requests.required_caregiver_gender (the requested constraint).


5. Booking & Scheduling

(a) Business requirements

The lifecycle has two phases separated into two tables so each table's invariants stay clean: a request phase (no money) and a booking phase (always implies captured payment).

Request → accept → pay → confirm lifecycle:

  1. Customer submits a booking request (nurse, patient, variant, address, date/time, requested caregiver gender, customer notes). Status pending_nurse_response.
  2. The nurse must respond before a response deadline (nurse_response_deadline_at, computed from config and frozen on the request). The nurse acceptsaccepted_awaiting_payment, or rejectsrejected_by_nurse, or the deadline passes → expired_no_response.
  3. On accept, a 30-minute payment window opens (payment_deadline_at). The customer pays within it → a bookings row is created (confirmed). If the window lapses → payment_deadline_expired.

Single-visit AND multi-session / long-duration engagements must both be representable. Home nursing is frequently multi-visit: post-surgery daily visits for ten days, month-long nightly or شبانه‌روزی (24h live-in) care. A booking therefore carries a session_count and owns N booking_sessions (one row per scheduled visit), each with its own schedule, its own EVV check-in/out, and its own payout eligibility. A single EVV per booking cannot represent a multi-day engagement, so the engagement-to-session split is the core scheduling model.

Booking lifecycle: pending_paymentconfirmed (payment captured) → in_progress (first/relevant session check-in) → completed (sessions checked out) → optionally disputedclosed; or cancelled before service. Allowed transitions are guarded explicitly so the booking and EVV state machines cannot silently contradict.

Snapshots: variant_snapshot_json and address_snapshot_json freeze the service and address at booking time.

(b) Iran-specific considerations

  • Multi-session and شبانه‌روزی live-in care is the dominant elder-care shape in Iran, not a niche — modeling only single visits would fail to represent demand.
  • Heavy platform control over multi-visit scheduling strengthens a worker-misclassification argument under labor law; this is flagged for counsel, and the platform deliberately keeps the nurse's accept/reject autonomy per request.
  • Availability slots/exceptions are soft guidance only (informing search), not hard blocks — the nurse still individually accepts or rejects each request, which also fits the Shamsi week and holiday rhythm.

(c) MVP vs DEFERRED

  • MVP: request→accept→pay→confirm lifecycle with response deadline + 30-min payment window; single-visit bookings; booking_sessions for multi-session/long-duration engagements with per-session EVV and payout; explicit status-transition guards; snapshots; soft availability slots/exceptions.
  • DEFERRED: open-ended recurring schedules (recurring_booking_schedules modeled, inactive — launch is all finite engagements); milestone/progress-payment UX beyond per-session accrual; hard availability-based booking blocks.

(d) Supporting database entities

booking_requests (carries nurse_response_deadline_at, payment_deadline_at, required_caregiver_gender), bookings (carries session_count, dispute_window_ends_at, fee split), booking_sessions, booking_care_instructions, nurse_availability_slots, nurse_availability_exceptions, nurse_service_variants, patients, customer_addresses.


6. EVV / Service Delivery

(a) Business requirements

  • Electronic Visit Verification (EVV) is the authoritative record that a visit actually happened, for how long, and where. The nurse clocks in and out via the app per session, capturing GPS coordinates and timestamps.
  • An address-match tolerance check computes whether the nurse's GPS at check-in falls within an acceptable radius of the booking address (evv_location_tolerance_meters). A mismatch is advisory — it raises a support alert / review flag but does not auto-cancel; it does not silently block the visit.
  • If the nurse has not checked in by a configurable threshold after the scheduled start, a no-show / late support alert is created and the family is notified.
  • Payout is gated on EVV completion. A session/booking becomes payout-eligible only after EVV check-out and the dispute window has closed (Section 10). EVV completion is the trigger that lets the booking enter the next weekly payout batch; for a multi-session engagement, payout accrues per completed session.

(b) Iran-specific considerations

  • EVV is the core operational-trust mitigation for unobserved in-home care of vulnerable patients who often cannot reliably report what happened (infants, dementia, post-anesthesia) — the platform compensates for unobservability with structured proof of service.
  • Releasing escrow against proof of service is also a financial-correctness requirement under the Iranian "hold then pay weekly" model — the platform must not pay a nurse for a visit that has no EVV evidence.

(c) MVP vs DEFERRED

  • MVP: per-session GPS check-in/out, timestamps, address-match tolerance flag, no-show alerting, payout gated on EVV completion + closed dispute window.
  • DEFERRED: continuous geofencing during a live-in shift; supervisory tele-check-ins; family-visible live care logs; consented in-home cameras.

(d) Supporting database entities

visit_verifications (per session, with check-in/out GPS, timestamps, check_in_address_match, status), booking_sessions, support_alerts (no-show / location-mismatch), platform_configs (evv_location_tolerance_meters).


7. Cancellation & Refunds

(a) Business requirements

  • Cancellation/refund rules are tiered and structured, not a single blunt "default 100%". The platform defines cancellation_policies tiers by lead time and initiating actor:
    • Free cancellation more than 24h before start.
    • Partial refund (e.g., 50%) under 24h.
    • Customer no-show: up to 100% charge.
    • Nurse no-show: full refund to the customer and a penalty/forfeiture for the nurse.
  • The applicable policy is snapshotted onto the booking at booking time (mirroring the per-booking fee-rate snapshot), so later policy edits never rewrite history. The resolved cancellation fee / refund percentage is recorded on the refund event.
  • For multi-session engagements, cancellation is per remaining session: cancelling mid-engagement refunds only the un-started sessions, while completed-and-verified sessions remain payout-eligible.
  • Refunds are admin-only — there is no customer self-service refund. A refund is initiated by an admin and must be linked to a support ticket (tickets) that holds the conversation and dispute evidence.
  • A refund decomposes across the two fee legs — how much of the platform commission and how much of the nurse payout is being reversed — because the booking gross is platform commission + nurse payout.

(b) Iran-specific considerations

  • A flat percentage is too blunt for شبانه‌روزی live-in engagements and Iranian holiday-period bookings; tiered, snapshotted policy reduces dispute load.
  • The refund money path depends on whether the nurse has already been paid (Section 8/10): pre-payout it is a clean reversal; post-payout it becomes a platform-funded refund plus a nurse clawback, because an Iranian bank transfer to a nurse's IBAN is effectively irreversible.
  • For BNPL bookings, the refund never goes nurse→customer or Balinyaar→customer directly — it is initiated through the BNPL provider's revert/cancel API (Section 8/9).

(c) MVP vs DEFERRED

  • MVP: tiered cancellation_policies; per-booking policy snapshot; admin-only, ticket-linked refunds; per-session cancellation for engagements; nurse-no-show vs customer-no-show handling; fee-leg decomposition on refunds.
  • DEFERRED: automated nurse no-show penalty (manual admin action at launch); self-service partial-refund UI; holiday-specific cancellation overrides.

(d) Supporting database entities

cancellation_policies, bookings (policy snapshot, dispute_window_ends_at), refunds (admin-only, ticket_id, fee-leg decomposition, refund_channel), tickets, nurse_clawbacks (post-payout case), ledger_entries.


8. Payments & Escrow

(a) Business requirements

  • The family pays the gross booking price through the platform by card via a licensed PSP's IPG. The platform is the merchant-of-record; the payment lands net of provider/Shaparak fees.
  • Escrow is an internal ledger state, not platform-held cash. The platform models money state with a minimal double-entry ledger_entries ledger: each money event posts balanced legs grouped by a transaction group. Account types: escrow_held, platform_revenue, nurse_payable, refund_payable, bnpl_fee_expense, nurse_clawback_receivable. The ledger is the single source of truth for "how much is held," "how much do we owe nurses now," and "what is our commission income" — replacing fragile inference from scattered status booleans.
    • On a successful card payment: debit escrow_held (gross), credit platform_revenue (Balinyaar commission), credit nurse_payable (nurse payout).
  • Settlement-sharing (تسهیم). The compliant marketplace primitive is splitting one incoming card payment across multiple registered IBANs (the nurse's share and the platform's commission) at settlement, performed by Shaparak/the provider — the platform never touches the actual split. The internal ledger mirrors this split; the per-booking fee snapshot freezes it.
  • Per-booking the three amounts are stored separately and never conflated: gross_price_irr (what the customer is charged), balinyaar_commission_irr (platform's cut — drives the nurse payout), and (for BNPL) bnpl_commission_irr (the provider's merchant discount — a platform expense). nurse_payout_amount = gross_price_irr balinyaar_commission_irr.
  • Webhook idempotency is mandatory before money moves. Every PSP/BNPL callback is stored raw and deduplicated by a unique external event id in payment_webhook_events before any money state mutates — preventing double-confirmed bookings and double-settlements from at-least-once, retried callbacks.
  • Payment uniqueness: at most one succeeded payment transaction per booking, and the Shaparak reference is unique — enforced so a retried success webhook cannot double-confirm.
  • Multi-provider failover. Provider settlement cut-offs are a real continuity risk (the Toman/Jibit Nov-2024 suspensions cut businesses off mid-cycle). The payment layer abstracts the provider behind configuration so a blocked provider can be swapped, and the reconciliation ledger survives a provider being cut off.

(b) Iran-specific considerations

  • The load-bearing legal constraint: a پرداخت‌یار may not hold customer deposits, run wallets, or move money between merchants; the Shaparak ban on inter-merchant/inter-facilitator transfers means the "delay the تسهیم and redistribute later from a platform pool" pattern is regulatory grey-to-prohibited. The compliant posture is: collect via the provider, model escrow as an internal ledger over funds custodied at the licensed provider/partner bank, and pay out by provider-side settlement to verified, registered nurse IBANs. A bank-grade escrow product (e.g., Vandar میندو / معاملات امن) is the only true hold/release/refund mechanism, and its EVV-triggered hold is unverified — so the platform never assumes it can lawfully custody the cash itself.
  • PSP received ≠ cash in bank. Iranian PAYA settlement is cyclic (T+0/T+1, holiday-deferred), so the ledger separates a clearing/receivable state from settled cash, making bank reconciliation possible.
  • Toman/PSP units differ from internal Rials; convert only at the API boundary. Amounts are BIGINT IRR internally to avoid float/rounding bugs.

(c) MVP vs DEFERRED

  • MVP: card payment via one licensed PSP; internal double-entry ledger_entries escrow; per-booking three-way amount split; تسهیم-style commission/nurse-share modeling; payment_webhook_events idempotency; single-succeeded-transaction-per-booking guard; provider abstraction for failover.
  • DEFERRED: a nurse-facing wallet with on-demand withdrawal (facilitator wallet prohibition risk); multiple simultaneous live PSPs at launch (abstraction is built, second provider added later); bank-grade EVV-triggered escrow product integration.

(d) Supporting database entities

payment_gateways, payment_transactions (unique Shaparak ref, single-succeeded-per-booking), payment_webhook_events, ledger_entries, bookings (gross_price_irr, balinyaar_commission_irr, platform_fee_rate, nurse_payout_amount), refunds, nurse_bank_accounts (verified registered IBANs).


9. Installments / BNPL

(a) Business requirements

  • BNPL is offered as an alternative checkout. The decisive, verified model is full-upfront settlement: on approval the BNPL provider pays Balinyaar the full booking amount in one lump, net of the provider's merchant commission, and bears 100% of customer-default risk. The customer's interest-free installment repayment (typically a 4-installment plan) is owned entirely by the provider and is decoupled from Balinyaar's escrow/EVV/payout cycle.
  • Therefore a BNPL order is, in Balinyaar's books, identical to a card payment that lands net-of-fee in one inbound settlement. Balinyaar does NOT track customer installments, per-installment webhooks, or default propagation — that fragile subsystem is intentionally not built.
  • A BNPL order is recorded once as a single inbound settlement in bnpl_transactions (1:1 with a payment transaction), capturing the provider, the merchant-of-record (Balinyaar), the external payment token / transaction id, order_amount_irr, settled_amount_irr (net of provider commission), bnpl_commission_irr, currency (converted at the boundary), an idempotent status state-machine (eligible/token_issued/verified/settled/reverted/cancelled/failed), installment_count (informational, default 4), settled_at, and the revert fields.
  • BNPL refunds flow only customer ↔ provider ↔ Balinyaar — never nurse→customer or Balinyaar→customer directly. Balinyaar initiates the reversal via the provider's revert (full) / cancel/update (partial, new amount strictly lower) API using the stored token; the provider cancels the customer's unpaid installments, restores their credit, and refunds any already-paid installment to the customer's bank in ~710 business days (asynchronous, owned by the provider). The refund still decomposes across the platform-fee and nurse-payout legs in Balinyaar's ledger.
  • The nurse's payout is unchanged by BNPL: computed from gross_price_irr balinyaar_commission_irr, paid weekly after EVV + dispute window — the provider's commission is a platform cost of accepting BNPL and is never passed through to the nurse.

This is a summary. Deep BNPL provider mechanics, the exact revert/cancel/settle API flows, commission-as-config, settlement-timing nuances, and provider-specific behavior are specified in payments-and-installments.md — cross-reference it for implementation detail.

(b) Iran-specific considerations

  • Provider-financed Iranian BNPLs (SnappPay, Digipay, Tara, Torob Pay) are uniformly full-upfront, provider-bears-risk, interest-free-to-customer; only bank-financed POS loans (Lendo) charge the customer interest and are a poor fit for short, cancellable nursing visits.
  • Settlement timing is contract-defined and may be gated on the customer's first installment (daily / T+1-3 / weekly / 15-day) — "full amount" does not mean "instant cash." Timing is config + a per-transaction settled_at; weekly nurse payout may key off settlement actually received, never an assumption.
  • Commission rate is per-contract and not public (anecdotal 715% for SnappPay; Torob Pay's published 6.6%) — always a config field read from the actual settlement, never hardcoded.
  • Onboarding requires جواز کسب and اینماد for the Balinyaar/partner entity, and whether a multi-vendor re-disbursing marketplace qualifies as a single BNPL merchant is publicly undocumented — an ops/contracting task, not a schema dependency.

(c) MVP vs DEFERRED

  • MVP: full-upfront BNPL via one provider modeled as a single inbound settlement (bnpl_transactions); provider-mediated revert/cancel refunds; nurse payout decoupled from BNPL; commission + settlement timing as config.
  • DEFERRED: customer installment tracking (installment_entriescut, owned by the provider); tranched settlement (bnpl_settlement_entries modeled-only, added if a future provider tranches); multiple BNPL providers.

(d) Supporting database entities

bnpl_transactions (replaces the old installment_plans; the old installment_entries is cut), payment_transactions, payment_webhook_events, refunds (refund_channel = 'bnpl_revert', external_revert_reference, expected_customer_refund_eta), ledger_entries. See payments-and-installments.md.


10. Payouts to Nurses

(a) Business requirements

  • Nurses are paid in weekly batches. A batch aggregates the amounts owed for completed, payout-eligible bookings/sessions and produces one payout per nurse with earnings in that window.
  • Payout eligibility is gated on EVV completion AND a closed dispute window. A booking/session enters a batch only when status = 'completed' AND dispute_window_ends_at < now() (the dispute window is config-driven, default 72h post-completion). This deliberately prevents paying a nurse before a dispute can surface, shrinking clawback frequency — important because an Iranian bank transfer, once sent, is effectively irreversible.
  • The nurse payout amount derives from gross_price_irr balinyaar_commission_irr (never from a BNPL provider's net settlement).
  • Clawbacks (nurse_clawbacks) handle the refund-after-payout case: if a booking is refunded/disputed after the nurse was already paid, a clawback receivable is recorded (negative ledger entry against the nurse) and recovered by netting against the nurse's next weekly batch, or written off if uncollectable. The nurse's payable balance is derived from the ledger (it may go negative), and a batch can net prior clawbacks (gross_earnings, clawback_applied, net_amount).
  • Each booking is paid at most once (the payout↔booking link is unique), preventing double-pay across batches.
  • Bank-holiday-aware scheduling. Payout period-end and processing dates are shifted off bank-closed days using a shared iranian_holidays calendar — a weekly payout landing on a multi-day Nowruz closure would otherwise fail, since PAYA/SATNA transfers do not settle on closed days.
  • Payouts go to the nurse's verified, registered primary IBAN, with the IBAN snapshotted and a transfer reference stored for reconciliation. Each payout item carries a unique track id + (for batches) a batch id.

(b) Iran-specific considerations

  • Payouts are real bank transfers to registered IBANs (PAYA/SATNA cycles, next-business-day on holidays) — there is no chargeback-style reversal, which is why the dispute window must close before payout and why clawback is a netting/receivable mechanism rather than an automatic reversal.
  • Provider settlement cut-offs (Toman/Jibit) mean payout must tolerate a provider being unavailable mid-cycle; the batch + reconciliation references survive a swap.
  • Each nurse must have a Shahkar/KYC-verified, IBAN-ownership-checked account registered as a beneficiary before any payout targets it.

(c) MVP vs DEFERRED

  • MVP: weekly batches; EVV + dispute-window gating; per-session accrual for engagements; nurse_clawbacks with next-batch netting and write-off; unique booking↔payout link; iranian_holidays-aware scheduling; verified-IBAN payouts with reconciliation references.
  • DEFERRED: on-demand / instant nurse withdrawal; per-nurse configurable payout frequency; automated clawback recovery beyond netting.

(d) Supporting database entities

nurse_payout_batches, nurse_payouts (with gross_earnings_irr, clawback_applied_irr, net_amount_irr, iban_snapshot), nurse_payout_booking_links (unique per booking), nurse_clawbacks, ledger_entries, iranian_holidays, bookings.dispute_window_ends_at, nurse_bank_accounts.


11. Reviews, Trust & Safety

(a) Business requirements

  • A customer can leave one review per completed booking (rating 15 + free text), tied to a verified, completed, on-platform booking.
  • Moderation: reviews enter pending_moderation and are not public until approved by an admin (or an AI moderator). Aggregate nurse rating/counts are recomputed on every review status transition — publish, hide, reject, unpublish — so hiding a 1-star review never leaves a stale, inflated average.
  • Low-rating alerting: a rating at or below a configurable threshold (default ≤ 2) with negative content automatically raises a support_alerts row for the support team to investigate.
  • Incident handling: rapid-response protocols with immediate suspension on credible complaints; structured family check-ins and easy in-app concern flagging (the patient is not the sole information source); high-acuity cases routed only to appropriately verified nurses.

(b) Iran-specific considerations

  • The buyers are vulnerable people cared for unobserved at home; a single incident can destroy a fragile, trust-first brand — so moderation, low-rating alerting, and immediate suspension are core, not optional.
  • Verified-trust is the brand; reviews must be bound to real completed bookings to resist fake-review fraud (gig-marketplace fraud is ~2× elsewhere, mostly impersonation).

(c) MVP vs DEFERRED

  • MVP: one-per-completed-booking customer reviews; moderation with full recompute-on-every-transition; low-rating support_alerts; manual incident suspension.
  • DEFERRED: two-way (nurse-reviews-customer) double-blind reviews with timed reveal; structured review-tag aggregation (review_tags_master / review_tag_links modeled but a phase-2 nicety); a dedicated incidents entity; ML fraud scoring.

(d) Supporting database entities

reviews (moderation status, recompute triggers), review_tags_master, review_tag_links, support_alerts (low-rating, fraud-signal), nurse_profiles (denormalized aggregates), audit_logs.


12. Messaging & On-Site Emergencies

(a) Business requirements

  • There is no live chat and no direct nurse↔customer messaging. All post-booking communication runs through a structured ticket system that admin can read in full. This is a deliberate anti-disintermediation and patient-safety design: it protects vulnerable patients, creates a dispute paper trail, and prevents families and nurses pairing off-platform.
  • A booking-scoped coordination ticket is auto-created so the nurse and customer can coordinate logistics (arrival time, room location) under admin visibility. Internal admin-only notes are supported and never shown to users.
  • Tickets also carry refund conversations and any support request, and are the mandatory anchor for admin refunds (Section 7).
  • On-site emergency playbook. The ticket system is async and has no real-time channel, so the operational playbook is explicit: in an emergency (no answer at the door, a medical emergency), the nurse calls the emergency-contact number surfaced in the app, then opens a ticket. The emergency contact number is surfaced prominently in the booking UI (drawn from encrypted care instructions), so a nurse never needs to find the family's number by other means (which would break the platform's communication control).

(b) Iran-specific considerations

  • Disintermediation is the predictable failure mode of recurring, relationship-based care; the ticket-only model retains value (escrow, dispute protection, backup coverage, insurance that only applies on-platform) instead of relying on punitive lock-in.
  • For unobserved in-home care of patients who cannot self-report, the controlled-but-auditable communication channel plus a clear emergency escalation path is a safety requirement.

(c) MVP vs DEFERRED

  • MVP: ticket-only messaging (admin-readable); auto-created booking-coordination ticket; internal notes; prominent in-app emergency contact + documented playbook.
  • DEFERRED: real-time chat; a first-class incidents/emergency-event entity with SLA; push/real-time alerting.

(d) Supporting database entities

tickets, ticket_participants, ticket_messages, booking_care_instructions (encrypted emergency contact), support_alerts.


(a) Business requirements

  • The nurse is the taxable seller of the nursing service; Balinyaar is the taxable seller only of its commission. This mirrors the Snapp/Tapsi sharing-economy precedent: the nurse's fee is the nurse's income (the nurse files their own income tax — out of Balinyaar's scope), and Balinyaar's commission is the company's VAT-relevant revenue.
  • VAT is 10% (configurable), applied to Balinyaar's commission line. The home-nursing service's own VAT treatment is unconfirmed (medical services are commonly exempt) — so the VAT field is config-driven and can be 0/exempt, keeping the model correct whichever way the ruling lands. Confirm with an Iranian tax advisor before launch.
  • سامانه مودیان (taxpayer system) readiness, minimal footprint. The platform produces a minimal invoices record per booking capturing the gross, the platform commission, any BNPL commission, VAT, and a place for the مودیان reference fields (22-digit fiscal number, memory tax id, status) and PDF. The seller issues the invoice (the buyer cannot), so Balinyaar issues only its own commission invoice; it does not issue the nurse's service invoice.
  • e-namad (نماد اعتماد الکترونیکی) is de-facto mandatory: a monetized Iranian site needs e-namad to obtain an online payment gateway from PSP/Shaparak. It is held by the legal launch entity.
  • Partner licensed-center (Asanism-style) as the launch legal vehicle. Home nursing is a licensed healthcare activity (MoH establishment permit پروانه تأسیس + technical-director license پروانه مسئول فنی via the Article-20 commission), in the home-nursing-services-center track (a nurse with BSc + ≥5 yrs experience can found/direct it). The fast, legal go-to-market is to partner with already-licensed centers while Balinyaar's own permit is pending. A partner_centers entity represents the licensed center that holds the جواز کسب + اینماد + MoH license, sponsors nurses, and may be the merchant-of-record / invoice issuer for payments — making BNPL and online payment legally feasible without each nurse holding a license.

(b) Iran-specific considerations

  • Operating without a permit is the real legal risk (penalty ladder up to permanent revocation + judicial referral). The partner-center vehicle is the launch-critical mechanism that makes the whole money flow legal.
  • مودیان obligation phases in by revenue thresholds; most individual nurses fall below mandatory thresholds early, but the platform's commission line is VAT/e-invoice-relevant — so per-nurse مودیان obligation is a configurable flag and the platform's own commission invoicing is the in-scope obligation.
  • The licensed center (not Balinyaar-the-tech-company, initially) is plausibly the IPG merchant-of-record and the invoice issuer — the data model represents this explicitly.

(c) MVP vs DEFERRED

  • MVP: partner_centers as the launch legal vehicle with merchant-of-record flag and nurse sponsorship; minimal per-booking invoices with 10% configurable VAT on commission and مودیان reference fields; e-namad held by the launch entity; nurse-as-taxable-seller / platform-as-commission-seller split.
  • DEFERRED: full مودیان e-invoice automation / digital-signature pipeline; nurse-side service-invoice issuance on the nurse's behalf; insurer/B2B-payor invoicing; the future employer-style organizations model.

(d) Supporting database entities

invoices (minimal, commission-focused, مودیان fields, VAT), partner_centers (MoH license, اینماد, merchant-of-record), nurse_profiles.partner_center_id, payment_transactions (Shaparak reference for reconciliation), platform_configs (VAT rate, merchant-of-record).


14. Notifications & Admin / Backoffice

(a) Business requirements

  • In-app notifications to all user types for booking, payment, payout, review, verification, and alert events. Carried as typed in-app records the front-end fetches on load and uses to deep-link to the relevant entity. No push notifications at launch.
  • A retention job hard-deletes read notifications older than 90 days to keep the table bounded.
  • Admin / backoffice tooling must cover the operational spine:
    • Verification queue — review uploaded MoH/INO/criminal-record documents, record structured credential numbers/expiries, pass/fail steps, and flip is_verified transactionally.
    • Refund tooling — initiate admin-only, ticket-linked refunds with tiered policy application and fee-leg decomposition; for BNPL, trigger the provider revert/cancel.
    • Payout tooling — initiate/inspect weekly batches, see eligibility (EVV + closed dispute window), apply clawback netting, schedule around bank holidays, and reconcile transfer references.
    • Support-alert console — triage low-rating, no-show, location-mismatch, expiry, and fraud-signal alerts.
    • RBAC — admin roles (super_admin / admin / support / finance / moderator) scope who can verify, refund, pay out, and moderate.
  • An append-only audit trail records every state-changing operation on sensitive entities (bookings, payments, refunds, verifications, reviews, users), and config changes (e.g., the platform fee rate) are auditable.

(b) Iran-specific considerations

  • No push at launch reflects a pragmatic MVP and the in-app polling norm; SMS-OTP already covers the critical auth path.
  • Back-office must reason over the Shamsi calendar and iranian_holidays for payout scheduling and deadline computation, and over the verification realities (manual MoH/INO checks, expiry-driven re-verification).
  • High-volume logs (audit_logs, system_events, notifications) need partitioning/retention planned before launch to avoid unbounded growth.

(c) MVP vs DEFERRED

  • MVP: in-app notifications with 90-day retention; admin verification/refund/payout/alert tooling; RBAC; append-only audit_logs; config-change auditing.
  • DEFERRED: push notifications; SMS/email notification channels beyond OTP; a full analytics warehouse (system_events piped out rather than queried in the transactional DB); ML fraud console.

(d) Supporting database entities

notifications, support_alerts, roles, user_roles, audit_logs, system_events, platform_configs, plus the operational entities each tool acts on (nurse_verifications / verification_steps / nurse_credentials, refunds, nurse_payout_batches / nurse_payouts / nurse_clawbacks, bookings).


Appendix — MVP vs Deferred at a glance

Area MVP Deferred
Onboarding phone-OTP; customer/nurse/admin; patient split customer KYC; org self-onboarding; push
Verification 6-step data-driven pipeline; nurse_credentials; IBAN ownership MoH/INO API; liability-insurance step; ML fraud
Catalog admin categories/options; nurse variants & price units holiday/surge pricing; companionship tier
Search geo + category; nurse_search_index; same-gender filter map discovery; availability hard-filter
Booking request→accept→pay→confirm; booking_sessions multi-visit recurring schedules; milestone-payment UX
EVV per-session GPS check-in/out; payout gating geofencing; tele-check-ins; cameras
Cancellation tiered policy + snapshot; admin/ticket refunds; per-session auto no-show penalty; self-service refunds
Payments/Escrow ledger escrow; payment_webhook_events; provider abstraction nurse wallet; multi-PSP live; bank escrow product
BNPL full-upfront bnpl_transactions; provider-revert refunds installment tracking (cut); tranched settlement; multi-provider
Payouts weekly batches; clawbacks; holiday-aware; verified IBAN instant withdrawal; per-nurse frequency
Reviews one-per-booking; moderation; low-rating alerts two-way reviews; tag aggregation; incidents
Messaging ticket-only; coordination ticket; emergency playbook live chat; emergency-event entity
Tax/Legal partner_centers; minimal invoices; 10% VAT on commission; e-namad full مودیان automation; nurse-side invoicing; B2B
Notifications/Admin in-app + retention; verify/refund/payout tooling; RBAC push; analytics warehouse; ML console