# Structure

How the codebase is organised and where each kind of logic belongs. Keeps
controllers thin and business logic in predictable places.

## Layout
```
app/
  Actions/            # Single-purpose write operations (PlaceOrder, IssueStoreCredit...)
  Enums/              # Backed enums for all controlled status/type values
  Http/
    Controllers/      # Thin: validate -> delegate -> respond
    Requests/         # Form Requests for validation (all substantial forms)
    Middleware/
  Livewire/           # Storefront components (cart, product, checkout...)
  Models/             # Eloquent models (relations, casts, scopes only)
  Policies/           # Authorization per model
  Services/           # Reusable domain logic (PricingService, GoldPriceProvider...)
  Support/            # Value objects, helpers (Money, etc.)
  Payments/           # PaymentGateway interface + implementations
config/
database/
  migrations/
  factories/
  seeders/
resources/
  views/
    components/       # Blade components (hero.blade.php, jewellery/ring.blade.php)
    pages/  layouts/  partials/
  css/                # theme.css (design tokens) + Tailwind, built via Vite
  js/                 # Alpine
routes/
  web.php  auth.php
lang/
  ms/  en/            # UI translation strings (default locale: ms)
tests/
  Feature/  Unit/
```
Admin is built with Filament (resources under `app/Filament/`), or hand-built
Livewire if Filament lacks Laravel 13 support.

## Module boundaries
Group work by domain. Each module owns its models, service(s), actions,
policies, form requests, and Livewire/Filament screens.

- **Catalog** — categories, products, variations, images, search.
- **Pricing** — `gold_prices`, `PricingService`, `GoldPriceProvider`.
- **Cart** — cart + items, live price rendering.
- **Order** — orders, order_items (price snapshot), checkout, `PlaceOrder` action.
- **Payment** — `PaymentGateway` interface, gateway impl, callback handling.
- **StoreCredit** — store_credits + ledger; issue/redeem actions.
- **TradeIn** — requests + items, approval workflow.
- **Affiliate** — affiliates, referrals, attribution, commission calc.
- **Review** — reviews, moderation.
- **Cms** — static/editorial pages.

## Where logic goes
- **Controllers / Livewire components:** thin. Validate (via Form Request /
  `rules()`), authorize (policy/gate), delegate to a Service or Action, return view/redirect.
- **Actions:** one write use-case each (e.g. `PlaceOrder`, `ApproveTradeIn`,
  `RedeemStoreCredit`). Wrap multi-step writes in DB transactions.
- **Services:** reusable/read logic and calculations (e.g. `PricingService`,
  `ShippingCalculator`). Stateless where possible.
- **Models:** relationships, casts, query scopes. No business rules.
- **Policies:** every ownership/authorization check (orders, affiliate dashboard,
  trade-ins, store credit).
- **Form Requests:** all non-trivial input validation.
- **Enums:** every controlled value (OrderStatus, TradeInStatus, Purity, etc.).

## Conventions
- **Money:** integer cents everywhere; format at the view layer only.
- **Weight:** `decimal(6,2)` grams.
- **Status/type columns:** backed enums, never free text.
- **Price snapshots:** `order_items` freeze weight, purity, gold price, upah,
  unit price at placement. Never recompute a placed order.
- **Mass assignment:** explicit `$fillable`; sensitive fields (`price_override`,
  balances, statuses) excluded from storefront input.
- **Queries:** eager-load relations to avoid N+1; paginate every list.
- **Naming:** descriptive, in English for code (variables, methods, columns,
  routes). User-facing copy is bilingual (BM + English) via translation files —
  never hardcode display strings. Tables snake_case plural; models singular;
  routes kebab-case.
- **Localization:** UI strings live in `lang/ms/*.php` and `lang/en/*.php`,
  accessed with `__()` / `@lang`. Translatable DB content (product name/
  description, category name, CMS pages) uses locale-keyed JSON columns
  (spatie/laravel-translatable). Default locale BM; locale resolved by
  middleware and persisted in session.
- **Return types:** explicit and strict on public methods.
- **Tenancy:** single store (not multi-tenant); "branch" (Nilai/TTDI) is a data
  attribute, not a tenancy boundary.
- **Theme:** colours/typography come from tokens in `resources/css/theme.css`
  (mapped into Tailwind); never hardcode hex in components. See tech.md → Design
  system for the token table and hero spec.
- **Hero:** the animated homepage hero is a Blade component
  (`components/hero.blade.php`) with the ring as a reusable partial
  (`components/jewellery/ring.blade.php`); copy via `lang/` files.

## Testing layout
- **Feature:** checkout price-lock, authorization/IDOR (affiliate, orders),
  store-credit redemption (no double-spend), trade-in approval, payment callback
  idempotency.
- **Unit:** `PricingService`, `ShippingCalculator`, commission calculation.
