| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- <?php
- namespace App\Module\Mex\Logic;
- use App\Module\Mex\Models\MexPriceConfig;
- use Illuminate\Support\Facades\Cache;
- /**
- * 农贸市场价格配置逻辑
- *
- * 处理价格配置相关的核心业务逻辑
- */
- class MexPriceConfigLogic
- {
- /**
- * 缓存键前缀
- */
- private const CACHE_PREFIX = 'mex_price_config:';
-
- /**
- * 缓存时间(秒)
- */
- private const CACHE_TTL = 600; // 10分钟
- /**
- * 获取商品价格配置
- *
- * @param int $itemId 商品ID
- * @return array|null 价格配置
- */
- public static function getItemPriceConfig(int $itemId): ?array
- {
- $cacheKey = self::CACHE_PREFIX . $itemId;
-
- return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($itemId) {
- $config = MexPriceConfig::where('item_id', $itemId)->first();
-
- if (!$config) {
- return null;
- }
- return [
- 'item_id' => $config->item_id,
- 'min_price' => $config->min_price,
- 'max_price' => $config->max_price,
- 'protection_threshold' => $config->protection_threshold,
- 'is_enabled' => $config->is_enabled,
- 'price_range' => $config->min_price . ' - ' . $config->max_price,
- 'price_range_width' => bcsub($config->max_price, $config->min_price, 5),
- 'created_at' => $config->created_at,
- 'updated_at' => $config->updated_at,
- ];
- });
- }
- /**
- * 获取多个商品的价格配置
- *
- * @param array $itemIds 商品ID数组
- * @return array 价格配置列表
- */
- public static function getItemsPriceConfig(array $itemIds): array
- {
- $result = [];
-
- foreach ($itemIds as $itemId) {
- $config = self::getItemPriceConfig($itemId);
- if ($config) {
- $result[$itemId] = $config;
- }
- }
- return $result;
- }
- /**
- * 验证卖出价格
- *
- * @param int $itemId 商品ID
- * @param string $price 价格
- * @return array 验证结果
- */
- public static function validateSellPrice(int $itemId, string $price): array
- {
- $config = self::getItemPriceConfig($itemId);
- if (!$config) {
- return [
- 'valid' => false,
- 'message' => '商品未配置价格信息',
- 'error_code' => 'CONFIG_NOT_FOUND'
- ];
- }
- if (!$config['is_enabled']) {
- return [
- 'valid' => false,
- 'message' => '商品价格配置已禁用',
- 'error_code' => 'CONFIG_DISABLED'
- ];
- }
- // 卖出价格不能低于最低价
- if (bccomp($price, $config['min_price'], 5) < 0) {
- return [
- 'valid' => false,
- 'message' => "卖出价格不能低于最低价 {$config['min_price']}",
- 'error_code' => 'PRICE_TOO_LOW',
- 'min_price' => $config['min_price']
- ];
- }
- // 卖出价格不能高于最高价
- if (bccomp($price, $config['max_price'], 5) > 0) {
- return [
- 'valid' => false,
- 'message' => "卖出价格不能高于最高价 {$config['max_price']}",
- 'error_code' => 'PRICE_TOO_HIGH',
- 'max_price' => $config['max_price']
- ];
- }
- return [
- 'valid' => true,
- 'message' => '价格验证通过',
- 'config' => $config
- ];
- }
- /**
- * 验证买入价格
- *
- * @param int $itemId 商品ID
- * @param string $price 价格
- * @return array 验证结果
- */
- public static function validateBuyPrice(int $itemId, string $price): array
- {
- $config = self::getItemPriceConfig($itemId);
-
- if (!$config) {
- return [
- 'valid' => false,
- 'message' => '商品未配置价格信息',
- 'error_code' => 'CONFIG_NOT_FOUND'
- ];
- }
- if (!$config['is_enabled']) {
- return [
- 'valid' => false,
- 'message' => '商品价格配置已禁用',
- 'error_code' => 'CONFIG_DISABLED'
- ];
- }
- if (bccomp($price, $config['max_price'], 5) < 0) {
- return [
- 'valid' => false,
- 'message' => "买入价格不能低于最高价 {$config['max_price']}",
- 'error_code' => 'PRICE_TOO_LOW',
- 'max_price' => $config['max_price']
- ];
- }
- return [
- 'valid' => true,
- 'message' => '价格验证通过',
- 'config' => $config
- ];
- }
- /**
- * 验证订单数量
- *
- * @param int $itemId 商品ID
- * @param int $quantity 数量
- * @return array 验证结果
- */
- public static function validateOrderQuantity(int $itemId, int $quantity): array
- {
- $config = self::getItemPriceConfig($itemId);
-
- if (!$config) {
- return [
- 'valid' => false,
- 'message' => '商品未配置价格信息',
- 'error_code' => 'CONFIG_NOT_FOUND'
- ];
- }
- if (!$config['is_enabled']) {
- return [
- 'valid' => false,
- 'message' => '商品价格配置已禁用',
- 'error_code' => 'CONFIG_DISABLED'
- ];
- }
- if ($quantity > $config['protection_threshold']) {
- return [
- 'valid' => false,
- 'message' => "订单数量不能超过保护阈值 {$config['protection_threshold']}",
- 'error_code' => 'QUANTITY_OVER_THRESHOLD',
- 'protection_threshold' => $config['protection_threshold']
- ];
- }
- return [
- 'valid' => true,
- 'message' => '数量验证通过',
- 'config' => $config
- ];
- }
- /**
- * 获取所有启用的价格配置
- *
- * @return array 价格配置列表
- */
- public static function getEnabledConfigs(): array
- {
- $cacheKey = self::CACHE_PREFIX . 'enabled_all';
-
- return Cache::remember($cacheKey, self::CACHE_TTL, function () {
- $configs = MexPriceConfig::where('is_enabled', true)
- ->orderBy('item_id', 'asc')
- ->get();
- $result = [];
- foreach ($configs as $config) {
- $result[] = [
- 'item_id' => $config->item_id,
- 'min_price' => $config->min_price,
- 'max_price' => $config->max_price,
- 'protection_threshold' => $config->protection_threshold,
- 'price_range' => $config->min_price . ' - ' . $config->max_price,
- 'price_range_width' => bcsub($config->max_price, $config->min_price, 5),
- ];
- }
- return $result;
- });
- }
- /**
- * 清除价格配置缓存
- *
- * @param int|null $itemId 商品ID,null表示清除所有
- * @return bool 操作结果
- */
- public static function clearCache(?int $itemId = null): bool
- {
- if ($itemId) {
- $cacheKey = self::CACHE_PREFIX . $itemId;
- return Cache::forget($cacheKey);
- }
- // 清除所有相关缓存
- Cache::forget(self::CACHE_PREFIX . 'enabled_all');
-
- // 这里可以根据需要清除特定商品的缓存
- // 由于无法直接获取所有缓存键,建议在配置更新时调用具体的清除方法
-
- return true;
- }
- /**
- * 挂单阶段参数验证(不验证价格和保护阈值)
- * 根据文档要求:挂单阶段无价格验证,所有订单都可以挂单并冻结资金/物品
- *
- * @param int $itemId 商品ID
- * @param string $price 价格(仅做基本格式验证)
- * @param int $quantity 数量(不验证保护阈值)
- * @param string $orderType 订单类型 (BUY/SELL)
- * @return array 验证结果
- */
- public static function validateOrderParamsForPlacement(int $itemId, string $price, int $quantity, string $orderType): array
- {
- // 注意:$orderType 参数保留用于接口一致性,挂单阶段不区分买卖类型的验证
- // 只验证价格配置是否存在,不验证价格范围
- $config = self::getItemPriceConfig($itemId);
- if (!$config) {
- return [
- 'valid' => false,
- 'message' => '商品未配置价格信息',
- 'error_code' => 'CONFIG_NOT_FOUND'
- ];
- }
- if (!$config['is_enabled']) {
- return [
- 'valid' => false,
- 'message' => '商品价格配置已禁用',
- 'error_code' => 'CONFIG_DISABLED'
- ];
- }
- // 基本的价格格式验证(确保是有效数字)
- if (!is_numeric($price) || bccomp($price, '0', 5) <= 0) {
- return [
- 'valid' => false,
- 'message' => '价格必须是大于0的数字',
- 'error_code' => 'INVALID_PRICE_FORMAT'
- ];
- }
- // 基本的数量验证(确保是正整数)
- if (!is_int($quantity) || $quantity <= 0) {
- return [
- 'valid' => false,
- 'message' => '数量必须是大于0的整数',
- 'error_code' => 'INVALID_QUANTITY'
- ];
- }
- return [
- 'valid' => true,
- 'message' => '挂单参数验证通过',
- 'config' => $config
- ];
- }
- /**
- * 撮合阶段价格和数量验证(用于撮合时的严格验证)
- *
- * @param int $itemId 商品ID
- * @param string $price 价格
- * @param int $quantity 数量
- * @param string $orderType 订单类型 (BUY/SELL)
- * @return array 验证结果
- */
- public static function validateOrderParamsForMatching(int $itemId, string $price, int $quantity, string $orderType): array
- {
- // 验证价格
- if ($orderType === 'SELL') {
- $priceResult = self::validateSellPrice($itemId, $price);
- } else {
- $priceResult = self::validateBuyPrice($itemId, $price);
- }
- if (!$priceResult['valid']) {
- return $priceResult;
- }
- // 验证数量(只对买入订单验证保护阈值)
- if ($orderType === 'BUY') {
- $quantityResult = self::validateOrderQuantity($itemId, $quantity);
- if (!$quantityResult['valid']) {
- return $quantityResult;
- }
- }
- return [
- 'valid' => true,
- 'message' => '撮合参数验证通过',
- 'config' => $priceResult['config']
- ];
- }
- /**
- * 批量验证价格和数量(已废弃,请使用validateOrderParamsForPlacement或validateOrderParamsForMatching)
- *
- * @deprecated 请根据使用场景选择validateOrderParamsForPlacement(挂单)或validateOrderParamsForMatching(撮合)
- * @param int $itemId 商品ID
- * @param string $price 价格
- * @param int $quantity 数量
- * @param string $orderType 订单类型 (BUY/SELL)
- * @return array 验证结果
- */
- public static function validateOrderParams(int $itemId, string $price, int $quantity, string $orderType): array
- {
- // 为了向后兼容,默认使用挂单验证
- return self::validateOrderParamsForPlacement($itemId, $price, $quantity, $orderType);
- }
- /**
- * 获取商品价格建议
- *
- * @param int $itemId 商品ID
- * @return array 价格建议
- */
- public static function getPriceSuggestion(int $itemId): array
- {
- $config = self::getItemPriceConfig($itemId);
-
- if (!$config) {
- return [
- 'has_suggestion' => false,
- 'message' => '商品未配置价格信息'
- ];
- }
- // 获取最新成交价格作为参考
- $latestPrice = MexTransactionLogic::getLatestPrice($itemId);
- return [
- 'has_suggestion' => true,
- 'min_price' => $config['min_price'],
- 'max_price' => $config['max_price'],
- 'latest_price' => $latestPrice,
- 'sell_suggestion' => $config['min_price'],
- 'buy_suggestion' => $config['max_price'],
- 'protection_threshold' => $config['protection_threshold'],
- ];
- }
- }
|