# B2B Trade Module

Adds trade account registration, tier-based pricing, and pay-on-account checkout for B2B customers.

## Features

- Trade customer registration with admin approval workflow
- Tier-based pricing with per-item trade prices and tier discounts
- Pay on Account at checkout — orders are fulfilled immediately, payment collected later
- PO number generation for each account order
- Member-facing outstanding orders page with batch payment
- Overdue payment reminder emails (scheduled daily)
- Admin dashboard for managing customers, tiers, pricing, and orders

## Configuration

| `.env` variable | Default | Description |
|---|---|---|
| `B2B_ENABLED` | `true` | Enable/disable the module |
| `B2B_PO_PREFIX` | `PO` | Prefix for generated PO numbers (e.g. `PO-00001`) |
| `B2B_OVERDUE_DAYS` | `30` | Days before an unpaid order is considered overdue |
| `B2B_REMINDER_INTERVAL_DAYS` | `7` | Minimum days between overdue reminder emails per order |
| `B2B_PAY_ON_ACCOUNT_ENABLED` | `true` | Enable/disable Pay on Account at checkout and the outstanding orders flow |

## Payment Gateway Integration

The B2B pay-outstanding-orders flow is fully implemented except for the gateway-specific layer. **This must be completed once the client confirms which payment gateway they are using.**

There are exactly two places to implement:

### 1. `templates/b2b/pay_orders.twig`

This is the payment initiation page shown to the customer before they pay. Replace the placeholder comment with the gateway's payment form.

```twig
{# TODO: Replace with gateway payment form #}
{# Examples:
   - Realex: render the HPP form pointing to the Realex hosted payment page
   - Judopay: render the Judopay SDK widget
   - EvoPay: render the EvoPay payment form
#}
```

### 2. `Http/Controllers/TradeAccountController::verifyGatewayCallback()`

This method is called when the customer is redirected back from the gateway after payment. It must verify the callback is genuine before marking orders as paid.

```php
private function verifyGatewayCallback(Request $request): bool
{
    // TODO: Implement gateway-specific verification, e.g.:
    //
    // Realex: validate HMAC-SHA256 hash of the response parameters
    // Judopay: fetch the transaction from the Judopay API server-side and check status
    // EvoPay: validate the callback hash per EvoPay documentation
}
```

> **Important:** Until this is implemented, the callback intentionally returns `false` in production, blocking any attempt to mark orders as paid via an unverified redirect. The full payment flow (session management, `markOrdersPaid`, confirmation emails, order status updates) requires no further changes — only these two gateway-specific pieces.

## Migrations

```sh
php artisan migrate
```

Migrations are auto-loaded by the service provider. Tables created:

| Table | Purpose |
|---|---|
| `b2b_trade_tiers` | Pricing tiers with discount percentages |
| `b2b_trade_customers` | Trade customer profiles linked to members |
| `b2b_trade_addresses` | Trade customer billing addresses |
| `b2b_account_orders` | Pay-on-account orders with PO numbers |
| `b2b_po_sequence` | Sequential PO number generation |
