|
|
@@ -23,13 +23,14 @@ use bizGhs\order\classes\CheckOrderItemClass;
|
|
|
use bizGhs\order\traits\OrderTrait;
|
|
|
use bizGhs\shop\classes\ShopAdminClass;
|
|
|
use bizGhs\stock\classes\StockRecordClass;
|
|
|
-use bizHd\notify\classes\NotifyClass;
|
|
|
use common\components\dict;
|
|
|
use common\components\imgUtil;
|
|
|
+use common\components\noticeUtil;
|
|
|
use common\components\orderSn;
|
|
|
use common\components\stringUtil;
|
|
|
use common\components\util;
|
|
|
use common\services\xhItemService;
|
|
|
+use PhpAmqpLib\Wire\AMQPTable;
|
|
|
use Yii;
|
|
|
|
|
|
class ProductClass extends BaseClass
|
|
|
@@ -37,12 +38,16 @@ class ProductClass extends BaseClass
|
|
|
use OrderTrait;
|
|
|
|
|
|
public static $baseFile = '\bizGhs\product\models\Product';
|
|
|
+
|
|
|
const PRICE_LABEL_AUTO = 1; //自动调价
|
|
|
const PRICE_LABEL_CHANGE = 2; //改价
|
|
|
const LOCK_STOCK = 'lock_stock';//修改库存锁
|
|
|
const LOCK_ON_STOCK = 'lock_on_stock';//修改库存锁
|
|
|
- const LOCK_PRICE = 'lock_price'; //改价锁
|
|
|
- const LOCK_CHECK_STOCK = 'lock_check_stock'; //判断库存
|
|
|
+
|
|
|
+ const LIMIT_BUY_KEY = 'limit_buy_';
|
|
|
+ const CLEAR_MARK_KEY = 'limit_buy_clear_at:';
|
|
|
+ const CLEAR_LOOP_KEY = 'limit_buy_clear_loop:';
|
|
|
+ const LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY = 'limitBuyRollbackSnapshot'; //记录限购旧值快照缓存键
|
|
|
|
|
|
public static function getNotShowFrontHideMainIds()
|
|
|
{
|
|
|
@@ -663,6 +668,23 @@ class ProductClass extends BaseClass
|
|
|
$list[$k]['autoPrice'] = $autoPrice;
|
|
|
$list[$k]['autoSkPrice'] = $skAutoPrice;
|
|
|
$list[$k]['userPrice'] = 0;
|
|
|
+
|
|
|
+ // 限购缓存
|
|
|
+ if ($v['limitBuy'] > 0) {
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $v['id'];
|
|
|
+ $has = Yii::$app->redis->executeCommand('HEXISTS', [$limitKey, 0]);
|
|
|
+ if (!empty($has)) {
|
|
|
+ // 获取缓存超时时间
|
|
|
+ $expire = Yii::$app->redis->executeCommand('TTL', [$limitKey]);
|
|
|
+ if ($expire > 0) {
|
|
|
+ $list[$k]['limitBuyClearTime'] = date('Y-m-d H:i:s', time() + $expire);
|
|
|
+ } else {
|
|
|
+ $list[$k]['limitBuyClearTime'] = '';
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $list[$k]['limitBuyClearTime'] = '';
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
return $list;
|
|
|
}
|
|
|
@@ -744,9 +766,19 @@ class ProductClass extends BaseClass
|
|
|
return $list;
|
|
|
}
|
|
|
|
|
|
- //输出价格 ssh 20211009
|
|
|
- //$params 原来是 $addPriceMap,现在 $addPriceMap 值没用了,把它改成 $params ,用作传别的参数
|
|
|
- public static function getFinalPrice($product, $level, $priceMap, $params, $changePrice = 0, $buyNum = 0)
|
|
|
+ /**
|
|
|
+ * 输出价格 ssh 20211009
|
|
|
+ * @param $product 花材信息
|
|
|
+ * @param $level 等级
|
|
|
+ * @param $priceMap 各个等级对应的price addPrice字段
|
|
|
+ * @param $params 原来是 $addPriceMap,现在 $addPriceMap 值没用了,把它改成 $params ,用作传别的参数
|
|
|
+ * @param int $changePrice 开单改价
|
|
|
+ * @param int $buyNum 当前购买数量
|
|
|
+ * @param int $totalBuyNum 已购买总数量
|
|
|
+ * @return int|string|null
|
|
|
+ * @throws \Exception
|
|
|
+ */
|
|
|
+ public static function getFinalPrice($product, $level, $priceMap, $params, $changePrice = 0, $buyNum = 0, $totalBuyNum = 0)
|
|
|
{
|
|
|
//开单改价优先级最高
|
|
|
if ($changePrice > 0) {
|
|
|
@@ -767,10 +799,13 @@ class ProductClass extends BaseClass
|
|
|
$price = $product[$currentPriceField] ?? 0;
|
|
|
}
|
|
|
|
|
|
+ //特价与限购的综合处理
|
|
|
$discountPrice = $product['discountPrice'] ?? 0;
|
|
|
$hjDiscountPrice = $product['hjDiscountPrice'] ?? 0;
|
|
|
$skDiscountPrice = $product['skDiscountPrice'] ?? 0;
|
|
|
+ $limitBuy = $product['limitBuy'];
|
|
|
if ($discountPrice > 0) {
|
|
|
+ $oldPrice = $price;
|
|
|
if ($level == 0) {
|
|
|
$price = $skDiscountPrice;
|
|
|
}
|
|
|
@@ -780,7 +815,24 @@ class ProductClass extends BaseClass
|
|
|
if ($level == 2) {
|
|
|
$price = $hjDiscountPrice;
|
|
|
}
|
|
|
+
|
|
|
+ //超出限购情况的价格计算
|
|
|
+ if ($limitBuy > 0 && $totalBuyNum > $limitBuy) {
|
|
|
+ $hasBuyNum = $totalBuyNum - $buyNum;
|
|
|
+ if ($hasBuyNum >= $limitBuy) {
|
|
|
+ $price = $oldPrice;
|
|
|
+ } else {
|
|
|
+ $overBuyNum = $totalBuyNum - $limitBuy;
|
|
|
+ $overBuyPrice = bcmul($overBuyNum, $oldPrice, 2); // 超出限购部分的价格
|
|
|
+
|
|
|
+ $leftBuyNum = $buyNum - $overBuyNum;
|
|
|
+ $leftBuyPrice = bcmul($leftBuyNum, $price, 2); // 未超出限购部分的价格
|
|
|
+ $price = bcdiv($overBuyPrice + $leftBuyPrice, $buyNum, 2); // 最终价格
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ //满多少数量,再优惠多少钱
|
|
|
$reachNum = $product['reachNum'] ?? 0;
|
|
|
$reachNumDiscount = $product['reachNumDiscount'] ?? 0;
|
|
|
if ($reachNum > 0) {
|
|
|
@@ -1067,9 +1119,9 @@ class ProductClass extends BaseClass
|
|
|
self::updateActualSoldById($productId, $newActualSold);
|
|
|
}
|
|
|
|
|
|
- //如果花材是自动补充库存类型的花材,则库存低于900时,自动补充到6850,多处要同步修改,关键词 auto_add_stock
|
|
|
+ //如果花材是自动补充库存类型的花材,则库存低于900时,自动补充到66820,多处要同步修改,关键词 auto_add_stock
|
|
|
if ($productData->virtualStock == 1 && $newStock < 900) {
|
|
|
- self::updateStockById($productId, 6850);
|
|
|
+ self::updateStockById($productId, 66820);
|
|
|
}
|
|
|
|
|
|
//库存=0 下架商品,特价去掉,限购去掉 lqh 2021.7.9 ssh 20251106 花材满减去掉 20260318
|
|
|
@@ -1390,22 +1442,21 @@ class ProductClass extends BaseClass
|
|
|
$itemInfo = self::mergeItemInfo($itemInfo);
|
|
|
|
|
|
$productIds = array_column($itemInfo, 'productId');
|
|
|
- $ghsProductData = ProductClass::getProductByIds($productIds);
|
|
|
+ $ghsProductData = self::getProductByIds($productIds);
|
|
|
$ghsProductData = array_column($ghsProductData, NULL, 'id');
|
|
|
- if ($live == 1) {
|
|
|
- $hdProductData = [];
|
|
|
- } else {
|
|
|
- $hdIds = array_column($itemInfo, 'hdProductId');
|
|
|
- $hdProductData = ProductClass::getByIds($hdIds, null, 'id');
|
|
|
- }
|
|
|
-
|
|
|
- $book = $moreParams['book'] ?? 0;
|
|
|
- $customShopAdminId = $moreParams['customShopAdminId'] ?? 0;
|
|
|
+// if ($live == 1) {
|
|
|
+// $hdProductData = [];
|
|
|
+// } else {
|
|
|
+// $hdIds = array_column($itemInfo, 'hdProductId');
|
|
|
+// $hdProductData = self::getByIds($hdIds, null, 'id');
|
|
|
+// }
|
|
|
|
|
|
$totalPrice = 0;
|
|
|
$totalBigNum = 0;
|
|
|
$totalSmallNum = 0;
|
|
|
|
|
|
+ $book = $moreParams['book'] ?? 0;
|
|
|
+ $customShopAdminId = $moreParams['customShopAdminId'] ?? 0;
|
|
|
$custom = $moreParams['custom'] ?? [];
|
|
|
//不同等级对应 price addPrice
|
|
|
$priceMap = CustomClass::$levelPriceKeyMap;
|
|
|
@@ -1421,12 +1472,15 @@ class ProductClass extends BaseClass
|
|
|
$totalCost = 0;
|
|
|
foreach ($itemInfo as $v) {
|
|
|
$ghsProductId = $v['productId'];
|
|
|
-
|
|
|
$currentGhsProduct = $ghsProductData[$ghsProductId] ?? [];
|
|
|
- $itemId = $currentGhsProduct['itemId'] ?? 0;
|
|
|
- $ratio = $currentGhsProduct['ratio'] ?? 0;
|
|
|
- $cost = $currentGhsProduct['avCost'] ?? 0;
|
|
|
- $classId = $currentGhsProduct['classId'] ?? 0;
|
|
|
+ if (empty($currentGhsProduct)) {
|
|
|
+ noticeUtil::push("ghsProductId={$ghsProductId} 在 ghsProductData 中为空");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $itemId = $currentGhsProduct['itemId'];
|
|
|
+ $ratio = $currentGhsProduct['ratio'];
|
|
|
+ $cost = $currentGhsProduct['avCost'];
|
|
|
+ $classId = $currentGhsProduct['classId'];
|
|
|
|
|
|
$bigNum = $v['bigNum'] ?? 0;
|
|
|
$smallNum = $v['smallNum'] ?? 0;
|
|
|
@@ -1442,8 +1496,12 @@ class ProductClass extends BaseClass
|
|
|
if ($book == 1 && $customShopAdminId > 0) {
|
|
|
$itemPrice = 0.1;
|
|
|
} else {
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $ghsProductId;
|
|
|
+ $hasBuyNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $custom['id']]);
|
|
|
+ $hasBuyNum = $itemNum + ($hasBuyNum == null ? 0 : $hasBuyNum); // 已购买总数量
|
|
|
+
|
|
|
//今日特价、会员价
|
|
|
- $itemPrice = self::getFinalPrice($currentGhsProduct, $level, $priceMap, $addPriceMap, $changePrice, $itemNum);
|
|
|
+ $itemPrice = self::getFinalPrice($currentGhsProduct, $level, $priceMap, $addPriceMap, $changePrice, $itemNum, $hasBuyNum);
|
|
|
}
|
|
|
$thisPrice = $itemPrice;
|
|
|
|
|
|
@@ -1455,7 +1513,6 @@ class ProductClass extends BaseClass
|
|
|
$totalReachDiscount = bcadd($totalReachDiscount, $currentReachDiscount, 2);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
} else {
|
|
|
$itemPrice = $v['unitPrice'] ?? 0;
|
|
|
$thisPrice = $itemPrice;
|
|
|
@@ -1471,8 +1528,6 @@ class ProductClass extends BaseClass
|
|
|
$tmp['productId'] = $ghsProductId;
|
|
|
$tmp['price'] = $price;
|
|
|
|
|
|
- $totalPrice = bcadd($totalPrice, $price, 2);
|
|
|
-
|
|
|
$tmp['name'] = $currentGhsProduct['name'] ?? '';
|
|
|
$tmp['smallUnit'] = $currentGhsProduct['smallUnit'] ?? '支';
|
|
|
$tmp['bigUnit'] = $currentGhsProduct['bigUnit'] ?? '扎';
|
|
|
@@ -1496,11 +1551,16 @@ class ProductClass extends BaseClass
|
|
|
$tmp['sjId'] = $currentGhsProduct['sjId'] ?? 0;
|
|
|
$tmp['shopId'] = $currentGhsProduct['shopId'] ?? 0;
|
|
|
$tmp['mainId'] = $currentGhsProduct['mainId'] ?? 0;
|
|
|
- $tmp['limitBuy'] = $currentGhsProduct['limitBuy'] ?? 0;
|
|
|
+ $tmp['limitBuy'] = $currentGhsProduct['limitBuy'];
|
|
|
$tmp['smallUnitPrice'] = $itemPrice;
|
|
|
$tmp['classId'] = $classId;
|
|
|
+ $tmp['kind'] = $currentGhsProduct['kind'] ?? 0;
|
|
|
$tmp['belongCost'] = $currentGhsProduct['belongCost'] ?? 0;
|
|
|
+ $tmp['hjDiscountPrice'] = $currentGhsProduct['hjDiscountPrice'];
|
|
|
+ $tmp['discountPrice'] = $currentGhsProduct['discountPrice'];
|
|
|
+ $tmp['skDiscountPrice'] = $currentGhsProduct['skDiscountPrice'];
|
|
|
|
|
|
+ $totalPrice = bcadd($totalPrice, $price, 2);
|
|
|
$totalBigNum += $bigNum;
|
|
|
$totalSmallNum += $smallNum;
|
|
|
|
|
|
@@ -1515,16 +1575,10 @@ class ProductClass extends BaseClass
|
|
|
|
|
|
$smallCost = bcdiv($cost, $ratio, 2);
|
|
|
$cost = $smallCost;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- $tmp['cost'] = $cost;
|
|
|
-
|
|
|
$xhPrice = bcmul($xhNum, $itemPrice, 2);
|
|
|
-
|
|
|
- $currentCost = bcmul($xhNum, $cost, 2);
|
|
|
- $totalCost = bcadd($totalCost, $currentCost, 2);
|
|
|
-
|
|
|
+ $tmp['cost'] = $cost;
|
|
|
$tmp['xhNum'] = $xhNum;
|
|
|
$tmp['xhUnitName'] = $xhUnitName;
|
|
|
$tmp['xhUnitType'] = $xhUnitType;
|
|
|
@@ -1535,8 +1589,10 @@ class ProductClass extends BaseClass
|
|
|
$tmp['xhPreUnitType'] = $xhUnitType;
|
|
|
$tmp['xhPreUnitPrice'] = $itemPrice;
|
|
|
$tmp['xhPrePrice'] = $xhPrice;
|
|
|
-
|
|
|
$data[] = $tmp;
|
|
|
+
|
|
|
+ $currentCost = bcmul($xhNum, $cost, 2);
|
|
|
+ $totalCost = bcadd($totalCost, $currentCost, 2); // TODO 根据限购与特价进行价格计算的关键参数
|
|
|
}
|
|
|
|
|
|
return ['product' => $data, 'totalReachDiscount' => $totalReachDiscount, 'smallNum' => $totalSmallNum,
|
|
|
@@ -1568,8 +1624,14 @@ class ProductClass extends BaseClass
|
|
|
return bcmul($mergeNum, $weight, 2);
|
|
|
}
|
|
|
|
|
|
- //修改product
|
|
|
- public static function updateProduct($data, $shop)
|
|
|
+ /**
|
|
|
+ * 修改product
|
|
|
+ * @param $data
|
|
|
+ * @param $shop
|
|
|
+ * @param $type 所属平台:ghs 或 hd
|
|
|
+ * @throws \Exception
|
|
|
+ */
|
|
|
+ public static function updateProduct($data, $shop, $type)
|
|
|
{
|
|
|
$id = $data['id'] ?? 0;
|
|
|
$adminId = $data['adminId'] ?? 0;
|
|
|
@@ -1702,7 +1764,11 @@ class ProductClass extends BaseClass
|
|
|
$upData['limitBuy'] = $data['limitBuy'];
|
|
|
//取消限购
|
|
|
if ($data['limitBuy'] == 0) {
|
|
|
- self::cancelLimitBuy($id);
|
|
|
+ if ($type == 'ghs') {
|
|
|
+ self::cancelLimitBuy($id);
|
|
|
+ } else {
|
|
|
+ \bizHd\product\classes\ProductClass::cancelLimitBuy($id);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
if (isset($data['stockWarning'])) {
|
|
|
@@ -1893,12 +1959,42 @@ class ProductClass extends BaseClass
|
|
|
/***************产品模块*****************/
|
|
|
|
|
|
self::updateById($id, $upData);
|
|
|
+
|
|
|
+ //创建限购缓存
|
|
|
+ $limitBuy = $data['limitBuy'] ?? 0;
|
|
|
+ if ($limitBuy > 0) {
|
|
|
+ $limitBuyClearType = $data['limitBuyClearType'];
|
|
|
+ $limitBuyClearLoopConfig = self::getLimitBuyClearLoopConfig($data);
|
|
|
+ if ($limitBuyClearType == 1 && !empty($limitBuyClearLoopConfig)) {
|
|
|
+ if ($type == 'ghs') {
|
|
|
+ self::createRecurringLimitBuyCache($id, $limitBuyClearLoopConfig['intervalDays'], $limitBuyClearLoopConfig['clearHour']);
|
|
|
+ } else {
|
|
|
+ \bizHd\product\classes\ProductClass::createRecurringLimitBuyCache($id, $limitBuyClearLoopConfig['intervalDays'], $limitBuyClearLoopConfig['clearHour']);
|
|
|
+ }
|
|
|
+ } elseif ($limitBuyClearType == 2 && isset($data['limitBuyClearTime']) && $data['limitBuyClearTime'] != '') {
|
|
|
+ $limitBuyClearTime = strtotime($data['limitBuyClearTime']);
|
|
|
+ if ($limitBuyClearTime > time()) {
|
|
|
+ if ($type == 'ghs') {
|
|
|
+ self::createLimitBuyCache($id, $limitBuyClearTime - time());
|
|
|
+ } else {
|
|
|
+ \bizHd\product\classes\ProductClass::createLimitBuyCache($id, $limitBuyClearTime - time());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ util::fail('清空时间必须大于当前时间');
|
|
|
+ }
|
|
|
+ } else { // 没有设置清空时间,则删除缓存
|
|
|
+ if ($type == 'ghs') {
|
|
|
+ self::createLimitBuyCache($id, 0);
|
|
|
+ } else {
|
|
|
+ \bizHd\product\classes\ProductClass::createLimitBuyCache($id, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//不影响其它直营店花材的上下架
|
|
|
unset($upData['status']);
|
|
|
|
|
|
if (isset($shop->default) && $shop->default == 1 && isset($shop->dataSync) && $shop->dataSync == 1) {
|
|
|
-
|
|
|
-
|
|
|
/***************产品模块*****************/
|
|
|
$ptClassList = PtCpClassClass::getAllByCondition(['delStatus' => 0], null, '*', 'id');
|
|
|
/***************产品模块*****************/
|
|
|
@@ -2091,10 +2187,8 @@ class ProductClass extends BaseClass
|
|
|
|
|
|
//直营店同步价格等重要因素
|
|
|
self::updateById($chainProduct->id, $params);
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
//变成自动改价 2021.4.14
|
|
|
@@ -2355,7 +2449,7 @@ class ProductClass extends BaseClass
|
|
|
$smallUnitId = $data['smallUnitId'] ?? 0;
|
|
|
|
|
|
$changeUnit = 0;
|
|
|
- if ($ptItemInfo->bigUnitId != $bigUnitId || $ptItemInfo->smallUnitId != $smallUnitId || $ptItemInfo->ratio != $ratio) {
|
|
|
+ if ($ptItemInfo !== null && ($ptItemInfo->bigUnitId != $bigUnitId || $ptItemInfo->smallUnitId != $smallUnitId || $ptItemInfo->ratio != $ratio)) {
|
|
|
//如果被修改了单位,则重新创建花材
|
|
|
$changeUnit = 1;
|
|
|
}
|
|
|
@@ -2618,28 +2712,475 @@ class ProductClass extends BaseClass
|
|
|
return $product['mainId'] ?? 0;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 创建限购缓存(有过期时间)
|
|
|
+ * @param $productId 花材ID
|
|
|
+ * @param int $seconds 过期时间
|
|
|
+ * @param array $options ['clearAt' => 0, 'recurring' => 0, 'intervalDays' => 0, 'clearHour' => 0] 循环清空配置
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function createLimitBuyCache($productId, $seconds = 0, $options = [])
|
|
|
+ {
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
+ $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
|
|
|
+ $clearLoopKey = self::CLEAR_LOOP_KEY . $productId;
|
|
|
+ $recurring = !empty($options['recurring']);
|
|
|
+
|
|
|
+ $has = Yii::$app->redis->executeCommand('HEXISTS', [$limitKey, 0]);
|
|
|
+ if (!empty($has)) {
|
|
|
+ // 获取缓存超时时间
|
|
|
+ $expire = Yii::$app->redis->executeCommand('TTL', [$limitKey]);
|
|
|
+ if ($expire > 0) {
|
|
|
+ //return;
|
|
|
+ }
|
|
|
+ //删除缓存
|
|
|
+ Yii::$app->redis->executeCommand('HDEL', [$limitKey, 0]);
|
|
|
+ }
|
|
|
+
|
|
|
+ Yii::$app->redis->executeCommand('HSET', [$limitKey, 0, 0]);
|
|
|
+ if ($seconds > 0) {
|
|
|
+ $clearAt = intval($options['clearAt'] ?? 0);
|
|
|
+ if ($clearAt <= 0) {
|
|
|
+ $clearAt = time() + intval($seconds);
|
|
|
+ }
|
|
|
+ Yii::$app->redis->executeCommand('EXPIRE', [$limitKey, $seconds]);
|
|
|
+ Yii::$app->redis->executeCommand('SET', [$clearMarkKey, $clearAt]);
|
|
|
+
|
|
|
+ if ($recurring) {
|
|
|
+ $intervalDays = intval($options['intervalDays'] ?? 0);
|
|
|
+ $clearHour = intval($options['clearHour'] ?? -1);
|
|
|
+ Yii::$app->redis->executeCommand('SET', [$clearLoopKey, json_encode([
|
|
|
+ 'intervalDays' => $intervalDays,
|
|
|
+ 'clearHour' => $clearHour,
|
|
|
+ ], JSON_UNESCAPED_UNICODE)]);
|
|
|
+ } else {
|
|
|
+ Yii::$app->redis->executeCommand('DEL', [$clearLoopKey]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 用 RabbitMQ 延迟消息在到期时清空订单项限购字段
|
|
|
+ $message = [
|
|
|
+ 'type' => 'limit_buy_clear',
|
|
|
+ 'ptType' => 'ghs',
|
|
|
+ 'productId' => $productId,
|
|
|
+ 'clearAt' => $clearAt,
|
|
|
+ ];
|
|
|
+ if ($recurring) {
|
|
|
+ $message['recurring'] = 1;
|
|
|
+ $message['intervalDays'] = intval($options['intervalDays'] ?? 0);
|
|
|
+ $message['clearHour'] = intval($options['clearHour'] ?? -1);
|
|
|
+ }
|
|
|
+ $message = serialize($message);
|
|
|
+ $producer = Yii::$app->rabbitmq->getProducer('stockProducer');
|
|
|
+ $producer->publish($message, 'limitBuyDelayExchange', 'limitBuyDelayRoute', [
|
|
|
+ 'delivery_mode' => 2,
|
|
|
+ 'content_type' => 'application/octet-stream',
|
|
|
+ 'application_headers' => new AMQPTable([
|
|
|
+ 'x-delay' => intval($seconds * 1000),
|
|
|
+ ]),
|
|
|
+ ]);
|
|
|
+ Yii::info('限购延迟消息已发送: ' . json_encode([
|
|
|
+ 'type' => 'limit_buy_clear',
|
|
|
+ 'ptType' => 'ghs',
|
|
|
+ 'productId' => intval($productId),
|
|
|
+ 'clearAt' => intval($clearAt),
|
|
|
+ 'delayMs' => intval($seconds * 1000),
|
|
|
+ 'recurring' => $recurring ? 1 : 0,
|
|
|
+ ], JSON_UNESCAPED_UNICODE), __METHOD__);
|
|
|
+ } else {
|
|
|
+ Yii::$app->redis->executeCommand('DEL', [$clearMarkKey]);
|
|
|
+ Yii::$app->redis->executeCommand('DEL', [$clearLoopKey]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析循环清空限购配置
|
|
|
+ public static function getLimitBuyClearLoopConfig($data)
|
|
|
+ {
|
|
|
+ if ($data['limitBuyClearType'] == 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ $hasIntervalDays = array_key_exists('limitBuyClearIntervalDays', $data) && $data['limitBuyClearIntervalDays'] !== '';
|
|
|
+ $hasClearHour = (array_key_exists('cleartAt', $data) && $data['cleartAt'] !== '')
|
|
|
+ || (array_key_exists('clearAt', $data) && $data['clearAt'] !== '');
|
|
|
+ if (!$hasIntervalDays && !$hasClearHour) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ if (!$hasIntervalDays || !$hasClearHour) {
|
|
|
+ util::fail('请填写循环清空限购的间隔天数和执行时间');
|
|
|
+ }
|
|
|
+ if (!is_numeric($data['limitBuyClearIntervalDays'])) {
|
|
|
+ util::fail('循环清空限购的间隔天数错误');
|
|
|
+ }
|
|
|
+ $clearHourValue = array_key_exists('cleartAt', $data) ? $data['cleartAt'] : $data['clearAt'];
|
|
|
+ if (!is_numeric($clearHourValue)) {
|
|
|
+ util::fail('循环清空限购的执行时间错误');
|
|
|
+ }
|
|
|
+ $intervalDays = intval($data['limitBuyClearIntervalDays']);
|
|
|
+ $clearHour = intval($clearHourValue);
|
|
|
+ if ($intervalDays <= 0) {
|
|
|
+ util::fail('循环清空限购的间隔天数必须大于0');
|
|
|
+ }
|
|
|
+ if ($clearHour < 0 || $clearHour > 23) {
|
|
|
+ util::fail('循环清空限购的执行时间必须在0点到23点之间');
|
|
|
+ }
|
|
|
+ return ['intervalDays' => $intervalDays, 'clearHour' => $clearHour];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建循环清空限购缓存
|
|
|
+ * @param $productId 花材ID
|
|
|
+ * @param int $intervalDays 循环清空限购的间隔天数
|
|
|
+ * @param int $clearHour 循环清空限购的执行时间点
|
|
|
+ * @param int $clearAt 循环清空限购的下次清空时间
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function createRecurringLimitBuyCache($productId, $intervalDays, $clearHour, $clearAt = 0)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ $intervalDays = intval($intervalDays);
|
|
|
+ $clearHour = intval($clearHour);
|
|
|
+ if ($productId <= 0 || $intervalDays <= 0 || $clearHour < 0 || $clearHour > 23) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ($clearAt <= 0) {
|
|
|
+ $clearAt = self::getNextLimitBuyClearAt($intervalDays, $clearHour);
|
|
|
+ }
|
|
|
+ $seconds = max(1, $clearAt - time());
|
|
|
+ self::createLimitBuyCache($productId, $seconds, [
|
|
|
+ 'recurring' => 1,
|
|
|
+ 'intervalDays' => $intervalDays,
|
|
|
+ 'clearHour' => $clearHour,
|
|
|
+ 'clearAt' => $clearAt,
|
|
|
+ ]);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算下一次循环清空时间
|
|
|
+ public static function getNextLimitBuyClearAt($intervalDays, $clearHour, $baseTime = 0)
|
|
|
+ {
|
|
|
+ $baseTime = $baseTime > 0 ? intval($baseTime) : time();
|
|
|
+ $targetDay = $baseTime + intval($intervalDays) * 86400;
|
|
|
+ $clearAt = strtotime(date('Y-m-d', $targetDay) . ' ' . sprintf('%02d:00:00', intval($clearHour)));
|
|
|
+ while ($clearAt <= $baseTime) {
|
|
|
+ $clearAt = strtotime('+' . intval($intervalDays) . ' days', $clearAt);
|
|
|
+ }
|
|
|
+ return $clearAt;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取循环清空限购配置
|
|
|
+ public static function getLimitBuyClearLoopConfigByProductId($productId)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ if ($productId <= 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ $clearLoopKey = self::CLEAR_LOOP_KEY . $productId;
|
|
|
+ $config = Yii::$app->redis->executeCommand('GET', [$clearLoopKey]);
|
|
|
+ if (empty($config)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ $config = json_decode($config, true);
|
|
|
+ return is_array($config) ? $config : [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取限购清空配置,用于商品详情回显
|
|
|
+ public static function getLimitBuyClearInfo($productId)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ $info = [
|
|
|
+ 'limitBuyClearType' => 0, // 0不清空 1定时清空 2循环清空
|
|
|
+ 'limitBuyClearTypeName' => '不清空',
|
|
|
+ 'limitBuyClearAt' => 0,
|
|
|
+ 'limitBuyClearTime' => '',
|
|
|
+ 'limitBuyNextClearAt' => 0,
|
|
|
+ 'limitBuyNextClearTime' => '',
|
|
|
+ 'limitBuyClearIntervalDays' => 0,
|
|
|
+ 'cleartAt' => '',
|
|
|
+ ];
|
|
|
+ if ($productId <= 0) {
|
|
|
+ return $info;
|
|
|
+ }
|
|
|
+
|
|
|
+ $loopConfig = self::getLimitBuyClearLoopConfigByProductId($productId);
|
|
|
+ if (!empty($loopConfig)) {
|
|
|
+ $info['limitBuyClearType'] = 1;
|
|
|
+ $info['limitBuyClearTypeName'] = '循环清空';
|
|
|
+ $info['limitBuyClearIntervalDays'] = intval($loopConfig['intervalDays'] ?? 0);
|
|
|
+ $info['cleartAt'] = intval($loopConfig['clearHour'] ?? 0);
|
|
|
+ return $info;
|
|
|
+ }
|
|
|
+
|
|
|
+ $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
|
|
|
+ $clearAt = intval(Yii::$app->redis->executeCommand('GET', [$clearMarkKey]));
|
|
|
+ if ($clearAt <= 0) {
|
|
|
+ return $info;
|
|
|
+ }
|
|
|
+
|
|
|
+ $info['limitBuyClearType'] = 2;
|
|
|
+ $info['limitBuyClearTypeName'] = '定时清空';
|
|
|
+ $info['limitBuyClearAt'] = $clearAt;
|
|
|
+ $info['limitBuyClearTime'] = date('Y-m-d H:i:s', $clearAt);
|
|
|
+ $info['limitBuyNextClearAt'] = $clearAt;
|
|
|
+ $info['limitBuyNextClearTime'] = $info['limitBuyClearTime'];
|
|
|
+
|
|
|
+ return $info;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清理循环清空限购配置
|
|
|
+ public static function clearLimitBuyClearLoopConfig($productId)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ if ($productId <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ $clearLoopKey = self::CLEAR_LOOP_KEY . $productId;
|
|
|
+ Yii::$app->redis->executeCommand('DEL', [$clearLoopKey]);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录限购缓存写入前快照(同一次请求内同商品同客户只记录一次)
|
|
|
+ *
|
|
|
+ * @param int $productId
|
|
|
+ * @param int $customId
|
|
|
+ * @param bool $hasOldValue
|
|
|
+ * @param string|int|float $oldValue
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public static function recordLimitBuyRollbackSnapshot($productId, $customId, $hasOldValue, $oldValue = 0)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ $customId = intval($customId);
|
|
|
+ if ($productId <= 0 || $customId <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $snapshotKey = $productId . '_' . $customId;
|
|
|
+ if (!isset(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY]) || !is_array(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY])) {
|
|
|
+ Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY] = [];
|
|
|
+ }
|
|
|
+ if (isset(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY][$snapshotKey])) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY][$snapshotKey] = [
|
|
|
+ 'productId' => $productId,
|
|
|
+ 'customId' => $customId,
|
|
|
+ 'hasOldValue' => $hasOldValue ? 1 : 0,
|
|
|
+ 'oldValue' => strval($oldValue),
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清理当前请求中记录的限购回滚快照
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public static function clearLimitBuyRollbackSnapshot()
|
|
|
+ {
|
|
|
+ unset(Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回滚当前请求中已记录的限购缓存变更
|
|
|
+ *
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function rollbackLimitBuySnapshot()
|
|
|
+ {
|
|
|
+ $snapshotList = Yii::$app->params[self::LIMIT_BUY_ROLLBACK_SNAPSHOT_KEY] ?? [];
|
|
|
+ if (empty($snapshotList) || !is_array($snapshotList)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ foreach ($snapshotList as $snapshot) {
|
|
|
+ $productId = intval($snapshot['productId'] ?? 0);
|
|
|
+ $customId = intval($snapshot['customId'] ?? 0);
|
|
|
+ if ($productId <= 0 || $customId <= 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
+ $hasOldValue = intval($snapshot['hasOldValue'] ?? 0);
|
|
|
+ if ($hasOldValue == 1) {
|
|
|
+ $oldValue = $snapshot['oldValue'] ?? '0';
|
|
|
+ Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $oldValue]);
|
|
|
+ } else {
|
|
|
+ Yii::$app->redis->executeCommand('HDEL', [$limitKey, $customId]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ self::clearLimitBuyRollbackSnapshot();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取客户当前采购清单中各花材的限购情况
|
|
|
+ public static function getLimitBuyInfoByList($list, $customId)
|
|
|
+ {
|
|
|
+ if (empty($list) || !is_array($list)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ $buyNumMap = [];
|
|
|
+ $ids = [];
|
|
|
+ foreach ($list as $item) {
|
|
|
+ $productId = $item['id'] ?? 0;
|
|
|
+ if (empty($productId)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $productId = intval($productId);
|
|
|
+ $bigNum = $item['bigCount'] ?? ($item['bigNum'] ?? 0);
|
|
|
+ $smallNum = $item['smallCount'] ?? ($item['smallNum'] ?? 0);
|
|
|
+ if (isset($buyNumMap[$productId]) == false) {
|
|
|
+ $buyNumMap[$productId] = [
|
|
|
+ 'bigNum' => 0,
|
|
|
+ 'smallNum' => 0,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ $buyNumMap[$productId]['bigNum'] = bcadd($buyNumMap[$productId]['bigNum'], $bigNum, 2);
|
|
|
+ $buyNumMap[$productId]['smallNum'] = bcadd($buyNumMap[$productId]['smallNum'], $smallNum, 2);
|
|
|
+ $ids[] = $productId;
|
|
|
+ }
|
|
|
+
|
|
|
+ $ids = array_values(array_unique($ids));
|
|
|
+ if (empty($ids)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ $productData = self::getProductByIds($ids);
|
|
|
+ $productData = array_column($productData, null, 'id');
|
|
|
+ $respond = [];
|
|
|
+ foreach ($ids as $productId) {
|
|
|
+ $product = $productData[$productId] ?? [];
|
|
|
+ if (empty($product)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $limitBuy = $product['limitBuy'] ?? 0;
|
|
|
+ $isLimit = $limitBuy > 0 ? true : false;
|
|
|
+ $hasBuyNum = 0;
|
|
|
+ if ($isLimit) {
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
+ $hasBuyNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
|
|
|
+ $hasBuyNum = $hasBuyNum == null ? 0 : $hasBuyNum;
|
|
|
+ }
|
|
|
+
|
|
|
+ $buyNum = $buyNumMap[$productId] ?? [];
|
|
|
+ $ratio = $product['ratio'] ?? 1;
|
|
|
+ $currentBuyNum = self::mergeItemNum($buyNum['bigNum'] ?? 0, $buyNum['smallNum'] ?? 0, $ratio);
|
|
|
+ $totalBuyNum = bcadd($hasBuyNum, $currentBuyNum, 2);
|
|
|
+ $specialPrice = (
|
|
|
+ ($product['hjDiscountPrice'] ?? 0) > 0
|
|
|
+ && ($product['discountPrice'] ?? 0) > 0
|
|
|
+ && ($product['skDiscountPrice'] ?? 0) > 0
|
|
|
+ ) ? true : false;
|
|
|
+
|
|
|
+ $respond[] = [
|
|
|
+ 'id' => $productId,
|
|
|
+ 'name' => $product['name'] ?? '',
|
|
|
+ 'isLimit' => $isLimit, //是否限购
|
|
|
+ 'limitBuy' => (float)$limitBuy, //限购数量
|
|
|
+ 'specialPrice' => $specialPrice, //是否特价
|
|
|
+ 'hasBuyNum' => $isLimit ? (float)$hasBuyNum : 0, //已购买数量
|
|
|
+ 'currentBuyNum' => (float)$currentBuyNum, //此次购买的数量
|
|
|
+ 'reachLimitBuyNum' => ($isLimit && $totalBuyNum > $limitBuy) ? true : false, //是否达到限购数量
|
|
|
+ 'exceedNum' => $isLimit ? (float)bcsub($hasBuyNum, $limitBuy, 2) : 0, //超出数量, 小于等于0表示未超出
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return $respond;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 限购处理
|
|
|
+ * @param $product
|
|
|
+ * @param $customId
|
|
|
+ * @param $num
|
|
|
+ */
|
|
|
+ public static function handleLimitBuy($product, $customId, $num)
|
|
|
+ {
|
|
|
+ $limitBuy = $product['limitBuy'];
|
|
|
+ if ($limitBuy <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $productId = $product['productId'];
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
+ $has = Yii::$app->redis->executeCommand('HEXISTS', [$limitKey, $customId]);
|
|
|
+ if (!empty($has)) {
|
|
|
+ $hasNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
|
|
|
+ self::recordLimitBuyRollbackSnapshot($productId, $customId, true, $hasNum);
|
|
|
+ $lastNum = bcadd($hasNum, $num);
|
|
|
+ if ($lastNum > $limitBuy) {
|
|
|
+ // 如果有特价,则超过的数量按原价卖;否则中断
|
|
|
+ if ($product['hjDiscountPrice'] > 0 && $product['discountPrice'] > 0 && $product['skDiscountPrice'] > 0) {
|
|
|
+ Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $lastNum]);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ util::error(-1, '累计已超出限购数', ['productId'=>$productId, 'limitBuy'=>$limitBuy, 'exceed'=>$lastNum - $limitBuy]);
|
|
|
+ }
|
|
|
+ Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $lastNum]);
|
|
|
+ } else {
|
|
|
+ self::recordLimitBuyRollbackSnapshot($productId, $customId, false, 0);
|
|
|
+ if ($num > $limitBuy) {
|
|
|
+ // 如果有特价,则超过的数量按原价卖;否则中断
|
|
|
+ if ($product['hjDiscountPrice'] > 0 && $product['discountPrice'] > 0 && $product['skDiscountPrice'] > 0) {
|
|
|
+ Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $num]);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ util::error(-1, '超出限购数', ['productId'=>$productId, 'limitBuy'=>$limitBuy, 'exceed'=>$num - $limitBuy]);
|
|
|
+ }
|
|
|
+ Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $num]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//取消限购的缓存 ssh 20240605
|
|
|
public static function cancelLimitBuy($productId)
|
|
|
{
|
|
|
- $limitKey = 'limit_buy_' . $productId;
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
$arr = Yii::$app->redis->executeCommand('HKEYS', [$limitKey]);
|
|
|
if (!empty($arr)) {
|
|
|
foreach ($arr as $field) {
|
|
|
self::baseClearLimitBuy($productId, $field);
|
|
|
}
|
|
|
}
|
|
|
+ self::clearLimitBuyClearMark($productId);
|
|
|
+ self::clearLimitBuyClearLoopConfig($productId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验清空限购消息是否是当前有效版本
|
|
|
+ public static function checkLimitBuyClearMessage($productId, $clearAt)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ $clearAt = intval($clearAt);
|
|
|
+ if ($productId <= 0 || $clearAt <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
|
|
|
+ $currentClearAt = intval(Yii::$app->redis->executeCommand('GET', [$clearMarkKey]));
|
|
|
+ return $currentClearAt > 0 && $currentClearAt == $clearAt;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清理限购清空标记
|
|
|
+ public static function clearLimitBuyClearMark($productId)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ if ($productId <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ $clearMarkKey = self::CLEAR_MARK_KEY . $productId;
|
|
|
+ Yii::$app->redis->executeCommand('DEL', [$clearMarkKey]);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
//$num -1 表示减全部,大于-1表示减值
|
|
|
public static function baseClearLimitBuy($productId, $customId, $num = -1)
|
|
|
{
|
|
|
- $limitKey = 'limit_buy_' . $productId;
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
if ($num <= -1) {
|
|
|
//清掉全部
|
|
|
Yii::$app->redis->executeCommand('HDEL', [$limitKey, $customId]);
|
|
|
} else {
|
|
|
$hasNum = Yii::$app->redis->executeCommand('HGET', [$limitKey, $customId]);
|
|
|
- $remainNum = $hasNum > $num ? bcsub($num, $hasNum) : 0;
|
|
|
+ $remainNum = $hasNum > $num ? bcsub($hasNum, $num) : 0;
|
|
|
$remainNum = floor($remainNum);
|
|
|
if ($remainNum > 0) {
|
|
|
Yii::$app->redis->executeCommand('HSET', [$limitKey, $customId, $remainNum]);
|
|
|
@@ -2649,11 +3190,23 @@ class ProductClass extends BaseClass
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 只清空已购买记录,不关闭商品限购配置
|
|
|
+ public static function clearLimitBuyRecordByProductId($productId)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ if ($productId <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
+ Yii::$app->redis->executeCommand('DEL', [$limitKey]);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
public static function getHasLimitBuyList($product)
|
|
|
{
|
|
|
$productId = $product->id;
|
|
|
- $limitBuy = $product->limitBuy ?? 0;
|
|
|
- $limitKey = 'limit_buy_' . $productId;
|
|
|
+ $limitBuy = $product->limitBuy;
|
|
|
+ $limitKey = self::LIMIT_BUY_KEY . $productId;
|
|
|
$arr = Yii::$app->redis->executeCommand('HKEYS', [$limitKey]);
|
|
|
$customList = [];
|
|
|
if (!empty($arr)) {
|
|
|
@@ -2664,18 +3217,39 @@ class ProductClass extends BaseClass
|
|
|
$numMap[$customId] = $num;
|
|
|
$ids[] = $customId;
|
|
|
}
|
|
|
+
|
|
|
+ $specialPrice = ($product['hjDiscountPrice'] > 0 && $product['discountPrice'] > 0 && $product['skDiscountPrice'] > 0); // 销售花材是否开启特价
|
|
|
$customList = CustomClass::getAllByCondition(['id' => ['in', $ids]], null, '*');
|
|
|
foreach ($customList as $key => $val) {
|
|
|
$customId = $val['id'];
|
|
|
$num = $numMap[$customId] ?? 0;
|
|
|
$customList[$key]['hasLimitBuyNum'] = $num;
|
|
|
- $customList[$key]['hasReachLimitBuyNum'] = $num >= $limitBuy ? 1 : 0;
|
|
|
+ $customList[$key]['reachLimitBuyNum'] = $num >= $limitBuy ? 1 : 0;
|
|
|
$avatar = $val['avatar'] ?? '';
|
|
|
$smallAvatar = imgUtil::groupImg($avatar);
|
|
|
$customList[$key]['smallAvatar'] = $smallAvatar . "?x-oss-process=image/resize,m_fill,h_80,w_80";
|
|
|
+ $customList[$key]['specialPrice'] = $specialPrice;
|
|
|
}
|
|
|
}
|
|
|
return $customList;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 根据花材清空订单项限购值
|
|
|
+ *
|
|
|
+ * @param int $productId
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public static function clearLimitBuyByProductId($productId)
|
|
|
+ {
|
|
|
+ $productId = intval($productId);
|
|
|
+ if ($productId <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ self::updateById($productId, ['limitBuy' => 0]);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
+
|