Files
web_work/app/Models/Order.php
2026-01-03 18:59:56 +03:00

181 lines
5.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Models;
use App\Core\Model;
use App\Core\Database;
class Order extends Model
{
protected string $table = 'orders';
protected string $primaryKey = 'order_id';
public function createFromCart(int $userId, array $cartItems, array $orderData): ?array
{
$db = Database::getInstance();
try {
$db->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;
}
}