Files
Salon/CLAUDE.md
2026-03-02 00:58:00 +03:00

5.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Goal

A salon booking platform for KSA (Saudi Arabia) with Django REST API backend and React/Vite frontend. Optimized for phone-first auth (OTP via SMS/WhatsApp), Moyasar payments, Arabic locale (ar-sa), and Riyadh timezone.

Commands

Backend

# Setup (from repo root)
python3 -m venv venv && source venv/bin/activate
pip install -r backend/requirements.txt -r backend/requirements-dev.txt
cp backend/.env.example backend/.env

# Migrations and dev server (from backend/)
cd backend
python3 manage.py migrate
python3 manage.py runserver

# Seed demo data
python3 manage.py seed_demo

# Run all tests (from backend/ with venv active)
cd backend
python3 -m pytest

# Run a single test file
python3 -m pytest apps/accounts/tests/test_otp_limits.py

# Run a single test
python3 -m pytest apps/accounts/tests/test_otp_limits.py::TestClassName::test_method_name

# Run external/integration tests (hits real third-party services)
PYTEST_ADDOPTS='' python3 -m pytest -m external

Authentica E2E Testing

Set these env vars before running external tests:

  • AUTHENTICA_E2E=1
  • AUTHENTICA_API_KEY=...
  • AUTHENTICA_E2E_PHONE=... (phone that will receive OTP)
  • AUTHENTICA_E2E_CODE=... (OTP code received)

Frontend

# From frontend/
cd frontend
npm install
npm run dev      # dev server at localhost:5173, proxies /api to localhost:8000
npm run test     # vitest
npm run build

Architecture

Backend (backend/)

Django project lives in backend/salon_api/ (settings, root urls, wsgi/asgi). All domain apps are under backend/apps/:

App Responsibility
accounts Custom User model, phone/OTP auth, JWT tokens, locale preferences
salons Salon catalog, services, staff profiles, availability windows, reviews
bookings Booking lifecycle, availability/overlap validation, status transitions
payments Moyasar integration (create, capture, refund), webhook reconciliation, idempotency
notifications Booking lifecycle SMS/WhatsApp messages, stored for auditability

Service layer pattern: Business logic lives in apps/<app>/services/ (not in views). Views are thin — they validate input, call services, return responses. Keep it this way.

OTP providers (apps/accounts/services/otp.py): pluggable via OTP_PROVIDER env var. Active providers: console (dev), twilio, authentica. unifonic is a scaffold. Authentica is the recommended production provider and uses a server-side OTP flow (uses_provider_otp = True) — it generates and verifies the code itself, so the DB stores a placeholder hash.

Payment gateway (apps/payments/services/gateway.py): MoyasarGateway implements BasePaymentGateway. Amounts are always in minor units (halalas). MOYASAR_SECRET_KEY and MOYASAR_PUBLISHABLE_KEY are required.

Sync-only (MVP): All external calls (OTP sends, notifications, payment gateway) run synchronously in the request path. No task queue. See docs/adr/0001-synchronous-external-calls-mvp.md.

Database: SQLite for local dev (default), PostgreSQL via DATABASE_URL env var for production. Tests use TEST_DATABASE_URL if set.

Localization: Default language ar-sa, timezone Asia/Riyadh. UserLocaleMiddleware applies per-user locale preference.

Frontend (frontend/)

React 18 + Vite app. Entry: src/main.jsxAuthProvider wraps App.

  • Routing: react-router-dom v7 with pages in src/pages/
  • Auth: JWT tokens managed via src/contexts/AuthContext.jsx; src/components/ProtectedRoute.jsx guards private pages
  • API: src/api/client.js is the axios/fetch wrapper
  • Hooks: Domain logic extracted into src/hooks/ (e.g., useSalonSearch, usePaymentForm)
  • i18n: react-i18next configured in src/i18n/index.js; supports ar-sa and en

Tests use Vitest + Testing Library. Setup in src/test/setupTests.js.

Key Env Vars

Backend (backend/.env):

  • DJANGO_SECRET_KEY, DJANGO_DEBUG, DATABASE_URL
  • OTP_PROVIDERconsole | twilio | authentica | unifonic
  • AUTHENTICA_API_KEY, AUTHENTICA_BASE_URL, AUTHENTICA_SENDER_NAME
  • TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER, TWILIO_WHATSAPP_FROM
  • MOYASAR_SECRET_KEY, MOYASAR_PUBLISHABLE_KEY
  • NOTIFICATION_PROVIDER — defaults to OTP_PROVIDER
  • OTP_EXPIRY_MINUTES, OTP_MAX_PER_WINDOW, OTP_WINDOW_MINUTES, OTP_RESEND_COOLDOWN_SECONDS
  • CORS_ALLOWED_ORIGINS

Testing Conventions

  • Backend tests live beside their apps: apps/<app>/tests/test_*.py
  • pytest.ini marks external tests as opt-in; default runs skip them
  • Frontend tests: Vitest + Testing Library; test files colocated with source (*.test.jsx)
  • Minimum coverage: auth flows, booking validation, payment state transitions

ExecPlans

For complex features, use an ExecPlan (see PLANS.md for the full spec and active plan pointer). ExecPlans are living documents in docs/execplans/. The active plan is listed in PLANS.md. Update docs/risks.md when opening or closing a significant gap.

Coding Conventions

  • Business logic in service layers; keep views thin
  • Predictable error responses: HTTP status code + detail field
  • Comment intent, edge cases, and non-obvious business rules; skip obvious comments
  • Payment and booking flows must be idempotent and auditable
  • Phone auth must be rate-limited (enforced in otp.py via OtpRateLimitError / OtpCooldownError)