# retail-demo — Claude Context

## Stack
- **Framework**: Laravel 10, PHP 8.1
- **Auth**: Laravel Sanctum + custom middleware (`auth.session`, `auth_api`, `api.role`, `api.permission`)
- **Excel**: `rap2hpoutre/fast-excel` (already installed)
- **PDF**: `barryvdh/laravel-dompdf`, `spatie/browsershot`
- **Permissions**: `spatie/laravel-permission`

## Project Layout
```
app/
  Http/Controllers/Dashboard/   # Admin API controllers
  Http/Controllers/Pos/         # Cashier/POS controllers
  Services/Dashboard/           # Business logic layer
  Repositories/Dashboard/       # Data access layer
  Models/                       # Eloquent models
  Traits/UploadFile.php         # File upload helper
routes/api/v1/
  dashboard.php                 # All dashboard routes (prefix: /v1/dashboard)
  pos.php                       # POS routes
```

## Auth & Roles
- Roles: `superadmin`, `admin`, `cashier`, `chief`
- Dashboard routes require `auth.session` + `auth_api` + `api.role:admin|superadmin`
- Permissions checked via `api.permission:item.read|item.create` etc.
- Authenticated user available as `$request->user` (not `$request->user()`)

## Key Models
| Model | Table | Notes |
|-------|-------|-------|
| Item | items | name, name_ar, slug, price, sku, unit, has_price, is_weight, is_custom |
| Category | categories | has `code` field used in SKU generation |
| ItemBranchStock | item_branch_stocks | item_id, branch_id, stock, min_stock |
| Attachment | attachments | polymorphic; type='image' for item images |

## Service Pattern
Controllers call Services which call Repositories.  
Services use `DB::beginTransaction()` / `DB::commit()` for multi-step writes.  
Repository `update(Item $item, array $data)` calls `$item->update($data)` directly.

## Item SKU Generation
`ItemService::generateItemSku(categoryId, hasPrice, hasWeight)` — uses `CAST(RIGHT(sku,4) AS UNSIGNED)` ordering with a DB lock. Pass `generate_sku=1` in store request to auto-generate.

## Excel Import/Export (Items)
- **Export** `GET /v1/dashboard/items/export` — downloads `items.xlsx` with columns: id, name, sku, price; optional query param `category_id` filters by category (filename becomes `items_category_{id}.xlsx`)
- **Import** `POST /v1/dashboard/items/import` — field: `file` (xlsx/xls/csv)
  - Matches row by `id`; updates existing item (name, sku, price) or creates new one
  - New items get defaults: has_price=1, is_weight=0, is_custom=0, slug=Str::slug(name)
  - Returns `{ created, updated, errors[] }`

## Routes Prefix
All dashboard API routes: `/v1/dashboard/<resource>/<action>`  
Example: `POST /v1/dashboard/items/create`

## Conventions
- Controllers return `response()->json(['success' => true|false, ...], status)`
- Use `$request->validate([...])` inline for simple validations; dedicated `Request` classes for store/update
- No trailing commas in route group closures
