# Task 02: Models, Enums & Relationships

## Goal
Create all models and enums. Implement all stock calculation and display methods on Product.
Create the ProductStockLog model.

## Enums (app/Enums/)
- `ProductType`      → `Digital`, `Physical`
- `DiscountType`     → `Percentage`, `Fixed`
- `StockMovement`    → `Initial`, `Restock`, `Sale`, `Return`, `Adjustment`
- `StockDirection`   → `In` (value: '+'), `Out` (value: '-')
- `OrderStatus`      → `Pending`, `Preparing`, `OnTheWay`, `Delivered`, `Completed`
- `PaymentStatus`    → `Unpaid`, `Paid`, `Failed`, `Refunded`
- `PaymentMethod`    → `CashOnDelivery`, `CreditCard`, `Online`

## Files
- `app/Enums/StockMovement.php`   ← NEW
- `app/Enums/StockDirection.php`  ← NEW
- `app/Models/Ecommerce/ProductStockLog.php` ← NEW
- `app/Models/Ecommerce/Product.php` ← primary focus
- `app/Models/Ecommerce/*.php` (all others)

## Steps
1. Create all Enums with backed `string` type
2. Create `ProductStockLog` model:
   - `$fillable`: product_id, movement_type, quantity, direction, note, order_id, admin_id
   - `$casts`: movement_type → StockMovement, direction → StockDirection
   - No `updated_at` → set `public $timestamps = false;` and manually manage `created_at`
   - Relationships: `product()`, `order()`, `admin()`
3. Update `Product` model:
   - `$casts`: discount_type → DiscountType, discount_expires_at → datetime
   - Implement ALL stock methods per relations.md:
     - `stockLogs(): HasMany`
     - `totalReceived(): int`
     - `totalSold(): int`
     - `totalReturned(): int`
     - `totalAdjustedOut(): int`
     - `currentStock(): ?int`
     - `stockStatus(): string`
     - `stockLabel(): string`
     - `isAvailableToOrder(): bool`
   - Implement all discount methods per relations.md
   - Add scopes:
     - `scopeActive()` → `where('is_active', true)`
     - `scopeInStock()` → products where `isAvailableToOrder()` would be true
     - `scopeTracksStock()` → `whereNotNull('stock_quantity')`
4. Verify in `php artisan tinker`:
   - Create a product, add `initial` stock log of 100
   - Add `sale` log of 30 → confirm `currentStock()` = 70
   - Add `return` log of 5 → confirm `currentStock()` = 75
   - Add `adjustment` direction `−` of 10 → confirm `currentStock()` = 65
   - Set `low_stock_threshold = 70` → confirm `stockStatus() = 'low_stock'`
   - Confirm `stockLabel()` = "Only 65 left!"
