# 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.