Merge branch 'v4.7.0dev' of https://gitee.com/ZhongBangKeJi/CRMEB into v4.7.0dev

This commit is contained in:
liaofei 2023-03-02 10:38:03 +08:00
commit 245fc1a011
24 changed files with 265 additions and 611 deletions

View File

@ -65,18 +65,8 @@ class StoreIntegralOrderController
$num = (int)$num;
//判断积分商品限量
$unique = $storeIntegralServices->checkoutProductStock($uid, $productInfo['product_id'], $num, $unique);
try {
//弹出队列
if (!CacheService::popStock($unique, $num, 4)) {
return app('json')->fail(410296);
}
$order = $this->services->createOrder($uid, $addressId, $mark, $request->user()->toArray(), $num, $productInfo);
} catch (\Throwable $e) {
//生成失败归还库存
CacheService::setStock($unique, $num, 4, false);
return app('json')->fail($e->getMessage());
}
$storeIntegralServices->checkoutProductStock($uid, $productInfo['product_id'], $num, $unique);
$order = $this->services->createOrder($uid, $addressId, $mark, $request->user()->toArray(), $num, $productInfo);
return app('json')->status('success', 410203, ['orderId' => $order['order_id']]);
}

View File

@ -165,8 +165,8 @@ class StoreOrderController
public function create(Request $request, StoreBargainServices $bargainServices, StorePinkServices $pinkServices, StoreOrderCreateServices $createServices, StoreSeckillServices $seckillServices, UserInvoiceServices $userInvoiceServices, StoreOrderInvoiceServices $storeOrderInvoiceServices, StoreCombinationServices $combinationServices, $key)
{
if (!$key) return app('json')->fail(100100);
$uid = (int)$request->uid();
if ($checkOrder = $this->services->getOne(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0]))
$userInfo = $request->user()->toArray();
if ($checkOrder = $this->services->getOne(['order_id|unique' => $key, 'uid' => $userInfo['uid'], 'is_del' => 0]))
return app('json')->status('extend_order', 410209, ['orderId' => $checkOrder['order_id'], 'key' => $key]);
[$addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckillId, $bargainId, $shipping_type, $real_name, $phone, $storeId, $news, $invoice_id, $quitUrl, $advanceId, $virtual_type, $customForm] = $request->postMore([
[['addressId', 'd'], 0],
@ -190,76 +190,10 @@ class StoreOrderController
['custom_form', []],
], true);
$payType = strtolower($payType);
// $cartGroup = $this->services->getCacheOrderInfo($uid, $key);
// if (!$cartGroup) {
// return app('json')->fail(410208);
// }
// //下单前砍价验证
// if ($bargainId) {
// $bargainServices->checkBargainUser((int)$bargainId, $uid);
// }
//
// if ($pinkId) {
// $pinkId = (int)$pinkId;
// /** @var StorePinkServices $pinkServices */
// $pinkServices = app()->make(StorePinkServices::class);
// if ($pinkServices->isPink($pinkId, $uid))
// return app('json')->status('ORDER_EXIST', 410210, ['orderId' => $this->services->getStoreIdPink($pinkId, $uid)]);
// if ($this->services->getIsOrderPink($pinkId, $uid))
// return app('json')->status('ORDER_EXIST', 410211, ['orderId' => $this->services->getStoreIdPink($pinkId, $uid)]);
// if (!CacheService::checkStock(md5($pinkId), 1, 3) || !CacheService::popStock(md5($pinkId), 1, 3)) {
// return app('json')->fail(410212);
// }
// }
//
// $cartInfo = null;
// if ($seckill_id || $combinationId || $bargainId || $advanceId) {
// $cartInfo = $cartGroup['cartInfo'];
// foreach ($cartInfo as $item) {
// $type = 0;
// if (!isset($item['product_attr_unique']) || !$item['product_attr_unique']) continue;
// if ($item['seckill_id']) {
// $type = 1;
// } elseif ($item['bargain_id']) {
// $type = 2;
// } elseif ($item['combination_id']) {
// $type = 3;
// } elseif ($item['advance_id']) {
// $type = 6;
// }
// if ($type && (!CacheService::checkStock($item['product_attr_unique'], (int)$item['cart_num'], $type) || !CacheService::popStock($item['product_attr_unique'], (int)$item['cart_num'], $type))) {
// return app('json')->fail(410214, null, ['cart_num' => $item['cart_num'], 'unit_name' => $item['productInfo']['unit_name']]);
//
// }
// }
// }
// $virtual_type = $cartGroup['cartInfo'][0]['productInfo']['virtual_type'] ?? 0;
$order = $createServices->createOrder($uid, $key, $request->user()->toArray(), $addressId, $payType, !!$useIntegral, $couponId, $mark, $combinationId, $pinkId, $seckillId, $bargainId, $shipping_type, $real_name, $phone, $storeId, !!$news, $advanceId, $customForm, $invoice_id);
// if ($order === false) {
// if ($seckill_id || $combinationId || $advanceId || $bargainId) {
// foreach ($cartInfo as $item) {
// $value = $item['cart_info'];
// $type = 0;
// if (!isset($value['product_attr_unique']) || $value['product_attr_unique']) continue;
// if ($value['seckill_id']) {
// $type = 1;
// } elseif ($value['bargain_id']) {
// $type = 2;
// } elseif ($value['combination_id']) {
// $type = 3;
// } elseif ($value['advance_id']) {
// $type = 6;
// }
// if ($type) CacheService::setStock($value['product_attr_unique'], (int)$value['cart_num'], $type, false);
// }
// }
// throw new ApiException(410200);
// }
$order = CacheService::lock('orderCreat' . $key, function () use ($createServices, $userInfo, $key, $addressId, $payType, $useIntegral, $couponId, $mark, $combinationId, $pinkId, $seckillId, $bargainId, $shipping_type, $real_name, $phone, $storeId, $news, $advanceId, $customForm, $invoice_id) {
return $createServices->createOrder($userInfo['uid'], $key, $userInfo, $addressId, $payType, !!$useIntegral, $couponId, $mark, $combinationId, $pinkId, $seckillId, $bargainId, $shipping_type, $real_name, $phone, $storeId, !!$news, $advanceId, $customForm, $invoice_id);
});
$orderId = $order['order_id'];
// $orderInfo = $this->services->getOne(['order_id' => $orderId]);
// if (!$orderInfo || !isset($orderInfo['paid'])) {
// return app('json')->fail(410194);
// }
return app('json')->status('success', 410203, compact('orderId', 'key'));
}

View File

@ -65,13 +65,6 @@ class UnpaidOrderCancelJob extends BaseJobs
$orderInfo->is_del = 1;
$orderInfo->mark = '订单未支付已超过系统预设时间';
$orderInfo->save();
try {
/** @var StoreSeckillServices $seckiiServices */
$seckiiServices = app()->make(StoreSeckillServices::class);
$seckiiServices->cancelOccupySeckillStock($cartInfo, $orderInfo['unique']);
$seckiiServices->rollBackStock($cartInfo);
} catch (\Throwable $e) {
}
}
return $res;
} catch (\Throwable $e) {

View File

@ -46,14 +46,6 @@ class OrderPaySuccessListener implements ListenerInterface
'change_time' => time()
]);
//回退秒杀库存占用
/** @var StoreOrderCartInfoServices $cartServices */
$cartServices = app()->make(StoreOrderCartInfoServices::class);
$cartInfo = $cartServices->getOrderCartInfo($orderInfo['id']);
/** @var StoreSeckillServices $seckiiServices */
$seckiiServices = app()->make(StoreSeckillServices::class);
$seckiiServices->cancelOccupySeckillStock($cartInfo, $orderInfo['unique']);
//赠送购买商品优惠券
/** @var StoreProductCouponServices $storeProductCouponServices */
$storeProductCouponServices = app()->make(StoreProductCouponServices::class);

View File

@ -115,13 +115,6 @@ class StoreAdvanceServices extends BaseServices
$valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$res->id, 6);
if (!$res) throw new AdminException(100022);
}
$res = true;
foreach ($valueGroup->toArray() as $item) {
$res = $res && CacheService::setStock($item['unique'], (int)$item['quota_show'], 6);
}
if (!$res) {
throw new AdminException(400092);
}
});
}

View File

@ -171,13 +171,6 @@ class StoreBargainServices extends BaseServices
$valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$res->id, 2);
if (!$res) throw new AdminException(100022);
}
$res = true;
foreach ($valueGroup->toArray() as $item) {
$res = $res && CacheService::setStock($item['unique'], (int)$item['quota_show'], 2);
}
if (!$res) {
throw new AdminException(400092);
}
});
}

View File

@ -187,8 +187,14 @@ class StoreBargainUserServices extends BaseServices
if (!$bargainUserUid) return [];
[$page, $limit] = $this->getPageValue();
$list = $this->dao->userAll($bargainUserUid, $page, $limit);
$bargainHelpServices = app()->make(StoreBargainUserHelpServices::class);
foreach ($list as &$item) {
$item['residue_price'] = bcsub((string)$item['bargain_price'], (string)$item['price'], 2);
if ($item['status'] == 3) {
$item['success_time'] = date('Y-m-d H:i:s', (int)$bargainHelpServices->getMax(['bargain_user_id' => $item['id']], 'add_time'));
} else {
$item['success_time'] = '';
}
}
return $list;
}

View File

@ -118,13 +118,6 @@ class StoreCombinationServices extends BaseServices
$valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$res->id, 3);
if (!$res) throw new AdminException(100022);
}
$res = true;
foreach ($valueGroup->toArray() as $item) {
$res = $res && CacheService::setStock($item['unique'], (int)$item['quota_show'], 3);
}
if (!$res) {
throw new AdminException(400092);
}
});
}

View File

@ -131,9 +131,6 @@ class StorePinkServices extends BaseServices
} else if ($countY) {//团员
$res = $this->dao->update($countY['id'], ['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
}
if ($res) {
CacheService::setStock(md5((string)$id), 1, 3, false);
}
return $res;
}
@ -478,9 +475,6 @@ class StorePinkServices extends BaseServices
$pink['id'] = $res1['id'];
}
$number = (int)bcsub((string)$pink['people'], '1', 0);
if ($number) CacheService::setStock(md5($pink['id']), $number, 3);
PinkJob::dispatchSecs((int)(($product->effective_time * 3600) + 60), [$pink['id']]);
// 开团成功发送模板消息
event('NoticeListener', [['orderInfo' => $orderInfo, 'title' => $product['title'], 'pink' => $pink], 'open_pink_success']);

View File

@ -87,7 +87,7 @@ class StoreIntegralServices extends BaseServices
$res = $this->dao->update($id, $data);
$storeDescriptionServices->saveDescription((int)$id, $description, 4);
$skuList = $storeProductServices->validateProductAttr($items, $detail, (int)$id, 4);
$valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$id, 4);
$storeProductAttrServices->saveProductAttr($skuList, (int)$id, 4);
if (!$res) throw new AdminException(100007);
} else {
if (!$storeProductServices->getOne(['is_show' => 1, 'is_del' => 0, 'id' => $data['product_id']])) {
@ -97,16 +97,9 @@ class StoreIntegralServices extends BaseServices
$res = $this->dao->save($data);
$storeDescriptionServices->saveDescription((int)$res->id, $description, 4);
$skuList = $storeProductServices->validateProductAttr($items, $detail, (int)$res->id, 4);
$valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$res->id, 4);
$storeProductAttrServices->saveProductAttr($skuList, (int)$res->id, 4);
if (!$res) throw new AdminException(100022);
}
$res = true;
foreach ($valueGroup->toArray() as $item) {
$res = $res && CacheService::setStock($item['unique'], (int)$item['quota_show'], 4);
}
if (!$res) {
throw new AdminException(400092);
}
});
}
@ -393,9 +386,6 @@ class StoreIntegralServices extends BaseServices
if ($product_stock < $num) {
throw new ApiException(410297, ['num' => $num]);
}
if (!CacheService::checkStock($unique, $num, 4)) {
throw new ApiException(410297, ['num' => $num]);
}
return $unique;
}

View File

@ -190,13 +190,6 @@ class StoreSeckillServices extends BaseServices
$valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$res->id, 1);
if (!$res) throw new AdminException(100022);
}
$res = true;
foreach ($valueGroup->toArray() as $item) {
$res = $res && CacheService::setStock($item['unique'], (int)$item['quota_show'], 1);
}
if (!$res) {
throw new AdminException(400092);
}
});
}
@ -602,33 +595,18 @@ class StoreSeckillServices extends BaseServices
}
/**
* 秒杀库存添加入redis的队列中
* @param string $unique sku唯一值
* @param int $type 类型
* @param int $number 库存个数
* @param bool $isPush 是否放入之前删除当前队列
* @return bool|int
*/
public function pushSeckillStock(string $unique, int $type, int $number, bool $isPush = false)
{
$name = 'seckill_' . $unique . '_' . $type;
/** @var CacheService $cache */
$cache = app()->make(CacheService::class);
$res = true;
if (!$isPush) {
$cache->delete($name);
}
for ($i = 1; $i <= $number; $i++) {
$res = $res && $cache->lPush($name, $i);
}
return $res;
}
/**
* @param int $productId
* @param string $unique
* 检查秒杀库存
* @param int $uid
* @param int $seckillId
* @param int $cartNum
* @param string $value
* @param string $unique
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/03/01
*/
public function checkSeckillStock(int $uid, int $seckillId, int $cartNum = 1, string $unique = '')
{
@ -661,139 +639,18 @@ class StoreSeckillServices extends BaseServices
return [$attrInfo, $unique, $StoreSeckillinfo];
}
/**
* 弹出redis队列中的库存条数
* @param string $unique
* @param int $type
* @return mixed
*/
public function popSeckillStock(string $unique, int $type, int $number = 1)
{
$name = 'seckill_' . $unique . '_' . $type;
/** @var CacheService $cache */
$cache = app()->make(CacheService::class);
if ($number > $cache->lLen($name)) {
return false;
}
$res = true;
for ($i = 1; $i <= $number; $i++) {
$res = $res && $cache->lPop($name);
}
return $res;
}
/**
* 是否有库存
* @param string $unique
* @param int $type
* @return mixed
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function isSeckillStock(string $unique, int $type, int $number)
{
/** @var CacheService $cache */
$cache = app()->make(CacheService::class);
return $cache->lLen('seckill_' . $unique . '_' . $type) >= $number;
}
/**
* 回滚库存
* @param array $cartInfo
* @param int $number
* @return bool
*/
public function rollBackStock(array $cartInfo)
{
$res = true;
foreach ($cartInfo as $item) {
$value = $item['cart_info'];
if ($value['seckill_id']) {
$res = $res && $this->pushSeckillStock($value['product_attr_unique'], 1, (int)$value['cart_num'], true);
}
}
return $res;
}
/**
* 占用库存
* @param $cartInfo
*/
public function occupySeckillStock($cartInfo, $key, $time = 0)
{
//占用库存
if ($cartInfo) {
if (!$time) {
$time = time() + 600;
}
foreach ($cartInfo as $val) {
if ($val['seckill_id']) {
$this->setSeckillStock($val['product_id'], $val['product_attr_unique'], $time, $key, (int)$val['cart_num']);
}
}
}
return true;
}
/**
* 取消秒杀占用的库存
* @param array $cartInfo
* @param string $key
* @return bool
*/
public function cancelOccupySeckillStock(array $cartInfo, string $key)
{
if ($cartInfo) {
foreach ($cartInfo as $val) {
if (isset($val['seckill_id']) && $val['seckill_id']) {
$this->backSeckillStock((int)$val['product_id'], $val['product_attr_unique'], $key, (int)$val['cart_num']);
}
}
}
return true;
}
/**
* 存入当前秒杀商品属性有序集合
* @param $product_id
* @param $unique
* @param $score
* @param $value
* @param int $cart_num
* @return bool
*/
public function setSeckillStock($product_id, $unique, $score, $value, $cart_num = 1)
{
$set_key = md5('seckill_set_attr_stock_' . $product_id . '_' . $unique);
$i = 0;
for ($i; $i < $cart_num; $i++) {
CacheService::zAdd($set_key, $score, $value . $i);
}
return true;
}
/**
* 取消集合中的秒杀商品
* @param int $product_id
* @param string $unique
* @param $value
* @param int $cart_num
* @return bool
*/
public function backSeckillStock(int $product_id, string $unique, $value, int $cart_num = 1)
{
$set_key = md5('seckill_set_attr_stock_' . $product_id . '_' . $unique);
$i = 0;
for ($i; $i < $cart_num; $i++) {
CacheService::zRem($set_key, $value . $i);
}
return true;
}
/**
* 修改秒杀库存
* @param int $num
* @param int $seckillId
* @param string $unique
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/03/01
*/
public function decSeckillStock(int $num, int $seckillId, string $unique = '')
{

View File

@ -208,9 +208,6 @@ class StoreCartServices extends BaseServices
if ($product_stock < $cartNum) {
throw new ApiException(410297, ['num' => $cartNum]);
}
if ($type != 5 && !CacheService::checkStock($unique, (int)$cartNum, $type)) {
throw new ApiException(410297, ['num' => $cartNum]);
}
}
return [$attrInfo, $unique, $bargainUserInfo['bargain_price_min'] ?? 0, $cartNum, $productInfo];
}

View File

@ -138,8 +138,6 @@ class StoreOrderCreateServices extends BaseServices
* @param array $customForm
* @param int $invoice_id
* @return mixed
* @throws \Psr\SimpleCache\InvalidArgumentException
* @throws \Throwable
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
@ -169,195 +167,147 @@ class StoreOrderCreateServices extends BaseServices
throw new ApiStatusException('ORDER_EXIST', 410210, ['orderId' => $storeOrderServices->getStoreIdPink($pinkId, $uid)]);
if ($storeOrderServices->getIsOrderPink($pinkId, $uid))
throw new ApiStatusException('ORDER_EXIST', 410211, ['orderId' => $storeOrderServices->getStoreIdPink($pinkId, $uid)]);
if (!CacheService::checkStock(md5($pinkId), 1, 3) || !CacheService::popStock(md5($pinkId), 1, 3)) {
throw new ApiException(410212);
}
}
$cartInfo = null;
if ($seckillId || $combinationId || $bargainId || $advanceId) {
$cartInfo = $cartGroup['cartInfo'];
foreach ($cartInfo as $item) {
$type = 0;
if (!isset($item['product_attr_unique']) || !$item['product_attr_unique']) continue;
if ($item['seckill_id']) {
$type = 1;
} elseif ($item['bargain_id']) {
$type = 2;
} elseif ($item['combination_id']) {
$type = 3;
} elseif ($item['advance_id']) {
$type = 6;
}
if ($type && (!CacheService::checkStock($item['product_attr_unique'], (int)$item['cart_num'], $type) || !CacheService::popStock($item['product_attr_unique'], (int)$item['cart_num'], $type))) {
throw new ApiException(410214, ['cart_num' => $item['cart_num'], 'unit_name' => $item['productInfo']['unit_name']]);
}
}
}
$virtual_type = $cartGroup['cartInfo'][0]['productInfo']['virtual_type'] ?? 0;
try {
//下单前发票验证
if ($invoice_id) {
app()->make(UserInvoiceServices::class)->checkInvoice((int)$invoice_id, $uid);
}
//下单前发票验证
if ($invoice_id) {
app()->make(UserInvoiceServices::class)->checkInvoice((int)$invoice_id, $uid);
}
/** @var StoreOrderComputedServices $computedServices */
$computedServices = app()->make(StoreOrderComputedServices::class);
$priceData = $computedServices->computedOrder($uid, $userInfo, $cartGroup, $addressId, $payType, $useIntegral, $couponId, true, $shippingType);
/** @var WechatUserServices $wechatServices */
$wechatServices = app()->make(WechatUserServices::class);
/** @var UserAddressServices $addressServices */
$addressServices = app()->make(UserAddressServices::class);
if ($shippingType == 1 && $virtual_type == 0) {
if (!$addressId) {
throw new ApiException(410045);
}
if (!$addressInfo = $addressServices->getOne(['uid' => $uid, 'id' => $addressId, 'is_del' => 0]))
throw new ApiException(410046);
$addressInfo = $addressInfo->toArray();
} else {
if ((!$real_name || !$phone) && $virtual_type == 0) {
throw new ApiException(410245);
}
$addressInfo['real_name'] = $real_name;
$addressInfo['phone'] = $phone;
$addressInfo['province'] = '';
$addressInfo['city'] = '';
$addressInfo['district'] = '';
$addressInfo['detail'] = '';
/** @var StoreOrderComputedServices $computedServices */
$computedServices = app()->make(StoreOrderComputedServices::class);
$priceData = $computedServices->computedOrder($uid, $userInfo, $cartGroup, $addressId, $payType, $useIntegral, $couponId, true, $shippingType);
/** @var WechatUserServices $wechatServices */
$wechatServices = app()->make(WechatUserServices::class);
/** @var UserAddressServices $addressServices */
$addressServices = app()->make(UserAddressServices::class);
if ($shippingType == 1 && $virtual_type == 0) {
if (!$addressId) {
throw new ApiException(410045);
}
$cartInfo = $cartGroup['cartInfo'];
$priceGroup = $cartGroup['priceGroup'];
$cartIds = [];
$totalNum = 0;
$gainIntegral = 0;
foreach ($cartInfo as $cart) {
$cartIds[] = $cart['id'];
$totalNum += $cart['cart_num'];
if (!$seckillId) $seckillId = $cart['seckill_id'];
if (!$bargainId) $bargainId = $cart['bargain_id'];
if (!$combinationId) $combinationId = $cart['combination_id'];
if (!$advanceId) $advanceId = $cart['advance_id'];
$cartInfoGainIntegral = isset($cart['productInfo']['give_integral']) ? bcmul((string)$cart['cart_num'], (string)$cart['productInfo']['give_integral'], 0) : 0;
$gainIntegral = bcadd((string)$gainIntegral, (string)$cartInfoGainIntegral, 0);
if (!$addressInfo = $addressServices->getOne(['uid' => $uid, 'id' => $addressId, 'is_del' => 0]))
throw new ApiException(410046);
$addressInfo = $addressInfo->toArray();
} else {
if ((!$real_name || !$phone) && $virtual_type == 0) {
throw new ApiException(410245);
}
if (count($cartInfo) == 1 && isset($cartInfo[0]['productInfo']['presale']) && $cartInfo[0]['productInfo']['presale'] == 1) {
$advance_id = $cartInfo[0]['product_id'];
} else {
$advance_id = 0;
}
$deduction = $seckillId || $bargainId || $combinationId;
if ($deduction) {
$couponId = 0;
$useIntegral = false;
}
//$shipping_type = 1 快递发货 $shipping_type = 2 门店自提
$storeSelfMention = sys_config('store_self_mention') ?? 0;
if (!$storeSelfMention) $shippingType = 1;
$addressInfo['real_name'] = $real_name;
$addressInfo['phone'] = $phone;
$addressInfo['province'] = '';
$addressInfo['city'] = '';
$addressInfo['district'] = '';
$addressInfo['detail'] = '';
}
$cartInfo = $cartGroup['cartInfo'];
$priceGroup = $cartGroup['priceGroup'];
$cartIds = [];
$totalNum = 0;
$gainIntegral = 0;
foreach ($cartInfo as $cart) {
$cartIds[] = $cart['id'];
$totalNum += $cart['cart_num'];
if (!$seckillId) $seckillId = $cart['seckill_id'];
if (!$bargainId) $bargainId = $cart['bargain_id'];
if (!$combinationId) $combinationId = $cart['combination_id'];
if (!$advanceId) $advanceId = $cart['advance_id'];
$cartInfoGainIntegral = isset($cart['productInfo']['give_integral']) ? bcmul((string)$cart['cart_num'], (string)$cart['productInfo']['give_integral'], 0) : 0;
$gainIntegral = bcadd((string)$gainIntegral, (string)$cartInfoGainIntegral, 0);
}
if (count($cartInfo) == 1 && isset($cartInfo[0]['productInfo']['presale']) && $cartInfo[0]['productInfo']['presale'] == 1) {
$advance_id = $cartInfo[0]['product_id'];
} else {
$advance_id = 0;
}
$deduction = $seckillId || $bargainId || $combinationId;
if ($deduction) {
$couponId = 0;
$useIntegral = false;
}
//$shipping_type = 1 快递发货 $shipping_type = 2 门店自提
$storeSelfMention = sys_config('store_self_mention') ?? 0;
if (!$storeSelfMention) $shippingType = 1;
$orderInfo = [
'uid' => $uid,
'order_id' => $this->getNewOrderId('cp'),
'real_name' => $addressInfo['real_name'],
'user_phone' => $addressInfo['phone'],
'user_address' => $addressInfo['province'] . ' ' . $addressInfo['city'] . ' ' . $addressInfo['district'] . ' ' . $addressInfo['detail'],
'cart_id' => $cartIds,
'total_num' => $totalNum,
'total_price' => $priceGroup['totalPrice'],
'total_postage' => $shippingType == 1 ? $priceGroup['storePostage'] : 0,
'coupon_id' => $couponId,
'coupon_price' => $priceData['coupon_price'],
'pay_price' => $priceData['pay_price'],
'pay_postage' => $priceData['pay_postage'],
'deduction_price' => $priceData['deduction_price'],
'paid' => 0,
'pay_type' => $payType,
'use_integral' => $priceData['usedIntegral'],
'gain_integral' => $gainIntegral,
'mark' => htmlspecialchars($mark),
'combination_id' => $combinationId,
'pink_id' => $pinkId,
'seckill_id' => $seckillId,
'bargain_id' => $bargainId,
'advance_id' => $advance_id,
'cost' => $priceGroup['costPrice'],
'add_time' => time(),
'unique' => $key,
'shipping_type' => $shippingType,
'channel_type' => $userInfo['user_type'],
'province' => strval($userInfo['user_type'] == 'wechat' || $userInfo['user_type'] == 'routine' ? $wechatServices->value(['uid' => $uid, 'user_type' => $userInfo['user_type']], 'province') : ''),
'spread_uid' => 0,
'spread_two_uid' => 0,
'virtual_type' => $virtual_type,
'pay_uid' => $uid,
'custom_form' => json_encode($customForm),
'division_id' => $userInfo['division_id'],
'agent_id' => $userInfo['agent_id'],
'staff_id' => $userInfo['staff_id'],
];
$orderInfo = [
'uid' => $uid,
'order_id' => $this->getNewOrderId('cp'),
'real_name' => $addressInfo['real_name'],
'user_phone' => $addressInfo['phone'],
'user_address' => $addressInfo['province'] . ' ' . $addressInfo['city'] . ' ' . $addressInfo['district'] . ' ' . $addressInfo['detail'],
'cart_id' => $cartIds,
'total_num' => $totalNum,
'total_price' => $priceGroup['totalPrice'],
'total_postage' => $shippingType == 1 ? $priceGroup['storePostage'] : 0,
'coupon_id' => $couponId,
'coupon_price' => $priceData['coupon_price'],
'pay_price' => $priceData['pay_price'],
'pay_postage' => $priceData['pay_postage'],
'deduction_price' => $priceData['deduction_price'],
'paid' => 0,
'pay_type' => $payType,
'use_integral' => $priceData['usedIntegral'],
'gain_integral' => $gainIntegral,
'mark' => htmlspecialchars($mark),
'combination_id' => $combinationId,
'pink_id' => $pinkId,
'seckill_id' => $seckillId,
'bargain_id' => $bargainId,
'advance_id' => $advance_id,
'cost' => $priceGroup['costPrice'],
'add_time' => time(),
'unique' => $key,
'shipping_type' => $shippingType,
'channel_type' => $userInfo['user_type'],
'province' => strval($userInfo['user_type'] == 'wechat' || $userInfo['user_type'] == 'routine' ? $wechatServices->value(['uid' => $uid, 'user_type' => $userInfo['user_type']], 'province') : ''),
'spread_uid' => 0,
'spread_two_uid' => 0,
'virtual_type' => $virtual_type,
'pay_uid' => $uid,
'custom_form' => json_encode($customForm),
'division_id' => $userInfo['division_id'],
'agent_id' => $userInfo['agent_id'],
'staff_id' => $userInfo['staff_id'],
];
if ($shippingType == 2) {
$orderInfo['verify_code'] = $this->getStoreCode();
/** @var SystemStoreServices $storeServices */
$storeServices = app()->make(SystemStoreServices::class);
$orderInfo['store_id'] = $storeServices->getStoreDispose($storeId, 'id');
if (!$orderInfo['store_id']) {
throw new ApiException(410247);
}
if ($shippingType == 2) {
$orderInfo['verify_code'] = $this->getStoreCode();
/** @var SystemStoreServices $storeServices */
$storeServices = app()->make(SystemStoreServices::class);
$orderInfo['store_id'] = $storeServices->getStoreDispose($storeId, 'id');
if (!$orderInfo['store_id']) {
throw new ApiException(410247);
}
/** @var StoreOrderCartInfoServices $cartServices */
$cartServices = app()->make(StoreOrderCartInfoServices::class);
/** @var StoreSeckillServices $seckillServices */
$seckillServices = app()->make(StoreSeckillServices::class);
$priceData['coupon_id'] = $couponId;
$order = $this->transaction(function () use ($cartIds, $orderInfo, $cartInfo, $key, $userInfo, $useIntegral, $priceData, $combinationId, $seckillId, $bargainId, $cartServices, $seckillServices, $uid, $addressId, $advanceId) {
//创建订单
$order = $this->dao->save($orderInfo);
if (!$order) {
throw new ApiException(410200);
}
//记录自提人电话和姓名
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userService->update(['uid' => $uid], ['real_name' => $orderInfo['real_name'], 'record_phone' => $orderInfo['user_phone']]);
//占用库存
$seckillServices->occupySeckillStock($cartInfo, $key);
//积分抵扣
if ($priceData['usedIntegral'] > 0) {
$this->deductIntegral($userInfo, $useIntegral, $priceData, (int)$userInfo['uid'], $order['id']);
}
//扣库存
$this->decGoodsStock($cartInfo, $combinationId, $seckillId, $bargainId, $advanceId);
//保存购物车商品信息
$cartServices->setCartInfo($order['id'], $uid, $cartInfo);
return $order;
});
}
/** @var StoreOrderCartInfoServices $cartServices */
$cartServices = app()->make(StoreOrderCartInfoServices::class);
/** @var StoreSeckillServices $seckillServices */
$seckillServices = app()->make(StoreSeckillServices::class);
$priceData['coupon_id'] = $couponId;
$order = $this->transaction(function () use ($cartIds, $orderInfo, $cartInfo, $key, $userInfo, $useIntegral, $priceData, $combinationId, $seckillId, $bargainId, $cartServices, $seckillServices, $uid, $addressId, $advanceId) {
//创建订单
$order = $this->dao->save($orderInfo);
if (!$order) {
throw new ApiException(410200);
}
//记录自提人电话和姓名
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userService->update(['uid' => $uid], ['real_name' => $orderInfo['real_name'], 'record_phone' => $orderInfo['user_phone']]);
//积分抵扣
if ($priceData['usedIntegral'] > 0) {
$this->deductIntegral($userInfo, $useIntegral, $priceData, (int)$userInfo['uid'], $order['id']);
}
//扣库存
$this->decGoodsStock($cartInfo, $combinationId, $seckillId, $bargainId, $advanceId);
//保存购物车商品信息
$cartServices->setCartInfo($order['id'], $uid, $cartInfo);
return $order;
});
//创建开票数据
if ($invoice_id) {
app()->make(StoreOrderInvoiceServices::class)->makeUp($uid, $order['order_id'], (int)$invoice_id);
}
} catch (\Throwable $e) {
if ($seckillId || $combinationId || $advanceId || $bargainId) {
foreach ($cartInfo as $item) {
$value = $item['cart_info'];
$type = 0;
if (!isset($value['product_attr_unique']) || $value['product_attr_unique']) continue;
if ($value['seckill_id']) {
$type = 1;
} elseif ($value['bargain_id']) {
$type = 2;
} elseif ($value['combination_id']) {
$type = 3;
} elseif ($value['advance_id']) {
$type = 6;
}
if ($type) CacheService::setStock($value['product_attr_unique'], (int)$value['cart_num'], $type, false);
}
}
throw $e;
//创建开票数据
if ($invoice_id) {
app()->make(StoreOrderInvoiceServices::class)->makeUp($uid, $order['order_id'], (int)$invoice_id);
}
// 订单创建成功后置事件

View File

@ -526,6 +526,10 @@ class StoreOrderRefundServices extends BaseServices
* 回退库存
* @param $order
* @return bool
* @throws \Psr\SimpleCache\InvalidArgumentException
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/03/01
*/
public function regressionStock($order)
{
@ -533,7 +537,6 @@ class StoreOrderRefundServices extends BaseServices
$combination_id = $order['combination_id'];
$seckill_id = $order['seckill_id'];
$bargain_id = $order['bargain_id'];
$advance_id = $order['advance_id'];
$res5 = true;
/** @var StoreOrderCartInfoServices $cartServices */
$cartServices = app()->make(StoreOrderCartInfoServices::class);
@ -553,20 +556,15 @@ class StoreOrderRefundServices extends BaseServices
//增库存减销量
$unique = isset($cart['cart_info']['productInfo']['attrInfo']) ? $cart['cart_info']['productInfo']['attrInfo']['unique'] : '';
$cart_num = (int)$cart['cart_info']['cart_num'];
$type = 0;
if ($combination_id) {
$type = 3;
$res5 = $res5 && $pinkServices->incCombinationStock($cart_num, (int)$combination_id, $unique);
} else if ($seckill_id) {
$type = 1;
$res5 = $res5 && $seckillServices->incSeckillStock($cart_num, (int)$seckill_id, $unique);
} else if ($bargain_id) {
$type = 2;
$res5 = $res5 && $bargainServices->incBargainStock($cart_num, (int)$bargain_id, $unique);
} else {
$res5 = $res5 && $services->incProductStock($cart_num, (int)$cart['cart_info']['productInfo']['id'], $unique);
}
if ($type) CacheService::setStock($unique, $cart_num, $type, false);
}
return $res5;
}

View File

@ -1930,10 +1930,6 @@ HTML;
throw new ApiException(100020);
}
});
/** @var StoreSeckillServices $seckiiServices */
$seckiiServices = app()->make(StoreSeckillServices::class);
$seckiiServices->cancelOccupySeckillStock($cartInfo, $order['unique']);
$seckiiServices->rollBackStock($cartInfo);
return true;
}
@ -2154,10 +2150,6 @@ HTML;
/** @var StoreOrderCartInfoServices $cartServices */
$cartServices = app()->make(StoreOrderCartInfoServices::class);
$cartInfo = $cartServices->getOrderCartInfo((int)$order['id']);
/** @var StoreSeckillServices $seckiiServices */
$seckiiServices = app()->make(StoreSeckillServices::class);
$seckiiServices->cancelOccupySeckillStock($cartInfo, $order['unique']);
$seckiiServices->rollBackStock($cartInfo);
} catch (\Throwable $e) {
Log::error('自动取消订单失败,失败原因:' . $e->getMessage(), $e->getTrace());

View File

@ -61,8 +61,15 @@ class StoreProductRelationServices extends BaseServices
}
/**
* 收藏
* @param int $uid
* @return mixed
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/03/01
*/
public function getUserCollectProduct(int $uid)
{

View File

@ -123,7 +123,7 @@ class UserRechargeServices extends BaseServices
$item['_pay_time'] = $item['pay_time'] ? date('Y-m-d H:i:s', $item['pay_time']) : '暂无';
$item['_add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '暂无';
$item['paid_type'] = $item['paid'] ? '已支付' : '未支付';
$item['avatar'] = strpos($item['avatar'], 'http') === false ? (sys_config('site_url') . $item['avatar']) : $item['avatar'];
$item['avatar'] = strpos($item['avatar'] ?? '', 'http') === false ? (sys_config('site_url') . $item['avatar']) : $item['avatar'];
unset($item['user']);
}
return compact('list', 'count');

View File

@ -145,104 +145,6 @@ class CacheService
}
}
/** 以下三个方法仅开启redis之后才使用 */
/**
* 设置redis入库队列
* @param string $unique
* @param int $number
* @param int $type
* @param bool $isPush
* @return false
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public static function setStock(string $unique, int $number, int $type = 1, bool $isPush = true)
{
if (Config::get('cache.default') == 'file') return true;
if (!$unique || !$number) return false;
$name = (self::$redisQueueKey[$type] ?? '') . '_' . $type . '_' . $unique;
if ($isPush) {
Cache::store('redis')->delete($name);
}
$data = [];
for ($i = 1; $i <= $number; $i++) {
$data[] = $i;
}
return Cache::store('redis')->lPush($name, ...$data);
}
/**
* 是否有库存|返回库存
* @param string $unique
* @param int $number
* @param int $type
* @return bool
*/
public static function checkStock(string $unique, int $number = 0, int $type = 1)
{
if (Config::get('cache.default') == 'file') return true;
$name = (self::$redisQueueKey[$type] ?? '') . '_' . $type . '_' . $unique;
if ($number) {
return Cache::store('redis')->lLen($name) >= $number;
} else {
return Cache::store('redis')->lLen($name);
}
}
/**
* 弹出redis队列中的库存条数
* @param string $unique
* @param int $number
* @param int $type
* @return bool
*/
public static function popStock(string $unique, int $number, int $type = 1)
{
if (Config::get('cache.default') == 'file') return true;
if (!$unique || !$number) return false;
$name = (self::$redisQueueKey[$type] ?? '') . '_' . $type . '_' . $unique;
$res = true;
if ($number > Cache::store('redis')->lLen($name)) {
return false;
}
for ($i = 1; $i <= $number; $i++) {
$res = $res && Cache::store('redis')->lPop($name);
}
return $res;
}
/**
* 存入当前秒杀商品属性有序集合
* @param $set_key
* @param $score
* @param $value
* @return false
*/
public static function zAdd($set_key, $score, $value)
{
if (Config::get('cache.default') == 'file') return true;
try {
return Cache::store('redis')->zAdd($set_key, $score, $value);
} catch (\Throwable $e) {
return false;
}
}
/**
* 取消集合中的秒杀商品
* @param $set_key
* @param $value
* @return false
*/
public static function zRem($set_key, $value)
{
if (Config::get('cache.default') == 'file') return true;
try {
return Cache::store('redis')->zRem($set_key, $value);
} catch (\Throwable $e) {
return false;
}
}
/**
* 检查锁
* @param string $key
@ -298,4 +200,22 @@ class CacheService
return Cache::store('redis');
}
}
/**
* 数据库锁
* @param $key
* @param $fn
* @param int $ex
* @return mixed
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/03/01
*/
public static function lock($key, $fn, int $ex = 6)
{
if (Config::get('cache.default') == 'file') {
return $fn();
}
return app()->make(LockService::class)->exec($key, $fn, $ex);
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace crmeb\services;
use think\facade\Cache;
class LockService
{
/**
* @param $key
* @param $fn
* @param int $ex
* @return mixed
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/03/01
*/
public function exec($key, $fn, int $ex = 6)
{
try {
$this->lock($key, $key, $ex);
return $fn();
} finally {
$this->unlock($key, $key);
}
}
public function tryLock($key, $value = '1', $ex = 6)
{
return Cache::store('redis')->handler()->set('lock_' . $key, $value, ["NX", "EX" => $ex]);
}
public function lock($key, $value = '1', $ex = 6)
{
if ($this->tryLock($key, $value, $ex)) {
return true;
}
usleep(200);
$this->lock($key, $value, $ex);
}
public function unlock($key, $value = '1')
{
$script = <<< EOF
if (redis.call("get", "lock_" .. KEYS[1]) == ARGV[1]) then
return redis.call("del", "lock_" .. KEYS[1])
else
return 0
end
EOF;
return Cache::store('redis')->handler()->eval($script, [$key, $value], 1) > 0;
}
}

View File

@ -1,6 +1,6 @@
<template>
<div>
<Card :bordered="false" dis-hover class="ivu-mt">
<Card :bordered="false" dis-hover class="ivu-mb-16">
<dateRadio @selectDate="onSelectDate"></dateRadio>
<DatePicker
:editable="false"
@ -13,11 +13,11 @@
placeholder="请选择时间"
style="width: 200px"
:options="options"
class="mr20"
class="mr20 "
></DatePicker>
</Card>
<cards-data :cardLists="cardLists" v-if="cardLists.length >= 0"></cards-data>
<Card :bordered="false" dis-hover>
<Card class="ivu-mb-16" :bordered="false" dis-hover>
<h3>余额使用趋势</h3>
<echarts-new :option-data="optionData" :styles="style" height="100%" width="100%" v-if="optionData"></echarts-new>
</Card>
@ -52,7 +52,7 @@
</Table>
</div>
</Card>
<Card :bordered="false" dis-hover class="ivu-mt">
<Card :bordered="false" dis-hover class="ivu-mt ml10">
<div class="acea-row row-between-wrapper">
<h3 class="header-title">余额消耗</h3>
<div class="change-style" @click="echartRight = !echartRight">切换样式</div>
@ -335,10 +335,10 @@ export default {
.code-row-bg {
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
}
.code-row-bg .ivu-mt {
min-width: 50%;
margin: 0 5px;
min-width: 49%;
}
.ech-box {
margin-top: 10px;

View File

@ -1,6 +1,6 @@
<template>
<div>
<Card :bordered="false" dis-hover class="ivu-mt">
<Card :bordered="false" dis-hover class="ivu-mb-16">
<dateRadio @selectDate="onSelectDate"></dateRadio>
<DatePicker
:editable="false"
@ -17,7 +17,7 @@
></DatePicker>
</Card>
<cards-data :cardLists="cardLists" v-if="cardLists.length >= 0"></cards-data>
<Card :bordered="false" dis-hover>
<Card class="ivu-mb-16" :bordered="false" dis-hover>
<h3>营业趋势</h3>
<echarts-new :option-data="optionData" :styles="style" height="100%" width="100%" v-if="optionData"></echarts-new>
</Card>
@ -361,10 +361,10 @@ export default {
.code-row-bg {
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
}
.code-row-bg .ivu-mt {
width: 100%;
margin: 0 5px;
width: calc(50% - 10px);
}
.ech-box {
margin-top: 10px;

View File

@ -1,5 +1,5 @@
<template>
<Card :bordered="false" dis-hover class="ivu-mt">
<Card :bordered="false" dis-hover class="ivu-mt-16">
<div class="acea-row row-between-wrapper mb20">
<div class="header-title">商品排行</div>
<div class="acea-row">

View File

@ -1,5 +1,5 @@
<template>
<Card :bordered="false" dis-hover class="ivu-mt">
<Card :bordered="false" dis-hover class="ivu-mt-16">
<div class="acea-row row-between-wrapper mb20">
<div class="header-title">
交易概况

View File

@ -21,8 +21,8 @@
</div>
<div class="bottom acea-row row-between-wrapper">
<div class="purple" v-if="item.status === 1">{{$t(`活动进行中`)}}</div>
<div class="success" v-else-if="item.status === 3">{{$t(`砍价成功`)}}</div>
<div class="end" v-else>{{$t(`活动已结束`)}}</div>
<div class="success" v-if="item.status === 3">{{$t(`砍价成功`)}}</div>
<div class="end" v-if="item.status === 2">{{$t(`活动已结束`)}}</div>
<div class="acea-row row-middle row-right">
<div class="bnt cancel" v-if="item.status === 1"
@click="getBargainUserCancel(item.bargain_id)">
@ -31,7 +31,9 @@
<div class="bnt bg-color-red" v-if="item.status === 1" @click="goDetail(item.bargain_id)">
{{$t(`继续砍价`)}}
</div>
<!-- <div class="bnt bg-color-red" v-else @click="goList">重开一个</div> -->
</div>
<div class="acea-row row-middle row-right success" v-if="item.status === 3">
{{item.success_time}}
</div>
</div>
</div>