Technical Review · File Map Edition
Where to find it in the repository
This document is the pointer index for the client's reviewer or developer: every item mentioned in the review is listed here with its exact file path and, where meaningful, its line-of-code (LOC) range, so it can be opened directly in the repository rather than searched for. It is intentionally light on explanation — pair it with the companion "Explained Edition" for the plain-language walkthrough.
How to use this document: open each cited path in the repository and jump to the listed lines to verify the implementation described in the review. Line numbers may drift slightly after future commits — use the named function or symbol as a secondary anchor if a line number is off by a few rows.
01 System Architecture Overview
| Layer | Responsibility | Entry / aggregator |
| HTTP / Express | Middleware, mounts API | loaders/express.js |
| API v1 router | Feature route aggregation | routes/v1/index.js L70–102 |
| Controllers | Thin HTTP handlers | controllers/*.controller.js |
| Services | Business logic | services/*.service.js |
| Repositories | Prisma queries | repositories/*.repository.js |
| Prisma schema | Data model | prisma/schema.prisma |
| Frontend panels | Multi-app UI | resources/views/src/routes/AppRoutes.jsx |
Request flow (backend)
Client → Express → /api/v1 → Feature Route → Zod validate → Controller → Service → Repository → Prisma/MySQL
Health endpoints
| Endpoint | File | LOC |
| Liveness | routes/v1/index.js | L40–42 |
| Readiness (DB ping) | routes/v1/index.js | L44–50 |
| Version health | routes/v1/index.js | L57–66 |
↑ top
02 Code Modularity and Reuse
2.1 — Backend layering (Route → Controller → Service → Repository)
| Layer | Example file | What to review | LOC |
| Route aggregator | routes/v1/index.js | All feature mounts | L70–102 |
| Feature routes | routes/v1/payments.routes.js | Auth + validate + controller | L12–16 |
| Feature routes | routes/v1/me.routes.js | User "me" APIs | (full file) |
| Feature routes | routes/v1/appointments.routes.js | Admin/business appointments | (full file) |
| Controller | controllers/payment.controller.js | Thin handlers | L6–19 |
| Controller | controllers/me.controller.js | Profile / pets / bookings | (full file) |
| Service | services/payment.service.js | Payment + booking orchestration | L26–186 |
| Service | services/me.service.js | Appointment creation | L229–270 |
| Repository | repositories/appointment.repository.js | Select shape + CRUD | L3–170 |
| Repository | repositories/transaction.repository.js | Transactions CRUD / summary | L25–139 |
Shared cross-cutting utilities
| Utility | File | LOC | Purpose |
| Success/error JSON | utils/apiResponse.js | (file) | Standard API envelope |
| Async error wrapper | utils/asyncHandler.js | (file) | Avoids try/catch in every controller |
| App errors | utils/AppError.js | (file) | Typed HTTP errors |
| Business scoping | utils/businessScope.util.js | (file) | Restricts vendor data by panel |
| Panel registry | config/panelRegistry.js | L6–33+ | Single config for all vendor panels |
Panel registry reuse (important for modularity)
- Registry definition:
config/panelRegistry.js L8–33 (CLINIC example: model, role, vendorType, onboarding steps)
- Consumed by auth for business JWTs:
middlewares/auth.middleware.js L24–48
2.2 — Frontend reuse patterns
| Pattern | File | LOC | Notes |
| Panel route composition | resources/views/src/routes/AppRoutes.jsx | (panel imports) | Admin / User / Business / Vet / Groomer |
| User app routes | resources/views/src/routes/UserRoutes.jsx | booking ~L65–67 | Booking deep-link |
| Axios client factory | resources/views/src/services/api/createApiClient.js | refresh ~L47–96 | Per-panel API + silent token refresh |
| Panel config | resources/views/src/config/panels.js | PANEL_TYPES / ROLE_MAP | Role → home path mapping |
| Shared list hook | resources/views/src/hooks/useEntityList.js | (file) | Generic paginated list for admin panels |
| Domain hook | resources/views/src/hooks/useAppointments.js | (file) | Composes entity list + appointment service |
| Payment orchestrator | resources/views/src/utils/bookWithPayment.js | L9–33 | Shared by booking page + modal |
Booking UI reuse: both UserBookingPage.jsx and BookingModal.jsx call the same bookWithPayment helper instead of duplicating Razorpay logic.
2.3 — What is modular / reusable today
- Feature-based
routes/v1/*.routes.js files (one domain per file)
- Zod schemas isolated under
validations/
- Vendor panels driven by
PANEL_REGISTRY instead of copy-pasted auth logic
- Frontend API clients created once via
createApiClient
2.4 — What is less modular (for reviewer attention)
- Appointment "extra" fields (hostel nights, lab tests, grooming services) are serialized into
notes rather than first-class columns — see services/me.service.js L232–246
- Polymorphic vendor linking (
vendorType + vendorId) without Prisma foreign keys — see Section 3
- Some services instantiate Prisma outside the singleton (see Section 5)
↑ top
03 Data Design
Source of truth: prisma/schema.prisma
3.1 — Database
| Item | Location |
| MySQL datasource | prisma/schema.prisma L8–11 |
| Connection env | DATABASE_URL in .env / .env.example |
3.2 — Core enums
| Enum | File | LOC | Values / purpose |
UserRole | prisma/schema.prisma | L13–18 | SUPER_ADMIN, ADMIN, PET_OWNER, VENDOR |
UserStatus | prisma/schema.prisma | L20–25 | ACTIVE / INACTIVE / PENDING / SUSPENDED |
BusinessPanelType | prisma/schema.prisma | L33–40 | CLINIC, GROOMING, LAB, HOSTEL, VETERINARIAN, INDIVIDUAL_GROOMER |
AppointmentServiceType | prisma/schema.prisma | ~L248–255 | VET_CHECKUP, GROOMING, LAB_TEST, HOSTEL_STAY, … |
AppointmentVendorType | prisma/schema.prisma | L257–264 | VET_CLINIC, GROOMING_CENTRE, DIAGNOSTIC_LAB, PET_HOSTEL, … |
AppointmentStatus | prisma/schema.prisma | L266–271 | PENDING, CONFIRMED, COMPLETED, CANCELLED |
TransactionPaymentStatus | prisma/schema.prisma | L1061–1066 | SUCCESS, PENDING, FAILED, REFUNDED |
TransactionPayoutStatus | prisma/schema.prisma | L1068–1073 | PENDING, PROCESSING, PAID, HOLD |
3.3 — Key models
User — prisma/schema.prisma L273–304
| Concern | Detail | LOC |
| Identity | Unique email, optional password | L276–278 |
| RBAC | role + status | L279–280 |
| Profile / geo | city, state, address | L283–285 |
| Relations | appointments, pets, refreshTokens, … | L291–298 |
| Indexes | role, status, city | L300–302 |
Pet — prisma/schema.prisma L376–403
| Concern | Detail | LOC |
| Owner FK | userId → User, cascade delete | L378, L399 |
| Clinical fields | breed, vaccination, allergies, documents JSON | L380–395 |
| Index | userId | L401 |
Design note: Appointment does not FK to Pet. Bookings store denormalized petName / petType (L1032–1033).
Appointment — prisma/schema.prisma L1029–1059
| Concern | Detail | LOC |
| Soft user link | optional userId → User | L1037, L1049 |
| Polymorphic vendor | vendorType + vendorId (no Prisma FK to clinic/lab/hostel) | L1040–1041 |
| Money | amount Decimal(10,2) | L1044 |
| Status | default PENDING | L1045 |
| Free-form notes | used for META JSON (hostel/lab extras) | L1046 |
| Indexes | code, email, serviceType, vendorType, status, date, createdAt | L1051–1057 |
Gaps for review:
- No
@@index([userId])
- No
@@index([vendorId])
- No FK from appointment → pet
- No first-class columns for check-in/out, selected tests/services (stored in notes via service layer)
BusinessTransaction — prisma/schema.prisma L1090–1116
| Concern | Detail | LOC |
| Business scope | panelType + businessId (no FK) | L1093–1094 |
| Booking link | optional appointmentId (no Prisma relation) | L1095 |
| Commission split | amount, platformFee, netAmount | L1099–1101 |
| Payment / payout | enums + paidAt | L1102–1105 |
| Indexes | [panelType, businessId], paymentStatus, payoutStatus, createdAt | L1111–1114 |
Vendor entities (parallel design)
| Model | Approx. LOC in schema | Notes |
VetClinic | ~L520–567 | Composite status/city index |
GroomingCentre | ~L609–653 | Same pattern |
DiagnosticLab | ~L749–797 | Same pattern |
PetHostel | ~L892–945 | Branch self-relation |
IndividualVeterinarian | ~L1191–1254 | Separate from clinic staff Veterinarian |
BusinessRegistration | ~L420–471 | Onboarding / approval bridge |
RefreshToken — prisma/schema.prisma L306–333 (approx.)
Stores a SHA-256 hash of the refresh token (comment at L306), with revoke / rotate fields — supports multi-device sessions.
3.4 — Runtime data mapping quirks
| Behavior | File | LOC |
Hostel nights / lab tests / grooming services serialized into notes with ---META--- separator | services/me.service.js | L232–246 |
| Maps only Prisma Appointment columns | services/me.service.js | L248–267 |
| Vendor type → transaction panel map | services/payment.service.js | L8–15 |
↑ top
04 Cache Usage
4.1 — Backend cache service
| Item | File | LOC |
Redis client + in-memory Map fallback | services/cache.service.js | L3–9 |
Init (Redis if REDIS_URL, else memory) | services/cache.service.js | L11–28 |
get / set / delete / pattern clear | services/cache.service.js | L31+ |
4.2 — HTTP response caching middleware
| Item | File | LOC |
GET-only cache, key = prefix:url | middlewares/cache.middleware.js | L3–44 |
| Cache HIT / MISS headers | middlewares/cache.middleware.js | L17, L34 |
| Invalidate on successful mutations | middlewares/cache.middleware.js | L46–61 |
4.3 — Where cache is applied
| Area | File | LOC |
Public catalog TTL 300s (public prefix) | routes/v1/publicCatalog.routes.js | L21, L27–54 |
| Invalidator wired on vendor CRUD mounts | routes/v1/index.js | L36, L68, L73–97 |
| Boot init | server.js (cacheService.init) | (boot file) |
Cached public endpoints (examples):
/public/banners, /public/search — L27–29
/public/vet-clinics, /public/grooming-centres, /public/pet-hostels, labs, lab-tests — L36–54
Not cached: location reverse/autocomplete/nearby (L31–34) — live Google Maps calls.
4.4 — Frontend cache
| Finding | Evidence |
| No TanStack React Query / Apollo cache | Frontend list state is local hooks (useEntityList), not a shared query cache |
| Token refresh coalescing only | createApiClient.js silent refresh on 401 |
Reviewer takeaway: server-side HTTP cache exists for public catalog; client-side data cache is minimal.
↑ top
05 Database Usage
5.1 — Prisma client singleton
| Item | File | LOC |
Singleton + globalThis reuse in non-prod | models/prisma.client.js | L1–18 |
| Connect on boot | loaders/database.js | (file) |
5.2 — Repository pattern
Typical pattern: explicit select, buildWhere, parallel findMany + count for pagination.
| Example | File | LOC |
| Appointment filters + pagination | repositories/appointment.repository.js | L32–110 |
| Transaction list / summary | repositories/transaction.repository.js | L25–138 |
Transaction create accepts optional tx | repositories/transaction.repository.js | create method |
5.3 — Atomic transactions (prisma.$transaction)
| Use case | File | LOC |
| Payment verify: confirm appointment + create transaction | services/payment.service.js | L101–120 (primary), L131–145 (legacy) |
| Business approval flows | services/businessApproval.service.js | (approval transaction block) |
5.4 — Query / indexing design
| Topic | Location | Notes |
| User indexes | schema L300–302 | role, status, city |
| Appointment indexes | schema L1051–1057 | missing userId / vendorId indexes |
| Transaction composite index | schema L1111 | [panelType, businessId] |
| Readiness SQL | routes/v1/index.js L46 | SELECT 1 |
5.5 — Deviations to review
| Issue | File | LOC |
New PrismaClient() inside a service method (bypasses singleton) | services/me.service.js | ~L287–288 (listNotifications) |
| Polymorphic IDs without FK constraints | Appointment / BusinessTransaction | schema L1040–1041, L1093–1095 |
↑ top
06 Payment Handling Logic
6.1 — End-to-end flow
User confirms booking (amount > 0)
→ Frontend bookWithPayment()
→ POST /payments/razorpay/order (creates PENDING appointment + Razorpay order)
→ Razorpay Checkout.js modal
→ POST /payments/razorpay/verify (HMAC verify → CONFIRMED + BusinessTransaction)
Zero-amount bookings skip Razorpay and call meService.createAppointment directly.
6.2 — Backend: Razorpay SDK wrapper
File: services/razorpay.service.js
| Function | LOC | Behavior |
getKeyId | L8–14 | Reads RAZORPAY_KEY_ID |
#getKeySecret | L16–22 | Reads RAZORPAY_KEY_SECRET |
#getClient | L24–32 | Lazily creates Razorpay SDK client |
createOrder | L34–57 | Amount in paise (* 100), min ₹1, attaches userId notes |
fetchOrder | L59–61 | Fetches order from Razorpay |
verifyPaymentSignature | L63–70 | HMAC-SHA256 of orderId|paymentId |
6.3 — Backend: Payment orchestration
File: services/payment.service.js
| Step | LOC | Behavior |
| Config | L27–29 | Exposes public Key ID only |
| Create order | L31–53 | Validates amount vs booking; pre-creates PENDING appointment; stores appointmentId in Razorpay order notes |
| Verify payment | L55–147 | Signature check → ownership check → amount check → $transaction |
| Confirm path | L100–120 | Updates appointment to CONFIRMED, creates transaction |
| Legacy fallback | L121–146 | Creates CONFIRMED appointment if no pre-created id |
| Commission transaction | L149–183 | Platform fee from settings (default 12%), paymentMethod: Razorpay, paymentStatus: SUCCESS |
Vendor → panel mapping for ledger: L8–15. Service labels: L17–24.
6.4 — Backend: HTTP surface
| Item | File | LOC |
| Auth required (PET_OWNER / ADMIN roles) | routes/v1/payments.routes.js | L12 |
GET /razorpay/config | routes/v1/payments.routes.js | L14 |
POST /razorpay/order | routes/v1/payments.routes.js | L15 |
POST /razorpay/verify | routes/v1/payments.routes.js | L16 |
| Mounted under API | routes/v1/index.js | L102 → /payments |
| Controller | controllers/payment.controller.js | L6–19 |
| Zod schemas | validations/payment.validation.js | order + verify + booking payload |
6.5 — Frontend: payment modules
| File | LOC | Role |
resources/views/src/services/paymentService.js | L3–13 | API client: config / order / verify |
resources/views/src/utils/razorpayCheckout.js | L5–22, L27–79 | Loads Checkout.js; opens modal; returns payment ids |
resources/views/src/utils/bookWithPayment.js | L9–33 | Orchestrates free vs paid booking |
resources/views/src/pages/user/UserBookingPage.jsx | ~L709–717 | Full-page booking confirm |
resources/views/src/components/user/BookingModal.jsx | ~L243–251 | Modal booking confirm |
6.6 — Environment configuration
| Variable | Template file | Notes |
RAZORPAY_KEY_ID | .env.example | Public key (safe for checkout) |
RAZORPAY_KEY_SECRET | .env.example | Server-only — never expose to frontend |
| Runtime values | .env (local) | Must not be committed |
6.7 — Payment security checks (implemented)
| Check | Location |
| HMAC signature verification | razorpay.service.js L63–70; used in payment.service.js L67–74 |
| Order belongs to requesting user | payment.service.js L76–79 |
| Amount matches appointment / booking | payment.service.js L35–37, L96–98, L126–128 |
| Appointment ownership | payment.service.js L93–95 |
| Atomic confirm + ledger write | payment.service.js L101–120 |
| Secret never returned to client | only keyId via config endpoint |
6.8 — Payment review gaps (developer checklist)
| Gap | Why it matters |
| No Razorpay webhook handler yet | Abandoned checkouts leave PENDING appointments; webhooks improve reconciliation |
| PENDING appointments on cancelled payments | User may dismiss modal after order create — cleanup / expiry job recommended |
| No refund API path | REFUNDED enum exists in schema but no automated refund flow |
| Duplicate verify risk | Idempotency key / "already CONFIRMED" short-circuit should be verified by reviewer |
↑ top
07 Authentication and Security
7.1 — JWT
| Item | File | LOC |
| Production refuses weak secrets | utils/jwt.util.js | L3–9 |
| Access token TTL (default 15m) | utils/jwt.util.js | L13–15 |
| Refresh TTL (default 30 days) | utils/jwt.util.js | L17–19 |
| Sign / verify | utils/jwt.util.js | L24–37 |
7.2 — Auth middleware
| Item | File | LOC |
| Bearer JWT authenticate | middlewares/auth.middleware.js | L13–65 |
Business panel resolve via PANEL_REGISTRY | middlewares/auth.middleware.js | L24–48 |
| Role authorize | middlewares/auth.middleware.js | L70–79 |
| Admin / business helpers | middlewares/auth.middleware.js | L82–100 |
7.3 — Express hardening
| Item | File | LOC |
| Helmet | loaders/express.js | L21–26 |
| CORS allow-list | loaders/express.js | L32–48 |
Rate limit 300 / 15 min on /api/ | loaders/express.js | L51–59 |
| JSON body limit 2mb | loaders/express.js | L61–62 |
7.4 — Frontend session
| Item | File | Notes |
| Silent refresh on 401 | resources/views/src/services/api/createApiClient.js | Coalesced refresh |
| Panel role maps | resources/views/src/config/panels.js | USER → PET_OWNER |
↑ top
08 API Structure and Validation
8.1 — Aggregation
| Item | File | LOC |
Mount /api/v1 | loaders/express.js | ~L93 |
| Feature mounts | routes/v1/index.js | L70–102 |
Major route groups include: auth, users, dashboard, vendor CRUD (vet-clinics, grooming-centres, diagnostic-labs, pet-hostels, …), appointments, transactions, me, public, payments, app-specific panels.
8.2 — Zod validation middleware
| Item | File | LOC |
validate(schema) factory | middlewares/validate.middleware.js | L3–28 |
Writes coerced values back to req | middlewares/validate.middleware.js | L21–24 |
| Payment schemas | validations/payment.validation.js | (full file) |
| Public catalog schemas | validations/publicCatalog.validation.js | used by public routes |
Pattern: route attaches validate(schema) before controller — example routes/v1/payments.routes.js L15–16.
↑ top
09 Frontend Architecture
9.1 — Multi-panel apps
Isolated route trees for: Public / marketing, Admin, Business (clinic, grooming, lab, hostel), Individual veterinarian, Individual groomer, Pet owner (user app).
Entry composition: resources/views/src/routes/AppRoutes.jsx
9.2 — User booking flow (cite for review)
| Step | File | LOC |
Route /booking/:categoryKey/:providerId | UserRoutes.jsx | ~L65–67 |
| Category → serviceType / vendorType map | UserBookingPage.jsx / BookingModal.jsx | CATEGORY_CONFIG at top of files |
| Build payload + amount | UserBookingPage.jsx | confirm handler (~L637–706) |
| Pay then book | bookWithPayment.js | L9–33 |
| Persist extras in notes | me.service.js | L232–246 |
9.3 — Service / hook layout
resources/views/src/
services/ # domain API wrappers (meService, paymentService, …)
services/api/ # axios factories (userApi, adminApi, …)
hooks/ # useEntityList + domain hooks
pages/user/ # User app screens
components/user/ # BookingModal, cards, …
utils/ # bookWithPayment, razorpayCheckout, formatters
config/ # panels, category configs
↑ top
10 Review Notes / Improvement Points
Intentional callouts for the client's developer review — not a change log.
Strengths
- Clear layered modularity (routes / controllers / services / repositories)
- Panel registry avoids duplicated vendor-auth logic
- Zod validation at the HTTP boundary
- Payment verification includes HMAC, user ownership, amount match, and
$transaction
- Cache with Redis + memory fallback on public catalog; mutation invalidation
- Security basics: Helmet, CORS, rate limit, JWT production secret guard, refresh-token hashing
Areas to tighten
| Area | Observation | Cite |
| Data design | Appointment extras in notes instead of columns | me.service.js L232–246 |
| Data design | Polymorphic vendor / transaction IDs without FKs | schema L1040–1041, L1095 |
| Indexes | Missing userId / vendorId on appointments | schema L1051–1057 |
| Payments | No webhook / PENDING cleanup / refund automation | Section 6.8 |
| Prisma usage | Occasional non-singleton PrismaClient | me.service.js notifications |
| Frontend cache | No React Query; lists refetch locally | Section 4.4 |
| Secrets | Ensure .env never committed; rotate keys exposed in chat/history | .env / .env.example |
Suggested developer review order
prisma/schema.prisma — models & indexes
routes/v1/index.js + one full feature slice (e.g. appointments)
services/payment.service.js + services/razorpay.service.js + frontend bookWithPayment.js
services/cache.service.js + middlewares/cache.middleware.js + public catalog routes
middlewares/auth.middleware.js + utils/jwt.util.js + config/panelRegistry.js
- User booking UI (
UserBookingPage.jsx, BookingModal.jsx)
↑ top
11 Quick File Index
| Theme | Primary files |
| API aggregation | routes/v1/index.js |
| Modularity / panels | config/panelRegistry.js, utils/businessScope.util.js |
| Data design | prisma/schema.prisma |
| Cache | services/cache.service.js, middlewares/cache.middleware.js, routes/v1/publicCatalog.routes.js |
| DB client | models/prisma.client.js, repositories/* |
| Payments | services/razorpay.service.js, services/payment.service.js, routes/v1/payments.routes.js, resources/views/src/utils/bookWithPayment.js, resources/views/src/utils/razorpayCheckout.js, resources/views/src/services/paymentService.js |
| Auth | utils/jwt.util.js, middlewares/auth.middleware.js, loaders/express.js |
| Validation | middlewares/validate.middleware.js, validations/* |
| Booking UX | resources/views/src/pages/user/UserBookingPage.jsx, resources/views/src/components/user/BookingModal.jsx |
| Appointment create | services/me.service.js L229–270 |
Document control
| Field | Value |
| Document | Client Technical Code Review — File & Line-Number Map |
| Audience | Client technical lead / developer reviewers |
| Scope | Code modularity, data design, cache, DB, payments, auth, API, frontend |
| Citation style | Path + line numbers (LOC) as of documentation generation |
| Note | Line numbers may shift slightly after future commits; use symbol/function names as secondary anchors |
↑ top