beginTransaction(); $subtotal = 0; foreach ($cartItems as $item) { $subtotal += $item['price'] * $item['quantity']; } $discountAmount = (float) ($orderData['discount'] ?? 0); $deliveryPrice = (float) ($orderData['delivery_price'] ?? 2000); $finalAmount = $subtotal - $discountAmount + $deliveryPrice; $orderNumber = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999); $orderId = $this->create([ 'user_id' => $userId, 'order_number' => $orderNumber, 'customer_name' => $orderData['customer_name'], 'customer_email' => $orderData['customer_email'], 'customer_phone' => $orderData['customer_phone'], 'delivery_address' => $orderData['delivery_address'], 'delivery_region' => $orderData['delivery_region'] ?? null, 'postal_code' => $orderData['postal_code'] ?? null, 'delivery_method' => $orderData['delivery_method'] ?? 'courier', 'payment_method' => $orderData['payment_method'] ?? 'card', 'subtotal' => $subtotal, 'discount_amount' => $discountAmount, 'delivery_price' => $deliveryPrice, 'final_amount' => $finalAmount, 'promo_code' => $orderData['promo_code'] ?? null, 'status' => 'pending', 'notes' => $orderData['notes'] ?? null ]); if (!$orderId) { throw new \Exception('Не удалось создать заказ'); } foreach ($cartItems as $item) { $this->addOrderItem($orderId, $item); } $productModel = new Product(); foreach ($cartItems as $item) { $productModel->decreaseStock($item['product_id'], $item['quantity']); } $cartModel = new Cart(); $cartModel->clearCart($userId); $db->commit(); return [ 'order_id' => $orderId, 'order_number' => $orderNumber, 'final_amount' => $finalAmount ]; } catch (\Exception $e) { $db->rollBack(); throw $e; } } private function addOrderItem(int $orderId, array $item): void { $sql = "INSERT INTO order_items (order_id, product_id, product_name, quantity, product_price, total_price) VALUES (?, ?, ?, ?, ?, ?)"; $totalPrice = $item['price'] * $item['quantity']; $this->execute($sql, [ $orderId, $item['product_id'], $item['name'], $item['quantity'], $item['price'], $totalPrice ]); } public function getWithDetails(int $orderId): ?array { $sql = "SELECT o.*, u.email as user_email, u.full_name as user_full_name FROM {$this->table} o LEFT JOIN users u ON o.user_id = u.user_id WHERE o.order_id = ?"; $order = $this->queryOne($sql, [$orderId]); if ($order) { $order['items'] = $this->getOrderItems($orderId); } return $order; } public function getOrderItems(int $orderId): array { $sql = "SELECT oi.*, p.image_url FROM order_items oi LEFT JOIN products p ON oi.product_id = p.product_id WHERE oi.order_id = ?"; return $this->query($sql, [$orderId]); } public function getUserOrders(int $userId, int $limit = 50): array { $sql = "SELECT * FROM {$this->table} WHERE user_id = ? ORDER BY created_at DESC LIMIT ?"; return $this->query($sql, [$userId, $limit]); } public function getAllForAdmin(int $limit = 50): array { $sql = "SELECT o.*, u.email as user_email FROM {$this->table} o LEFT JOIN users u ON o.user_id = u.user_id ORDER BY o.created_at DESC LIMIT ?"; return $this->query($sql, [$limit]); } public function updateStatus(int $orderId, string $status): bool { $updateData = [ 'status' => $status, 'updated_at' => date('Y-m-d H:i:s') ]; if ($status === 'completed') { $updateData['completed_at'] = date('Y-m-d H:i:s'); } return $this->update($orderId, $updateData); } public function getStats(): array { $stats = []; $result = $this->queryOne("SELECT COUNT(*) as cnt FROM {$this->table}"); $stats['total'] = (int) $result['cnt']; $result = $this->queryOne( "SELECT COALESCE(SUM(final_amount), 0) as revenue FROM {$this->table} WHERE status = 'completed'" ); $stats['revenue'] = (float) $result['revenue']; $statuses = $this->query( "SELECT status, COUNT(*) as cnt FROM {$this->table} GROUP BY status" ); $stats['by_status'] = []; foreach ($statuses as $s) { $stats['by_status'][$s['status']] = (int) $s['cnt']; } return $stats; } }