You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

212 lines
8.0 KiB

<?php
namespace addons\shopro\library\traits;
use addons\shopro\exception\Exception;
use addons\shopro\model\ActivityGoodsSkuPrice;
use addons\shopro\model\Goods;
use addons\shopro\model\GoodsSkuPrice;
use addons\shopro\model\OrderItem;
use addons\shopro\model\ScoreGoodsSkuPrice;
/**
* 库存销量
*/
trait StockSale
{
use StockWarning;
// cache 正向加销量,添加订单之前拦截
public function cacheForwardSale($goods_list) {
try {
// 记录库存不足,中断的位置
$break_key = -1;
foreach ($goods_list as $key => $goods) {
$detail = $goods['detail'];
$activity = $detail['activity'];
// 没有活动,不是秒杀|拼团,或者没有 redis
if (!$activity || !in_array($activity['type'], ['seckill', 'groupon']) || !$this->hasRedis()) {
continue;
}
// 实例化 redis
$redis = $this->getRedis();
$keys = $this->getKeys([
'goods_id' => $detail['id'],
'goods_sku_price_id' => $detail['current_sku_price']['id'],
], [
'activity_id' => $activity['id'],
'activity_type' => $activity['type'],
]);
extract($keys);
// 活动商品规格
$goodsSkuPrice = $redis->HGET($activityHashKey, $goodsSkuPriceKey);
$goodsSkuPrice = json_decode($goodsSkuPrice, true);
// 活动商品库存
$stock = $goodsSkuPrice['stock'] ?? 0;
// 当前销量 + 购买数量 ,salekey 如果不存在,自动创建
$sale = $redis->HINCRBY($activityHashKey, $saleKey, $goods['goods_num']);
if ($sale > $stock) {
// 记录中断的位置
$break_key = $key;
throw new \Exception('活动商品库存不足');
}
}
} catch (\Exception $e) {
// 将 缓存的 销量减掉
if ($break_key >= 0) {
foreach ($goods_list as $key => $goods) {
if ($key > $break_key) { // 上面库存不足中断的位置
break;
}
$detail = $goods['detail'];
$activity = $detail['activity'];
// 没有活动,不是秒杀|拼团,或者没有 redis
if (!$activity || !in_array($activity['type'], ['seckill', 'groupon']) || !$this->hasRedis()) {
continue;
}
// 实例化 redis
$redis = $this->getRedis();
$keys = $this->getKeys([
'goods_id' => $detail['id'],
'goods_sku_price_id' => $detail['current_sku_price']['id'],
], [
'activity_id' => $activity['id'],
'activity_type' => $activity['type'],
]);
extract($keys);
if ($redis->EXISTS($activityHashKey) && $redis->HEXISTS($activityHashKey, $saleKey)) {
$sale = $redis->HINCRBY($activityHashKey, $saleKey, -$goods['goods_num']);
}
}
new Exception('商品库存不足');
}
new Exception($e->getMessage());
}
}
// cache 反向减销量,取消订单/订单自动关闭 时候
public function cacheBackSale($order) {
$items = OrderItem::where('order_id', $order['id'])->select();
foreach ($items as $key => $item) {
$this->cacheBackSaleByItem($item);
}
}
// 真实正向 减库存加销量(支付成功扣库存,加销量)
public function realForwardStockSale($order) {
$items = OrderItem::where('order_id', $order['id'])->select();
foreach ($items as $key => $orderItem) {
// 增加商品销量
Goods::where('id', $orderItem->goods_id)->setInc('sales', $orderItem->goods_num);
$goodsSkuPrice = GoodsSkuPrice::where('id', $orderItem->goods_sku_price_id)->find();
if ($goodsSkuPrice) {
$goodsSkuPrice->setDec('stock', $orderItem->goods_num); // 减少库存
$goodsSkuPrice->setInc('sales', $orderItem->goods_num); // 增加销量
// 库存预警检测
$this->checkStockWarning($goodsSkuPrice);
}
if ($orderItem->item_goods_sku_price_id) {
if ($order['type'] == 'score') {
// 积分商城商品,扣除积分规格库存
$itemGoodsSkuPrice = ScoreGoodsSkuPrice::where('id', $orderItem->item_goods_sku_price_id)->find();
} else {
// 扣除活动库存
$itemGoodsSkuPrice = ActivityGoodsSkuPrice::where('id', $orderItem->item_goods_sku_price_id)->find();
}
if ($itemGoodsSkuPrice) {
$itemGoodsSkuPrice->setDec('stock', $orderItem->goods_num); // 减少库存
$itemGoodsSkuPrice->setInc('sales', $orderItem->goods_num); // 增加销量
}
}
// 已经真实减库存 减掉预销量,库存都是在缓存中读取的, 真是减库存,没有减掉 缓存库存,所以不需要减掉预销量, 设置开始的活动不可编辑
// $this->cacheBackSaleByItem($orderItem);
}
}
// 真实反向 加库存减销量(支付过的现在没有返库存,暂时没用)
public function realBackStockSale($order)
{
$items = OrderItem::where('order_id', $order['id'])->select();
foreach ($items as $key => $orderItem) {
// 返还商品销量
Goods::where('id', $orderItem->goods_id)->setDec('sales', $orderItem->goods_num);
// 返还规格库存
$goodsSkuPrice = GoodsSkuPrice::where('id', $orderItem->goods_sku_price_id)->find();
if ($goodsSkuPrice) {
$goodsSkuPrice->setInc('stock', $orderItem->goods_num);
$goodsSkuPrice->setDec('sales', $orderItem->goods_num);
}
if ($orderItem->item_goods_sku_price_id) {
if ($order['type'] == 'score') {
// 积分商城商品,扣除积分规格库存
$itemGoodsSkuPrice = ScoreGoodsSkuPrice::where('id', $orderItem->item_goods_sku_price_id)->find();
} else {
$itemGoodsSkuPrice = ActivityGoodsSkuPrice::where('id', $orderItem->item_goods_sku_price_id)->find();
}
if ($itemGoodsSkuPrice) {
$itemGoodsSkuPrice->setInc('stock', $orderItem->goods_num); // 增加库存
$itemGoodsSkuPrice->setDec('sales', $orderItem->goods_num); // 减少销量
}
}
}
}
// 通过 OrderItem 减预库存
private function cacheBackSaleByItem($item)
{
// 不是秒杀|拼团,或者 没有配置 redis
if ((strpos($item['activity_type'], 'groupon') === false && strpos($item['activity_type'], 'seckill') === false) || !$this->hasRedis()) {
return false;
}
// 实例化 redis
$redis = $this->getRedis();
$keys = $this->getKeys([
'goods_id' => $item['goods_id'],
'goods_sku_price_id' => $item['goods_sku_price_id'],
], [
'activity_id' => $item['activity_id'],
'activity_type' => $item['activity_type'],
]);
extract($keys);
if ($redis->EXISTS($activityHashKey) && $redis->HEXISTS($activityHashKey, $saleKey)) {
$sale = $redis->HINCRBY($activityHashKey, $saleKey, -$item['goods_num']);
}
return true;
}
}