---
description: POS transaction flow. 10 steps. All-or-nothing.
globs: ["app/Domain/POS/**", "app/Livewire/POS/**", "resources/views/livewire/pos/**"]
---

# POS — The 10-Step Flow

ALL steps happen within ONE `DB::transaction`. If any step fails, NOTHING is committed.

## Steps

1. **Identify participant** (optional for walk-in product sales, required for enrollment)
2. **Add items** — product (check stock), kit (check component availability), program (check prerequisites)
3. **Calculate prices** — each item through pricing engine individually
4. **Apply coupon** (validate all 8 checks)
5. **Calculate totals** — subtotal, discount, tax, total
6. **Select payment method** — cash, card, wallet, split
7. **Validate payment** — wallet balance check with lockForUpdate
8. **Commit transaction** (single DB::transaction):
   - pos_transactions + items
   - invoice + items
   - payment(s) + double-entry transactions
   - wallet deduction (if wallet)
   - inventory movements (if tracked products/kits)
   - enrollment record (if program)
   - session totals update
9. **Generate receipt** — number format: `RCP-{BRANCH}-{YYYYMMDD}-{SEQ}`
10. **Dispatch events** — POSTransactionCompleted, EnrollmentCreated (if applicable)

## Guards (BLOCK sale if)

- No POS session open → "يجب فتح وردية أولاً"
- Participant suspended → block new purchases (allow paying outstanding balance only)
- Duplicate enrollment → "مسجل بالفعل في هذا البرنامج"
- Split payment doesn't cover total → "المبلغ المدفوع أقل من الإجمالي"
- Cart empty → disable submit

## Product Out of Stock

- Show warning with remaining quantity
- Allow admin override (sell what's physically there)
- Movement still created (stock goes to 0 or negative with flag)

## POS Session

- One open session per user per branch at a time
- Must be open before any sale
- Links to cash_session for financial reconciliation
- Tracks: transactions_count, total_sales
