|
|
@@ -0,0 +1,210 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Mex\Logic;
|
|
|
+
|
|
|
+use App\Module\Mex\Models\MexOrder;
|
|
|
+use App\Module\Mex\Models\MexPriceConfig;
|
|
|
+use App\Module\Mex\Enums\OrderType;
|
|
|
+use App\Module\Mex\Enums\OrderStatus;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 农贸市场订单逻辑
|
|
|
+ *
|
|
|
+ * 处理订单相关的核心业务逻辑
|
|
|
+ */
|
|
|
+class MexOrderLogic
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 创建卖出订单
|
|
|
+ *
|
|
|
+ * @param int $userId 用户ID
|
|
|
+ * @param int $itemId 商品ID
|
|
|
+ * @param int $quantity 数量
|
|
|
+ * @param string $price 价格
|
|
|
+ * @return array 操作结果
|
|
|
+ */
|
|
|
+ public static function createSellOrder(int $userId, int $itemId, int $quantity, string $price): array
|
|
|
+ {
|
|
|
+ // 验证价格配置
|
|
|
+ $priceConfig = MexPriceConfig::where('item_id', $itemId)->where('is_enabled', true)->first();
|
|
|
+ if (!$priceConfig) {
|
|
|
+ return ['success' => false, 'message' => '商品未配置价格信息'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证卖出价格
|
|
|
+ if (bccomp($price, $priceConfig->min_price, 5) > 0) {
|
|
|
+ return ['success' => false, 'message' => "卖出价格不能高于最低价 {$priceConfig->min_price}"];
|
|
|
+ }
|
|
|
+
|
|
|
+ $totalAmount = bcmul($price, $quantity, 5);
|
|
|
+
|
|
|
+ try {
|
|
|
+ $order = MexOrder::create([
|
|
|
+ 'user_id' => $userId,
|
|
|
+ 'item_id' => $itemId,
|
|
|
+ 'order_type' => OrderType::SELL,
|
|
|
+ 'quantity' => $quantity,
|
|
|
+ 'price' => $price,
|
|
|
+ 'total_amount' => $totalAmount,
|
|
|
+ 'status' => OrderStatus::PENDING,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 卖出订单立即处理
|
|
|
+ $result = self::processSellOrderImmediately($order);
|
|
|
+
|
|
|
+ return ['success' => true, 'order_id' => $order->id, 'result' => $result];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return ['success' => false, 'message' => '创建订单失败:' . $e->getMessage()];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建买入订单
|
|
|
+ *
|
|
|
+ * @param int $userId 用户ID
|
|
|
+ * @param int $itemId 商品ID
|
|
|
+ * @param int $quantity 数量
|
|
|
+ * @param string $price 价格
|
|
|
+ * @return array 操作结果
|
|
|
+ */
|
|
|
+ public static function createBuyOrder(int $userId, int $itemId, int $quantity, string $price): array
|
|
|
+ {
|
|
|
+ // 验证价格配置
|
|
|
+ $priceConfig = MexPriceConfig::where('item_id', $itemId)->where('is_enabled', true)->first();
|
|
|
+ if (!$priceConfig) {
|
|
|
+ return ['success' => false, 'message' => '商品未配置价格信息'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证买入价格
|
|
|
+ if (bccomp($price, $priceConfig->max_price, 5) < 0) {
|
|
|
+ return ['success' => false, 'message' => "买入价格不能低于最高价 {$priceConfig->max_price}"];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证数量保护阈值
|
|
|
+ if ($quantity > $priceConfig->protection_threshold) {
|
|
|
+ return ['success' => false, 'message' => "订单数量不能超过保护阈值 {$priceConfig->protection_threshold}"];
|
|
|
+ }
|
|
|
+
|
|
|
+ $totalAmount = bcmul($price, $quantity, 5);
|
|
|
+
|
|
|
+ try {
|
|
|
+ $order = MexOrder::create([
|
|
|
+ 'user_id' => $userId,
|
|
|
+ 'item_id' => $itemId,
|
|
|
+ 'order_type' => OrderType::BUY,
|
|
|
+ 'quantity' => $quantity,
|
|
|
+ 'price' => $price,
|
|
|
+ 'total_amount' => $totalAmount,
|
|
|
+ 'status' => OrderStatus::PENDING,
|
|
|
+ 'frozen_amount' => $totalAmount,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return ['success' => true, 'order_id' => $order->id, 'message' => '买入订单创建成功,等待撮合'];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return ['success' => false, 'message' => '创建订单失败:' . $e->getMessage()];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 立即处理卖出订单
|
|
|
+ *
|
|
|
+ * @param MexOrder $order 订单
|
|
|
+ * @return array 处理结果
|
|
|
+ */
|
|
|
+ private static function processSellOrderImmediately(MexOrder $order): array
|
|
|
+ {
|
|
|
+ // 这里应该调用账户流转逻辑
|
|
|
+ // 暂时返回成功结果
|
|
|
+ $order->update([
|
|
|
+ 'status' => OrderStatus::COMPLETED,
|
|
|
+ 'completed_quantity' => $order->quantity,
|
|
|
+ 'completed_amount' => $order->total_amount,
|
|
|
+ 'completed_at' => now(),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return ['success' => true, 'message' => '卖出订单已完成'];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取消订单
|
|
|
+ *
|
|
|
+ * @param int $userId 用户ID
|
|
|
+ * @param int $orderId 订单ID
|
|
|
+ * @return array 操作结果
|
|
|
+ */
|
|
|
+ public static function cancelOrder(int $userId, int $orderId): array
|
|
|
+ {
|
|
|
+ $order = MexOrder::where('id', $orderId)->where('user_id', $userId)->first();
|
|
|
+ if (!$order) {
|
|
|
+ return ['success' => false, 'message' => '订单不存在'];
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($order->status !== OrderStatus::PENDING) {
|
|
|
+ return ['success' => false, 'message' => '只能取消等待中的订单'];
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $order->update(['status' => OrderStatus::CANCELLED]);
|
|
|
+ return ['success' => true, 'message' => '订单已取消'];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return ['success' => false, 'message' => '取消订单失败:' . $e->getMessage()];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户订单列表
|
|
|
+ *
|
|
|
+ * @param int $userId 用户ID
|
|
|
+ * @param int $page 页码
|
|
|
+ * @param int $pageSize 每页数量
|
|
|
+ * @return array 订单列表
|
|
|
+ */
|
|
|
+ public static function getUserOrders(int $userId, int $page = 1, int $pageSize = 20): array
|
|
|
+ {
|
|
|
+ $orders = MexOrder::where('user_id', $userId)
|
|
|
+ ->orderBy('created_at', 'desc')
|
|
|
+ ->paginate($pageSize, ['*'], 'page', $page);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'orders' => $orders->items(),
|
|
|
+ 'total' => $orders->total(),
|
|
|
+ 'page' => $page,
|
|
|
+ 'page_size' => $pageSize,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取订单详情
|
|
|
+ *
|
|
|
+ * @param int $userId 用户ID
|
|
|
+ * @param int $orderId 订单ID
|
|
|
+ * @return array|null 订单详情
|
|
|
+ */
|
|
|
+ public static function getOrderDetail(int $userId, int $orderId): ?array
|
|
|
+ {
|
|
|
+ $order = MexOrder::where('id', $orderId)->where('user_id', $userId)->first();
|
|
|
+ return $order ? $order->toArray() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取待撮合的买入订单
|
|
|
+ *
|
|
|
+ * @param int $itemId 商品ID
|
|
|
+ * @param int $limit 限制数量
|
|
|
+ * @return array 订单列表
|
|
|
+ */
|
|
|
+ public static function getPendingBuyOrders(int $itemId, int $limit = 100): array
|
|
|
+ {
|
|
|
+ $orders = MexOrder::where('item_id', $itemId)
|
|
|
+ ->where('order_type', OrderType::BUY)
|
|
|
+ ->where('status', OrderStatus::PENDING)
|
|
|
+ ->orderBy('price', 'desc')
|
|
|
+ ->orderBy('created_at', 'asc')
|
|
|
+ ->orderBy('quantity', 'asc')
|
|
|
+ ->limit($limit)
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ return $orders->toArray();
|
|
|
+ }
|
|
|
+}
|