# OMS Feature Implementation Plan

## Overview

Transform Orion into a **"Lightweight OMS for Letzshop Sellers"** by building the missing features that justify the tier pricing structure.

**Goal:** Ship Essential tier quickly, then build Professional differentiators, then Business features.

## Design Decisions (Confirmed)

| Decision | Choice |
|----------|--------|
| Phase 1 scope | Invoicing + Tier Limits together |
| PDF library | WeasyPrint (HTML/CSS to PDF) |
| Invoice style | Simple & Clean (minimal design) |

---

## Current State Summary

### Already Production-Ready
- Multi-tenant architecture (Merchant → Store hierarchy)
- Letzshop order sync, confirmation, tracking
- Inventory management with locations and reservations
- Unified Order model (direct + marketplace)
- Customer model with pre-calculated stats (total_orders, total_spent)
- Team management + RBAC
- CSV export patterns (products)

### Needs to be Built
| Feature | Tier Impact | Priority |
|---------|-------------|----------|
| Basic LU Invoice (PDF) | Essential | P0 |
| Tier limits enforcement | Essential | P0 |
| Store VAT Settings | Professional | P1 |
| EU VAT Invoice | Professional | P1 |
| Incoming Stock / PO | Professional | P1 |
| Customer CSV Export | Professional | P1 |
| Multi-store view | Business | P2 |
| Accounting export | Business | P2 |

---

## Phase 1: Essential Tier (Target: 1 week)

**Goal:** Launch Essential (€49) with basic invoicing and tier enforcement.

### Step 1.1: Store Invoice Settings (1 day)

**Create model for store billing details:**

```
models/database/store_invoice_settings.py
```

Fields:
- `store_id` (FK, unique - one-to-one)
- `merchant_name` (legal name for invoices)
- `merchant_address`, `merchant_city`, `merchant_postal_code`, `merchant_country`
- `vat_number` (e.g., "LU12345678")
- `invoice_prefix` (default "INV")
- `invoice_next_number` (auto-increment)
- `payment_terms` (optional text)
- `bank_details` (optional IBAN etc.)
- `footer_text` (optional)

**Pattern to follow:** `models/database/letzshop.py` (StoreLetzshopCredentials)

**Files to create/modify:**
- `models/database/store_invoice_settings.py` (new)
- `models/database/__init__.py` (add import)
- `models/database/store.py` (add relationship)
- `models/schema/invoice.py` (new - Pydantic schemas)
- `alembic/versions/xxx_add_store_invoice_settings.py` (migration)

---

### Step 1.2: Basic Invoice Model (0.5 day)

**Create invoice storage:**

```
models/database/invoice.py
```

Fields:
- `id`, `store_id` (FK)
- `order_id` (FK, nullable - for manual invoices later)
- `invoice_number` (unique per store)
- `invoice_date`
- `seller_details` (JSONB snapshot)
- `buyer_details` (JSONB snapshot)
- `line_items` (JSONB snapshot)
- `subtotal_cents`, `vat_rate`, `vat_amount_cents`, `total_cents`
- `currency` (default EUR)
- `status` (draft, issued, paid, cancelled)
- `pdf_generated_at`, `pdf_path` (optional)

**Files to create/modify:**
- `models/database/invoice.py` (new)
- `models/database/__init__.py` (add import)
- `alembic/versions/xxx_add_invoices_table.py` (migration)

---

### Step 1.3: Invoice Service - Basic LU Only (1 day)

**Create service for invoice generation:**

```
app/services/invoice_service.py
```

Methods:
- `create_invoice_from_order(order_id, store_id)` - Generate invoice from order
- `get_invoice(invoice_id, store_id)` - Retrieve invoice
- `list_invoices(store_id, skip, limit)` - List store invoices
- `_generate_invoice_number(settings)` - Auto-increment number
- `_snapshot_seller(settings)` - Capture store details
- `_snapshot_buyer(order)` - Capture customer details
- `_calculate_totals(order)` - Calculate with LU VAT (17%)

**For Essential tier:** Fixed 17% Luxembourg VAT only. EU VAT comes in Professional.

**Files to create:**
- `app/services/invoice_service.py` (new)

---

### Step 1.4: PDF Generation (1.5 days)

**Add WeasyPrint dependency and create PDF service:**

```
app/services/invoice_pdf_service.py
```

Methods:
- `generate_pdf(invoice)` - Returns PDF bytes
- `_render_html(invoice)` - Jinja2 template rendering

**Template:**
```
app/templates/invoices/invoice.html
```

Simple, clean invoice layout:
- Seller details (top left)
- Buyer details (top right)
- Invoice number + date
- Line items table
- Totals with VAT breakdown
- Footer (payment terms, bank details)

**Files to create/modify:**
- `requirements.txt` (add weasyprint)
- `app/services/invoice_pdf_service.py` (new)
- `app/templates/invoices/invoice.html` (new)
- `app/templates/invoices/invoice.css` (new, optional)

---

### Step 1.5: Invoice API Endpoints (0.5 day)

**Create store invoice endpoints:**

```
app/api/v1/store/invoices.py
```

Endpoints:
- `POST /orders/{order_id}/invoice` - Generate invoice for order
- `GET /invoices` - List invoices
- `GET /invoices/{invoice_id}` - Get invoice details
- `GET /invoices/{invoice_id}/pdf` - Download PDF

**Files to create/modify:**
- `app/api/v1/store/invoices.py` (new)
- `app/api/v1/store/__init__.py` (add router)

---

### Step 1.6: Invoice Settings UI (0.5 day)

**Add invoice settings to store settings page:**

Modify existing store settings template to add "Invoice Settings" section:
- Merchant name, address fields
- VAT number
- Invoice prefix
- Payment terms
- Bank details

**Files to modify:**
- `app/templates/store/settings.html` (add section)
- `static/store/js/settings.js` (add handlers)
- `app/api/v1/store/settings.py` (add endpoints if needed)

---

### Step 1.7: Order Detail - Invoice Button (0.5 day)

**Add "Generate Invoice" / "Download Invoice" button to order detail:**

- If no invoice: Show "Generate Invoice" button
- If invoice exists: Show "Download Invoice" link

**Files to modify:**
- `app/templates/store/order-detail.html` (add button)
- `static/store/js/order-detail.js` (add handler)

---

### Step 1.8: Tier Limits Enforcement (1 day)

**Create tier/subscription model:**

```
models/database/store_subscription.py
```

Fields:
- `store_id` (FK, unique)
- `tier` (essential, professional, business)
- `orders_this_month` (counter, reset monthly)
- `period_start`, `period_end`
- `is_active`

**Create limits service:**

```
app/services/tier_limits_service.py
```

Methods:
- `check_order_limit(store_id)` - Returns (allowed: bool, remaining: int)
- `increment_order_count(store_id)` - Called when order synced
- `get_tier_limits(tier)` - Returns limit config
- `reset_monthly_counters()` - Cron job

**Tier limits:**
| Tier | Orders/month | Products |
|------|--------------|----------|
| Essential | 100 | 200 |
| Professional | 500 | Unlimited |
| Business | Unlimited | Unlimited |

**Integration points:**
- `order_service.py` - Check limit before creating order
- Letzshop sync - Check limit before importing

**Files to create/modify:**
- `models/database/store_subscription.py` (new)
- `app/services/tier_limits_service.py` (new)
- `app/services/order_service.py` (add limit check)
- `app/services/letzshop/order_service.py` (add limit check)

---

## Phase 2: Professional Tier (Target: 2 weeks)

**Goal:** Build the differentiating features that justify €99/month.

### Step 2.1: EU VAT Rates Table (0.5 day)

**Create VAT rates reference table:**

```
models/database/eu_vat_rates.py
```

Fields:
- `country_code` (LU, DE, FR, etc.)
- `country_name`
- `standard_rate` (decimal)
- `reduced_rate_1`, `reduced_rate_2` (optional)
- `effective_from`, `effective_until`

**Seed with current EU rates (27 countries).**

**Files to create:**
- `models/database/eu_vat_rates.py` (new)
- `alembic/versions/xxx_add_eu_vat_rates.py` (migration + seed)

---

### Step 2.2: Enhanced Store VAT Settings (0.5 day)

**Add OSS fields to StoreInvoiceSettings:**

- `is_oss_registered` (boolean)
- `oss_registration_country` (if different from merchant country)

**Files to modify:**
- `models/database/store_invoice_settings.py` (add fields)
- `alembic/versions/xxx_add_oss_fields.py` (migration)

---

### Step 2.3: VAT Service (1 day)

**Create VAT calculation service:**

```
app/services/vat_service.py
```

Methods:
- `get_vat_rate(country_code, as_of_date)` - Lookup rate
- `determine_vat_regime(seller_country, buyer_country, buyer_vat_number, is_oss)` - Returns (regime, rate)
- `validate_vat_number(vat_number)` - Format check (VIES integration later)

**VAT Decision Logic:**
1. B2B with valid VAT number → Reverse charge (0%)
2. Domestic sale → Domestic VAT
3. Cross-border + OSS registered → Destination VAT
4. Cross-border + under threshold → Origin VAT

**Files to create:**
- `app/services/vat_service.py` (new)

---

### Step 2.4: Enhanced Invoice Service (1 day)

**Upgrade invoice service for EU VAT:**

- Add `vat_regime` field to invoice (domestic, oss, reverse_charge, origin)
- Add `destination_country` field
- Use VATService to calculate correct rate
- Update invoice template for regime-specific text

**Files to modify:**
- `models/database/invoice.py` (add fields)
- `app/services/invoice_service.py` (use VATService)
- `app/templates/invoices/invoice.html` (add regime text)
- `alembic/versions/xxx_add_vat_regime_to_invoices.py`

---

### Step 2.5: Purchase Order Model (1 day)

**Create purchase order tracking:**

```
models/database/purchase_order.py
```

**PurchaseOrder:**
- `id`, `store_id` (FK)
- `po_number` (auto-generated)
- `supplier_name` (free text for now)
- `status` (draft, ordered, partial, received, cancelled)
- `order_date`, `expected_date`
- `notes`

**PurchaseOrderItem:**
- `purchase_order_id` (FK)
- `product_id` (FK)
- `quantity_ordered`
- `quantity_received`
- `unit_cost_cents` (optional)

**Files to create:**
- `models/database/purchase_order.py` (new)
- `models/database/__init__.py` (add import)
- `models/schema/purchase_order.py` (new)
- `alembic/versions/xxx_add_purchase_orders.py`

---

### Step 2.6: Purchase Order Service (1 day)

**Create PO management service:**

```
app/services/purchase_order_service.py
```

Methods:
- `create_purchase_order(store_id, data)` - Create PO
- `add_item(po_id, product_id, quantity)` - Add line item
- `receive_items(po_id, items)` - Mark items received, update inventory
- `get_incoming_stock(store_id)` - Summary of pending stock
- `list_purchase_orders(store_id, status, skip, limit)`

**Integration:** When items received → call `inventory_service.adjust_inventory()`

**Files to create:**
- `app/services/purchase_order_service.py` (new)

---

### Step 2.7: Purchase Order UI (1.5 days)

**Create PO management page:**

```
app/templates/store/purchase-orders.html
```

Features:
- List POs with status
- Create new PO (select products, quantities, expected date)
- Receive items (partial or full)
- View incoming stock summary

**Inventory page enhancement:**
- Show "On Order" column in inventory list
- Query: SUM of quantity_ordered - quantity_received for pending POs

**Files to create/modify:**
- `app/templates/store/purchase-orders.html` (new)
- `static/store/js/purchase-orders.js` (new)
- `app/api/v1/store/purchase_orders.py` (new endpoints)
- `app/routes/store_pages.py` (add route)
- `app/templates/store/partials/sidebar.html` (add menu item)
- `app/templates/store/inventory.html` (add On Order column)

---

### Step 2.8: Customer Export Service (1 day)

**Create customer export functionality:**

```
app/services/customer_export_service.py
```

Methods:
- `export_customers_csv(store_id, filters)` - Returns CSV string

**CSV Columns:**
- email, first_name, last_name, phone
- customer_number
- total_orders, total_spent, avg_order_value
- first_order_date, last_order_date
- preferred_language
- marketing_consent
- tags (if we add tagging)

**Files to create:**
- `app/services/customer_export_service.py` (new)

---

### Step 2.9: Customer Export API + UI (0.5 day)

**Add export endpoint:**

```
GET /api/v1/store/customers/export?format=csv
```

**Add export button to customers page:**
- "Export to CSV" button
- Downloads file directly

**Files to modify:**
- `app/api/v1/store/customers.py` (add export endpoint)
- `app/templates/store/customers.html` (add button)

---

## Phase 3: Business Tier (Target: 1-2 weeks)

**Goal:** Build features for teams and high-volume operations.

### Step 3.1: Multi-Store Consolidated View (2 days)

**For merchants with multiple Letzshop accounts:**

**New page:**
```
app/templates/store/multi-store-dashboard.html
```

Features:
- See all store accounts under same merchant
- Consolidated order count, revenue
- Switch between store contexts
- Unified reporting

**Requires:** Merchant-level authentication context (already exists via Merchant → Store relationship)

**Files to create/modify:**
- `app/templates/store/multi-store-dashboard.html` (new)
- `app/services/multi_store_service.py` (new)
- `app/api/v1/store/multi_store.py` (new)

---

### Step 3.2: Accounting Export (1 day)

**Export invoices in accounting-friendly formats:**

```
app/services/accounting_export_service.py
```

Methods:
- `export_invoices_csv(store_id, date_from, date_to)` - Simple CSV
- `export_invoices_xml(store_id, date_from, date_to)` - For accounting software

**CSV format for accountants:**
- invoice_number, invoice_date
- customer_name, customer_vat
- subtotal, vat_rate, vat_amount, total
- currency, status

**Files to create:**
- `app/services/accounting_export_service.py` (new)
- `app/api/v1/store/accounting.py` (new endpoints)

---

### Step 3.3: API Access Documentation (1 day)

**If not already documented, create API documentation page:**

- Document existing store API endpoints
- Add rate limiting for API tier
- Generate API keys for stores

**Files to create/modify:**
- `docs/api/store-api.md` (documentation)
- `app/services/api_key_service.py` (if needed)

---

## Implementation Order Summary

### Week 1: Essential Tier
| Day | Task | Deliverable |
|-----|------|-------------|
| 1 | Step 1.1 | Store Invoice Settings model |
| 1 | Step 1.2 | Invoice model |
| 2 | Step 1.3 | Invoice Service (LU only) |
| 3-4 | Step 1.4 | PDF Generation |
| 4 | Step 1.5 | Invoice API |
| 5 | Step 1.6 | Invoice Settings UI |
| 5 | Step 1.7 | Order Detail button |

### Week 2: Tier Limits + EU VAT Start
| Day | Task | Deliverable |
|-----|------|-------------|
| 1 | Step 1.8 | Tier limits enforcement |
| 2 | Step 2.1 | EU VAT rates table |
| 2 | Step 2.2 | OSS fields |
| 3 | Step 2.3 | VAT Service |
| 4 | Step 2.4 | Enhanced Invoice Service |
| 5 | Testing | End-to-end invoice testing |

### Week 3: Purchase Orders + Customer Export
| Day | Task | Deliverable |
|-----|------|-------------|
| 1 | Step 2.5 | Purchase Order model |
| 2 | Step 2.6 | Purchase Order service |
| 3-4 | Step 2.7 | Purchase Order UI |
| 5 | Step 2.8-2.9 | Customer Export |

### Week 4: Business Tier
| Day | Task | Deliverable |
|-----|------|-------------|
| 1-2 | Step 3.1 | Multi-store view |
| 3 | Step 3.2 | Accounting export |
| 4 | Step 3.3 | API documentation |
| 5 | Testing + Polish | Full testing |

---

## Key Files Reference

### Models to Create
- `models/database/store_invoice_settings.py`
- `models/database/invoice.py`
- `models/database/eu_vat_rates.py`
- `models/database/store_subscription.py`
- `models/database/purchase_order.py`

### Services to Create
- `app/services/invoice_service.py`
- `app/services/invoice_pdf_service.py`
- `app/services/vat_service.py`
- `app/services/tier_limits_service.py`
- `app/services/purchase_order_service.py`
- `app/services/customer_export_service.py`
- `app/services/accounting_export_service.py`

### Templates to Create
- `app/templates/invoices/invoice.html`
- `app/templates/store/purchase-orders.html`

### Existing Files to Modify
- `models/database/__init__.py`
- `models/database/store.py`
- `app/services/order_service.py`
- `app/templates/store/settings.html`
- `app/templates/store/order-detail.html`
- `app/templates/store/inventory.html`
- `app/templates/store/customers.html`
- `requirements.txt`

---

## Dependencies to Add

```
# requirements.txt
weasyprint>=60.0
```

**Note:** WeasyPrint requires system dependencies:
- `libpango-1.0-0`
- `libpangocairo-1.0-0`
- `libgdk-pixbuf2.0-0`

Add to Dockerfile if deploying via Docker.

---

## Testing Strategy

### Unit Tests
- `tests/unit/services/test_invoice_service.py`
- `tests/unit/services/test_vat_service.py`
- `tests/unit/services/test_tier_limits_service.py`
- `tests/unit/services/test_purchase_order_service.py`

### Integration Tests
- `tests/integration/api/v1/store/test_invoices.py`
- `tests/integration/api/v1/store/test_purchase_orders.py`

### Manual Testing
- Generate invoice for LU customer
- Generate invoice for DE customer (OSS)
- Generate invoice for B2B with VAT number (reverse charge)
- Create PO, receive items, verify inventory update
- Export customers CSV, import to Mailchimp

---

## Success Criteria

### Essential Tier Ready When:
- [ ] Can generate PDF invoice from order (LU VAT)
- [ ] Invoice settings page works
- [ ] Order detail shows invoice button
- [ ] Tier limits enforced on order sync

### Professional Tier Ready When:
- [ ] EU VAT calculated correctly by destination
- [ ] OSS regime supported
- [ ] Reverse charge for B2B supported
- [ ] Purchase orders can be created and received
- [ ] Incoming stock shows in inventory
- [ ] Customer export to CSV works

### Business Tier Ready When:
- [ ] Multi-store dashboard works
- [ ] Accounting export works
- [ ] API access documented
