Files
shopPRO/.paul/phases/07-coupon-bugfix/07-01-PLAN.md
Jacek b3233497f0 fix: naprawiono crash przy składaniu zamówienia z kuponem rabatowym
Fatal Error: Call to undefined method stdClass::is_one_time() w OrderRepository:793.
Zamieniono wywołania nieistniejących metod na stdClass na dostęp do właściwości
+ istniejącą metodę CouponRepository::markAsUsed().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:04:18 +01:00

2.1 KiB

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):

if ($coupon && $coupon->is_one_time()) {
    $coupon->set_as_used();
}

Fix:

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.