191020-完全修复农贸市场挂单成交问题.md 5.2 KB

完全修复农贸市场挂单成交问题

任务时间

  • 开始时间:2025-06-19 10:05:32
  • 完成时间:2025-06-19 10:20:10

问题总结

用户反馈农贸市场模块"挂单成交了,但是没产生订单",经过深入分析发现了两个关键问题。

根本原因分析

1. 物品冻结机制缺失

问题:订单创建时没有冻结用户物品

  • MexOrderLogic::createSellOrder 只创建订单记录,未冻结物品
  • 撮合时调用 transferFrozenItemsToWarehouse 期望物品已冻结
  • 实际上物品没有被冻结,导致撮合逻辑无法正确执行

根据文档要求

  • 第19行:冻结机制:所有订单挂单时都冻结资金或物品,不受保护阈值影响
  • 第159行:资金冻结:冻结用户账户对应资金(所有订单都冻结)

2. MexTransaction模型配置错误

问题:数据库表结构与模型配置不匹配

  • kku_mex_transactions 表只有 created_at 字段,没有 updated_at 字段
  • Laravel Model 默认尝试插入 created_atupdated_at 字段
  • 导致SQL错误:Unknown column 'updated_at' in 'field list'

修复方案

1. 修复物品冻结机制

修改 app/Module/Mex/Logic/MexOrderLogic.php

public static function createSellOrder(int $userId, int $itemId, int $quantity, float $price, ?FUND_CURRENCY_TYPE $currencyType = null): array
{
    return DB::transaction(function () use ($userId, $itemId, $quantity, $price, $currencyType, $totalAmount) {
        // 1. 验证用户是否有足够的物品
        $checkResult = ItemService::checkItemQuantity($userId, $itemId, $quantity);
        if (!$checkResult->success) {
            return ['success' => false, 'message' => $checkResult->message];
        }

        // 2. 创建订单记录
        $order = MexOrder::create([...]);

        // 3. 冻结用户物品
        $freezeResult = ItemService::freezeItem(
            $userId,
            $itemId,
            null,
            $quantity,
            "农贸市场卖出订单冻结,订单ID:{$order->id}",
            [
                'reason_type' => FREEZE_REASON_TYPE::TRADE_ORDER->value,
                'source_id' => $order->id,
                'source_type' => 'mex_sell_order',
            ]
        );

        if (!$freezeResult['success']) {
            throw new \Exception('冻结物品失败:' . $freezeResult['message']);
        }

        return ['success' => true, 'order_id' => $order->id, ...];
    });
}

2. 修复MexTransaction模型

修改 app/Module/Mex/Models/MexTransaction.php

class MexTransaction extends ModelCore
{
    protected $table = 'mex_transactions';
    
    // 禁用updated_at字段的自动管理,因为表中只有created_at字段
    public const UPDATED_AT = null;
    
    // ... 其他配置
}

验证测试

1. 创建订单测试

$result = MexOrderService::createSellOrder(39068, 3, 50, 10.00000, FUND_CURRENCY_TYPE::ZUANSHI);
// 结果:成功创建订单64,物品正确冻结

2. 撮合流程测试

php artisan mex:user-sell-item-match --item=3

撮合结果

  • ✅ 订单64状态:PENDING → COMPLETED
  • ✅ 成交记录:创建记录ID=17,关联订单64
  • ✅ 物品流转:用户物品减少50个,仓库库存增加50个
  • ✅ 资金流转:用户收到500钻石,仓库账户支付500钻石

3. 价格验证测试

  • ✅ 订单64价格10.00000 ≤ 最低价10.50000,成功撮合
  • ✅ 订单57价格25.80000 > 最低价10.50000,不撮合(符合文档要求)

技术细节

撮合条件验证

根据文档第26行和第150行:

  • 用户卖出物品价格验证:价格必须 等于或低于 系统设置的最低价才能成交
  • 撮合阶段价格验证:用户卖出物品价格≤最低价

事务处理

  • MexMatchService 正确使用 DB::transaction() 包装撮合逻辑
  • ItemService::consumeItem 需要在事务中执行(Helper::check_tr() 验证)
  • 订单创建也使用事务确保物品冻结和订单创建的原子性

账户体系

  • 仓库账户:USER_ID = 15(与文档一致)
  • 买方:仓库账户(15)
  • 卖方:用户账户(39068)

数据验证

成交记录示例

{
  "id": 17,
  "buy_order_id": null,
  "sell_order_id": 64,
  "buyer_id": 15,
  "seller_id": 39068,
  "item_id": 3,
  "currency_type": 2,
  "quantity": 50,
  "price": "10.00000",
  "total_amount": "500.00000",
  "transaction_type": "USER_SELL",
  "is_admin_operation": 0,
  "created_at": "2025-06-19T10:20:10.000Z"
}

撮合统计

  • 今日撮合订单:4个
  • 今日成交数量:210个
  • 今日成交金额:1870钻石

结论

问题完全解决

  1. 挂单时正确冻结物品
  2. 撮合时正确创建成交记录
  3. 订单状态正确更新为COMPLETED
  4. 物品和资金流转正确执行
  5. 价格验证逻辑符合文档要求

系统完整性

  • 数据一致性:订单、成交记录、物品、资金都正确关联
  • 事务安全性:所有操作在事务中执行,确保原子性
  • 业务逻辑:严格按照文档规范实现撮合条件

现在农贸市场的挂单撮合功能完全正常,用户卖出订单能够正确成交并产生对应的成交记录。