# Phase 4: New Payment Methods (POS & Cash) — Completion Log

## Date Completed
2026-03-12

## Files Created
| File | Purpose |
|---|---|
| `app/Actions/ShopManager/ProcessPosPaymentAction.php` | POS payment logic: stores receipt photo, sets payment_details, marks PAID |
| `app/Actions/ShopManager/ProcessCashPaymentAction.php` | Cash payment logic: stores cash photo, amounts, marks PAID |
| `app/Http/Controllers/Api/Employee/ShopManager/PosPayOrderController.php` | POST endpoint for POS payment with receipt photo |
| `app/Http/Controllers/Api/Employee/ShopManager/CashPayOrderController.php` | POST endpoint for cash payment with amounts + photo |
| `app/Http/Controllers/Api/Employee/ShopManager/WalletPayCartController.php` | Wallet payment wrapper for shop manager context |
| `app/Http/Controllers/Api/Employee/ShopManager/StripePayCartController.php` | Stripe Checkout session wrapper for shop manager context |
| `app/Http/Controllers/Api/Employee/ShopManager/CryptoPayCartController.php` | NOWPayments wrapper for shop manager context |
| `app/Http/Requests/ShopManager/PosPaymentRequest.php` | Validates receipt_photo (image, max 10MB) + optional terminal_id |
| `app/Http/Requests/ShopManager/CashPaymentRequest.php` | Validates amount_received, amount_returned, currency, cash_photo |
| `app/Http/Resources/ShopManager/PaymentDetailsResource.php` | Payment confirmation response (order_id, status, provider, details, receipt_url, total, paid_at) |
| `tests/Feature/Controllers/ShopManager/PaymentTest.php` | 26 tests covering POS, Cash, Wallet, cross-cutting scenarios |

## Files Modified
| File | Change |
|---|---|
| `app/Models/Order.php` | Added `HasMedia` interface, `InteractsWithMedia` trait, `registerMediaCollections()` with `payment_receipt` and `cash_photo` collections |
| `routes/api.php` | Added 5 payment routes under shop manager group + use statements |

## Migrations
No new migrations needed — `payment_details` (JSON) column already exists on orders table from Phase 1-10 foundation. Media is handled by Spatie MediaLibrary (polymorphic, no migration needed).

## Tests Written
| Test File | Test Count | All Pass? |
|---|---|---|
| `tests/Feature/Controllers/ShopManager/PaymentTest.php` | 26 | Yes |

**Total Shop Manager tests: 105 passing (295 assertions)**

## Swagger Docs
- [x] All new controllers have `@OA\` annotations
- [x] `PaymentDetailsResource` has `@OA\Schema` annotation

## Quality Checks
- [x] All 105 Shop Manager tests pass
- [x] Pint linting applied (auto-fixed style issues)
- [x] All new classes are `final`
- [x] All files have `declare(strict_types=1)`
- [x] `public_id` used in API (never `id`)
- [x] No `dd()`, `dump()`, `var_dump()` in code

## API Endpoints
| Method | Path | Controller |
|---|---|---|
| POST | `/v1/places/{place}/shop/carts/{order}/pay/pos` | PosPayOrderController |
| POST | `/v1/places/{place}/shop/carts/{order}/pay/cash` | CashPayOrderController |
| POST | `/v1/places/{place}/shop/carts/{order}/pay/wallet` | WalletPayCartController |
| POST | `/v1/places/{place}/shop/carts/{order}/pay/stripe` | StripePayCartController |
| POST | `/v1/places/{place}/shop/carts/{order}/pay/crypto` | CryptoPayCartController |

## Test Coverage Summary
### POS Payment (6 tests)
- Receipt photo required + stored on media collection
- Non-image file rejected (422)
- terminal_id optional, stored in payment_details
- Already PAID order rejected (422)
- OrderPaid event dispatched

### Cash Payment (8 tests)
- Valid amounts + photo marks order PAID
- Amounts stored in payment_details JSON
- Cash photo stored on media collection
- amount_received < total rejected (422)
- Wrong change calculation rejected (422)
- Missing photo / negative amounts rejected (422)
- Already PAID order rejected (422)
- OrderPaid event dispatched

### Wallet Payment (3 tests)
- Deducts from customer wallet, marks PAID
- Insufficient balance returns 400
- Already PAID order rejected (422)

### Cross-Cutting (9 tests)
- Empty cart rejected for POS, Cash, Wallet (422)
- Other employee's cart rejected (403)
- Payment provider correctly recorded for POS, CASH, WALLET
- PaymentDetailsResource structure verified for POS and Cash

## Architecture Decisions
- **POS & Cash are new payment types** — `DESK` is intentionally untouched (per architecture decisions). POS differs by requiring receipt photo proof.
- **Wrapper controllers for Stripe/Wallet/Crypto** — follow existing employee controller patterns adapted for shop manager middleware context. Stripe uses Checkout Sessions (same as employee flow), not PaymentIntents.
- **Change validation is server-side** — Cash payment validates `amount_returned == amount_received - order_total` with ±0.01 tolerance for float precision.
- **Media collections on Order** — `payment_receipt` (POS) and `cash_photo` (Cash) are both `singleFile()` collections via Spatie MediaLibrary.
- **No migration needed** — `payment_details` JSON column already existed; media uses polymorphic `media` table.

## Commits
Not yet committed — user to decide when to commit.

## Blockers / Open Questions
- Stripe and Crypto payment tests are not included (they require external API mocking for Stripe SDK and HTTP facade for NOWPayments). These are covered by the existing employee payment test patterns and can be added in a dedicated integration test pass.
- `./gitCheck.sh` was run but PHPStan may have timed out due to server load (per AGENT_INIT guidance). Pint auto-fixed all style issues successfully.

## Next Phase
Ready for **Phase 5: Invoices** (auto-generation on OrderPaid, PDF download, email send).
