# F-072 — Architect: Dynamic VAT tax rates in product edit prices tab

## Current state

`PricingSection.tsx` (admin) has **hardcoded** VAT logic:
```ts
const VAT_GENERAL = 1.21;   // hardcoded constant
const VAT_REDUCED = 1.10;    // hardcoded constant

// calcGross: gross = net * VAT_GENERAL/VAT_REDUCED
```

The dropdown has **two hardcoded options**:
```tsx
<option value="general">21% gen.</option>
<option value="reduced">10% red.</option>
```

But the DB `tax_rates` table already has **3 active rates**:
- IVA Superreducido: 4% (applies_to: `super-reduced`)
- IVA Reducido: 10% (applies_to: `reduced`)
- IVA General: 21% (applies_to: `general`)

The 4% rate is **missing** from the dropdown and calculation.

## Goal

Replace hardcoded VAT constants and dropdown with **dynamic** fetch of active tax rates from `GET /admin/tax-rates`. Also add `super-reduced` support to the backend so the 4% rate can be used.

## Scope IN

- `project/src/modules/pricing/domain/price.ts` — add `super-reduced` to `VatRate` type and `VAT_BASIS_POINTS`
- `project/src/modules/pricing/api/pricing.routes.ts` — accept 'super-reduced' in `vatRateSchema`
- `project/migrations/031_vat_super_reduced.js` — update CHECK constraints on `pricing_variant_prices.vat_rate` and `pricing_price_history` columns to include 'super-reduced'
- `project/apps/admin/src/features/products/components/sections/PricingSection.tsx` — fetch active tax rates from `GET /admin/tax-rates`, populate dropdown dynamically, use fetched rate percentages for calculations
- `project/apps/admin/src/lib/api-client.ts` — extend `VariantPrice.vatRate` type to include `super-reduced`

## Scope OUT

- Tax rates admin page (`/tax-rates`) — no changes needed, already supports activate/deactivate
- Backend pricing service — already generic, only needs domain type update
- Storefront/frontend — no changes

## Design

### Backend: add super-reduced

`price.ts`:
```ts
export type VatRate = 'general' | 'reduced' | 'super-reduced';
export const VAT_BASIS_POINTS: Record<VatRate, number> = {
  general: 2100,      // 21%
  reduced: 1000,      // 10%
  'super-reduced': 400, // 4%
};
```

`pricing.routes.ts` — `vatRateSchema`:
```ts
const vatRateSchema = z.enum(['general', 'reduced', 'super-reduced']);
```

### Migration 031

Update CHECK constraints to:
```sql
CHECK (vat_rate IN ('general', 'reduced', 'super-reduced'))
```

### PricingSection.tsx

1. Add `TaxRate[]` state for active tax rates
2. `useEffect` on mount: fetch `taxApi.list()`, filter `active === true`
3. Replace `VAT_GENERAL/VAT_REDUCED` constants with dynamic lookup:
   ```ts
   const rate = activeRates.find(r => r.appliesTo === vatRate[variantId]);
   const multiplier = 1 + (rate?.ratePercent ?? 21) / 100;
   const grossCents = Math.round(netCents * multiplier);
   ```
4. Dropdown maps `appliesTo` → option value, displays `name + ratePercent%`:
   ```tsx
   {activeRates.map(r => (
     <option key={r.appliesTo} value={r.appliesTo}>
       {r.name} ({r.ratePercent}%)
     </option>
   ))}
   ```
5. `setVatRate` stores `appliesTo` key (e.g. `'super-reduced'`) as the vat rate value
6. Default: use first active rate if none selected

### Admin api-client

Extend `VariantPrice.vatRate` type to include `'super-reduced'`:
```ts
vatRate: 'general' | 'reduced' | 'super-reduced';
```

## Risk

- **Low risk**: adding a new allowed value to an existing enum + updating a CHECK constraint; no data migration needed (existing data already uses 'general' or 'reduced')
- **Risk mitigation**: migration is additive (adds 'super-reduced' to allowed values, doesn't remove any); rollback simply reverts constraint

## Verification

- `npx tsc --noEmit` on all projects
- `npx eslint` on changed files
- Apply migration 031 to dev DB
- Backend rebuilt and restarted
- API test: `PATCH /pricing/variants/:id` with `vatRate: 'super-reduced'` → HTTP 200
- Admin product edit → pricing tab → dropdown shows all 3 active rates
- `./scripts/verify.sh` green
