03-commande-ecommerce

<?php
class Order {
    private array $items = [];
    private string $customerEmail;
    private string $status = 'pending';
    
    public function __construct(string $email) {
        $this->customerEmail = $email;
    }
    
    public function addItem(string $productId, int $quantity, float $price): void {
        $this->items[] = ['id' => $productId, 'qty' => $quantity, 'price' => $price];
    }
    
    public function getTotal(): float {
        $total = 0;
        foreach($this->items as $item) {
            $total += $item['price'] * $item['qty'];
        }
        return $total;
    }
    
    public function place(): bool {
        $total = $this->getTotal();
        
        $payment = new StripePayment();
        $payment->setApiKey('sk_test_123456');
        
        if(!$payment->charge($total, $this->customerEmail)) {
            return false;
        }
        
        $this->status = 'paid';
        
        $db = new PDO('mysql:host=localhost;dbname=shop','root','');
        $stmt = $db->prepare('INSERT INTO orders (customer_email,total,status) VALUES (?,?,?)');
        $stmt->execute([$this->customerEmail, $total, $this->status]);
        $orderId = $db->lastInsertId();
        
        foreach($this->items as $item) {
            $stmt = $db->prepare('INSERT INTO order_items (order_id,product_id,quantity,price) VALUES (?,?,?,?)');
            $stmt->execute([$orderId, $item['id'], $item['qty'], $item['price']]);
            
            $stmt = $db->prepare('UPDATE products SET stock = stock - ? WHERE id = ?');
            $stmt->execute([$item['qty'], $item['id']]);
        }
        
        $subject = "Commande confirmée";
        $body = "Votre commande d'un montant de $total EUR a été confirmée.";
        mail($this->customerEmail, $subject, $body);
        
        $this->notifyWarehouse($orderId);
        
        return true;
    }
    
    private function notifyWarehouse(int $orderId): void {
        $warehouseApi = new WarehouseAPI();
        $warehouseApi->setEndpoint('https://warehouse.example.com/api');
        $warehouseApi->notifyNewOrder($orderId);
    }
}

class StripePayment {
    private string $apiKey;
    public function setApiKey(string $key): void { $this->apiKey = $key; }
    public function charge(float $amount, string $email): bool { return true; }
}

class WarehouseAPI {
    private string $endpoint;
    public function setEndpoint(string $url): void { $this->endpoint = $url; }
    public function notifyNewOrder(int $id): void { /* API call */ }
}

/*
=== USER STORIES ===

US1: En tant que développeur, je veux tester la logique de commande sans appeler 
     réellement Stripe, la base de données et l'API warehouse.

US2: En tant que product owner, je veux supporter PayPal comme moyen de paiement 
     en plus de Stripe.

US3: En tant que développeur, je veux envoyer des notifications par SMS au lieu 
     d'email pour certains clients.

US4: En tant que product manager, je veux appliquer automatiquement un code promo 
     de 10% si le total dépasse 100 EUR.

US5: En tant que logisticien, je veux pouvoir utiliser une API d'entrepôt différente 
     selon la zone géographique du client.
*/