start of manual testing
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,66 @@
|
||||

|
||||
in the login page, the main card has a big border radius number which should be less, and in fact for all papers that should happen
|
||||
|
||||
the options under the main paper should move inside the paper and have a better positioning
|
||||
|
||||
there is no need for the top bar in the login page,
|
||||
the language and theme switch also should be only in the settings, not in every top bar in the app,
|
||||
|
||||
the icon sets should be totally replaced with a more modern icon set, and the icon mappign should be realted.
|
||||
|
||||
the default route should be dynamically deteceted,
|
||||
i mean now whan i open the app and go to /fa or /en
|
||||
it stays there and just a loading is displayed to me but it should be infered based on the user role and navigate the user to the right path
|
||||
and if the
|
||||
|
||||
i get this error when i enter the phone number and submit the form
|
||||
# error start
|
||||
## Error Type
|
||||
Console Error
|
||||
|
||||
## Error Message
|
||||
Functions are not valid as a React child. This may happen if you return transformed instead of <transformed /> from render. Or maybe you meant to call this function rather than return it.
|
||||
<p>{transformed}</p>
|
||||
|
||||
|
||||
at p (<anonymous>:null:null)
|
||||
at OtpStep (src/components/auth/OtpStep.tsx:103:9)
|
||||
at LoginFlow (src/components/auth/LoginFlow.tsx:52:9)
|
||||
at LoginScreen (src/app/[locale]/(public-routes)/login/LoginScreen.tsx:12:7)
|
||||
at Page (src\app\[locale]\(public-routes)\login\page.tsx:12:10)
|
||||
|
||||
## Code Frame
|
||||
101 | {t('otp_title')}
|
||||
102 | </Typography>
|
||||
> 103 | <Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
| ^
|
||||
104 | {t.rich('otp_sent_to', {
|
||||
105 | // <bdi dir="ltr"> isolates the masked number so the RTL sent...
|
||||
106 | // never reorders the digit/bullet runs around it (the classi...
|
||||
|
||||
Next.js version: 16.2.9 (Turbopack)
|
||||
# Error End
|
||||
|
||||

|
||||
after submitting the phone number the otp input ui needs a better spacing, the first two input are stuck together. this is in fa locale, in the en locale its ok.
|
||||
|
||||
|
||||
# nurse dashboard Start
|
||||

|
||||

|
||||

|
||||
|
||||
this dashboard should be totally refactorred,
|
||||
the ui is kinda old and not a modren and with a good ux,
|
||||
some text has not proper placing and some of them are too large,
|
||||
the header and the type of accessing to the dashboard is too old style,
|
||||
there must not be a header like that, and a side drawer, i modern smooth bottom navbar which have only three options ( as the groups of the drawer items are ) and just a forth item for the support and setting.
|
||||
so each of the gropus of the side bar should have a root page which handles the links to the sub pages. and in those root pages its better to have a summary of that domain.
|
||||
two notes:
|
||||
- icons should be changed till here so i don't mention them again
|
||||
- ui have much work to do to be acceptable.
|
||||
|
||||
there is a horizontal scroll in this page, this should not be like that,
|
||||
the whole app should be scoped to a mobile size app, i mean if i scretch the chrome responsive mode, the header and the footer should have a maximum width not to strech and fit to the space
|
||||
no matter what is the device view port, this should be a mobile sized app. all that sidebar in the desktop width is not needed, at least for now, we have to make the app very user friendly with a mobile user mindset
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
# Balinyaar — Manual Testing Plan
|
||||
|
||||
The flow-by-flow walkthrough for testing the whole product against the **seeded lifecycle demo world**.
|
||||
Written after the UI/backend/refinement phase chains completed (2026-07-26). Companion docs:
|
||||
|
||||
- **Bring-up**: [refinement/RUNBOOK.md](refinement/RUNBOOK.md) — how to boot API + client, OTP login mechanics.
|
||||
- **Business rules with numbers**: `product/business/` — what "correct" means; the load-bearing numbers are
|
||||
repeated inline below.
|
||||
|
||||
> **How to use this doc:** pick a flow section, log in as the named account, follow the steps, compare
|
||||
> against *Expected*. Anything marked ⚠ **known gap** is pre-existing and filed (REQ-xxx) — record it as
|
||||
> confirmation, not as a new bug. Anything else that deviates is a genuine finding.
|
||||
|
||||
---
|
||||
|
||||
## 1. Environment
|
||||
|
||||
| Piece | Where | Notes |
|
||||
| --- | --- | --- |
|
||||
| API | `http://localhost:5002` (`cd server && dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj`) | Boots in Development: migrates + seeds (reference + demo world + **lifecycle world**) against the DB in `appsettings.Development.json` — currently the **remote dev SQL Server** (`87.107.152.16`). Swagger at `/swagger`. |
|
||||
| Client | `http://localhost:3000` (`cd client && npm run dev`) | `.env.development` already points at `http://localhost:5002`. |
|
||||
| Crypto keys | `dotnet user-secrets` (from `server/src/API/Baya.Web.Api`) | The committed config carries `SET_VIA_USER_SECRETS_OR_ENV` placeholders. The remote DB's data is encrypted under the **dev keys** — any machine booting against it must set the same four user-secrets: `IdentitySettings:SecretKey` = `dev-only-jwe-signing-key-not-for-production-0123456789abcdef`, `IdentitySettings:Encryptkey` = `dev-only-16bytes`, `Seams:FieldEncryption:Key` = `local-dev-field-encryption-key-not-for-production`, `Seams:FieldEncryption:HashKey` = `local-dev-field-hash-key-not-for-production`. Booting with *different* field keys makes every phone lookup miss and every PII read throw `Padding is invalid`. |
|
||||
| OTP codes | server console (`MOCK SMS — OTP code …`) or `GET /api/v1/dev/last_otp/{phone}` | Resend window 120 s, 5 wrong attempts per code, OTP valid 60 s. The OTP endpoints are rate-limited per IP — hammering logins in scripts will 429. |
|
||||
| Reset | drop the `Baya` DB (`dotnet ef database drop --force --project src/Infrastructure/Baya.Infrastructure.Persistence --startup-project src/API/Baya.Web.Api`), reboot | Everything reseeds. Needed when the **time-relative scenarios age out** (see §3 note). |
|
||||
|
||||
---
|
||||
|
||||
## 2. Test accounts
|
||||
|
||||
All log in via phone-OTP at `/login`. Any listed account works immediately.
|
||||
|
||||
| Phone | Actor | Who | Carries |
|
||||
| --- | --- | --- | --- |
|
||||
| `09120000001` | nurse (verified) | زهرا عزیزی | 4 variants (incl. the 5-session package), whole-city+2-district coverage, ★5.00 (1 published review), 3 completed bookings, a pending request in the inbox, the in-progress visit today, earnings incl. a **paid** payout and a **pending clawback** |
|
||||
| `09120000002` | nurse (verified) | علی کریمی | Partner-sponsored (مرکز پرستاری آرامش), 2 completed bookings (one BNPL), a **draft** payout waiting, a hidden 1★ review, an expired request |
|
||||
| `09120000003` | nurse (unverified) | مریم احمدی | Mid-pipeline verification (KYC+Shahkar passed, MoH license in review w/ document, criminal record pending) — **never searchable** |
|
||||
| `09120000010` | customer | سارا محمدی | 2 patients, 1 address, 6 bookings across all states, pending/accepted/rejected requests, tickets, notifications, care records |
|
||||
| `09120000011` | customer | رضا حسینی | 1 infant patient, 2 completed bookings (one BNPL w/ processing refund), expired + cancelled requests, a closed support ticket |
|
||||
| `09120000020` | admin (`super_admin`) | نگار مدیری | Full `/admin` console incl. RBAC |
|
||||
| `09120000021` | admin (`finance`) | کامران مالی | `/admin` scoped to money consoles (`useAdminCapabilities`) |
|
||||
| `09120000030` | partner owner | بهنام رستگار | Owns the merchant-of-record center; **navigate to `/partner` manually** after login (⚠ REQ-038 — no `/me` partner signal) |
|
||||
| any new `09xxxxxxxxx` | fresh user | — | Registers on first OTP verify → `/select-role` → onboarding. Use for first-run testing. |
|
||||
|
||||
---
|
||||
|
||||
## 3. The seeded world at a glance
|
||||
|
||||
Booking scenarios (all Tehran; seed-time-relative — **T0 = the boot that first seeded**):
|
||||
|
||||
| Key | Who | State | Money / attachments |
|
||||
| --- | --- | --- | --- |
|
||||
| pending request | محمدی → عزیزی | `pending_nurse_response`, 24 h countdown | nurse-inbox + C5 tracker fodder |
|
||||
| accepted request | محمدی → عزیزی | `accepted_awaiting_payment` (24 h demo window, not the real 30 min) | checkout entry; **1 failed card attempt** (wallet history) |
|
||||
| rejected / expired / cancelled requests | mixed | terminal request states | C5 terminal cards + inbox tabs |
|
||||
| B1 `upcoming` | محمدی × عزیزی | confirmed, scheduled T0+3d, care instructions written | paid (card), invoice issued, coordination ticket |
|
||||
| B2 `in_progress` | محمدی × عزیزی | 5-session package: 2 done, **session 3 checked-in now**, 2 scheduled | paid, emergency ticket logged |
|
||||
| B3 `completed_in_window` | محمدی × عزیزی | completed T0−1d, dispute window open until T0+2d | review **pending moderation**, care record |
|
||||
| B4 `completed_paid` | محمدی × عزیزی | completed T0−10d, **paid out** | ★5 **published** review (punctual/professional), care record |
|
||||
| B5 `completed_eligible` | حسینی × کریمی | completed T0−5d, in the **draft batch** | hidden 1★ review, **out-of-range EVV** (1220 m) |
|
||||
| B6 `bnpl_settled` | حسینی × کریمی | completed T0−6d, paid via SnappPay (net-of-fee) | **processing `bnpl_revert` 50% refund** (ETA ~10 business days), excluded from payouts, care record |
|
||||
| B7 `cancelled_refunded` | محمدی × عزیزی | cancelled ≥24 h ahead (standard_24h, 100%) | **succeeded card refund** |
|
||||
| C8 `clawback` | محمدی × عزیزی | completed T0−11d, paid out, then fully refunded | **pending nurse clawback**, support alert |
|
||||
|
||||
Plus: 9+ tickets (coordination per booking, 3 refund tickets, open support w/ an **internal admin note**,
|
||||
closed support, emergency), notifications for every persona (mixed read/unread), 4 support alerts
|
||||
(low-rating / EVV-mismatch / clawback / emergency), a paid + a draft payout batch, invoices for all 8
|
||||
bookings (کریمی's resolve to the partner center as merchant-of-record).
|
||||
|
||||
> **Time decay:** the world is date-relative and ages. After ~24 h the pending request expires (the sweep
|
||||
> runs every minute); after ~2 days B3's dispute window closes and the "review-eligible + in-window" state
|
||||
> is gone; the accepted request's payment window lasts 24 h. **To refresh the timeline: drop the DB and
|
||||
> reboot** (seeder guards make an in-place re-run a no-op, not a re-date).
|
||||
|
||||
---
|
||||
|
||||
## 4. Mock-vs-real map (critical for honest testing)
|
||||
|
||||
15 of 22 client domains hit the real API. **7 still run on in-browser mocks** (`USE_*_MOCK = true` in
|
||||
`client/src/services/{domain}/constants.ts`) because a blocking backend REQ is deferred. On those screens
|
||||
the UI shows **mock data regardless of the seeded DB** — test the UI/UX there, and verify the *server*
|
||||
data through Swagger instead.
|
||||
|
||||
| Mocked domain | Screens affected | Server data still verifiable via |
|
||||
| --- | --- | --- |
|
||||
| `verification` | nurse `/nurse/verification/*` journey, admin `/admin/verification` queue | `GET nurse_verification/status` (nurse token), Swagger |
|
||||
| `refunds` | customer cancel flow + `/bookings/[id]/refund_status`, wallet «استردادها» | `GET /api/v1/refunds/by_booking/{id}`, `GET /api/v1/admin_refunds` |
|
||||
| `payouts` | nurse `/nurse/earnings*`, admin `/admin/payouts` | `GET /api/v1/nurse_payouts/earnings_balance|history`, `GET /api/v1/admin_payouts/batches` |
|
||||
| `admin` | `/admin/config|holidays|audit|alerts|roles|users` | b1 admin endpoints in Swagger |
|
||||
| `bnpl` | the whole D1–D5 BNPL checkout + wallet «اقساط» | `GET /api/v1/admin_bnpl/{id}` |
|
||||
| `partnerCenter` | `/partner/*` portal + `/admin/partners` | `GET /api/v1/admin/partner-centers` |
|
||||
| `patientRecords` | E2 family care record editor + nurse visit-note panel | `GET /api/v1/patients/{id}/care_records` |
|
||||
|
||||
**Real domains** (UI = server truth): auth, geography, patients, profiles, nurse-bank, addresses,
|
||||
serviceAreas, catalog, search, bookingRequests, bookings, payment, reviews (incl. **admin moderation**),
|
||||
tickets (incl. **admin ticket console**), notifications.
|
||||
|
||||
---
|
||||
|
||||
## 5. Flow walkthroughs
|
||||
|
||||
### 5.1 Auth & first-run (real)
|
||||
|
||||
| # | Steps | Expected |
|
||||
| --- | --- | --- |
|
||||
| A1 | `/login` → fresh phone → request code → wrong code ×5 | Refused after 5 attempts until a fresh code; resend locked 120 s; no reveal whether the phone exists |
|
||||
| A2 | Fresh phone, correct code | → `/select-role` (no roles yet) → pick خانواده → `/onboarding` wizard (relation → first patient) → customer home |
|
||||
| A3 | Same phone again later | Straight to customer home (role remembered) |
|
||||
| A4 | Nurse `09120000001` login | Routed to `/nurse` dashboard (never a flash of the customer shell) |
|
||||
| A5 | Admin `09120000020` vs `09120000021` | Both land `/admin`; finance sees **only** money consoles in the sidebar |
|
||||
| A6 | Deep link while logged out (e.g. `/bookings`) | → `/login?next=/bookings` → after login lands back on `/bookings` |
|
||||
| A7 | Logged out, open `/` | Public landing (`/welcome` content, URL stays `/`) — ⚠ verify via `npm run build && npm start` (dev-server root-path quirk, ui-phase-13) |
|
||||
|
||||
### 5.2 Customer — discovery & booking request (real)
|
||||
|
||||
Login: `09120000010`.
|
||||
|
||||
| # | Steps | Expected |
|
||||
| --- | --- | --- |
|
||||
| C1 | Home → search entry → category سالمند, region Tehran/whole city | Live count CTA > 0; unverified مریم احمدی **never** appears in any result |
|
||||
| C2 | Results | عزیزی shows ★5.00 (1 نظر), 3 visits, tappable verified badge; district-3 search still shows her whole-city rows |
|
||||
| C3 | Gender filter مرد | Only کریمی remains |
|
||||
| C4 | Open عزیزی's profile | Trust dossier: badge → verification panel (credential **types only**, never numbers); services/prices tab; «نظرات» tab shows exactly **1** published review with tags — the pending + hidden ones never |
|
||||
| C5 | «درخواست رزرو» → C4 form: patient حسن, address, tomorrow, morning window → submit | Request created; C5 tracker shows a **24 h** countdown ring |
|
||||
| C6 | As عزیزی (second browser/profile): `/nurse/requests` | New request at top with urgency countdown; detail shows **only** customer notes + coarse city/district (⚠ stage-1 masked address) |
|
||||
| C7 | Accept it | Customer C5 flips to accepted + **30-minute** payment window countdown (real window — the seeded one is a 24 h demo exception) |
|
||||
| C8 | Reject another (with reason) | C5 terminal card + «درخواست دوباره» / «پرستاران مشابه» off-ramps |
|
||||
|
||||
### 5.3 Customer — checkout & payment (real contract, mock PSP)
|
||||
|
||||
| # | Steps | Expected |
|
||||
| --- | --- | --- |
|
||||
| P1 | C5 of the seeded accepted request → «پرداخت» → C6 | Nurse identity + `<Money>` total (variant price), reconciling breakdown, escrow explainer. ⚠ REQ-046: avatar/badge enrichment may be absent on the real path |
|
||||
| P2 | «ادامه پرداخت» (card) | Initiate succeeds → browser redirects to `https://mock-psp.local/...` — a **dead page. Expected**: the mock PSP has no UI (real E2E completion needs the Phase-8 real PSP config). |
|
||||
| P3 | To actually complete a payment: Swagger → `POST /api/v1/bookings/convert` body `{"bookingRequestId": <id>}` with the **customer's** bearer token (Dev-only capture simulator) | Booking appears under «رزروها» as confirmed; coordination ticket auto-opens; invoice issued; nurse gets a notification |
|
||||
| P4 | Wallet «پرداختها» | ⚠ REQ-047: **empty on the real path** (no transactions-list endpoint). The seeded failed+succeeded transactions are visible in DB/Swagger only |
|
||||
| P5 | BNPL branch (D1–D5) | ⚠ Whole flow is client-**mock** (REQ-022/024); `/bookings/checkout/bnpl/gateway` only exists under `npm run dev`. Server-side BNPL truth: `admin_bnpl` via Swagger (B6 is `reverted`) |
|
||||
|
||||
### 5.4 Customer — bookings lifecycle (real)
|
||||
|
||||
| # | Steps | Expected |
|
||||
| --- | --- | --- |
|
||||
| L1 | `/bookings` tabs | «در انتظار پاسخ»: pending request w/ countdown · «فعال»: B1, B2 · «گذشته»: B3, B4, B7, C8 |
|
||||
| L2 | B1 (upcoming) detail | Status timeline at تایید شده; next-session headline T0+3d; `.ics` download; address card |
|
||||
| L3 | B2 (package) detail | 5 sessions listed: 2 completed, 1 **در حال ویزیت** (presence headline), 2 scheduled |
|
||||
| L4 | B3 review CTA | Star strip on the completed row → review form (context recap + moderation note) — but B3 already carries a pending review, so expect the **"under review"** state, never a second form |
|
||||
| L5 | B4 | «مشاهده نظر» shows the published ★5 review state |
|
||||
| L6 | B1 → لغو رزرو | Off-ramps first; tier disclosure: **≥48 h → 100%، ≥24 h → 50%، <24 h → 0%** (server tiers) — ⚠ the UI copy states a single 24 h boundary (REQ-065 divergence; record the exact numbers shown). ⚠ the actual cancel + refund-status screens run on the **mock** refunds domain — server truth via Swagger |
|
||||
| L7 | B7 → وضعیت استرداد | ⚠ mock domain: UI shows mock stages. Server truth: refund `succeeded`, channel `psp_card` (`GET refunds/by_booking/{B7}`) |
|
||||
| L8 | `/bookings/[B1]/invoice` | Real invoice: sequential number, VAT = 10% **on the commission line only**, مودیان state `pending`. ⚠ REQ-049: payment-method/reference/seller-fiscal block may be absent |
|
||||
|
||||
### 5.5 Customer — account, care circle, tickets, notifications
|
||||
|
||||
| # | Steps | Expected |
|
||||
| --- | --- | --- |
|
||||
| E1 | `/patients` («حلقهٔ مراقبت») | حسن + فاطمه cards; add/edit/archive (real); tap → E2 record |
|
||||
| E2 | `/patients/[حسن]/record` | ⚠ patientRecords domain is **mock**: meds/routine/tasks + the nurse visit-note history shown are mock data (the 2 real seeded notes are server-side only). Access-denied state testable with the mock's foreign-patient id 8888 |
|
||||
| E3 | `/addresses` | Real CRUD; map is the canvas stand-in unless `NEXT_PUBLIC_NESHAN_KEY` is set |
|
||||
| E4 | `/profile` | Identity header (server-masked phone), personal-info edit, language row, emergency-contact card; avatar upload round-trips |
|
||||
| E5 | `/support/tickets` | Real inbox: refund tickets (`TKT-DEMORF0x`), open support `TKT-DEMOSUP1`, coordination tickets; thread of `TKT-DEMOSUP1` shows customer msg + admin reply + follow-up — **the internal admin note must never appear** |
|
||||
| E6 | Send a message; send another containing `/fail` | Normal send lands; ⚠ `/fail` sentinel only drives the mock — on the real path it just sends |
|
||||
| E7 | `/notifications` | Seeded rows, unread-first, day-grouped; mark-read flips the bell count. ⚠ **Notification titles/bodies are English** — server-rendered copy from the real handlers (finding F-4 §7) |
|
||||
|
||||
### 5.6 Nurse — daily ops (real except earnings)
|
||||
|
||||
Login: `09120000001`.
|
||||
|
||||
| # | Steps | Expected |
|
||||
| --- | --- | --- |
|
||||
| N1 | `/nurse` dashboard | Next-visit card (B2 today), requests strip (pending w/ countdown), earnings snapshot (⚠ mock numbers — payouts domain), activation checklist collapsed to «فعال در جستجو» |
|
||||
| N2 | `/nurse/visits` | Today's feed shows B2 session 3 **checked-in** → the check-out CTA is the hero action |
|
||||
| N3 | Check out (confirm step) | Session completes; EVV panel updates. GPS: set `NEXT_PUBLIC_EVV_MOCK_GPS=in_range` in `client/.env.local` to force a passing location, else real geolocation runs (out-of-tolerance is **advisory** — banner + staff alert, never a block). Completing the **last** session would complete the booking and start its 72 h dispute clock |
|
||||
| N4 | `/nurse/visits/[B2]` | Address card + map link (⚠ REQ-051: address may stay masked w/ quiet fallback note), gated care card (care instructions **readable** post-confirmation), visit-note composer (⚠ mock — patientRecords) |
|
||||
| N5 | `/nurse/requests` | Tabs: pending (live countdown) / answered / expired. Accept behind confirm dialog → opens the payment window |
|
||||
| N6 | `/nurse/earnings` + `/payouts` | ⚠ **Mock domain** — UI shows mock buckets. Server truth (Swagger, nurse token): `earnings_balance` = signed ledger sum (عزیزی: B1+B2+B3 payouts pending — B7 reversed, B4/C8 paid out), `history` shows the **paid** payout w/ masked IBAN |
|
||||
| N7 | `/nurse/services` | 4 offerings incl. the package variant; edit/deactivate; the accepting-bookings toggle is real (pausing → disappears from search) |
|
||||
| N8 | `/nurse/coverage` | Whole-city + districts 1&3; duplicate add → 409 message |
|
||||
| N9 | `/nurse/bank` | Verified account, masked IBAN, ownership state «تأیید شده» |
|
||||
| N10 | As کریمی (`09120000002`) | Draft-batch earnings waiting; B6's payout share reversed by the 50% refund; hidden review does **not** appear on his public profile (0 reviews) |
|
||||
| N11 | As احمدی (`09120000003`) | Activation checklist far from complete; `/nurse/verification` — ⚠ **mock domain**: the journey UI shows mock state; the real mid-pipeline case (KYC ✓, Shahkar ✓, license in-review, criminal pending) is server-side (`nurse_verification/status` via Swagger). She must never appear in search |
|
||||
|
||||
### 5.7 Admin console
|
||||
|
||||
Login: `09120000020` (all consoles) and `09120000021` (money only).
|
||||
|
||||
| # | Console | Real/Mock | What the seeded world provides (server-side) |
|
||||
| --- | --- | --- | --- |
|
||||
| AD1 | `/admin/reviews` moderation queue | **Real** | B3's pending review — publish it → عزیزی's public aggregate recomputes (★ count 2); hide/reject paths; the hidden 1★ shows the hide flow already happened |
|
||||
| AD2 | `/admin/tickets` | **Real** | Full queue incl. emergency (red) + refund tickets; thread of `TKT-DEMOSUP1` **shows** the internal note distinctly; composer's internal-note mode goes amber |
|
||||
| AD3 | `/admin/verification` | ⚠ Mock | Real queue data (احمدی in review + document metadata) via Swagger `admin_verifications`; the document's signed-URL fetch 404s (no real bytes — expected) |
|
||||
| AD4 | `/admin/payouts` | ⚠ Mock | Real: `admin_payouts/batches` shows the **completed** batch (2 links) + the **draft** batch; `batches/{id}/process` on the draft is the demoable money-out action; `eligible` preview |
|
||||
| AD5 | Refunds (via ticket RefundPanel) | ⚠ Mock | Real: `admin_refunds` lists 3 refunds; `{id}/confirm_settlement` on the **processing BNPL** refund is the demoable action (posts the clearing leg) |
|
||||
| AD6 | `/admin/alerts` | ⚠ Mock | Real: 4 seeded alerts (low_rating / evv_location_mismatch / nurse_clawback / emergency) via `support_alerts` endpoints |
|
||||
| AD7 | `/admin/config`, `/admin/holidays`, `/admin/audit`, `/admin/users`, `/admin/roles` | ⚠ Mock | Real: b1 endpoints (config list incl. the §6 numbers, audit trail rows for every seeded money/trust entity — actor `null` = system) |
|
||||
| AD8 | `/admin/partners` | ⚠ Mock | Real: `admin/partner-centers` shows مرکز پرستاری آرامش (MoR, verified, masked IBAN), کریمی sponsored |
|
||||
|
||||
### 5.8 Partner portal (⚠ mock — REQ-032/033/038)
|
||||
|
||||
Login `09120000030` → navigate to `/partner` manually. UI runs on mock center data; the real center +
|
||||
MoR invoice resolution (کریمی's two invoices carry `issuing_entity_type = partner_center`) is verifiable
|
||||
via Swagger. Test the portal chrome, the MoR settlement view, and the CSV export against mock data.
|
||||
|
||||
---
|
||||
|
||||
## 6. The numbers the UI must respect
|
||||
|
||||
From seeded `platform_configs` (admins can change them; rates are **snapshotted** — a change never
|
||||
re-prices an existing booking/invoice/deadline):
|
||||
|
||||
| Rule | Value |
|
||||
| --- | --- |
|
||||
| Nurse response deadline | **24 h** (frozen per request) |
|
||||
| Payment window after accept | **30 min** (frozen per request) |
|
||||
| Dispute window after completion | **72 h** → then payout-eligible |
|
||||
| Platform commission | **15%** of gross (`gross = commission + payout`, always) |
|
||||
| VAT | **10%**, on the **commission line only** |
|
||||
| Cancellation tiers | ≥48 h → 100% · ≥24 h → 50% · <24 h → 0% (⚠ client copy says a single 24 h boundary — REQ-065) |
|
||||
| BNPL provider fee | **7%** — a **platform expense**; the nurse payout is payment-method-invariant |
|
||||
| BNPL refund ETA | ~**10 business days** (Fridays skipped); UI copy says 7–10 |
|
||||
| EVV tolerance | **200 m**, advisory only |
|
||||
| No-show threshold | **60 min** after scheduled start |
|
||||
| Payout cadence | weekly generation (auto, draft); **processing stays a manual admin action** |
|
||||
| Review alert | rating ≤ **2** raises a staff alert |
|
||||
| OTP | resend 120 s · 5 attempts · code lives 60 s · session 30 d · access token 60 min |
|
||||
|
||||
---
|
||||
|
||||
## 7. Findings from this bring-up (decide / track)
|
||||
|
||||
Recorded while building the seed — each needs an owner decision:
|
||||
|
||||
| # | Finding | State |
|
||||
| --- | --- | --- |
|
||||
| F-1 | **Committed real DB credential**: `appsettings.Development.json` ships the remote server's SQL login in git (the exact thing refinement-phase-5 removed; the pre-commit hook that blocks it isn't enabled on this clone). Recommendation: move the connection strings to user-secrets like the crypto keys and restore placeholders. | **Open — decision needed** |
|
||||
| F-2 | **`/me` hardcoded `hasCustomerProfile`/`hasNurseProfile`/`nurseVerificationStatus`** to `false`/`not_started` for everyone (broke the customer home profile nudge + profile-hook invalidations). | **Fixed** this session (snapshot projection + `ToMeResult`) |
|
||||
| F-3 | **Stored Persian text is normalized destructively**: an `ApplicationDbContext` save hook runs `Fa2En().FixPersianChars()` over every string property — Persian digits become ASCII and **ZWNJ becomes a space** in everything persisted (e.g. «شبانهروزی» → «شبانه روزی»), contradicting the client's STYLE.md ZWNJ rules. Any Persian-literal equality against stored data silently misses. | **Open — decision needed** (legacy starter behavior; removing it changes stored data shape) |
|
||||
| F-4 | **Notification copy is English on the real path** — the b-phase handlers write `"Booking confirmed"`-style titles/bodies straight into `ops.Notifications`; the Persian UI renders them verbatim. | **Open — decision needed** (server-side i18n or client-side type→copy mapping) |
|
||||
| F-5 | Mock PSP redirect goes to a dead host (`mock-psp.local`) — in-browser card completion impossible until a real PSP is configured (`Payments:Provider=zarinpal`); the Dev `bookings/convert` affordance is the workaround (§5.3 P3). | By design (refinement-phase-8 rails exist behind config) |
|
||||
| F-6 | 7 client domains still mocked (§4) — the biggest lever for "test everything for real" is flipping `verification`, `refunds`, `payouts` (user halves are contract-ready; the blocking REQs are admin-side). Flipping a shared flag turns the admin half's screens into real-API screens against missing endpoints. | **Open — decision needed** (split flags per half, or deliver the admin REQs) |
|
||||
| F-7 | Seeded object-storage keys (verification document, invoice PDFs) have no real bytes — signed-URL fetches 404 in admin viewers. | Accepted for dev (never fake bytes) |
|
||||
|
||||
---
|
||||
|
||||
## 8. Suggested test order
|
||||
|
||||
1. **Auth & routing** (§5.1) — everything depends on it.
|
||||
2. **Customer discovery → request → accept → convert → booking** (§5.2–5.4) — the core funnel, all real.
|
||||
3. **Nurse ops** (§5.6) — inbox/EVV against the same bookings.
|
||||
4. **Reviews + tickets + notifications** (§5.4 L4/L5, §5.5 E5–E7) — real, seeded both sides.
|
||||
5. **Admin real consoles** (§5.7 AD1/AD2) — moderation + tickets.
|
||||
6. **Mock-domain UI passes** (§5.3 P5, §5.5 E2, §5.6 N6/N11, §5.7 AD3–AD8, §5.8) — UX only, verify server truth via Swagger as listed.
|
||||
7. Sweep §7's decisions.
|
||||
@@ -86,6 +86,15 @@ demo nurses with priced variants + Tehran coverage (and therefore real `nurse_se
|
||||
customers with patients and addresses. The console logs `Demo world seeded: 3 nurse(s), 2 customer(s)…` (or
|
||||
`already seeded — no-op` on a subsequent run). It is **idempotent** and **never runs outside Development**.
|
||||
|
||||
On top of that, the **lifecycle seeder** (`DemoLifecycleSeeder`) populates every flow's mid-state so manual
|
||||
testing never starts from an empty world: booking requests in every status, 8 bookings across every reachable
|
||||
state (incl. a 5-session package mid-engagement and a cancelled-and-refunded one), the balanced ledger, three
|
||||
refunds (card-succeeded / BNPL-processing / post-payout clawback), a **paid** and a **draft** payout batch,
|
||||
reviews in all moderation states, tickets, notifications, patient care records, a merchant-of-record partner
|
||||
center, and a mid-pipeline verification case. The console logs `Demo lifecycle seeded: …` (or `already
|
||||
seeded — no-op`). The full scenario map + per-flow walkthroughs live in
|
||||
[`dev/post-phase/manual-testing-plan.md`](../manual-testing-plan.md).
|
||||
|
||||
### Terminal 2 — frontend (from `client/`)
|
||||
|
||||
```bash
|
||||
@@ -114,6 +123,7 @@ endpoint works). Use them to see the real path populated:
|
||||
| `09120000011` | customer | رضا حسینی (male) | 1 patient, 1 Tehran address |
|
||||
| `09120000020` | admin (`super_admin`) | نگار مدیری (female) | full backoffice — **lands on `/admin`**, sees every console incl. RBAC |
|
||||
| `09120000021` | admin (`finance`) | کامران مالی (male) | scoped backoffice — lands on `/admin`, sidebar shows only the money consoles (`useAdminCapabilities` gating) |
|
||||
| `09120000030` | partner-center owner | بهنام رستگار (male) | owns مرکز پرستاری آرامش (merchant-of-record, sponsors علی کریمی). No admin/nurse role — log in, then navigate to `/partner` manually (REQ-038: no `/me` partner signal yet) |
|
||||
|
||||
> The old username+password `admin`/`qw123321` account is **no longer auto-seeded** (refinement-phase-5 —
|
||||
> no committed credential). To bootstrap a break-glass username+password admin, set both secrets before boot,
|
||||
|
||||
Reference in New Issue
Block a user