# PLAN 07-01: Fix coupon stdClass method call crash

## Goal
Fix Fatal Error when placing an order with a coupon code — `stdClass::is_one_time()` undefined method.

## Bug Analysis

**Error**: `Call to undefined method stdClass::is_one_time()` at `OrderRepository.php:793`
**Stack**: `ShopBasketController::basketSave()` → `OrderRepository::createFromBasket()`

**Root cause**: `CouponRepository::findByName()` returns `(object)$coupon` — a plain `stdClass`. Line 793-794 in `OrderRepository::createFromBasket()` call `$coupon->is_one_time()` and `$coupon->set_as_used()` as if `$coupon` were a domain object with methods. `stdClass` has no methods.

**Impact**: CRITICAL — no orders with coupon codes can be placed (Fatal Error crashes the page).

## Tasks

### T1: Fix OrderRepository::createFromBasket() coupon handling
**File**: `autoload/Domain/Order/OrderRepository.php` (lines 793-795)

**Current (broken)**:
```php
if ($coupon && $coupon->is_one_time()) {
    $coupon->set_as_used();
}
```

**Fix**:
```php
if ($coupon && (int)$coupon->one_time === 1) {
    (new \Domain\Coupon\CouponRepository($this->db))->markAsUsed((int)$coupon->id);
}
```

**Rationale**:
- `one_time` is a property on stdClass (from `findByName()` casting)
- `CouponRepository::markAsUsed()` already exists (line 235) — sets `used=1` and `date_used`
- Consistent with how `incrementUsedCount()` is already called on line 722

### T2: Add test for coupon one-time marking in order creation
**File**: `tests/Unit/Domain/Order/OrderRepositoryTest.php` (or new if needed)

Verify that when `$coupon->one_time === 1`, `markAsUsed` is called on the coupon repository.

## Acceptance Criteria

- [ ] Orders with coupon codes complete without Fatal Error
- [ ] One-time coupons are correctly marked as used after order
- [ ] Non-one-time coupons are NOT marked as used
- [ ] Existing tests pass (`./test.ps1`)

## Risk Assessment

- **Low risk** — single-line property access fix, uses existing `markAsUsed()` method
- **No schema changes** needed
- **No side effects** — logic remains identical, just uses correct API

## Estimated Scope
~5 lines changed in 1 file. Minimal.
