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.

Base path: repository root (VETnCO-main/)
Stack: Node.js + Express (/api/v1) · Prisma + MySQL · React (Vite) · Redis · Razorpay
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

LayerResponsibilityEntry / aggregator
HTTP / ExpressMiddleware, mounts APIloaders/express.js
API v1 routerFeature route aggregationroutes/v1/index.js L70–102
ControllersThin HTTP handlerscontrollers/*.controller.js
ServicesBusiness logicservices/*.service.js
RepositoriesPrisma queriesrepositories/*.repository.js
Prisma schemaData modelprisma/schema.prisma
Frontend panelsMulti-app UIresources/views/src/routes/AppRoutes.jsx

Request flow (backend)

Client Express /api/v1 Feature Route Zod validate Controller Service Repository Prisma/MySQL

Health endpoints

EndpointFileLOC
Livenessroutes/v1/index.jsL40–42
Readiness (DB ping)routes/v1/index.jsL44–50
Version healthroutes/v1/index.jsL57–66
↑ top

02 Code Modularity and Reuse

2.1 — Backend layering (Route → Controller → Service → Repository)

LayerExample fileWhat to reviewLOC
Route aggregatorroutes/v1/index.jsAll feature mountsL70–102
Feature routesroutes/v1/payments.routes.jsAuth + validate + controllerL12–16
Feature routesroutes/v1/me.routes.jsUser "me" APIs(full file)
Feature routesroutes/v1/appointments.routes.jsAdmin/business appointments(full file)
Controllercontrollers/payment.controller.jsThin handlersL6–19
Controllercontrollers/me.controller.jsProfile / pets / bookings(full file)
Serviceservices/payment.service.jsPayment + booking orchestrationL26–186
Serviceservices/me.service.jsAppointment creationL229–270
Repositoryrepositories/appointment.repository.jsSelect shape + CRUDL3–170
Repositoryrepositories/transaction.repository.jsTransactions CRUD / summaryL25–139

Shared cross-cutting utilities

UtilityFileLOCPurpose
Success/error JSONutils/apiResponse.js(file)Standard API envelope
Async error wrapperutils/asyncHandler.js(file)Avoids try/catch in every controller
App errorsutils/AppError.js(file)Typed HTTP errors
Business scopingutils/businessScope.util.js(file)Restricts vendor data by panel
Panel registryconfig/panelRegistry.jsL6–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

PatternFileLOCNotes
Panel route compositionresources/views/src/routes/AppRoutes.jsx(panel imports)Admin / User / Business / Vet / Groomer
User app routesresources/views/src/routes/UserRoutes.jsxbooking ~L65–67Booking deep-link
Axios client factoryresources/views/src/services/api/createApiClient.jsrefresh ~L47–96Per-panel API + silent token refresh
Panel configresources/views/src/config/panels.jsPANEL_TYPES / ROLE_MAPRole → home path mapping
Shared list hookresources/views/src/hooks/useEntityList.js(file)Generic paginated list for admin panels
Domain hookresources/views/src/hooks/useAppointments.js(file)Composes entity list + appointment service
Payment orchestratorresources/views/src/utils/bookWithPayment.jsL9–33Shared 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

ItemLocation
MySQL datasourceprisma/schema.prisma L8–11
Connection envDATABASE_URL in .env / .env.example

3.2 — Core enums

EnumFileLOCValues / purpose
UserRoleprisma/schema.prismaL13–18SUPER_ADMIN, ADMIN, PET_OWNER, VENDOR
UserStatusprisma/schema.prismaL20–25ACTIVE / INACTIVE / PENDING / SUSPENDED
BusinessPanelTypeprisma/schema.prismaL33–40CLINIC, GROOMING, LAB, HOSTEL, VETERINARIAN, INDIVIDUAL_GROOMER
AppointmentServiceTypeprisma/schema.prisma~L248–255VET_CHECKUP, GROOMING, LAB_TEST, HOSTEL_STAY, …
AppointmentVendorTypeprisma/schema.prismaL257–264VET_CLINIC, GROOMING_CENTRE, DIAGNOSTIC_LAB, PET_HOSTEL, …
AppointmentStatusprisma/schema.prismaL266–271PENDING, CONFIRMED, COMPLETED, CANCELLED
TransactionPaymentStatusprisma/schema.prismaL1061–1066SUCCESS, PENDING, FAILED, REFUNDED
TransactionPayoutStatusprisma/schema.prismaL1068–1073PENDING, PROCESSING, PAID, HOLD

3.3 — Key models

User — prisma/schema.prisma L273–304

ConcernDetailLOC
IdentityUnique email, optional passwordL276–278
RBACrole + statusL279–280
Profile / geocity, state, addressL283–285
Relationsappointments, pets, refreshTokens, …L291–298
Indexesrole, status, cityL300–302

Pet — prisma/schema.prisma L376–403

ConcernDetailLOC
Owner FKuserId → User, cascade deleteL378, L399
Clinical fieldsbreed, vaccination, allergies, documents JSONL380–395
IndexuserIdL401
Design note: Appointment does not FK to Pet. Bookings store denormalized petName / petType (L1032–1033).

Appointment — prisma/schema.prisma L1029–1059

ConcernDetailLOC
Soft user linkoptional userId → UserL1037, L1049
Polymorphic vendorvendorType + vendorId (no Prisma FK to clinic/lab/hostel)L1040–1041
Moneyamount Decimal(10,2)L1044
Statusdefault PENDINGL1045
Free-form notesused for META JSON (hostel/lab extras)L1046
Indexescode, email, serviceType, vendorType, status, date, createdAtL1051–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

ConcernDetailLOC
Business scopepanelType + businessId (no FK)L1093–1094
Booking linkoptional appointmentId (no Prisma relation)L1095
Commission splitamount, platformFee, netAmountL1099–1101
Payment / payoutenums + paidAtL1102–1105
Indexes[panelType, businessId], paymentStatus, payoutStatus, createdAtL1111–1114

Vendor entities (parallel design)

ModelApprox. LOC in schemaNotes
VetClinic~L520–567Composite status/city index
GroomingCentre~L609–653Same pattern
DiagnosticLab~L749–797Same pattern
PetHostel~L892–945Branch self-relation
IndividualVeterinarian~L1191–1254Separate from clinic staff Veterinarian
BusinessRegistration~L420–471Onboarding / 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

BehaviorFileLOC
Hostel nights / lab tests / grooming services serialized into notes with ---META--- separatorservices/me.service.jsL232–246
Maps only Prisma Appointment columnsservices/me.service.jsL248–267
Vendor type → transaction panel mapservices/payment.service.jsL8–15
↑ top

04 Cache Usage

4.1 — Backend cache service

ItemFileLOC
Redis client + in-memory Map fallbackservices/cache.service.jsL3–9
Init (Redis if REDIS_URL, else memory)services/cache.service.jsL11–28
get / set / delete / pattern clearservices/cache.service.jsL31+

4.2 — HTTP response caching middleware

ItemFileLOC
GET-only cache, key = prefix:urlmiddlewares/cache.middleware.jsL3–44
Cache HIT / MISS headersmiddlewares/cache.middleware.jsL17, L34
Invalidate on successful mutationsmiddlewares/cache.middleware.jsL46–61

4.3 — Where cache is applied

AreaFileLOC
Public catalog TTL 300s (public prefix)routes/v1/publicCatalog.routes.jsL21, L27–54
Invalidator wired on vendor CRUD mountsroutes/v1/index.jsL36, L68, L73–97
Boot initserver.js (cacheService.init)(boot file)

Cached public endpoints (examples):

  • /public/banners, /public/searchL27–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

FindingEvidence
No TanStack React Query / Apollo cacheFrontend list state is local hooks (useEntityList), not a shared query cache
Token refresh coalescing onlycreateApiClient.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

ItemFileLOC
Singleton + globalThis reuse in non-prodmodels/prisma.client.jsL1–18
Connect on bootloaders/database.js(file)

5.2 — Repository pattern

Typical pattern: explicit select, buildWhere, parallel findMany + count for pagination.

ExampleFileLOC
Appointment filters + paginationrepositories/appointment.repository.jsL32–110
Transaction list / summaryrepositories/transaction.repository.jsL25–138
Transaction create accepts optional txrepositories/transaction.repository.jscreate method

5.3 — Atomic transactions (prisma.$transaction)

Use caseFileLOC
Payment verify: confirm appointment + create transactionservices/payment.service.jsL101–120 (primary), L131–145 (legacy)
Business approval flowsservices/businessApproval.service.js(approval transaction block)

5.4 — Query / indexing design

TopicLocationNotes
User indexesschema L300–302role, status, city
Appointment indexesschema L1051–1057missing userId / vendorId indexes
Transaction composite indexschema L1111[panelType, businessId]
Readiness SQLroutes/v1/index.js L46SELECT 1

5.5 — Deviations to review

IssueFileLOC
New PrismaClient() inside a service method (bypasses singleton)services/me.service.js~L287–288 (listNotifications)
Polymorphic IDs without FK constraintsAppointment / BusinessTransactionschema 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

FunctionLOCBehavior
getKeyIdL8–14Reads RAZORPAY_KEY_ID
#getKeySecretL16–22Reads RAZORPAY_KEY_SECRET
#getClientL24–32Lazily creates Razorpay SDK client
createOrderL34–57Amount in paise (* 100), min ₹1, attaches userId notes
fetchOrderL59–61Fetches order from Razorpay
verifyPaymentSignatureL63–70HMAC-SHA256 of orderId|paymentId

6.3 — Backend: Payment orchestration

File: services/payment.service.js

StepLOCBehavior
ConfigL27–29Exposes public Key ID only
Create orderL31–53Validates amount vs booking; pre-creates PENDING appointment; stores appointmentId in Razorpay order notes
Verify paymentL55–147Signature check → ownership check → amount check → $transaction
Confirm pathL100–120Updates appointment to CONFIRMED, creates transaction
Legacy fallbackL121–146Creates CONFIRMED appointment if no pre-created id
Commission transactionL149–183Platform 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

ItemFileLOC
Auth required (PET_OWNER / ADMIN roles)routes/v1/payments.routes.jsL12
GET /razorpay/configroutes/v1/payments.routes.jsL14
POST /razorpay/orderroutes/v1/payments.routes.jsL15
POST /razorpay/verifyroutes/v1/payments.routes.jsL16
Mounted under APIroutes/v1/index.jsL102/payments
Controllercontrollers/payment.controller.jsL6–19
Zod schemasvalidations/payment.validation.jsorder + verify + booking payload

6.5 — Frontend: payment modules

FileLOCRole
resources/views/src/services/paymentService.jsL3–13API client: config / order / verify
resources/views/src/utils/razorpayCheckout.jsL5–22, L27–79Loads Checkout.js; opens modal; returns payment ids
resources/views/src/utils/bookWithPayment.jsL9–33Orchestrates free vs paid booking
resources/views/src/pages/user/UserBookingPage.jsx~L709–717Full-page booking confirm
resources/views/src/components/user/BookingModal.jsx~L243–251Modal booking confirm

6.6 — Environment configuration

VariableTemplate fileNotes
RAZORPAY_KEY_ID.env.examplePublic key (safe for checkout)
RAZORPAY_KEY_SECRET.env.exampleServer-only — never expose to frontend
Runtime values.env (local)Must not be committed

6.7 — Payment security checks (implemented)

CheckLocation
HMAC signature verificationrazorpay.service.js L63–70; used in payment.service.js L67–74
Order belongs to requesting userpayment.service.js L76–79
Amount matches appointment / bookingpayment.service.js L35–37, L96–98, L126–128
Appointment ownershippayment.service.js L93–95
Atomic confirm + ledger writepayment.service.js L101–120
Secret never returned to clientonly keyId via config endpoint

6.8 — Payment review gaps (developer checklist)

GapWhy it matters
No Razorpay webhook handler yetAbandoned checkouts leave PENDING appointments; webhooks improve reconciliation
PENDING appointments on cancelled paymentsUser may dismiss modal after order create — cleanup / expiry job recommended
No refund API pathREFUNDED enum exists in schema but no automated refund flow
Duplicate verify riskIdempotency key / "already CONFIRMED" short-circuit should be verified by reviewer
↑ top

07 Authentication and Security

7.1 — JWT

ItemFileLOC
Production refuses weak secretsutils/jwt.util.jsL3–9
Access token TTL (default 15m)utils/jwt.util.jsL13–15
Refresh TTL (default 30 days)utils/jwt.util.jsL17–19
Sign / verifyutils/jwt.util.jsL24–37

7.2 — Auth middleware

ItemFileLOC
Bearer JWT authenticatemiddlewares/auth.middleware.jsL13–65
Business panel resolve via PANEL_REGISTRYmiddlewares/auth.middleware.jsL24–48
Role authorizemiddlewares/auth.middleware.jsL70–79
Admin / business helpersmiddlewares/auth.middleware.jsL82–100

7.3 — Express hardening

ItemFileLOC
Helmetloaders/express.jsL21–26
CORS allow-listloaders/express.jsL32–48
Rate limit 300 / 15 min on /api/loaders/express.jsL51–59
JSON body limit 2mbloaders/express.jsL61–62

7.4 — Frontend session

ItemFileNotes
Silent refresh on 401resources/views/src/services/api/createApiClient.jsCoalesced refresh
Panel role mapsresources/views/src/config/panels.jsUSER → PET_OWNER
↑ top

08 API Structure and Validation

8.1 — Aggregation

ItemFileLOC
Mount /api/v1loaders/express.js~L93
Feature mountsroutes/v1/index.jsL70–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

ItemFileLOC
validate(schema) factorymiddlewares/validate.middleware.jsL3–28
Writes coerced values back to reqmiddlewares/validate.middleware.jsL21–24
Payment schemasvalidations/payment.validation.js(full file)
Public catalog schemasvalidations/publicCatalog.validation.jsused 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)

StepFileLOC
Route /booking/:categoryKey/:providerIdUserRoutes.jsx~L65–67
Category → serviceType / vendorType mapUserBookingPage.jsx / BookingModal.jsxCATEGORY_CONFIG at top of files
Build payload + amountUserBookingPage.jsxconfirm handler (~L637–706)
Pay then bookbookWithPayment.jsL9–33
Persist extras in notesme.service.jsL232–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

  1. Clear layered modularity (routes / controllers / services / repositories)
  2. Panel registry avoids duplicated vendor-auth logic
  3. Zod validation at the HTTP boundary
  4. Payment verification includes HMAC, user ownership, amount match, and $transaction
  5. Cache with Redis + memory fallback on public catalog; mutation invalidation
  6. Security basics: Helmet, CORS, rate limit, JWT production secret guard, refresh-token hashing

Areas to tighten

AreaObservationCite
Data designAppointment extras in notes instead of columnsme.service.js L232–246
Data designPolymorphic vendor / transaction IDs without FKsschema L1040–1041, L1095
IndexesMissing userId / vendorId on appointmentsschema L1051–1057
PaymentsNo webhook / PENDING cleanup / refund automationSection 6.8
Prisma usageOccasional non-singleton PrismaClientme.service.js notifications
Frontend cacheNo React Query; lists refetch locallySection 4.4
SecretsEnsure .env never committed; rotate keys exposed in chat/history.env / .env.example

Suggested developer review order

  1. prisma/schema.prisma — models & indexes
  2. routes/v1/index.js + one full feature slice (e.g. appointments)
  3. services/payment.service.js + services/razorpay.service.js + frontend bookWithPayment.js
  4. services/cache.service.js + middlewares/cache.middleware.js + public catalog routes
  5. middlewares/auth.middleware.js + utils/jwt.util.js + config/panelRegistry.js
  6. User booking UI (UserBookingPage.jsx, BookingModal.jsx)
↑ top

11 Quick File Index

ThemePrimary files
API aggregationroutes/v1/index.js
Modularity / panelsconfig/panelRegistry.js, utils/businessScope.util.js
Data designprisma/schema.prisma
Cacheservices/cache.service.js, middlewares/cache.middleware.js, routes/v1/publicCatalog.routes.js
DB clientmodels/prisma.client.js, repositories/*
Paymentsservices/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
Authutils/jwt.util.js, middlewares/auth.middleware.js, loaders/express.js
Validationmiddlewares/validate.middleware.js, validations/*
Booking UXresources/views/src/pages/user/UserBookingPage.jsx, resources/views/src/components/user/BookingModal.jsx
Appointment createservices/me.service.js L229–270

Document control

FieldValue
DocumentClient Technical Code Review — File & Line-Number Map
AudienceClient technical lead / developer reviewers
ScopeCode modularity, data design, cache, DB, payments, auth, API, frontend
Citation stylePath + line numbers (LOC) as of documentation generation
NoteLine numbers may shift slightly after future commits; use symbol/function names as secondary anchors
↑ top