# Track Pricing Package Flow

## Pricing Rule

Each pricing row is one unique combination:

- Program: `track_id`
- Track Type: `track_type_id`
- Student Type: `pricing_plan_type_id`
- Package: `package_id`

Each row stores:

- `level_price`: the one-level price used as the calculation base
- `price`: the final package price
- `discount_percentage`: percentage discount for this pricing row

## Screen Flow

1. Admin opens `tracks-pricing-plan/{track}` for one program.
2. Admin selects Program Mode and Program Audience.
3. The UI resolves both selects to the hidden `track_type_id`, using the same Track Type parsing flow used in `track_slots.blade.php`.
4. Admin selects Student Type.
5. Admin selects Package.
6. Admin enters Price only when the selected package has `levels_count = 1`.
7. For packages with `levels_count > 1`, the UI shows a calculated readonly Price from the matching one-level row.
8. Admin optionally enters Discount Percentage.
9. AJAX save creates or updates the row for the exact combination.

## Validation

The backend validates:

- `track_type_id` is required and must exist in `track_types`.
- `pricing_plan_type_id` is required.
- `package_id` is required.
- `discount_percentage` is nullable, numeric, and between 0 and 100.
- If the package has `levels_count = 1`, `price` is required and saved as `level_price`.
- If the package has `levels_count > 1`, `price` is calculated from the matching one-level row:

```text
price = one_level_price * selected_package.levels_count
```

If no one-level row exists for the same program, track type, and student type, save fails.

Uniqueness is enforced by:

```text
track_id + track_type_id + pricing_plan_type_id + package_id
```

If the combination already exists, save updates the existing row.

## Invoice Price Lookup

Invoice creation must look up pricing with the selected package:

```text
track_id + track_type_id + pricing_plan_type_id + package_id
```

Invoice creation uses saved `price` directly, then applies `discount_percentage`.
