|
|
|
@ -117,6 +117,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
public function do($marketId, $userId, $userAddrId, $storeList, $totalMoney, $deliveryTimeNote='尽快送达', $serviceMoney=0, $receiveCouponIds=null, $plat=''){ |
|
|
|
|
|
|
|
$redis = ApplicationContext::getContainer()->get(Redis::class); |
|
|
|
$isCacheInventory = false; |
|
|
|
$carts = []; |
|
|
|
Db::beginTransaction(); |
|
|
|
try { |
|
|
|
@ -157,6 +158,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
$dataChildren = []; # 子订单
|
|
|
|
$dataOrderGoods = []; # 订单商品
|
|
|
|
$storeTypeIds = []; # 订单中的商户类型,用于校验红包
|
|
|
|
$activityGoodsIds = []; # 活动商品IDs
|
|
|
|
|
|
|
|
foreach ($storeList as $key => &$storeItem) { |
|
|
|
|
|
|
|
@ -189,7 +191,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
} |
|
|
|
$check = $this->goodsService->check($goods, $cart->num); |
|
|
|
if (true !== $check) { |
|
|
|
throw new ErrorCodeException($check, '['.$goods->name.'/'.$goods->goods_unit.']'); |
|
|
|
throw new ErrorCodeException($check, '['.$goods->name.']'); |
|
|
|
} |
|
|
|
} elseif ($cart->activity_type == 2) { |
|
|
|
$goods = GoodsActivity::query()->lockForUpdate()->with('store')->find($cart->goods_id); |
|
|
|
@ -198,11 +200,25 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
} |
|
|
|
$check = $this->goodsActivityService->check($goods, $cart->num, $userId); |
|
|
|
if (true !== $check) { |
|
|
|
throw new ErrorCodeException($check, '['.$goods->name.'/'.$goods->goods_unit.']'); |
|
|
|
throw new ErrorCodeException($check, '['.$goods->name.']'); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 压redis库存
|
|
|
|
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
|
|
|
|
$inventoryKey = 'goods_inventory_sold_'.$cart->activity_type.'_'.$cart->goods_id; // 拼接activity_type和goods_id
|
|
|
|
if (!$redis->exists($inventoryKey)) { |
|
|
|
$redis->set($inventoryKey, $cart->num); |
|
|
|
} else { |
|
|
|
$redis->incrBy($inventoryKey, intval($cart->num)); |
|
|
|
} |
|
|
|
$isCacheInventory = true; |
|
|
|
|
|
|
|
if ($cart->activity_type == 2) { |
|
|
|
$activityGoodsIds[] = $cart->goods_id; |
|
|
|
} |
|
|
|
|
|
|
|
// 算金额
|
|
|
|
$goodsAmount = bcmul((string)$goods->price, (string)$cart->num); # 当前商品的金额
|
|
|
|
$subAmount = bcadd((string)$subAmount, (string)$goodsAmount); # 当前店铺子订单的金额
|
|
|
|
@ -319,7 +335,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
} |
|
|
|
|
|
|
|
// 判断是否有购买多个特价商品
|
|
|
|
$check = $this->goodsActivityService->checkOrderActivityCount($dataOrderGoods); |
|
|
|
$check = $this->goodsActivityService->checkOrderActivityCount($activityGoodsIds); |
|
|
|
if(!$check){ |
|
|
|
$this->log->event(LogLabel::ORDER_ONLINE_LOG, ['msg' => '订单中有活动商品超过限购数量', 'data' => json_encode($dataOrderGoods)]); |
|
|
|
throw new ErrorCodeException(ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT); |
|
|
|
@ -328,11 +344,12 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
// 订单成功,做一些处理
|
|
|
|
// 活动商品购买记录
|
|
|
|
foreach ($dataOrderGoods as $key => &$goods) { |
|
|
|
foreach ($goods as $k => &$goodsItem) |
|
|
|
foreach ($goods as $k => &$goodsItem) { |
|
|
|
if ($goodsItem['activity_type'] == 2) { |
|
|
|
$this->goodsActivityService->cacheRecord($goodsItem['goods_id'], $goodsItem['number'], $userId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Db::commit(); |
|
|
|
|
|
|
|
@ -350,6 +367,8 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
return $this->paymentService->do($globalOrderId, $totalAmount, $userId, config('wechat.notify_url.online')); |
|
|
|
} catch (Exception $e) { |
|
|
|
Db::rollBack(); |
|
|
|
|
|
|
|
if ($isCacheInventory) { |
|
|
|
// 释redis库存
|
|
|
|
foreach ($carts as $k => &$cart) { |
|
|
|
// 拼接activity_type和goods_id
|
|
|
|
@ -358,11 +377,17 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
if (!$redis->exists($inventoryKey)) { |
|
|
|
$redis->set($inventoryKey, 0); |
|
|
|
} else { |
|
|
|
$redis->decrBy($inventoryKey, $cart->num); |
|
|
|
$redis->decrBy($inventoryKey, intval($cart->num)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
$this->log->event(LogLabel::ORDER_ONLINE_LOG, ['msg' => $e->getMessage()]); |
|
|
|
throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL); |
|
|
|
|
|
|
|
$message = ''; |
|
|
|
if ($e instanceof ErrorCodeException) { |
|
|
|
$message = $e->getMessage(); |
|
|
|
} |
|
|
|
throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL, $message); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -425,7 +450,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
if (!$redis->exists($inventoryKey)) { |
|
|
|
$redis->set($inventoryKey, 0); |
|
|
|
} else { |
|
|
|
$redis->decrBy($inventoryKey, $goodsItem['number']); |
|
|
|
$redis->decrBy($inventoryKey, intval($goodsItem['number'])); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -520,7 +545,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
if (!$redis->exists($inventoryKey)) { |
|
|
|
$redis->set($inventoryKey, 0); |
|
|
|
} else { |
|
|
|
$redis->decrBy($inventoryKey, $goodsItem['number']); |
|
|
|
$redis->decrBy($inventoryKey, intval($goodsItem['number'])); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -630,9 +655,80 @@ class OrderOnlineService implements OrderOnlineServiceInterface |
|
|
|
|
|
|
|
$orderMain = $this->check($globalOrderId, $userId, OrderState::REFUNDING); |
|
|
|
|
|
|
|
$orderIds = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->pluck('id'); |
|
|
|
$orderGoods = OrderGoods::query()->whereIn('order_id', $orderIds)->get()->toArray(); |
|
|
|
|
|
|
|
// 释redis库存
|
|
|
|
$redis = ApplicationContext::getContainer()->get(Redis::class); |
|
|
|
foreach ($orderGoods as $k => &$goodsItem) { |
|
|
|
// 拼接activity_type和goods_id
|
|
|
|
$inventoryKey = 'goods_inventory_sold_'.$goodsItem['activity_type'].'_'.$goodsItem['goods_id']; |
|
|
|
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
|
|
|
|
if (!$redis->exists($inventoryKey)) { |
|
|
|
$redis->set($inventoryKey, 0); |
|
|
|
} else { |
|
|
|
$redis->decrBy($inventoryKey, intval($goodsItem['number'])); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 微信退款
|
|
|
|
if ($orderMain->pay_type == Payment::WECHAT) { |
|
|
|
return $this->paymentService->undo($orderMain->global_order_id, $userId); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public function autoCancel() |
|
|
|
{ |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
$orderMains = OrderMain::query() |
|
|
|
->where(['state' => OrderState::UNPAID]) |
|
|
|
->where('created_at', '<', time()-900) |
|
|
|
->limit(100) |
|
|
|
->get(); |
|
|
|
|
|
|
|
foreach ($orderMains as $key => &$orderMain) { |
|
|
|
|
|
|
|
// 订单取消
|
|
|
|
OrderMain::query()->where(['id' => $orderMain->id])->update(['state' => OrderState::CANCELED]); |
|
|
|
|
|
|
|
// 退还优惠券
|
|
|
|
$this->couponService->orderRefundCoupons($orderMain->global_order_id); |
|
|
|
|
|
|
|
// 撤销活动商品购买记录
|
|
|
|
$orders = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->get()->toArray(); |
|
|
|
$orderGoods = OrderGoods::query() |
|
|
|
->whereIn('order_id', array_values(array_column($orders, 'id'))) |
|
|
|
->get() |
|
|
|
->toArray(); |
|
|
|
foreach ($orderGoods as $key => &$goods) { |
|
|
|
if ($goods['activity_type'] == 2) { |
|
|
|
$this->goodsActivityService->clearCacheRecord($goods['goods_id'], $goods['number'], $orderMain->user_id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 释redis库存
|
|
|
|
$redis = ApplicationContext::getContainer()->get(Redis::class); |
|
|
|
foreach ($orderGoods as $k => &$goodsItem) { |
|
|
|
// 拼接activity_type和goods_id
|
|
|
|
$inventoryKey = 'goods_inventory_sold_'.$goodsItem['activity_type'].'_'.$goodsItem['goods_id']; |
|
|
|
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
|
|
|
|
if (!$redis->exists($inventoryKey)) { |
|
|
|
$redis->set($inventoryKey, 0); |
|
|
|
} else { |
|
|
|
$redis->decrBy($inventoryKey, intval($goodsItem['number'])); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 记录badge
|
|
|
|
$orderChildIds = array_values(array_column($orders, 'store_id')); |
|
|
|
$this->badgeService->doByOrder($orderMain->user_id, $orderChildIds, $orderMain->global_order_id, OrderState::CANCELED); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception $e) { |
|
|
|
$this->log->event(LogLabel::ORDER_AUTO_CANCEL_FAIL_LOG, ['message' => $e->getMessage()]); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |