# BAOPCL Project Structure Notes

## New Modules

### Exhibition QR Tracking
- Admin routes live under `/admin/exhibitions`.
- Each exhibition owns one `scanner_links` record and uses `/scan/{token}` as its public QR target.
- QR scans create scan-event records and are also grouped into unique scanner visits/sessions.
- Leads submitted after a QR scan are linked to the exhibition, scanner link, and scanner visit where available.
- Deactivating an exhibition deactivates the QR target but preserves historical scans and leads.

### Dynamic Products
- Admin routes live under `/admin/products`.
- Public product detail pages use `/products/{product:slug}`.
- Active, non-archived products appear on the homepage product section.
- Admin product forms use BAOPCL's fixed five-product catalogue: Fresh Ginger, Organic Ginger Dry Slice, Ginger Powder, Ginger Oil, and Ginger Oleoresin.
- Admin product forms can link multiple existing available batches from a dropdown; sold-out batches are excluded from this selector.
- Selected batches stay preselected when returning to edit, and their quantity, production date, and batch details show automatically.
- Product batches can optionally link to a managed product while preserving the legacy `product_type` field.

## New Tables

### `exhibitions`
- `scanner_link_id` nullable FK to `scanner_links`
- `name`, `slug`, `location`, `starts_on`, `ends_on`, `notes`
- `is_active`

### `scanner_scan_events`
- Stores every QR scan event independently from unique sessions.
- Links to `scanner_links`, `scanner_visits`, and `exhibitions`.
- Tracks `event_uuid`, `ip_address`, `user_agent`, and `scanned_at`.

### `products`
- `name`, `slug`, `description`
- `images` JSON for multiple product images
- `specifications` JSON
- `packaging_details` JSON
- `moq`, `status`, `sort_order`
- `seo_title`, `seo_description`
- `archived_at`

## Updated Tables

### `scanner_visits`
- Added `exhibition_id`
- Added `session_uuid`
- Added `submitted_at`

### `lead_submissions`
- Added `exhibition_id`
- Added `scanner_visit_id`
- Added `submission_token` to prevent repeated form submissions from creating duplicate leads.

### `product_batches`
- Added nullable `product_id` FK to `products`.
- Existing `product_type` remains for compatibility and historical records.

## Important Routes

- `GET /scan/{token}` records QR scan events and redirects to the enquiry form.
- `GET /client-enquiry` shows the buyer enquiry form.
- `POST /client-enquiry` stores direct website or scanner-attributed leads.
- `GET /products/{product:slug}` shows a dynamic product detail page.
- `GET /quality-reports/{batch:slug}` shows available batch lab reports.
- Product detail pages show linked available batches, active batch-wise lab reports, and current approved certificates.
- `GET /admin/exhibitions/{exhibition}/leads` shows leads for one exhibition only.
- `GET /admin/exhibitions/{exhibition}/qr/svg` downloads exhibition QR as SVG.
- `GET /admin/exhibitions/{exhibition}/qr/png` downloads exhibition QR as PNG.

## Relationships

- Exhibition belongs to ScannerLink.
- Exhibition has many ScannerVisits, ScannerScanEvents, and LeadSubmissions.
- ScannerLink has one Exhibition.
- ScannerVisit belongs to Exhibition and ScannerLink.
- LeadSubmission belongs to Exhibition, ScannerLink, and ScannerVisit.
- Product has many ProductBatches.
- ProductBatch belongs to Product and has many LabReports.
