        async placeOrder() {
            this.placing = true;
            try {
                const order = await apiClient.post(
                    `/api/v1/public/vendors/${window.vendorId}/orders`,
                    {
                        shipping_address_id: this.selectedShippingAddress,
                        billing_address_id: this.selectedBillingAddress,
                        shipping_method: 'standard',
                        payment_method: this.paymentMethod,
                        customer_notes: ''
                    }
                );
                
                this.orderNumber = order.order_number;
                this.currentStep = 4;
                
                // Clear cart from localStorage
                clearCart();
            } catch (error) {
                showNotification(error.message || 'Failed to place order', 'error');
            } finally {
                this.placing = false;
            }
        }
    }
}
</script>
{% endblock %}
```

#### Customer Order History (`templates/shop/account/orders.html`)

```html
{% extends "shop/base_shop.html" %}

{% block content %}
<div x-data="orderHistory()" x-init="loadOrders()">
    <div class="account-page">
        <h1>My Orders</h1>
        
        <template x-if="orders.length === 0 && !loading">
            <div class="empty-state">
                <p>You haven't placed any orders yet.</p>
                <a href="/shop/products" class="btn btn-primary">Start Shopping</a>
            </div>
        </template>
        
        <template x-if="orders.length > 0">
            <div class="orders-list">
                <template x-for="order in orders" :key="order.id">
                    <div class="order-card">
                        <div class="order-header">
                            <div class="order-info">
                                <h3 x-text="order.order_number"></h3>
                                <span class="order-date" x-text="formatDate(order.created_at)"></span>
                            </div>
                            <span 
                                class="badge"
                                :class="{
                                    'badge-warning': order.status === 'pending' || order.status === 'processing',
                                    'badge-info': order.status === 'confirmed' || order.status === 'shipped',
                                    'badge-success': order.status === 'delivered',
                                    'badge-danger': order.status === 'cancelled'
                                }"
                                x-text="order.status"
                            ></span>
                        </div>
                        
                        <div class="order-items">
                            <template x-for="item in order.items" :key="item.id">
                                <div class="order-item">
                                    <img :src="item.product_image" :alt="item.product_title">
                                    <div class="item-details">
                                        <p x-text="item.product_title"></p>
                                        <p class="text-muted">Qty: <span x-text="item.quantity"></span></p>
                                    </div>
                                    <p class="item-price">€<span x-text="item.total_price.toFixed(2)"></span></p>
                                </div>
                            </template>
                        </div>
                        
                        <div class="order-footer">
                            <p class="order-total">
                                Total: €<span x-text="order.total_amount.toFixed(2)"></span>
                            </p>
                            <a :href="`/shop/account/orders/${order.id}`" class="btn btn-sm">
                                View Details
                            </a>
                        </div>
                    </div>
                </template>
            </div>
        </template>
        
        <!-- Pagination -->
        <div x-show="hasMore" class="text-center mt-3">
            <button @click="loadMore()" class="btn btn-secondary" :disabled="loading">
                <span x-show="!loading">Load More</span>
                <span x-show="loading" class="loading-spinner"></span>
            </button>
        </div>
    </div>
</div>

<script>
    window.vendorId = {{ vendor.id }};
</script>
{% endblock %}

{% block extra_scripts %}
<script>
function orderHistory() {
    return {
        orders: [],
        loading: false,
        page: 0,
        hasMore: true,
        
        async loadOrders() {
            this.loading = true;
            try {
                const newOrders = await apiClient.get(
                    `/api/v1/public/vendors/${window.vendorId}/orders/my-orders?skip=${this.page * 20}&limit=20`
                );
                
                this.orders = [...this.orders, ...newOrders];
                this.hasMore = newOrders.length === 20;
            } catch (error) {
                showNotification('Failed to load orders', 'error');
            } finally {
                this.loading = false;
            }
        },
        
        async loadMore() {
            this.page++;
            await this.loadOrders();
        },
        
        formatDate(dateString) {
            return new Date(dateString).toLocaleDateString();
        }
    }
}
</script>
{% endblock %}
```

#### Vendor Order Management (`templates/vendor/orders/list.html`)

```html
{% extends "vendor/base_vendor.html" %}

{% block title %}Order Management{% endblock %}

{% block content %}
<div x-data="orderManagement()" x-init="loadOrders()">
    <!-- Page Header -->
    <div class="page-header">
        <h1>Orders</h1>
        <div class="header-actions">
            <button @click="exportOrders()" class="btn btn-secondary">
                Export Orders
            </button>
        </div>
    </div>
    
    <!-- Filters -->
    <div class="filters-bar">
        <div class="filter-group">
            <label>Status</label>
            <select x-model="filters.status" @change="loadOrders()">
                <option value="">All Statuses</option>
                <option value="pending">Pending</option>
                <option value="confirmed">Confirmed</option>
                <option value="processing">Processing</option>
                <option value="shipped">Shipped</option>
                <option value="delivered">Delivered</option>
                <option value="cancelled">Cancelled</option>
            </select>
        </div>
        
        <div class="filter-group">
            <label>Search</label>
            <input 
                type="text" 
                x-model="filters.search"
                @input.debounce.500ms="loadOrders()"
                placeholder="Order #, customer name..."
                class="form-control"
            >
        </div>
        
        <div class="filter-group">
            <label>Date From</label>
            <input 
                type="date" 
                x-model="filters.date_from"
                @change="loadOrders()"
                class="form-control"
            >
        </div>
        
        <div class="filter-group">
            <label>Date To</label>
            <input 
                type="date" 
                x-model="filters.date_to"
                @change="loadOrders()"
                class="form-control"
            >
        </div>
    </div>
    
    <!-- Orders Table -->
    <div class="card">
        <template x-if="orders.length === 0 && !loading">
            <p class="text-center text-muted">No orders found</p>
        </template>
        
        <template x-if="orders.length > 0">
            <table class="data-table">
                <thead>
                    <tr>
                        <th>Order #</th>
                        <th>Customer</th>
                        <th>Date</th>
                        <th>Items</th>
                        <th>Total</th>
                        <th>Status</th>
                        <th>Payment</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <template x-for="order in orders" :key="order.id">
                        <tr>
                            <td>
                                <strong x-text="order.order_number"></strong>
                            </td>
                            <td>
                                <div x-text="order.customer.first_name + ' ' + order.customer.last_name"></div>
                                <small class="text-muted" x-text="order.customer.email"></small>
                            </td>
                            <td x-text="formatDate(order.created_at)"></td>
                            <td x-text="order.items.length"></td>
                            <td>€<span x-text="order.total_amount.toFixed(2)"></span></td>
                            <td>
                                <span 
                                    class="badge"
                                    :class="{
                                        'badge-warning': order.status === 'pending',
                                        'badge-info': order.status === 'processing' || order.status === 'confirmed',
                                        'badge-primary': order.status === 'shipped',
                                        'badge-success': order.status === 'delivered',
                                        'badge-danger': order.status === 'cancelled'
                                    }"
                                    x-text="order.status"
                                ></span>
                            </td>
                            <td>
                                <span 
                                    class="badge"
                                    :class="{
                                        'badge-warning': order.payment_status === 'pending',
                                        'badge-success': order.payment_status === 'paid',
                                        'badge-danger': order.payment_status === 'failed'
                                    }"
                                    x-text="order.payment_status"
                                ></span>
                            </td>
                            <td>
                                <button 
                                    @click="viewOrder(order.id)" 
                                    class="btn btn-sm"
                                >
                                    View
                                </button>
                                <button 
                                    @click="showStatusModal(order)" 
                                    class="btn btn-sm btn-secondary"
                                >
                                    Update Status
                                </button>
                            </td>
                        </tr>
                    </template>
                </tbody>
            </table>
        </template>
    </div>
    
    <!-- Status Update Modal -->
    <div x-show="statusModal.show" class="modal-overlay" @click.self="statusModal.show = false">
        <div class="modal">
            <div class="modal-header">
                <h3>Update Order Status</h3>
                <button @click="statusModal.show = false" class="modal-close">×</button>
            </div>
            <div class="modal-body">
                <form @submit.prevent="updateStatus()">
                    <div class="form-group">
                        <label>Order Number</label>
                        <input 
                            type="text" 
                            :value="statusModal.order?.order_number"
                            class="form-control"
                            readonly
                        >
                    </div>
                    
                    <div class="form-group">
                        <label>Current Status</label>
                        <input 
                            type="text" 
                            :value="statusModal.order?.status"
                            class="form-control"
                            readonly
                        >
                    </div>
                    
                    <div class="form-group">
                        <label>New Status</label>
                        <select x-model="statusModal.newStatus" class="form-control" required>
                            <option value="confirmed">Confirmed</option>
                            <option value="processing">Processing</option>
                            <option value="shipped">Shipped</option>
                            <option value="delivered">Delivered</option>
                            <option value="cancelled">Cancelled</option>
                        </select>
                    </div>
                    
                    <div class="form-group" x-show="statusModal.newStatus === 'shipped'">
                        <label>Tracking Number</label>
                        <input 
                            type="text" 
                            x-model="statusModal.trackingNumber"
                            class="form-control"
                            placeholder="Enter tracking number"
                        >
                    </div>
                    
                    <div class="form-group">
                        <label>Notes (Optional)</label>
                        <textarea 
                            x-model="statusModal.notes"
                            class="form-control"
                            rows="3"
                        ></textarea>
                    </div>
                    
                    <div class="modal-footer">
                        <button type="button" @click="statusModal.show = false" class="btn btn-secondary">
                            Cancel
                        </button>
                        <button type="submit" class="btn btn-primary" :disabled="statusModal.updating">
                            <span x-show="!statusModal.updating">Update Status</span>
                            <span x-show="statusModal.updating" class="loading-spinner"></span>
                        </button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
{% endblock %}

{% block extra_scripts %}
<script>
function orderManagement() {
    return {
        orders: [],
        loading: false,
        filters: {
            status: '',
            search: '',
            date_from: '',
            date_to: ''
        },
        statusModal: {
            show: false,
            order: null,
            newStatus: '',
            trackingNumber: '',
            notes: '',
            updating: false
        },
        
        async loadOrders() {
            this.loading = true;
            try {
                const params = new URLSearchParams();
                if (this.filters.status) params.append('status', this.filters.status);
                if (this.filters.search) params.append('search', this.filters.search);
                if (this.filters.date_from) params.append('date_from', this.filters.date_from);
                if (this.filters.date_to) params.append('date_to', this.filters.date_to);
                
                this.orders = await apiClient.get(`/api/v1/vendor/orders?${params}`);
            } catch (error) {
                showNotification('Failed to load orders', 'error');
            } finally {
                this.loading = false;
            }
        },
        
        viewOrder(orderId) {
            window.location.href = `/vendor/orders/${orderId}`;
        },
        
        showStatusModal(order) {
            this.statusModal.show = true;
            this.statusModal.order = order;
            this.statusModal.newStatus = order.status;
            this.statusModal.trackingNumber = order.tracking_number || '';
            this.statusModal.notes = '';
        },
        
        async updateStatus() {
            this.statusModal.updating = true;
            try {
                await apiClient.put(
                    `/api/v1/vendor/orders/${this.statusModal.order.id}/status`,
                    {
                        status: this.statusModal.newStatus,
                        tracking_number: this.statusModal.trackingNumber,
                        notes: this.statusModal.notes
                    }
                );
                
                showNotification('Order status updated', 'success');
                this.statusModal.show = false;
                await this.loadOrders();
            } catch (error) {
                showNotification(error.message || 'Failed to update status', 'error');
            } finally {
                this.statusModal.updating = false;
            }
        },
        
        async exportOrders() {
            // Implement CSV export
            showNotification('Export feature coming soon', 'info');
        },
        
        formatDate(dateString) {
            return new Date(dateString).toLocaleDateString();
        }
    }
}
</script>
{% endblock %}
```

## ✅ Testing Checklist

### Backend Tests

#### Order Creation
- [ ] Order created successfully from cart
- [ ] Order number generated uniquely
- [ ] Order items created with product snapshots
- [ ] Inventory reserved correctly
- [ ] Customer stats updated (total_orders, total_spent)
- [ ] Cart cleared after order placement
- [ ] Order status history recorded
- [ ] Shipping/billing addresses validated
- [ ] Tax calculated correctly
- [ ] Shipping cost calculated correctly

#### Order Management
- [ ] Customer can view their order history
- [ ] Customer can view order details
- [ ] Vendor can view all orders
- [ ] Order filtering works (status, date, search)
- [ ] Order search works (order number, customer name)
- [ ] Vendor can update order status
- [ ] Status history tracked correctly
- [ ] Tracking number can be added

#### Payment Integration
- [ ] Payment method validation
- [ ] Payment status tracking
- [ ] Stripe integration ready (placeholder)

#### Notifications
- [ ] Order confirmation email sent
- [ ] Status update email sent
- [ ] Email contains correct order details

### Frontend Tests

#### Checkout Flow
- [ ] Multi-step checkout works
- [ ] Cart review displays correctly
- [ ] Address selection works
- [ ] New address creation works
- [ ] Payment method selection works
- [ ] Order summary calculates correctly
- [ ] Order placement succeeds
- [ ] Confirmation page displays
- [ ] Loading states work
- [ ] Error handling works

#### Customer Order History
- [ ] Order list displays correctly
- [ ] Order cards show correct information
- [ ] Status badges display correctly
- [ ] Order details link works
- [ ] Pagination works
- [ ] Empty state displays

#### Vendor Order Management
- [ ] Order table displays correctly
- [ ] Filters work (status, date, search)
- [ ] Order details modal works
- [ ] Status update modal works
- [ ] Status updates successfully
- [ ] Real-time status updates
- [ ] Export functionality (when implemented)

### Integration Tests

#### Complete Order Flow
- [ ] Customer adds products to cart
- [ ] Customer proceeds to checkout
- [ ] Customer completes checkout
- [ ] Order appears in customer history
- [ ] Order appears in vendor orders
- [ ] Vendor updates order status
- [ ] Customer sees status update
- [ ] Emails sent at each step

#### Vendor Isolation
- [ ] Orders scoped to correct vendor
- [ ] Customers can only see their orders
- [ ] Vendors can only manage their orders
- [ ] Cross-vendor access prevented

#### Data Integrity
- [ ] Inventory correctly reserved/updated
- [ ] Product snapshots preserved
- [ ] Customer stats accurate
- [ ] Order totals calculate correctly
- [ ] Status history maintained

## 📝 Additional Features (Optional)

### Payment Integration
- [ ] Stripe payment element integration
- [ ] Payment intent creation
- [ ] Payment confirmation handling
- [ ] Refund processing

### Email Notifications
- [ ] Order confirmation template
- [ ] Order shipped notification
- [ ] Order delivered notification
- [ ] Order cancelled notification

### Advanced Features
- [ ] Order notes/communication
- [ ] Partial refunds
- [ ] Order tracking page
- [ ] Invoice generation
- [ ] Bulk order status updates
- [ ] Order analytics dashboard

## 🚀 Deployment Checklist

### Environment Setup
- [ ] Email service configured (SendGrid, Mailgun, etc.)
- [ ] Stripe API keys configured (test and live)
- [ ] Order number prefix configured
- [ ] Tax rates configured by country
- [ ] Shipping rates configured

### Testing
- [ ] Complete checkout flow tested
- [ ] Payment processing tested (test mode)
- [ ] Email notifications tested
- [ ] Order management tested
- [ ] Mobile checkout tested

### Production Readiness
- [ ] Stripe live mode enabled
- [ ] Email templates reviewed
- [ ] Error logging enabled
- [ ] Order monitoring set up
- [ ] Backup strategy for orders

## 🎯 Acceptance Criteria

Slice 5 is complete when:

1. **Customer Checkout Works**
   - [ ] Multi-step checkout functional
   - [ ] Address management works
   - [ ] Orders can be placed successfully
   - [ ] Confirmation displayed

2. **Customer Order Management Works**
   - [ ] Order history displays
   - [ ] Order details accessible
   - [ ] Order tracking works

3. **Vendor Order Management Works**
   - [ ] All orders visible
   - [ ] Filtering and search work
   - [ ] Status updates work
   - [ ] Order details accessible

4. **System Integration Complete**
   - [ ] Inventory updates correctly
   - [ ] Emails sent automatically
   - [ ] Data integrity maintained
   - [ ] Vendor isolation enforced

5. **Production Ready**
   - [ ] All tests pass
   - [ ] Payment integration ready
   - [ ] Email system configured
   - [ ] Error handling robust

## 🎉 Platform Complete!

After completing Slice 5, your multi-tenant ecommerce platform is **production-ready** with:

✅ **Multi-tenant foundation** - Complete vendor isolation  
✅ **Admin management** - Vendor creation and management  
✅ **Marketplace integration** - CSV product imports  
✅ **Product catalog** - Vendor product management  
✅ **Customer shopping** - Browse, search, cart  
✅ **Order processing** - Complete checkout and fulfillment  

### Next Steps for Production

1. **Security Audit**
   - Review authentication
   - Test vendor isolation
   - Verify payment security
   - Check data encryption

2. **Performance Optimization**
   - Database indexing
   - Query optimization
   - Caching strategy
   - CDN setup

3. **Monitoring & Analytics**
   - Set up error tracking (Sentry)
   - Configure analytics
   - Set up uptime monitoring
   - Create admin dashboards

4. **Documentation**
   - User guides for vendors
   - Admin documentation
   - API documentation
   - Deployment guide

5. **Launch Preparation**
   - Beta testing with real vendors
   - Load testing
   - Backup procedures
   - Support system

---

**Slice 5 Status**: 📋 Not Started  
**Dependencies**: Slices 1, 2, 3, & 4 must be complete  
**Estimated Duration**: 5 days  
**Platform Status After Completion**: 🚀 Production Ready!# Slice 5: Order Processing
## Complete Checkout and Order Management

**Status**: 📋 NOT STARTED  
**Timeline**: Week 5 (5 days)  
**Prerequisites**: Slices 1, 2, 3, & 4 complete

## 🎯 Slice Objectives

Complete the ecommerce transaction workflow with checkout, order placement, and order management for both customers and vendors.

### User Stories
- As a Customer, I can proceed to checkout with my cart
- As a Customer, I can select shipping address
- As a Customer, I can place orders
- As a Customer, I can view my order history
- As a Customer, I can view order details and status
- As a Vendor Owner, I can view all customer orders
- As a Vendor Owner, I can manage orders (update status, view details)
- As a Vendor Owner, I can filter and search orders
- Order confirmation emails are sent automatically

### Success Criteria
- [ ] Customers can complete multi-step checkout process
- [ ] Address selection/creation works
- [ ] Orders are created with proper vendor isolation
- [ ] Inventory is reserved/updated on order placement
- [ ] Customers can view their order history
- [ ] Customers can track order status
- [ ] Vendors can view all their orders
- [ ] Vendors can update order status
- [ ] Order status changes trigger notifications
- [ ] Order confirmation emails sent
- [ ] Payment integration ready (placeholder for Stripe)

## 📋 Backend Implementation

### Database Models

#### Order Model (`models/database/order.py`)

```python
class Order(Base, TimestampMixin):
    """Customer orders"""
    __tablename__ = "orders"
    
    id = Column(Integer, primary_key=True, index=True)
    vendor_id = Column(Integer, ForeignKey("vendors.id"), nullable=False)
    customer_id = Column(Integer, ForeignKey("customers.id"), nullable=False)
    
    # Order identification
    order_number = Column(String, unique=True, nullable=False, index=True)
    
    # Order status
    status = Column(
        String, 
        nullable=False, 
        default="pending"
    )  # pending, confirmed, processing, shipped, delivered, cancelled
    
    # Amounts
    subtotal = Column(Numeric(10, 2), nullable=False)
    shipping_cost = Column(Numeric(10, 2), default=0)
    tax_amount = Column(Numeric(10, 2), default=0)
    discount_amount = Column(Numeric(10, 2), default=0)
    total_amount = Column(Numeric(10, 2), nullable=False)
    currency = Column(String(3), default="EUR")
    
    # Addresses (snapshot at time of order)
    shipping_address_id = Column(Integer, ForeignKey("customer_addresses.id"))
    billing_address_id = Column(Integer, ForeignKey("customer_addresses.id"))
    
    # Shipping
    shipping_method = Column(String)
    tracking_number = Column(String)
    shipped_at = Column(DateTime, nullable=True)
    delivered_at = Column(DateTime, nullable=True)
    
    # Payment
    payment_status = Column(String, default="pending")  # pending, paid, failed, refunded
    payment_method = Column(String)  # stripe, paypal, etc.
    payment_reference = Column(String)  # External payment ID
    paid_at = Column(DateTime, nullable=True)
    
    # Customer notes
    customer_notes = Column(Text)
    internal_notes = Column(Text)  # Vendor-only notes
    
    # Metadata
    ip_address = Column(String)
    user_agent = Column(String)
    
    # Relationships
    vendor = relationship("Vendor", back_populates="orders")
    customer = relationship("Customer", back_populates="orders")
    items = relationship("OrderItem", back_populates="order", cascade="all, delete-orphan")
    shipping_address = relationship("CustomerAddress", foreign_keys=[shipping_address_id])
    billing_address = relationship("CustomerAddress", foreign_keys=[billing_address_id])
    status_history = relationship("OrderStatusHistory", back_populates="order")
    
    # Indexes
    __table_args__ = (
        Index('ix_order_vendor_customer', 'vendor_id', 'customer_id'),
        Index('ix_order_status', 'vendor_id', 'status'),
        Index('ix_order_date', 'vendor_id', 'created_at'),
    )

class OrderItem(Base, TimestampMixin):
    """Items in an order"""
    __tablename__ = "order_items"
    
    id = Column(Integer, primary_key=True, index=True)
    order_id = Column(Integer, ForeignKey("orders.id"), nullable=False)
    product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
    
    # Product snapshot at time of order
    product_sku = Column(String, nullable=False)
    product_title = Column(String, nullable=False)
    product_image = Column(String)
    
    # Pricing
    quantity = Column(Integer, nullable=False)
    unit_price = Column(Numeric(10, 2), nullable=False)
    total_price = Column(Numeric(10, 2), nullable=False)
    
    # Tax
    tax_rate = Column(Numeric(5, 2), default=0)
    tax_amount = Column(Numeric(10, 2), default=0)
    
    # Relationships
    order = relationship("Order", back_populates="items")
    product = relationship("Product", back_populates="order_items")

class OrderStatusHistory(Base, TimestampMixin):
    """Track order status changes"""
    __tablename__ = "order_status_history"
    
    id = Column(Integer, primary_key=True, index=True)
    order_id = Column(Integer, ForeignKey("orders.id"), nullable=False)
    
    # Status change
    from_status = Column(String)
    to_status = Column(String, nullable=False)
    
    # Who made the change
    changed_by_type = Column(String)  # 'customer', 'vendor', 'system'
    changed_by_id = Column(Integer)
    
    # Notes
    notes = Column(Text)
    
    # Relationships
    order = relationship("Order", back_populates="status_history")
```

### Pydantic Schemas

#### Order Schemas (`models/schema/order.py`)

```python
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from decimal import Decimal

class OrderItemCreate(BaseModel):
    """Order item from cart"""
    product_id: int
    quantity: int
    unit_price: Decimal

class OrderCreate(BaseModel):
    """Create new order"""
    shipping_address_id: int
    billing_address_id: int
    shipping_method: Optional[str] = "standard"
    payment_method: str = "stripe"
    customer_notes: Optional[str] = None

class OrderItemResponse(BaseModel):
    """Order item details"""
    id: int
    product_id: int
    product_sku: str
    product_title: str
    product_image: Optional[str]
    quantity: int
    unit_price: float
    total_price: float
    tax_amount: float
    
    class Config:
        from_attributes = True

class OrderResponse(BaseModel):
    """Order details"""
    id: int
    vendor_id: int
    customer_id: int
    order_number: str
    status: str
    subtotal: float
    shipping_cost: float
    tax_amount: float
    discount_amount: float
    total_amount: float
    currency: str
    payment_status: str
    payment_method: Optional[str]
    tracking_number: Optional[str]
    customer_notes: Optional[str]
    created_at: datetime
    updated_at: datetime
    items: List[OrderItemResponse]
    
    class Config:
        from_attributes = True

class OrderStatusUpdate(BaseModel):
    """Update order status"""
    status: str = Field(..., regex="^(pending|confirmed|processing|shipped|delivered|cancelled)$")
    tracking_number: Optional[str] = None
    notes: Optional[str] = None

class OrderListFilters(BaseModel):
    """Filters for order list"""
    status: Optional[str] = None
    customer_id: Optional[int] = None
    date_from: Optional[datetime] = None
    date_to: Optional[datetime] = None
    search: Optional[str] = None  # Order number or customer name
```

### Service Layer

#### Order Service (`app/services/order_service.py`)

```python
from typing import List, Optional
from sqlalchemy.orm import Session
from datetime import datetime
from decimal import Decimal

class OrderService:
    """Handle order operations"""
    
    async def create_order_from_cart(
        self,
        vendor_id: int,
        customer_id: int,
        cart_id: int,
        order_data: OrderCreate,
        db: Session
    ) -> Order:
        """Create order from shopping cart"""
        
        # Get cart with items
        cart = db.query(Cart).filter(
            Cart.id == cart_id,
            Cart.vendor_id == vendor_id
        ).first()
        
        if not cart or not cart.items:
            raise CartEmptyError("Cart is empty")
        
        # Verify addresses belong to customer
        shipping_addr = db.query(CustomerAddress).filter(
            CustomerAddress.id == order_data.shipping_address_id,
            CustomerAddress.customer_id == customer_id
        ).first()
        
        billing_addr = db.query(CustomerAddress).filter(
            CustomerAddress.id == order_data.billing_address_id,
            CustomerAddress.customer_id == customer_id
        ).first()
        
        if not shipping_addr or not billing_addr:
            raise AddressNotFoundError()
        
        # Calculate totals
        subtotal = sum(item.line_total for item in cart.items)
        shipping_cost = self._calculate_shipping(order_data.shipping_method)
        tax_amount = self._calculate_tax(subtotal, shipping_addr.country)
        total_amount = subtotal + shipping_cost + tax_amount
        
        # Generate order number
        order_number = self._generate_order_number(vendor_id, db)
        
        # Create order
        order = Order(
            vendor_id=vendor_id,
            customer_id=customer_id,
            order_number=order_number,
            status="pending",
            subtotal=subtotal,
            shipping_cost=shipping_cost,
            tax_amount=tax_amount,
            discount_amount=0,
            total_amount=total_amount,
            currency="EUR",
            shipping_address_id=order_data.shipping_address_id,
            billing_address_id=order_data.billing_address_id,
            shipping_method=order_data.shipping_method,
            payment_method=order_data.payment_method,
            payment_status="pending",
            customer_notes=order_data.customer_notes
        )
        
        db.add(order)
        db.flush()  # Get order ID
        
        # Create order items from cart
        for cart_item in cart.items:
            # Verify product still available
            product = db.query(Product).get(cart_item.product_id)
            if not product or not product.is_active:
                continue
            
            # Check inventory
            if product.track_inventory and product.stock_quantity < cart_item.quantity:
                raise InsufficientInventoryError(f"Not enough stock for {product.title}")
            
            # Create order item
            order_item = OrderItem(
                order_id=order.id,
                product_id=cart_item.product_id,
                product_sku=product.sku,
                product_title=product.title,
                product_image=product.featured_image,
                quantity=cart_item.quantity,
                unit_price=cart_item.unit_price,
                total_price=cart_item.line_total,
                tax_rate=self._get_tax_rate(shipping_addr.country),
                tax_amount=cart_item.line_total * self._get_tax_rate(shipping_addr.country) / 100
            )
            db.add(order_item)
            
            # Reserve inventory
            if product.track_inventory:
                await self._reserve_inventory(product, cart_item.quantity, order.id, db)
        
        # Record initial status
        status_history = OrderStatusHistory(
            order_id=order.id,
            from_status=None,
            to_status="pending",
            changed_by_type="customer",
            changed_by_id=customer_id,
            notes="Order created"
        )
        db.add(status_history)
        
        # Clear cart
        db.query(CartItem).filter(CartItem.cart_id == cart_id).delete()
        
        # Update customer stats
        customer = db.query(Customer).get(customer_id)
        customer.total_orders += 1
        customer.total_spent += float(total_amount)
        
        db.commit()
        db.refresh(order)
        
        # Send order confirmation email
        await self._send_order_confirmation(order, db)
        
        return order
    
    def get_customer_orders(
        self,
        vendor_id: int,
        customer_id: int,
        db: Session,
        skip: int = 0,
        limit: int = 20
    ) -> List[Order]:
        """Get customer's order history"""
        
        return db.query(Order).filter(
            Order.vendor_id == vendor_id,
            Order.customer_id == customer_id
        ).order_by(
            Order.created_at.desc()
        ).offset(skip).limit(limit).all()
    
    def get_vendor_orders(
        self,
        vendor_id: int,
        db: Session,
        filters: OrderListFilters,
        skip: int = 0,
        limit: int = 50
    ) -> List[Order]:
        """Get vendor's orders with filters"""
        
        query = db.query(Order).filter(Order.vendor_id == vendor_id)
        
        if filters.status:
            query = query.filter(Order.status == filters.status)
        
        if filters.customer_id:
            query = query.filter(Order.customer_id == filters.customer_id)
        
        if filters.date_from:
            query = query.filter(Order.created_at >= filters.date_from)
        
        if filters.date_to:
            query = query.filter(Order.created_at <= filters.date_to)
        
        if filters.search:
            query = query.filter(
                or_(
                    Order.order_number.ilike(f"%{filters.search}%"),
                    Order.customer.has(
                        or_(
                            Customer.first_name.ilike(f"%{filters.search}%"),
                            Customer.last_name.ilike(f"%{filters.search}%"),
                            Customer.email.ilike(f"%{filters.search}%")
                        )
                    )
                )
            )
        
        return query.order_by(
            Order.created_at.desc()
        ).offset(skip).limit(limit).all()
    
    async def update_order_status(
        self,
        vendor_id: int,
        order_id: int,
        status_update: OrderStatusUpdate,
        changed_by_id: int,
        db: Session
    ) -> Order:
        """Update order status"""
        
        order = db.query(Order).filter(
            Order.id == order_id,
            Order.vendor_id == vendor_id
        ).first()
        
        if not order:
            raise OrderNotFoundError()
        
        old_status = order.status
        new_status = status_update.status
        
        # Update order
        order.status = new_status
        
        if status_update.tracking_number:
            order.tracking_number = status_update.tracking_number
        
        if new_status == "shipped":
            order.shipped_at = datetime.utcnow()
        elif new_status == "delivered":
            order.delivered_at = datetime.utcnow()
        
        # Record status change
        status_history = OrderStatusHistory(
            order_id=order.id,
            from_status=old_status,
            to_status=new_status,
            changed_by_type="vendor",
            changed_by_id=changed_by_id,
            notes=status_update.notes
        )
        db.add(status_history)
        
        db.commit()
        db.refresh(order)
        
        # Send notification to customer
        await self._send_status_update_email(order, old_status, new_status, db)
        
        return order
    
    def _generate_order_number(self, vendor_id: int, db: Session) -> str:
        """Generate unique order number"""
        from models.database.vendor import Vendor
        
        vendor = db.query(Vendor).get(vendor_id)
        today = datetime.utcnow().strftime("%Y%m%d")
        
        # Count orders today
        today_start = datetime.utcnow().replace(hour=0, minute=0, second=0)
        count = db.query(Order).filter(
            Order.vendor_id == vendor_id,
            Order.created_at >= today_start
        ).count()
        
        return f"{vendor.vendor_code}-{today}-{count+1:05d}"
    
    def _calculate_shipping(self, method: str) -> Decimal:
        """Calculate shipping cost"""
        shipping_rates = {
            "standard": Decimal("5.00"),
            "express": Decimal("15.00"),
            "free": Decimal("0.00")
        }
        return shipping_rates.get(method, Decimal("5.00"))
    
    def _calculate_tax(self, subtotal: Decimal, country: str) -> Decimal:
        """Calculate tax amount"""
        tax_rate = self._get_tax_rate(country)
        return subtotal * tax_rate / 100
    
    def _get_tax_rate(self, country: str) -> Decimal:
        """Get tax rate by country"""
        tax_rates = {
            "LU": Decimal("17.00"),  # Luxembourg VAT
            "FR": Decimal("20.00"),  # France VAT
            "DE": Decimal("19.00"),  # Germany VAT
            "BE": Decimal("21.00"),  # Belgium VAT
        }
        return tax_rates.get(country, Decimal("0.00"))
    
    async def _reserve_inventory(
        self,
        product: Product,
        quantity: int,
        order_id: int,
        db: Session
    ):
        """Reserve inventory for order"""
        
        inventory = db.query(Inventory).filter(
            Inventory.product_id == product.id
        ).first()
        
        if inventory:
            inventory.available_quantity -= quantity
            inventory.reserved_quantity += quantity
            
            # Record movement
            movement = InventoryMovement(
                inventory_id=inventory.id,
                movement_type="reserved",
                quantity_change=-quantity,
                reference_type="order",
                reference_id=order_id,
                notes=f"Reserved for order #{order_id}"
            )
            db.add(movement)
        
        # Update product stock count
        product.stock_quantity -= quantity
    
    async def _send_order_confirmation(self, order: Order, db: Session):
        """Send order confirmation email to customer"""
        # Implement email sending
        # This will be part of notification service
        pass
    
    async def _send_status_update_email(
        self,
        order: Order,
        old_status: str,
        new_status: str,
        db: Session
    ):
        """Send order status update email"""
        # Implement email sending
        pass
```

### API Endpoints

#### Customer Order Endpoints (`app/api/v1/public/vendors/orders.py`)

```python
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List

router = APIRouter()

@router.post("", response_model=OrderResponse, status_code=201)
async def create_order(
    vendor_id: int,
    order_data: OrderCreate,
    current_customer: Customer = Depends(get_current_customer),
    db: Session = Depends(get_db)
):
    """Place order from cart"""
    
    # Get customer's cart
    cart = db.query(Cart).filter(
        Cart.vendor_id == vendor_id,
        Cart.customer_id == current_customer.id
    ).first()
    
    if not cart:
        raise HTTPException(status_code=404, detail="Cart not found")
    
    service = OrderService()
    order = await service.create_order_from_cart(
        vendor_id,
        current_customer.id,
        cart.id,
        order_data,
        db
    )
    
    return order

@router.get("/my-orders", response_model=List[OrderResponse])
async def get_my_orders(
    vendor_id: int,
    skip: int = 0,
    limit: int = 20,
    current_customer: Customer = Depends(get_current_customer),
    db: Session = Depends(get_db)
):
    """Get customer's order history"""
    
    service = OrderService()
    orders = service.get_customer_orders(
        vendor_id,
        current_customer.id,
        db,
        skip,
        limit
    )
    
    return orders

@router.get("/my-orders/{order_id}", response_model=OrderResponse)
async def get_my_order(
    vendor_id: int,
    order_id: int,
    current_customer: Customer = Depends(get_current_customer),
    db: Session = Depends(get_db)
):
    """Get specific order details"""
    
    order = db.query(Order).filter(
        Order.id == order_id,
        Order.vendor_id == vendor_id,
        Order.customer_id == current_customer.id
    ).first()
    
    if not order:
        raise HTTPException(status_code=404, detail="Order not found")
    
    return order
```

#### Vendor Order Management Endpoints (`app/api/v1/vendor/orders.py`)

```python
@router.get("", response_model=List[OrderResponse])
async def get_vendor_orders(
    status: Optional[str] = None,
    customer_id: Optional[int] = None,
    date_from: Optional[datetime] = None,
    date_to: Optional[datetime] = None,
    search: Optional[str] = None,
    skip: int = 0,
    limit: int = 50,
    current_user: User = Depends(get_current_vendor_user),
    vendor: Vendor = Depends(get_current_vendor),
    db: Session = Depends(get_db)
):
    """Get vendor's orders with filters"""
    
    filters = OrderListFilters(
        status=status,
        customer_id=customer_id,
        date_from=date_from,
        date_to=date_to,
        search=search
    )
    
    service = OrderService()
    orders = service.get_vendor_orders(vendor.id, db, filters, skip, limit)
    
    return orders

@router.get("/{order_id}", response_model=OrderResponse)
async def get_order_details(
    order_id: int,
    current_user: User = Depends(get_current_vendor_user),
    vendor: Vendor = Depends(get_current_vendor),
    db: Session = Depends(get_db)
):
    """Get order details"""
    
    order = db.query(Order).filter(
        Order.id == order_id,
        Order.vendor_id == vendor.id
    ).first()
    
    if not order:
        raise HTTPException(status_code=404, detail="Order not found")
    
    return order

@router.put("/{order_id}/status", response_model=OrderResponse)
async def update_order_status(
    order_id: int,
    status_update: OrderStatusUpdate,
    current_user: User = Depends(get_current_vendor_user),
    vendor: Vendor = Depends(get_current_vendor),
    db: Session = Depends(get_db)
):
    """Update order status"""
    
    service = OrderService()
    order = await service.update_order_status(
        vendor.id,
        order_id,
        status_update,
        current_user.id,
        db
    )
    
    return order
```

## 🎨 Frontend Implementation

### Templates

#### Checkout Page (`templates/shop/checkout.html`)

```html
{% extends "shop/base_shop.html" %}

{% block content %}
<div x-data="checkout()" x-init="init()">
    <!-- Progress Steps -->
    <div class="checkout-steps">
        <div class="step" :class="{'active': currentStep >= 1, 'completed': currentStep > 1}">
            <span class="step-number">1</span>
            <span class="step-label">Cart Review</span>
        </div>
        <div class="step" :class="{'active': currentStep >= 2, 'completed': currentStep > 2}">
            <span class="step-number">2</span>
            <span class="step-label">Shipping</span>
        </div>
        <div class="step" :class="{'active': currentStep >= 3, 'completed': currentStep > 3}">
            <span class="step-number">3</span>
            <span class="step-label">Payment</span>
        </div>
        <div class="step" :class="{'active': currentStep === 4}">
            <span class="step-number">4</span>
            <span class="step-label">Confirmation</span>
        </div>
    </div>
    
    <!-- Step 1: Cart Review -->
    <div x-show="currentStep === 1" class="checkout-section">
        <h2>Review Your Cart</h2>
        <div class="cart-items">
            <template x-for="item in cart.items" :key="item.id">
                <div class="cart-item">
                    <img :src="item.product_image" :alt="item.product_title">
                    <div class="item-details">
                        <h3 x-text="item.product_title"></h3>
                        <p>Quantity: <span x-text="item.quantity"></span></p>
                        <p class="price">€<span x-text="item.line_total.toFixed(2)"></span></p>
                    </div>
                </div>
            </template>
        </div>
        
        <div class="cart-summary">
            <p>Subtotal: €<span x-text="cart.subtotal.toFixed(2)"></span></p>
            <button @click="nextStep()" class="btn btn-primary btn-lg">
                Continue to Shipping
            </button>
        </div>
    </div>
    
    <!-- Step 2: Shipping Address -->
    <div x-show="currentStep === 2" class="checkout-section">
        <h2>Shipping Address</h2>
        
        <!-- Existing Addresses -->
        <template x-if="addresses.length > 0">
            <div class="address-selection">
                <template x-for="address in addresses" :key="address.id">
                    <div 
                        class="address-card"
                        :class="{'selected': selectedShippingAddress === address.id}"
                        @click="selectedShippingAddress = address.id"
                    >
                        <input 
                            type="radio" 
                            :value="address.id"
                            x-model="selectedShippingAddress"
                        >
                        <div class="address-info">
                            <strong x-text="`${address.first_name} ${address.last_name}`"></strong>
                            <p x-text="address.address_line1"></p>
                            <p x-text="`${address.postal_code} ${address.city}`"></p>
                        </div>
                    </div>
                </template>
            </div>
        </template>
        
        <button @click="showAddressForm = true" class="btn btn-secondary">
            + Add New Address
        </button>
        
        <!-- New Address Form -->
        <div x-show="showAddressForm" class="address-form">
            <!-- Address form fields -->
        </div>
        
        <div class="checkout-actions">
            <button @click="prevStep()" class="btn btn-secondary">Back</button>
            <button 
                @click="nextStep()" 
                class="btn btn-primary"
                :disabled="!selectedShippingAddress"
            >
                Continue to Payment
            </button>
        </div>
    </div>
    
    <!-- Step 3: Payment -->
    <div x-show="currentStep === 3" class="checkout-section">
        <h2>Payment Method</h2>
        
        <div class="payment-methods">
            <div class="payment-option">
                <input type="radio" value="stripe" x-model="paymentMethod">
                <label>Credit Card (Stripe)</label>
            </div>
        </div>
        
        <!-- Stripe Payment Element -->
        <div id="payment-element">
            <!-- Stripe.js will inject payment form here -->
        </div>
        
        <div class="order-summary">
            <h3>Order Summary</h3>
            <p>Subtotal: €<span x-text="cart.subtotal.toFixed(2)"></span></p>
            <p>Shipping: €<span x-text="shippingCost.toFixed(2)"></span></p>
            <p>Tax: €<span x-text="taxAmount.toFixed(2)"></span></p>
            <p class="total">Total: €<span x-text="totalAmount.toFixed(2)"></span></p>
        </div>
        
        <div class="checkout-actions">
            <button @click="prevStep()" class="btn btn-secondary">Back</button>
            <button 
                @click="placeOrder()" 
                class="btn btn-primary btn-lg"
                :disabled="placing"
            >
                <span x-show="!placing">Place Order</span>
                <span x-show="placing" class="loading-spinner"></span>
            </button>
        </div>
    </div>
    
    <!-- Step 4: Confirmation -->
    <div x-show="currentStep === 4" class="checkout-section">
        <div class="order-confirmation">
            <h2>✓ Order Confirmed!</h2>
            <p>Thank you for your order!</p>
            <p>Order Number: <strong x-text="orderNumber"></strong></p>
            <p>We've sent a confirmation email to your address.</p>
            
            <a href="/shop/account/orders" class="btn btn-primary">
                View Order Details
            </a>
        </div>
    </div>
</div>

<script>
    window.vendorId = {{ vendor.id }};
    window.customerId = {{ customer.id if customer else 'null' }};
</script>
{% endblock %}

{% block extra_scripts %}
<script src="https://js.stripe.com/v3/"></script>
<script>
function checkout() {
    return {
        currentStep: 1,
        cart: {},
        addresses: [],
        selectedShippingAddress: null,
        selectedBillingAddress: null,
        paymentMethod: 'stripe',
        showAddressForm: false,
        placing: false,
        orderNumber: null,
        
        // Calculated
        shippingCost: 5.00,
        taxRate: 0.17,
        
        get taxAmount() {
            return this.cart.subtotal * this.taxRate;
        },
        
        get totalAmount() {
            return this.cart.subtotal + this.shippingCost + this.taxAmount;
        },
        
        async init() {
            await this.loadCart();
            await this.loadAddresses();
        },
        
        async loadCart() {
            try {
                const sessionId = getSessionId();
                this.cart = await apiClient.get(
                    `/api/v1/public/vendors/${window.vendorId}/cart/${sessionId}`
                );
            } catch (error) {
                showNotification('Failed to load cart', 'error');
            }
        },
        
        async loadAddresses() {
            try {
                this.addresses = await apiClient.get(
                    `/api/v1/public/vendors/${window.vendorId}/customers/addresses`
                );
                
                // Select default address
                const defaultAddr = this.addresses.find(a => a.is_default);
                if (defaultAddr) {
                    this.selectedShippingAddress = defaultAddr.id;
                    this.selectedBillingAddress = defaultAddr.id;
                }
            } catch (error) {
                console.error('Failed to load addresses', error);
            }
        },
        
        nextStep() {
            if (this.currentStep < 4) {
                this.currentStep++;
            }
        },
        
        prevStep() {
            if (this.currentStep > 1) {
                this.currentStep--;
            }
        },
        
        async placeOrder