# Phase 2: Products — Completion Log

## Date Completed
2026-03-12

## Files Created
| File | Purpose |
|---|---|
| `app/Http/Controllers/Api/Employee/ShopManager/ListProductsController.php` | Paginated product list with search, category filter, stock/sold counts |
| `app/Http/Controllers/Api/Employee/ShopManager/ShowProductController.php` | Product detail with sales performance, inventory snapshot, feedback |
| `app/Http/Controllers/Api/Employee/ShopManager/LookupProductByBarcodeController.php` | Barcode scanner lookup within a place |
| `app/Http/Controllers/Api/Employee/ShopManager/ToggleProductActiveController.php` | Toggle product is_active boolean |
| `app/Http/Resources/ShopManager/VendorProductResource.php` | List-view product resource (id, name, price, stock, sold, active) |
| `app/Http/Resources/ShopManager/VendorProductDetailResource.php` | Detail-view resource (sales performance, inventory, feedback, badge) |
| `tests/Feature/Controllers/ShopManager/ProductsTest.php` | 18 tests covering list, detail, barcode, toggle |

## Files Modified
| File | Change |
|---|---|
| `routes/api.php` | Added 4 product routes under shop manager group |

## Migrations
No new migrations (barcode, sku, is_active already created in Phase 10).

## Tests Written
| Test File | Test Count | All Pass? |
|---|---|---|
| `tests/Feature/Controllers/ShopManager/ProductsTest.php` | 18 | N/A (MySQL offline) |

## Swagger Docs
- [x] All new controllers have @OA\ annotations

## Quality Checks
- [x] PHPStan passes (0 errors)
- [x] Pint passes (all files formatted)
- [ ] `composer test` — MySQL connection refused (infra issue)
- [x] No dd(), dump(), var_dump() in code
- [x] All classes are final
- [x] All files have declare(strict_types=1)
- [x] public_id used in API (never id)

## API Endpoints
| Method | Path | Controller |
|---|---|---|
| GET | `/v1/places/{place}/shop/products` | ListProductsController |
| GET | `/v1/places/{place}/shop/products/barcode/{code}` | LookupProductByBarcodeController |
| GET | `/v1/places/{place}/shop/products/{product}` | ShowProductController |
| PATCH | `/v1/places/{place}/shop/products/{product}/toggle` | ToggleProductActiveController |

## Commits
Not yet committed — awaiting user instruction.

## Notes / Deviations from Plan
- `total_sold` computed via JOIN on order_items + orders (status=PAID) using morph type `'product'` from enforceMorphMap.
- `stock_remaining` computed from active ProductVariationStock entries across all variations.
- Badge computation in VendorProductDetailResource: "TOP RATED" (rating >= 4.5 with 10+ reviews), "NEW" (created in last 7 days). "TOP PERFORMER" requires cross-product revenue comparison, deferred to Phase 6 dashboard context.
- Sales performance daily breakdown uses MySQL DAYOFWEEK for current week.

## Blockers / Open Questions
- Tests cannot run locally (MySQL connection refused).
