# Task 04: Product CRUD

## Goal
Full product management. On create: if stock_quantity is set, write the first
`product_stock_logs` entry with `movement_type = 'initial'` automatically.

## Database
- `products`, `product_files`, `product_stock_logs`

## Files
- `app/Services/Ecommerce/ProductService.php`
- `app/Services/Ecommerce/FileStorageService.php`
- `app/Services/Ecommerce/StockService.php`  ← NEW (see Task 11)
- `app/Http/Controllers/Admin/Ecommerce/ProductController.php`
- `app/Http/Controllers/Api/ProductController.php`
- `app/Http/Requests/Ecommerce/StoreProductRequest.php`
- `app/Http/Requests/Ecommerce/UpdateProductRequest.php`
- `app/Http/Resources/Ecommerce/ProductResource.php`
- `app/Http/Resources/Ecommerce/Admin/AdminProductResource.php`  ← NEW
- `resources/views/dashbord/admin/ecommerce/products/`

## ProductResource (for users) — fields
```json
{
  "id": 1,
  "name": "...",
  "digital_price": 50.00,
  "physical_price": 80.00,
  "has_active_discount": true,
  "digital_final_price": 40.00,
  "physical_final_price": 64.00,
  "stock_status": "low_stock",
  "stock_label": "Only 3 left!",
  "is_available_to_order": true,
  "category": {},
  "files": [{ "id": 1, "file_name": "...", "file_size": 204800 }]
}
```
> Raw `stock_quantity` and `currentStock()` number NEVER appear in user-facing resource.

## AdminProductResource (for admin) — additional fields
```json
{
  "stock_quantity": 100,
  "current_stock": 3,
  "total_received": 100,
  "total_sold": 97,
  "total_returned": 0,
  "total_adjusted_out": 0,
  "low_stock_threshold": 5,
  "stock_status": "low_stock"
}
```

## Steps
1. `ProductService::store(array $data, array $files)`:
   - Create product
   - If `stock_quantity` is provided → call `StockService::recordInitial($product, $qty, $admin)`
   - Attach files via `FileStorageService`
2. `ProductService::update()` → update fields, sync files; do NOT touch stock here
   (stock changes go through Task 11 screen only)
3. `ProductResource` → call model methods: `stockStatus()`, `stockLabel()`, `isAvailableToOrder()`
4. `AdminProductResource` → also call: `currentStock()`, `totalReceived()`, `totalSold()`, `totalReturned()`, `totalAdjustedOut()`
5. API `index()` supports filter `?on_discount=true` and `?stock_status=low_stock|out_of_stock`
6. Register routes
