21日1819-修复Mex挂单验证器物品数量检查逻辑.md 4.9 KB

修复Mex挂单验证器物品数量检查逻辑

任务时间: 2025年06月21日 18:19
任务类型: 错误修复
模块: Mex/Validators

任务概述

根据错误日志分析,修复了Mex挂单验证器中物品数量检查逻辑不一致的问题。问题源于Validation层和Logic层使用了不同的物品数量检查方法,导致验证通过但实际操作失败。

问题分析

1. 错误现象

  • 错误信息: 创建订单失败:用户 39077 的物品 2 可用数量不足,无法冻结 100 个
  • 错误类型: 系统异常(Exception),而不是验证错误
  • 问题位置: MexOrderLogic::createSellOrder() 第84行抛出异常

2. 根本原因

验证层和逻辑层使用不同的数量检查方法

Validation层(MexOrderValidator)

  • 使用 ItemQuantity::getUserItemQuantity()
  • 检查总物品数量(包括已冻结的物品)
  • SQL查询不包含 is_frozen 条件

Logic层(MexOrderLogic)

  • 使用 ItemService::freezeItem()
  • 检查可用数量(排除已冻结的物品)
  • SQL查询包含 is_frozen = '' 条件

3. 问题场景

用户有物品总数量足够,但部分物品已被冻结:

  • 总数量:足够通过Validation验证
  • 可用数量:不足以完成冻结操作
  • 结果:验证通过但Logic层操作失败

修复方案

1. 修改验证方法

MexOrderValidator::validateUserItemQuantity() 方法改为检查可用数量:

修复前

private function validateUserItemQuantity(int $userId, int $itemId, int $requiredQuantity): bool
{
    $userQuantity = ItemQuantity::getUserItemQuantity($userId, $itemId);

    if ($userQuantity < $requiredQuantity) {
        $this->addError("物品数量不足,当前拥有 {$userQuantity} 个,需要 {$requiredQuantity} 个");
        return false;
    }

    return true;
}

修复后

private function validateUserItemQuantity(int $userId, int $itemId, int $requiredQuantity): bool
{
    // 使用ItemService获取可用数量(排除已冻结的物品)
    $availableQuantity = \App\Module\GameItems\Services\ItemService::getAvailableQuantity($userId, $itemId);

    if ($availableQuantity < $requiredQuantity) {
        $this->addError("可用物品数量不足,当前可用 {$availableQuantity} 个,需要 {$requiredQuantity} 个");
        return false;
    }

    return true;
}

2. 关键改进

  1. 统一检查逻辑: Validation层和Logic层都使用可用数量检查
  2. 错误信息优化: 明确显示"可用数量"而非"总数量"
  3. 错误处理层级: 物品不足错误在Validation层处理,返回VALIDATE_ERROR

验证结果

1. 修复前

  • 错误类型: 系统异常(Exception)
  • 错误信息: 创建订单失败:用户 39077 的物品 2 可用数量不足,无法冻结 100 个
  • 响应代码: 可能导致500错误

2. 修复后

使用 php artisan debug:reproduce-error 69003573 验证:

  • 错误类型: 验证错误(VALIDATE_ERROR)
  • 错误信息: 可用物品数量不足,当前可用 22 个,需要 100 个
  • 响应代码: 200,正常的业务错误响应

3. 数据分析

  • 用户总物品数量:≥22个(可能更多,但部分被冻结)
  • 用户可用数量:22个
  • 请求挂单数量:100个
  • 结果:验证正确拦截,避免系统异常

技术细节

1. 物品数量检查方法对比

方法 检查范围 SQL条件 用途
ItemQuantity::getUserItemQuantity() 总数量 is_frozen条件 查看用户拥有的所有物品
ItemService::getAvailableQuantity() 可用数量 is_frozen = '' 实际可操作的物品数量

2. 冻结机制

  • 物品冻结时设置 is_frozen = true
  • 冻结的物品不能再次被冻结或消耗
  • 解冻时恢复 is_frozen = false

3. 验证一致性原则

根据用户偏好,验证应该严格按照实际操作逻辑进行,不提供向后兼容或回退逻辑。

影响范围

  • 修改文件: app/Module/Mex/Validators/MexOrderValidator.php
  • 影响功能: 农贸市场卖出挂单验证
  • 风险评估: 低风险,提高了验证准确性
  • 用户体验: 错误信息更准确,避免系统异常

提交信息

修复Mex挂单验证器物品数量检查逻辑

- 问题:MexOrderValidator使用总物品数量验证,但Logic层使用可用数量冻结,导致验证通过但冻结失败
- 修复:将validateUserItemQuantity方法改为检查可用数量(排除已冻结物品)
- 影响:物品数量不足错误现在在Validation层正确处理,返回VALIDATE_ERROR而非系统异常
- 测试:使用debug:reproduce-error验证修复效果,错误信息从系统异常变为验证错误

相关文档

  • 参考用户偏好:严格错误处理,不提供向后兼容
  • 验证层使用示例:docs/Validation使用示例.md
  • 错误应在Validation层处理而非Logic层抛出异常