diff --git a/crmeb/app/api/ApiExceptionHandle.php b/crmeb/app/api/ApiExceptionHandle.php index 15cc5d842..2326d29ac 100644 --- a/crmeb/app/api/ApiExceptionHandle.php +++ b/crmeb/app/api/ApiExceptionHandle.php @@ -14,6 +14,7 @@ namespace app\api; use crmeb\exceptions\AdminException; use crmeb\exceptions\ApiException; +use crmeb\exceptions\ApiStatusException; use crmeb\exceptions\AuthException; use think\db\exception\DbException; use think\exception\Handle; @@ -86,11 +87,13 @@ class ApiExceptionHandle extends Handle ] : []; $message = Env::get('app_debug', false) ? $e->getMessage() : '很抱歉,系统开小差了'; // 添加自定义异常处理机制 + if ($e instanceof ApiStatusException) { + return app('json')->status($e->getApiStatus(), $message, $e->getApiData()); + } if ($e instanceof AuthException || $e instanceof AdminException || $e instanceof ApiException || $e instanceof ValidateException) { return app('json')->make($e->getCode() ?: 400, $message, $massageData); - } else { - return app('json')->fail($message, $massageData); } + return app('json')->fail($message, $massageData); } } diff --git a/crmeb/app/api/controller/v1/order/StoreOrderController.php b/crmeb/app/api/controller/v1/order/StoreOrderController.php index 9f61275a2..d9ae57585 100644 --- a/crmeb/app/api/controller/v1/order/StoreOrderController.php +++ b/crmeb/app/api/controller/v1/order/StoreOrderController.php @@ -15,6 +15,8 @@ use app\services\pay\PayServices; use app\services\shipping\ExpressServices; use app\services\system\admin\SystemAdminServices; use app\services\user\UserInvoiceServices; +use crmeb\exceptions\ApiException; +use crmeb\exceptions\ApiStatusException; use crmeb\services\pay\extend\allinpay\AllinPay; use app\services\activity\{lottery\LuckLotteryServices, bargain\StoreBargainServices, @@ -166,7 +168,7 @@ class StoreOrderController $uid = (int)$request->uid(); if ($checkOrder = $this->services->getOne(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0])) return app('json')->status('extend_order', 410209, ['orderId' => $checkOrder['order_id'], 'key' => $key]); - [$addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, $shipping_type, $real_name, $phone, $storeId, $news, $invoice_id, $quitUrl, $advanceId, $virtual_type, $customForm] = $request->postMore([ + [$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], [['couponId', 'd'], 0], ['payType', ''], @@ -188,77 +190,76 @@ 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, $cartGroup, $request->user()->toArray(), $addressId, $payType, !!$useIntegral, $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, $shipping_type, $real_name, $phone, $storeId, !!$news, $advanceId, $virtual_type, $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); - } - } - return app('json')->fail(410200); - } +// $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); +// } $orderId = $order['order_id']; - $orderInfo = $this->services->getOne(['order_id' => $orderId]); - if (!$orderInfo || !isset($orderInfo['paid'])) { - return app('json')->fail(410194); - } - +// $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')); } @@ -338,7 +339,7 @@ class StoreOrderController if ($payPriceStatus)//0元支付成功 return app('json')->status('success', 410195, ['order_id' => $orderInfo['order_id'], 'key' => $orderInfo['unique']]); else - return app('json')->status('pay_error'); + return app('json')->status('pay_error', 410216); } switch ($paytype) { diff --git a/crmeb/app/dao/order/StoreOrderStoreOrderStatusDao.php b/crmeb/app/dao/order/StoreOrderStoreOrderStatusDao.php index 3a4a8eb6a..ec20f00cc 100644 --- a/crmeb/app/dao/order/StoreOrderStoreOrderStatusDao.php +++ b/crmeb/app/dao/order/StoreOrderStoreOrderStatusDao.php @@ -81,6 +81,12 @@ class StoreOrderStoreOrderStatusDao extends BaseDao * @param array $where * @param int $limit * @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 getTakeOrderIds(array $where, int $limit = 0) { diff --git a/crmeb/app/listener/crontab/SystemCrontabListener.php b/crmeb/app/listener/crontab/SystemCrontabListener.php index ee8c19a72..5242c815f 100644 --- a/crmeb/app/listener/crontab/SystemCrontabListener.php +++ b/crmeb/app/listener/crontab/SystemCrontabListener.php @@ -2,17 +2,10 @@ namespace app\listener\crontab; -use app\services\activity\combination\StorePinkServices; -use app\services\activity\live\LiveGoodsServices; -use app\services\activity\live\LiveRoomServices; -use app\services\agent\AgentManageServices; -use app\services\order\StoreOrderServices; -use app\services\order\StoreOrderTakeServices; -use app\services\product\product\StoreProductServices; -use app\services\system\attachment\SystemAttachmentServices; +use app\services\system\crontab\CrontabRunServices; use app\services\system\crontab\SystemCrontabServices; use crmeb\interfaces\ListenerInterface; -use think\facade\Log; +use think\helper\Str; use Workerman\Crontab\Crontab; /** @@ -22,133 +15,23 @@ class SystemCrontabListener implements ListenerInterface { public function handle($event): void { + $systemCrontabServices = app()->make(SystemCrontabServices::class); + $crontabRunServices = app()->make(CrontabRunServices::class); + //自动写入文件方便检测是否启动定时任务命令 new Crontab('*/6 * * * * *', function () { file_put_contents(root_path() . 'runtime/.timer', time()); }); - /** @var SystemCrontabServices $systemTimerServices */ - $systemCrontabServices = app()->make(SystemCrontabServices::class); $list = $systemCrontabServices->selectList(['is_del' => 0, 'is_open' => 1])->toArray(); foreach ($list as &$item) { + //转化小驼峰 + $functionName = Str::camel($item['mark']); //获取定时任务时间字符串 $timeStr = $this->getTimerStr($item); - //未支付自动取消订单 - if ($item['mark'] == 'order_cancel') { - new Crontab($timeStr, function () { - try { - app()->make(StoreOrderServices::class)->orderUnpaidCancel(); - $this->crontabLog(' 执行未支付自动取消订单'); - } catch (\Throwable $e) { - Log::error('自动取消订单失败,失败原因:' . $e->getMessage()); - } - }); - } - //拼团到期订单处理 - elseif ($item['mark'] == 'pink_expiration') { - new Crontab($timeStr, function () { - try { - app()->make(StorePinkServices::class)->statusPink(); - $this->crontabLog(' 执行拼团到期订单处理'); - } catch (\Throwable $e) { - Log::error('拼团到期订单处理失败,失败原因:' . $e->getMessage()); - } - }); - } - //自动解绑上级绑定 - elseif ($item['mark'] == 'agent_unbind') { - new Crontab($timeStr, function () { - try { - app()->make(AgentManageServices::class)->removeSpread(); - $this->crontabLog(' 执行自动解绑上级绑定'); - } catch (\Throwable $e) { - Log::error('自动解除上级绑定失败,失败原因:' . $e->getMessage()); - } - }); - } - //更新直播商品状态 - elseif ($item['mark'] == 'live_product_status') { - new Crontab($timeStr, function () { - try { - app()->make(LiveGoodsServices::class)->syncGoodStatus(); - $this->crontabLog(' 执行更新直播商品状态'); - } catch (\Throwable $e) { - Log::error('更新直播商品状态失败,失败原因:' . $e->getMessage()); - } - }); - } - //更新直播间状态 - elseif ($item['mark'] == 'live_room_status') { - new Crontab($timeStr, function () { - try { - app()->make(LiveRoomServices::class)->syncRoomStatus(); - $this->crontabLog(' 执行更新直播间状态'); - } catch (\Throwable $e) { - Log::error('更新直播间状态失败,失败原因:' . $e->getMessage()); - } - }); - } - //自动收货 - elseif ($item['mark'] == 'take_delivery') { - new Crontab($timeStr, function () { - try { - app()->make(StoreOrderTakeServices::class)->autoTakeOrder(); - $this->crontabLog(' 执行自动收货'); - } catch (\Throwable $e) { - Log::error('自动收货失败,失败原因:' . $e->getMessage()); - } - }); - } - //查询预售到期商品自动下架 - elseif ($item['mark'] == 'advance_off') { - new Crontab($timeStr, function () { - try { - app()->make(StoreProductServices::class)->downAdvance(); - $this->crontabLog(' 执行预售到期商品自动下架'); - } catch (\Throwable $e) { - Log::error('预售到期商品自动下架失败,失败原因:' . $e->getMessage()); - } - }); - } - //自动好评 - elseif ($item['mark'] == 'product_replay') { - new Crontab($timeStr, function () { - try { - app()->make(StoreOrderServices::class)->autoComment(); - $this->crontabLog(' 执行自动好评'); - } catch (\Throwable $e) { - Log::error('自动好评失败,失败原因:' . $e->getMessage()); - } - }); - } - //清除昨日海报 - elseif ($item['mark'] == 'clear_poster') { - new Crontab($timeStr, function () { - try { - app()->make(SystemAttachmentServices::class)->emptyYesterdayAttachment(); - $this->crontabLog(' 执行清除昨日海报'); - } catch (\Throwable $e) { - Log::error('清除昨日海报失败,失败原因:' . $e->getMessage()); - } - }); - } - // - else { - - } - } - } - - /** - * 定时任务日志 - * @param $msg - */ - public function crontabLog($msg) - { - $timer_log_open = config("log.timer_log", false); - if ($timer_log_open){ - $date = date('Y-m-d H:i:s', time()); - Log::write($date . $msg, 'crontab'); + new Crontab($timeStr, function () use ($crontabRunServices, $functionName) { + $crontabRunServices->$functionName(); + }); } } diff --git a/crmeb/app/services/order/StoreOrderCreateServices.php b/crmeb/app/services/order/StoreOrderCreateServices.php index 3672e93e9..334cffb5b 100644 --- a/crmeb/app/services/order/StoreOrderCreateServices.php +++ b/crmeb/app/services/order/StoreOrderCreateServices.php @@ -13,10 +13,12 @@ namespace app\services\order; use app\services\activity\advance\StoreAdvanceServices; +use app\services\activity\combination\StorePinkServices; use app\services\agent\AgentLevelServices; use app\services\activity\coupon\StoreCouponUserServices; use app\services\agent\DivisionServices; use app\services\pay\PayServices; +use app\services\pc\OrderServices; use app\services\product\product\StoreCategoryServices; use app\services\shipping\ShippingTemplatesFreeServices; use app\services\shipping\ShippingTemplatesRegionServices; @@ -25,6 +27,7 @@ use app\services\user\UserInvoiceServices; use app\services\wechat\WechatUserServices; use app\services\BaseServices; use crmeb\exceptions\ApiException; +use crmeb\exceptions\ApiStatusException; use crmeb\services\CacheService; use app\dao\order\StoreOrderDao; use app\services\user\UserServices; @@ -116,11 +119,10 @@ class StoreOrderCreateServices extends BaseServices * 创建订单 * @param $uid * @param $key - * @param $cartGroup * @param $userInfo * @param $addressId * @param $payType - * @param bool $useIntegral + * @param false $useIntegral * @param int $couponId * @param string $mark * @param int $combinationId @@ -131,158 +133,231 @@ class StoreOrderCreateServices extends BaseServices * @param string $real_name * @param string $phone * @param int $storeId - * @param bool $news + * @param false $news * @param int $advanceId - * @param int $virtual_type * @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 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 */ - public function createOrder($uid, $key, $cartGroup, $userInfo, $addressId, $payType, $useIntegral = false, $couponId = 0, $mark = '', $combinationId = 0, $pinkId = 0, $seckillId = 0, $bargainId = 0, $shippingType = 1, $real_name = '', $phone = '', $storeId = 0, $news = false, $advanceId = 0, $virtual_type = 0, $customForm = [], $invoice_id = 0) + public function createOrder($uid, $key, $userInfo, $addressId, $payType, $useIntegral = false, $couponId = 0, $mark = '', $combinationId = 0, $pinkId = 0, $seckillId = 0, $bargainId = 0, $shippingType = 1, $real_name = '', $phone = '', $storeId = 0, $news = false, $advanceId = 0, $customForm = [], $invoice_id = 0) { - //下单前发票验证 - if ($invoice_id) { - app()->make(UserInvoiceServices::class)->checkInvoice((int)$invoice_id, $uid); + /** @var StoreOrderServices $orderService */ + $storeOrderServices = app()->make(StoreOrderServices::class); + $bargainServices = app()->make(StoreBargainServices::class); + $cartGroup = $storeOrderServices->getCacheOrderInfo($uid, $key); + if (!$cartGroup) { + throw new ApiException(410208); + } + //下单前砍价验证 + if ($bargainId) { + $bargainServices->checkBargainUser((int)$bargainId, $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 ($pinkId) { + $pinkId = (int)$pinkId; + /** @var StorePinkServices $pinkServices */ + $pinkServices = app()->make(StorePinkServices::class); + if ($pinkServices->isPink($pinkId, $uid)) + 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); } - 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'] = ''; } - $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; + $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']]); - $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); + } } } - /** @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; - }); - //创建开票数据 - if ($invoice_id) { - app()->make(StoreOrderInvoiceServices::class)->makeUp($uid, $order['order_id'], (int)$invoice_id); + $virtual_type = $cartGroup['cartInfo'][0]['productInfo']['virtual_type'] ?? 0; + + try { + //下单前发票验证 + 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'] = ''; + } + $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'], + ]; + + 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; + }); + + //创建开票数据 + 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; } // 订单创建成功后置事件 diff --git a/crmeb/app/services/system/crontab/CrontabRunServices.php b/crmeb/app/services/system/crontab/CrontabRunServices.php new file mode 100644 index 000000000..fe1d52be6 --- /dev/null +++ b/crmeb/app/services/system/crontab/CrontabRunServices.php @@ -0,0 +1,193 @@ +crontabLog($name . '方法不存在'); + } + + /** + * 定时任务日志 + * @param $msg + */ + protected function crontabLog($msg) + { + $timer_log_open = config("log.timer_log", false); + if ($timer_log_open) { + $date = date('Y-m-d H:i:s', time()); + Log::write($date . $msg, 'crontab'); + } + } + + /** + * 未支付自动取消订单 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function orderCancel() + { + try { + app()->make(StoreOrderServices::class)->orderUnpaidCancel(); + $this->crontabLog(' 执行未支付自动取消订单'); + } catch (\Throwable $e) { + $this->crontabLog('自动取消订单失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 拼团到期订单处理 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function pinkExpiration() + { + try { + app()->make(StorePinkServices::class)->statusPink(); + $this->crontabLog(' 执行拼团到期订单处理'); + } catch (\Throwable $e) { + $this->crontabLog('拼团到期订单处理失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 自动解除上级绑定 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function agentUnbind() + { + try { + app()->make(AgentManageServices::class)->removeSpread(); + $this->crontabLog(' 执行自动解绑上级绑定'); + } catch (\Throwable $e) { + $this->crontabLog('自动解除上级绑定失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 更新直播商品状态 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function liveProductStatus() + { + try { + app()->make(LiveGoodsServices::class)->syncGoodStatus(); + $this->crontabLog(' 执行更新直播商品状态'); + } catch (\Throwable $e) { + $this->crontabLog('更新直播商品状态失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 更新直播间状态 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function liveRoomStatus() + { + try { + app()->make(LiveRoomServices::class)->syncRoomStatus(); + $this->crontabLog(' 执行更新直播间状态'); + } catch (\Throwable $e) { + $this->crontabLog('更新直播间状态失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 自动收货 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function takeDelivery() + { + try { + app()->make(StoreOrderTakeServices::class)->autoTakeOrder(); + $this->crontabLog(' 执行自动收货'); + } catch (\Throwable $e) { + $this->crontabLog('自动收货失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 预售到期商品自动下架 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function advanceOff() + { + try { + app()->make(StoreProductServices::class)->downAdvance(); + $this->crontabLog(' 执行预售到期商品自动下架'); + } catch (\Throwable $e) { + $this->crontabLog('预售到期商品自动下架失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 自动好评 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function productReplay() + { + try { + app()->make(StoreOrderServices::class)->autoComment(); + $this->crontabLog(' 执行自动好评'); + } catch (\Throwable $e) { + $this->crontabLog('自动好评失败,失败原因:' . $e->getMessage()); + } + } + + /** + * 清除昨日海报 + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function clearPoster() + { + try { + app()->make(SystemAttachmentServices::class)->emptyYesterdayAttachment(); + $this->crontabLog(' 执行清除昨日海报'); + } catch (\Throwable $e) { + $this->crontabLog('清除昨日海报失败,失败原因:' . $e->getMessage()); + } + } +} diff --git a/crmeb/app/services/system/crontab/SystemCrontabServices.php b/crmeb/app/services/system/crontab/SystemCrontabServices.php index ae74fae79..c3b0acca0 100644 --- a/crmeb/app/services/system/crontab/SystemCrontabServices.php +++ b/crmeb/app/services/system/crontab/SystemCrontabServices.php @@ -14,6 +14,7 @@ use app\services\product\product\StoreProductServices; use app\services\system\attachment\SystemAttachmentServices; use crmeb\exceptions\AdminException; use think\facade\Log; +use think\helper\Str; class SystemCrontabServices extends BaseServices { @@ -205,67 +206,19 @@ class SystemCrontabServices extends BaseServices */ public function crontabRun() { + $crontabRunServices = app()->make(CrontabRunServices::class); $time = time(); file_put_contents(root_path() . 'runtime/.timer', $time); //检测定时任务是否正常 $list = $this->dao->selectList(['is_open' => 1, 'is_del' => 0])->toArray(); foreach ($list as $item) { if ($item['next_execution_time'] < $time) { - if ($item['mark'] == 'order_cancel') { - //未支付自动取消订单 - app()->make(StoreOrderServices::class)->orderUnpaidCancel(); - $this->crontabLog(' 执行未支付自动取消订单'); - } elseif ($item['mark'] == 'pink_expiration') { - //拼团到期订单处理 - app()->make(StorePinkServices::class)->statusPink(); - $this->crontabLog(' 执行拼团到期订单处理'); - } elseif ($item['mark'] == 'agent_unbind') { - //自动解绑上级绑定 - app()->make(AgentManageServices::class)->removeSpread(); - $this->crontabLog(' 执行自动解绑上级绑定'); - } elseif ($item['mark'] == 'live_product_status') { - //更新直播商品状态 - app()->make(LiveGoodsServices::class)->syncGoodStatus(); - $this->crontabLog(' 执行更新直播商品状态'); - } elseif ($item['mark'] == 'live_room_status') { - //更新直播间状态 - app()->make(LiveRoomServices::class)->syncRoomStatus(); - $this->crontabLog(' 执行更新直播间状态'); - } elseif ($item['mark'] == 'take_delivery') { - //自动收货 - app()->make(StoreOrderTakeServices::class)->autoTakeOrder(); - $this->crontabLog(' 执行自动收货'); - } elseif ($item['mark'] == 'advance_off') { - //查询预售到期商品自动下架 - app()->make(StoreProductServices::class)->downAdvance(); - $this->crontabLog(' 执行预售到期商品自动下架'); - } elseif ($item['mark'] == 'product_replay') { - //自动好评 - app()->make(StoreOrderServices::class)->autoComment(); - $this->crontabLog(' 执行自动好评'); - } elseif ($item['mark'] == 'clear_poster') { - //清除昨日海报 - app()->make(SystemAttachmentServices::class)->emptyYesterdayAttachment(); - $this->crontabLog(' 执行清除昨日海报'); - } + //转化小驼峰方法名 + $functionName = Str::camel($item['mark']); + //执行定时任务 + $crontabRunServices->$functionName(); //写入本次执行时间和下次执行时间 $this->dao->update(['mark' => $item['mark']], ['last_execution_time' => $time, 'next_execution_time' => $this->getTimerCycleTime($item)]); } } } - - /** - * 定时任务日志 - * @param $msg - * @author 吴汐 - * @email 442384644@qq.com - * @date 2023/02/21 - */ - public function crontabLog($msg) - { - $timer_log_open = config("log.timer_log", false); - if ($timer_log_open) { - $date = date('Y-m-d H:i:s', time()); - Log::write($date . $msg, 'crontab'); - } - } } \ No newline at end of file diff --git a/crmeb/app/services/user/UserServices.php b/crmeb/app/services/user/UserServices.php index 1072ea838..25321e37b 100644 --- a/crmeb/app/services/user/UserServices.php +++ b/crmeb/app/services/user/UserServices.php @@ -68,8 +68,15 @@ class UserServices extends BaseServices /** * 获取用户信息 - * @param $id - * @param $field + * @param int $uid + * @param string $field + * @return array|\think\Model|null + * @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 getUserInfo(int $uid, $field = '*') { @@ -1014,14 +1021,25 @@ class UserServices extends BaseServices /** * 赠送付费会员时长 - * @param int $uid - * @return mixed - * */ + * @param $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ public function giveLevelTime($id) { - if (!$this->getUserInfo($id)) { + $userInfo = $this->getUserInfo($id); + if (!$userInfo) { throw new AdminException(400214); } + $timeDiff = $userInfo['is_ever_level'] == 1 ? '永久' : date('Y-m-d H:i:s', $userInfo['overdue_time']); + $dayDiff = intval(($userInfo['overdue_time'] - time()) / 86400); + $field[] = Form::input('time_diff', '到期时间', $timeDiff)->style(['width' => '200px'])->readonly(true); + if ($userInfo['is_ever_level'] == 0) { + $field[] = Form::input('day_diff', '剩余天数', $dayDiff)->style(['width' => '200px'])->readonly(true); + } $field[] = Form::number('days', '增加时长(天)')->precision(0)->style(['width' => '200px'])->required(); return create_form('赠送付费会员时长', $field, Url::buildUrl('/user/save_give_level_time/' . $id), 'PUT'); } diff --git a/crmeb/crmeb/exceptions/ApiStatusException.php b/crmeb/crmeb/exceptions/ApiStatusException.php new file mode 100644 index 000000000..8362bf321 --- /dev/null +++ b/crmeb/crmeb/exceptions/ApiStatusException.php @@ -0,0 +1,60 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\exceptions; + +/** + * API应用错误信息 + * Class ApiException + * @package crmeb\exceptions + */ +class ApiStatusException extends \RuntimeException +{ + protected $apiStatus; + protected $apiData; + + public function __construct($status, $message, $data = [], $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + $this->apiData = $data; + $this->apiStatus = $status; + + parent::__construct($message, $code, $previous); + } + + /** + * @return mixed + */ + public function getApiStatus() + { + return $this->apiStatus; + } + + /** + * @return array|mixed + */ + public function getApiData() + { + return $this->apiData; + } +} diff --git a/crmeb/public/install/crmeb.sql b/crmeb/public/install/crmeb.sql index 6d84ca6d8..9a08732f0 100755 --- a/crmeb/public/install/crmeb.sql +++ b/crmeb/public/install/crmeb.sql @@ -33520,7 +33520,8 @@ INSERT INTO `eb_system_config` (`id`, `menu_name`, `type`, `input_type`, `config (428, 'queue_open', 'radio', 'input', 26, '0=>关闭\n1=>开启', 1, '', 0, 0, '\"0\"', '消息队列', '是否启用消息队列,启用后提升程序运行速度,启用前必须配置Redis缓存,文档地址:https://doc.crmeb.com/single/crmeb_v4/7217', 0, 1), (429, 'get_avatar', 'radio', 'input', 7, '0=>关闭\n1=>开启', 1, '', 0, 0, '\"0\"', '强制获取昵称头像', '是否在小程序用户授权之后,弹窗获取用户的昵称和头像', 0, 1), (430, 'share_qrcode', 'radio', 'input', 2, '0=>商城\n1=>公众号', 1, '', 0, 0, '\"0\"', '公众号推广码类型', '公众号生成的推广码类型:商城:扫码直接进入商城,公众号:扫码进入公众号后推送商城的链接', 0, 1), -(431, 'member_brokerage', 'radio', 'input', 73, '1=>开启\n0=>关闭', 1, '', 0, 0, '\"0\"', '购买付费会员返佣', '购买付费会员是否按照设置的佣金比例进行返佣', 98, 1); +(431, 'member_brokerage', 'radio', 'input', 73, '1=>开启\n0=>关闭', 1, '', 0, 0, '\"0\"', '购买付费会员返佣', '购买付费会员是否按照设置的佣金比例进行返佣', 98, 1), +(432, 'user_brokerage_type', 'radio', 'input', 73, '0=>按照商品价格返佣\n1=>按照实际支付价格返佣', 1, '', 0, 0, '\"0\"', '返佣类型', '选择返佣类型,按照商品价格返佣(按照商品售价计算返佣金额)以及按照实际支付价格返佣(按照商品的实际支付价格计算返佣 )', 97, 1); -- -------------------------------------------------------- diff --git a/template/admin/src/pages/system/crontab/index.vue b/template/admin/src/pages/system/crontab/index.vue index 4ed2bbbe9..df30aad44 100644 --- a/template/admin/src/pages/system/crontab/index.vue +++ b/template/admin/src/pages/system/crontab/index.vue @@ -3,7 +3,7 @@