Order.php 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\api\model;
  13. use app\api\model\Goods as GoodsModel;
  14. use app\api\model\kj\KjActivityGood;
  15. use app\api\model\kj\KjActivityJoin;
  16. use app\api\model\OrderGoods as OrderGoodsModel;
  17. use app\api\model\Setting as SettingModel;
  18. use app\api\model\GoodsSku as GoodsSkuModel;
  19. use app\api\model\user\CommissionsDetail as CommissionsDetailApi;
  20. use app\api\model\user\CommissionsDetail;
  21. use app\api\service\User as UserService;
  22. use app\api\service\Payment as PaymentService;
  23. use app\api\service\order\PaySuccess as OrderPaySuccesService;
  24. use app\api\service\order\source\Factory as OrderSourceFactory;
  25. use app\common\enum\order\PayType;
  26. use app\common\enum\order\refund\RefundStatus as RefundStatusEnum;
  27. use app\common\model\Order as OrderModel;
  28. use app\common\service\Order as OrderService;
  29. use app\common\enum\Setting as SettingEnum;
  30. use app\common\enum\OrderType as OrderTypeEnum;
  31. use app\common\enum\order\PayType as OrderPayTypeEnum;
  32. use app\common\enum\order\PayStatus as PayStatusEnum;
  33. use app\common\enum\order\OrderStatus as OrderStatusEnum;
  34. use app\common\enum\order\ReceiptStatus as ReceiptStatusEnum;
  35. use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
  36. use app\common\library\helper;
  37. use app\common\exception\BaseException;
  38. use app\common\model\groupbuy\GroupBuyJoin;
  39. use app\common\model\groupbuy\GroupBuyActivity;
  40. use app\common\model\groupbuy\GroupBuyGoods;
  41. use app\common\model\groupbuy\GroupBuyHelp;
  42. use app\common\model\groupbuylb\GroupBuyLbJoin;
  43. use app\common\model\groupbuylb\GroupBuyLbActivity;
  44. use app\common\model\groupbuylb\GroupBuyLbGoods;
  45. use app\common\model\groupbuylb\GroupBuyLbHelp;
  46. use app\common\model\ms\MsActivityGood;
  47. use app\common\model\ms\MsActivity;
  48. use app\common\enum\order\OrderSource as OrderSourceEnum;
  49. use app\api\model\za\{ZaActivityGood,ZaActivityRelation,ZaActivity};
  50. /**
  51. * 订单模型
  52. * Class Order
  53. * @package app\api\model
  54. */
  55. class Order extends OrderModel
  56. {
  57. /**
  58. * 隐藏字段
  59. * @var array
  60. */
  61. protected $hidden = [
  62. 'store_id',
  63. 'update_time'
  64. ];
  65. /**
  66. * 追加字段
  67. * @var array
  68. */
  69. protected $append = [
  70. 'state_text', // 售后单状态文字描述
  71. 'state_value', // 售后状态码 20已取消 30已完成 11待支付 12待收货未发货 13待收货已发货
  72. 'djs_time', // 待支付倒计时(时间戳)
  73. 'dsh_time', // 待收货倒计时(时间戳)
  74. ];
  75. /**
  76. * 待支付订单详情
  77. * @param string $orderNo 订单号
  78. * @return null|static
  79. */
  80. public static function getPayDetail(string $orderNo)
  81. {
  82. return self::detail(['order_no' => $orderNo, 'pay_status' => 10, 'is_delete' => 0], ['goods', 'user']);
  83. }
  84. /**
  85. * 订单支付事件
  86. * @param int $payType
  87. * @return bool
  88. */
  89. public function onPay(int $payType = OrderPayTypeEnum::WECHAT)
  90. {
  91. // 判断订单状态
  92. $orderSource = OrderSourceFactory::getFactory($this['order_source']);
  93. if (!$orderSource->checkOrderStatusOnPay($this)) {
  94. $this->error = $orderSource->getError();
  95. return false;
  96. }
  97. // 余额支付
  98. if ($payType == OrderPayTypeEnum::BALANCE) {
  99. return $this->onPaymentByBalance($this['order_no']);
  100. }
  101. return true;
  102. }
  103. /**
  104. * 构建支付请求的参数
  105. * @param self $order 订单信息
  106. * @param string $payType 订单支付方式
  107. * @return array
  108. * @throws BaseException
  109. * @throws \think\db\exception\DataNotFoundException
  110. * @throws \think\db\exception\DbException
  111. * @throws \think\db\exception\ModelNotFoundException
  112. */
  113. public function onOrderPayment(self $order, int $payType)
  114. {
  115. if ($payType == OrderPayTypeEnum::WECHAT) {
  116. if($order['order_source']!=OrderTypeEnum::ZA){
  117. return $this->onPaymentByWechat($order);
  118. }
  119. return $this->onPrePayByWechat($order,$order['order_source']);
  120. }
  121. return [];
  122. }
  123. // 预调起支付
  124. public function onPrePayByWechat(array $order,$order_type){
  125. return PaymentService::wechat(
  126. $order['order_id'],
  127. $order['order_no'],
  128. $order['pay_price'],
  129. $order_type
  130. // OrderTypeEnum::ORDER
  131. );
  132. }
  133. /**
  134. * 构建微信支付请求
  135. * @param self $order 订单详情
  136. * @return array
  137. * @throws BaseException
  138. * @throws \think\db\exception\DataNotFoundException
  139. * @throws \think\db\exception\DbException
  140. * @throws \think\db\exception\ModelNotFoundException
  141. */
  142. protected function onPaymentByWechat(self $order)
  143. {
  144. return PaymentService::wechat(
  145. $order['order_id'],
  146. $order['order_no'],
  147. $order['pay_price'],
  148. OrderTypeEnum::ORDER
  149. );
  150. }
  151. /**
  152. * 立即购买:获取订单商品列表
  153. * @param int $goodsId 商品ID
  154. * @param string $goodsSkuId 商品SKU
  155. * @param int $goodsNum 购买数量
  156. * @param int $staffUserId 分享链接用户ID 可不传
  157. * @return mixed
  158. * @throws BaseException
  159. */
  160. public function getOrderGoodsListByNow(int $goodsId, string $goodsSkuId, int $goodsNum, int $staffUserId = 0)
  161. {
  162. // 获取商品列表
  163. $model = new GoodsModel;
  164. $goodsList = $model->getListByIdsFromApi([$goodsId]);
  165. if ($goodsList->isEmpty()) {
  166. throwError('未找到商品信息2');
  167. }
  168. // 隐藏冗余的属性
  169. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  170. // 返回商品处理
  171. // 获取链接分享者的用户ID和店铺ID
  172. $data = $this->getStaffUserId($staffUserId);
  173. foreach ($goodsList as &$item) {
  174. // 商品sku信息
  175. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  176. // 商品单价
  177. $item['goods_price'] = $item['skuInfo']['goods_price'];
  178. // 商品购买数量
  179. $item['total_num'] = $goodsNum;
  180. // 商品SKU索引
  181. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  182. // 商品购买总金额
  183. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  184. $item['staffUserId'] = $data['staffUserId'];
  185. $item['shopId'] = $data['shopId'];
  186. $item['distributorRadio'] = $data['distributorRadio'];
  187. }
  188. return $goodsList;
  189. }
  190. /**
  191. * 立即购买:获取订单商品列表
  192. * @param int $goodsId 商品ID
  193. * @param string $goodsSkuId 商品SKU
  194. * @param int $goodsNum 购买数量
  195. * @param int $bargainId 砍价活动ID
  196. * @return mixed
  197. * @throws BaseException
  198. */
  199. public function getOrderGoodsZaListByNow(int $goodsId, string $goodsSkuId, int $goodsNum, int $zaGoodsId,int $staffUserId = 0,bool $isReceive = false)
  200. {
  201. // 获取商品列表
  202. $model = new GoodsModel;
  203. $goodsList = $model->getListByIdsFromApi([$goodsId]);
  204. if ($goodsList->isEmpty()) {
  205. throwError('未找到商品信息');
  206. }
  207. //获取砍价数据
  208. $user = UserService::getCurrentLoginUser(true);
  209. $zaGoods = ZaActivityGood::where('goods_id',$goodsId)->where('id',$zaGoodsId)->find();
  210. if(empty($zaGoods)){
  211. throwError('未找到买一赠一信息');
  212. }
  213. if(!$isReceive){
  214. if($zaGoods['stock_num']<=1){
  215. throwError('该买一赠一商品库存不足');
  216. }
  217. }
  218. // 隐藏冗余的属性
  219. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  220. // 返回商品处理
  221. $data = $this->getStaffUserId($staffUserId);
  222. foreach ($goodsList as &$item) {
  223. // 商品sku信息
  224. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  225. // 商品单价
  226. $item['goods_price'] = $item['skuInfo']['goods_price'];
  227. // 商品购买数量
  228. $item['total_num'] = $goodsNum;
  229. // 商品SKU索引
  230. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  231. // 商品购买总金额
  232. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  233. // 获取砍价活动的最终金额
  234. // $item['bargain_price'] = $KjActivityJoin['kj_price'];
  235. // $item['bargain_id'] = $bargainId;
  236. $item['za_goods_id'] = $zaGoods['id'];
  237. $item['staffUserId'] = $data['staffUserId'];
  238. $item['shopId'] = $data['shopId'];
  239. $item['distributorRadio'] = $data['distributorRadio'];
  240. }
  241. return $goodsList;
  242. }
  243. /**
  244. * 立即购买:获取订单商品列表
  245. * @param int $goodsId 商品ID
  246. * @param string $goodsSkuId 商品SKU
  247. * @param int $goodsNum 购买数量
  248. * @param int $bargainId 砍价活动ID
  249. * @return mixed
  250. * @throws BaseException
  251. */
  252. public function getOrderGoodsBargainListByNow(int $goodsId, string $goodsSkuId, int $goodsNum, int $bargainId,int $staffUserId = 0)
  253. {
  254. // 获取商品列表
  255. $model = new GoodsModel;
  256. $goodsList = $model->getListByIdsFromApi([$goodsId]);
  257. if ($goodsList->isEmpty()) {
  258. throwError('未找到商品信息2');
  259. }
  260. //获取砍价数据
  261. $user = UserService::getCurrentLoginUser(true);
  262. $KjActivityJoin = KjActivityJoin::where('user_id',$user['user_id'])->find($bargainId);
  263. if (!$KjActivityJoin) {
  264. throwError('未找到砍价信息');
  265. }
  266. if($KjActivityJoin['is_submit_order']|| (strtotime($KjActivityJoin['end_time'])+3600*48)<time()){
  267. // if($KjActivityJoin['is_submit_order']|| (strtotime($KjActivityJoin['end_time'])+300)<time()){
  268. throwError('该砍价记录已下单或超过下单时间');
  269. }
  270. $KjActivityGood = KjActivityGood::where(['goods_id'=>$goodsId,'activity_id'=>$KjActivityJoin['activity_id']])->find();
  271. if($KjActivityGood['limit_stock']-$KjActivityGood['purchase_stock']<=0){
  272. throwError('该砍价商品没有库存了');
  273. }
  274. // 隐藏冗余的属性
  275. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  276. // 返回商品处理
  277. $data = $this->getStaffUserId($staffUserId);
  278. foreach ($goodsList as &$item) {
  279. // 商品sku信息
  280. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  281. // 商品单价
  282. $item['goods_price'] = $item['skuInfo']['goods_price'];
  283. // 商品购买数量
  284. $item['total_num'] = $goodsNum;
  285. // 商品SKU索引
  286. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  287. // 商品购买总金额
  288. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  289. // 获取砍价活动的最终金额
  290. $item['bargain_price'] = $KjActivityJoin['kj_price'];
  291. $item['bargain_id'] = $bargainId;
  292. $item['bargain_activity_id'] = $KjActivityJoin['activity_id'];
  293. $item['staffUserId'] = $data['staffUserId'];
  294. $item['shopId'] = $data['shopId'];
  295. $item['distributorRadio'] = $data['distributorRadio'];
  296. }
  297. return $goodsList;
  298. }
  299. //当前秒杀活动商品买了多少件
  300. public function miaoshaHaveBuyCnt($ms_goods_id,$user_id){
  301. $order_id_arr = Order::where('order_source',OrderSourceEnum::MIAOSHA)->where('order_source_id',$ms_goods_id)->where('user_id', $user_id)->where('pay_status',PayStatusEnum::SUCCESS)->column("order_id");
  302. if(count($order_id_arr)==0){
  303. return 0;
  304. }
  305. else if(count($order_id_arr)>0){
  306. $total_num = OrderGoodsModel::where("order_id",'in',$order_id_arr)->sum('total_num');
  307. return $total_num;
  308. }
  309. }
  310. /**
  311. * 立即购买:获取订单商品列表
  312. * @param int $goodsId 商品ID
  313. * @param string $goodsSkuId 商品SKU
  314. * @param int $goodsNum 购买数量
  315. * @param int $bargainId 砍价活动ID
  316. * @return mixed
  317. * @throws BaseException
  318. */
  319. public function getOrderGoodsMiaoshaListByNow(int $goodsId, string $goodsSkuId, int $goodsNum, int $msId,int $staffUserId = 0)
  320. {
  321. // 获取商品列表
  322. $model = new GoodsModel;
  323. $goodsList = $model->getListByIdsFromApi([$goodsId]);
  324. if ($goodsList->isEmpty()) {
  325. throwError('未找到商品信息2');
  326. }
  327. //获取秒杀数据
  328. $user = UserService::getCurrentLoginUser(true);
  329. $msGood = MsActivityGood::where('id',$msId)->find();
  330. if (!$msGood) {
  331. throwError('未找到秒杀信息');
  332. }
  333. if($goodsNum>$msGood->stock_num){
  334. throwError("库存不足");
  335. }
  336. if(time()>strtotime($msGood->end_time)){
  337. throwError("秒杀活动已结束");
  338. }
  339. $activity = MsActivity::where("id",$msGood->ms_activity_id)->find();
  340. if($activity->is_up==0||$activity->audit_status!=1){
  341. throwError("秒杀活动已结束!");
  342. }
  343. if($msGood->limit_mount>0&&$goodsNum>$msGood->limit_mount){
  344. throwError("超过限购数量");
  345. }
  346. if($msGood->limit_mount>0){
  347. $order_id_arr = Order::where('order_source',OrderSourceEnum::MIAOSHA)->where('order_source_id',$msGood->id)->where('user_id', $user->user_id)->where('pay_status',PayStatusEnum::SUCCESS)->column("order_id");
  348. if(count($order_id_arr)>0){
  349. $total_num = OrderGoodsModel::where("order_id",'in',$order_id_arr)->sum('total_num');
  350. if($total_num>=$msGood->limit_mount){
  351. throwError("限购".$msGood->limit_mount."件!");
  352. }
  353. }
  354. }
  355. // 隐藏冗余的属性
  356. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  357. // 返回商品处理
  358. $data = $this->getStaffUserId($staffUserId);
  359. foreach ($goodsList as &$item) {
  360. // 商品sku信息
  361. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  362. // 商品单价
  363. $item['goods_price'] = $item['skuInfo']['goods_price'];
  364. // 商品购买数量
  365. $item['total_num'] = $goodsNum;
  366. // 商品SKU索引
  367. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  368. // 商品购买总金额
  369. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  370. // 获取秒杀活动的最终金额
  371. $item['ms_price'] = $msGood['ms_price'];
  372. $item['ms_id'] = $msId;
  373. $item['staffUserId'] = $data['staffUserId'];
  374. $item['shopId'] = $data['shopId'];
  375. $item['distributorRadio'] = $data['distributorRadio'];
  376. $item['limit_mount'] = $msGood['limit_mount'];
  377. }
  378. return $goodsList;
  379. }
  380. /**
  381. * 立即购买:获取订单商品列表
  382. * @param int $goodsId 商品ID
  383. * @param string $goodsSkuId 商品SKU
  384. * @param int $goodsNum 购买数量
  385. * @param int $activity_id 拼团活动ID
  386. * @return mixed
  387. * @throws BaseException
  388. */
  389. public function getOrderGoodsGroupListByNow(int $goodsId, string $goodsSkuId, int $goodsNum, int $joinId=0,int $activity_id=0,int $staffUserId = 0)
  390. {
  391. // 获取商品列表
  392. $model = new GoodsModel;
  393. $goodsList = $model->getListByIdsFromApi([$goodsId]);
  394. if ($goodsList->isEmpty()) {
  395. throwError('未找到商品信息');
  396. }
  397. //获取砍价数据
  398. $user = UserService::getCurrentLoginUser(true);
  399. $now = Date("Y-m-d H:i:s",time());
  400. if($joinId>0){
  401. $join = GroupBuyJoin::where('id',$joinId)->lock('for update')->find();
  402. $helpCnt = GroupBuyHelp::where("join_id",$join->id)->where('pay_state','in',[0,1])->count();
  403. $have = GroupBuyHelp::where("join_id",$join->id)->where('user_id',$user->user_id)->where('pay_state','in',[0,1])->find();
  404. if($have&&$have->pay_state==0){
  405. throwError("你有一个待支付的拼团");
  406. }
  407. if($have&&$have->pay_state==1){
  408. throwError("你已经参与该拼团");
  409. }
  410. if($helpCnt>=$join->people_count){
  411. throwError("拼团人数已够");
  412. }
  413. if($now>$join->end_time){
  414. throwError('拼团已结束');
  415. }
  416. if($join->status==1){
  417. throwError("拼团已完成");
  418. }
  419. if($join->status==2){
  420. throwError("拼团结束");
  421. }
  422. $groupgoods = GroupBuyGoods::where('group_buy_activity_id',$join['group_buy_activity_id'])->find();
  423. if(empty($groupgoods)){
  424. throwError('找不到商品');
  425. }
  426. if($groupgoods->goods_id!=$goodsId){
  427. throwError('商品id跟活动商品id对不上');
  428. }
  429. if($goodsNum>$groupgoods->limit_mount){
  430. throwError('超过限购数量');
  431. }
  432. if($goodsNum>$groupgoods->residue_stock){
  433. throwError('拼团活动库存不足');
  434. }
  435. }
  436. else if($activity_id>0){
  437. $activity = GroupBuyActivity::where("id",$activity_id)->find();
  438. if(empty($activity)){
  439. throwError("找不到拼团活动");
  440. }
  441. if($now>$activity->end_time){
  442. throwError('拼团活动已结束');
  443. }
  444. if($activity->audit_status!=1||$activity->status!=1){
  445. throwError('拼团活动不存在');
  446. }
  447. $join = GroupBuyJoin::where('user_id',$user->user_id)->where('group_buy_activity_id',$activity_id)->where('status',0)->where('end_time',">",$now)->find();
  448. if($join){
  449. throwError('你有一个拼团正在进行中');
  450. }
  451. $groupgoods = GroupBuyGoods::where('group_buy_activity_id',$activity_id)->find();
  452. if(empty($groupgoods)){
  453. throwError('找不到商品');
  454. }
  455. if($groupgoods->goods_id!=$goodsId){
  456. throwError('商品id跟活动商品id对不上');
  457. }
  458. if($goodsNum>$groupgoods->limit_mount){
  459. throwError('超过限购数量');
  460. }
  461. //判断库存数量
  462. if($groupgoods->limit_stock - $groupgoods->purchase_stock <=0){
  463. throwError('活动已结束~');
  464. }
  465. }
  466. if(empty($groupgoods)){
  467. throwError("找不到商品");
  468. }
  469. // 隐藏冗余的属性
  470. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  471. // 返回商品处理
  472. $data = $this->getStaffUserId($staffUserId);
  473. foreach ($goodsList as &$item) {
  474. // 商品sku信息
  475. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  476. // 商品单价
  477. $item['goods_price'] = $item['skuInfo']['goods_price'];
  478. // 商品购买数量
  479. $item['total_num'] = $goodsNum;
  480. // 商品SKU索引
  481. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  482. // 商品购买总金额
  483. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  484. // 获取最终拼团单价金额
  485. $item['group_price'] = $groupgoods['group_price'];
  486. $item['group_buy_id'] = $joinId>0 ? $join['group_buy_activity_id'] : $activity_id;
  487. $item['join_id'] = $joinId;
  488. $item['limit_mount'] = $groupgoods['limit_mount'];
  489. $item['staffUserId'] = $data['staffUserId'];
  490. $item['shopId'] = $data['shopId'];
  491. $item['distributorRadio'] = $data['distributorRadio'];
  492. }
  493. return $goodsList;
  494. }
  495. /**拼团裂变
  496. * 立即购买:获取订单商品列表
  497. * @param int $goodsId 商品ID
  498. * @param string $goodsSkuId 商品SKU
  499. * @param int $goodsNum 购买数量
  500. * @param int $bargainId 砍价活动ID
  501. * @return mixed
  502. * @throws BaseException
  503. */
  504. public function getOrderGoodsGroupLbListByNow(int $goodsId, string $goodsSkuId, int $goodsNum, int $joinId=0,int $activity_id=0)
  505. {
  506. // 获取商品列表
  507. $model = new GoodsModel;
  508. $goodsList = $model->getListByIdsFromApi([$goodsId]);
  509. if ($goodsList->isEmpty()) {
  510. throwError('未找到商品信息');
  511. }
  512. //获取砍价数据
  513. $user = UserService::getCurrentLoginUser(true);
  514. $now = Date("Y-m-d H:i:s",time());
  515. if($joinId>0){
  516. $join = GroupBuyLbJoin::where('id',$joinId)->lock('for update')->find();
  517. $helpCnt = GroupBuyLbHelp::where("join_id",$join->id)->where('pay_state','in',[0,1])->count();
  518. $have = GroupBuyLbHelp::where("join_id",$join->id)->where('user_id',$user->user_id)->where('pay_state','in',[0,1])->find();
  519. if($have&&$have->pay_state==0){
  520. throwError("你有一个待支付的拼团");
  521. }
  522. if($have&&$have->pay_state==1){
  523. throwError("你已经参与该拼团");
  524. }
  525. if($helpCnt>=$join->people_count){
  526. throwError("拼团人数已够");
  527. }
  528. if($now>$join->end_time){
  529. throwError('拼团已结束');
  530. }
  531. if($join->status==1){
  532. throwError("拼团已完成");
  533. }
  534. if($join->status==2){
  535. throwError("拼团结束");
  536. }
  537. $groupgoods = GroupBuyLbGoods::where('group_buy_lb_activity_id',$join['group_buy_lb_activity_id'])->find();
  538. if(empty($groupgoods)){
  539. throwError('找不到商品');
  540. }
  541. if($groupgoods->goods_id!=$goodsId){
  542. throwError('商品id跟活动商品id对不上');
  543. }
  544. if($goodsNum>$groupgoods->limit_mount){
  545. throwError('超过限购数量');
  546. }
  547. }
  548. else if($activity_id>0){
  549. $activity = GroupBuyLbActivity::where("id",$activity_id)->find();
  550. if(empty($activity)){
  551. throwError("找不到拼团活动");
  552. }
  553. if($now>$activity->end_time){
  554. throwError('拼团活动已结束');
  555. }
  556. if($activity->audit_status!=1||$activity->status!=1){
  557. throwError('拼团活动不存在');
  558. }
  559. $join = GroupBuyLbJoin::where('user_id',$user->user_id)->where('group_buy_lb_activity_id',$activity_id)->where('status',0)->where('end_time',">",$now)->find();
  560. if($join){
  561. // throwError('你有一个拼团正在进行中');
  562. }
  563. $groupgoods = GroupBuyLbGoods::where('group_buy_lb_activity_id',$activity_id)->find();
  564. if(empty($groupgoods)){
  565. throwError('找不到商品');
  566. }
  567. if($groupgoods->goods_id!=$goodsId){
  568. throwError('商品id跟活动商品id对不上');
  569. }
  570. if($goodsNum>$groupgoods->limit_mount){
  571. throwError('超过限购数量');
  572. }
  573. //判断库存数量
  574. if($groupgoods->limit_stock - $groupgoods->purchase_stock <=0){
  575. throwError('活动已结束~');
  576. }
  577. }
  578. if(empty($groupgoods)){
  579. throwError("找不到商品");
  580. }
  581. // 隐藏冗余的属性
  582. $goodsList->hidden(array_merge($model->hidden, ['content', 'goods_images', 'images']));
  583. // 返回商品处理
  584. foreach ($goodsList as &$item) {
  585. // 商品sku信息
  586. $item['skuInfo'] = GoodsSkuModel::detail($item['goods_id'], $goodsSkuId);
  587. // 商品单价
  588. $item['goods_price'] = $item['skuInfo']['goods_price'];
  589. // 商品购买数量
  590. $item['total_num'] = $goodsNum;
  591. // 商品SKU索引
  592. $item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
  593. // 商品购买总金额
  594. $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
  595. // 获取最终拼团单价金额
  596. $item['group_price'] = $groupgoods['group_price'];
  597. $item['join_id'] = $joinId;
  598. $item['group_buy_lb_id'] = $joinId>0 ? $join['group_buy_lb_activity_id'] : $activity_id;
  599. $item['limit_mount'] = $groupgoods['limit_mount'];
  600. }
  601. return $goodsList;
  602. }
  603. /**
  604. * 余额支付标记订单已支付
  605. * @param string $orderNo 订单号
  606. * @return bool
  607. */
  608. public function onPaymentByBalance(string $orderNo)
  609. {
  610. // 获取订单详情
  611. $service = new OrderPaySuccesService($orderNo);
  612. // 发起余额支付
  613. $status = $service->onPaySuccess(OrderPayTypeEnum::BALANCE);
  614. if (!$status) {
  615. $this->error = $service->getError();
  616. }
  617. return $status;
  618. }
  619. /**
  620. * 积分兑换支付标记订单已支付
  621. * @param string $orderNo 订单号
  622. * @return bool
  623. */
  624. public function onPaymentByAccumulatePoints(string $orderNo)
  625. {
  626. // 获取订单详情
  627. $service = new OrderPaySuccesService($orderNo);
  628. // 发起积分支付
  629. $status = $service->onPaySuccess(OrderPayTypeEnum::EXCHANGE);
  630. if (!$status) {
  631. $this->error = $service->getError();
  632. }
  633. return $status;
  634. }
  635. /**
  636. * 获取用户订单列表
  637. * @param string $type 订单类型 (all全部 payment待付款 delivery待发货 received待收货 completed已完成 comment待评价)
  638. * @param boolean $isExchange 是否积分兑换订单
  639. * @return \think\Paginator
  640. * @throws BaseException
  641. * @throws \think\db\exception\DbException
  642. */
  643. public function getList($type = 'all',$isExchange = false)
  644. {
  645. /* // 筛选条件
  646. $filter = [];
  647. // 订单数据类型
  648. switch ($type) {
  649. case 'all':
  650. break;
  651. case 'payment':
  652. $filter['pay_status'] = PayStatusEnum::PENDING;
  653. $filter['order_status'] = OrderStatusEnum::NORMAL;
  654. break;
  655. // case 'delivery':
  656. // $filter['pay_status'] = PayStatusEnum::SUCCESS;
  657. // $filter['delivery_status'] = DeliveryStatusEnum::NOT_DELIVERED;
  658. // $filter['order_status'] = OrderStatusEnum::NORMAL;
  659. // break;
  660. case 'received':
  661. $filter['pay_status'] = PayStatusEnum::SUCCESS;
  662. // $filter['delivery_status'] = DeliveryStatusEnum::DELIVERED;
  663. $filter['receipt_status'] = ReceiptStatusEnum::NOT_RECEIVED;
  664. $filter['order_status'] = OrderStatusEnum::NORMAL;
  665. break;
  666. case 'completed':
  667. $filter['is_comment'] = 0;
  668. $filter['order_status'] = OrderStatusEnum::COMPLETED;
  669. break;
  670. case 'comment':
  671. $filter['is_comment'] = 0;
  672. $filter['order_status'] = OrderStatusEnum::COMPLETED;
  673. break;
  674. }*/
  675. $filter = $this->getFilter($type);
  676. if ($isExchange){
  677. $filter['pay_type'] = PayType::EXCHANGE;
  678. }
  679. // 当前用户ID
  680. $userId = UserService::getCurrentLoginUserId();
  681. // 查询列表数据
  682. return $this->with(['goods.image'])
  683. ->where($filter)
  684. ->where('user_id', '=', $userId)
  685. ->where('is_delete', '=', 0)
  686. ->order(['create_time' => 'desc'])
  687. ->paginate(15)->each(function($e){
  688. $e['goods_total_num'] = 0;
  689. foreach ($e['goods'] as $good){
  690. $e['goods_total_num'] += $good['total_num'];
  691. }
  692. $e['za'] =null;
  693. if($e['order_source']==OrderSourceEnum::ZA){
  694. //OrderPayTypeEnum::ACTIVITY 这个类型肯定是领取人
  695. if($e['pay_type']!=OrderPayTypeEnum::ACTIVITY){
  696. $za = ZaActivityRelation::where("order_id",$e['order_id'])->where('is_pay',1)->field('sign_str,receive_state,expire_time,is_pay,za_activity_id')->find();
  697. if($za){
  698. $now = Date("Y-m-d H:i:s",time());
  699. $data['is_expire'] =$now > $za->expire_time ? true: false;
  700. $data['sign_str'] = $za->sign_str;
  701. $data['is_receive'] = $za->receive_state;
  702. $data['expire_time'] = $za->expire_time;
  703. $data['share_title'] = ZaActivity::where("id",$za->za_activity_id)->value("share_title")??'';
  704. $e['za'] = $data;
  705. }
  706. }
  707. }
  708. });
  709. }
  710. public function getFilter($type){
  711. // 筛选条件
  712. $filter = [];
  713. // 订单数据类型
  714. switch ($type) {
  715. case 'all':
  716. break;
  717. case 'payment':
  718. $filter['pay_status'] = PayStatusEnum::PENDING;
  719. $filter['order_status'] = OrderStatusEnum::NORMAL;
  720. break;
  721. // case 'delivery':
  722. // $filter['pay_status'] = PayStatusEnum::SUCCESS;
  723. // $filter['delivery_status'] = DeliveryStatusEnum::NOT_DELIVERED;
  724. // $filter['order_status'] = OrderStatusEnum::NORMAL;
  725. // break;
  726. case 'received':
  727. $filter['pay_status'] = PayStatusEnum::SUCCESS;
  728. // $filter['delivery_status'] = DeliveryStatusEnum::DELIVERED;
  729. $filter['receipt_status'] = ReceiptStatusEnum::NOT_RECEIVED;
  730. $filter['order_status'] = OrderStatusEnum::NORMAL;
  731. break;
  732. case 'completed':
  733. // $filter['is_comment'] = 0;
  734. $filter['order_status'] = OrderStatusEnum::COMPLETED;
  735. break;
  736. case 'comment':
  737. $filter['is_comment'] = 0;
  738. $filter['order_status'] = OrderStatusEnum::COMPLETED;
  739. break;
  740. case 'cancel':
  741. $filter['order_status'] = OrderStatusEnum::CANCELLED;
  742. break;
  743. case 'close':
  744. $filter['order_status'] = OrderStatusEnum::CLOSE;
  745. break;
  746. }
  747. return $filter;
  748. }
  749. /**
  750. * 取消订单
  751. * @return bool|mixed
  752. */
  753. public function cancel()
  754. {
  755. if ($this['pay_status'] == PayStatusEnum::SUCCESS) {
  756. $this->error = '已支付订单不可取消';
  757. return false;
  758. }
  759. if ($this['delivery_status'] == DeliveryStatusEnum::DELIVERED) {
  760. $this->error = '已发货订单不可取消';
  761. return false;
  762. }
  763. // 订单取消事件
  764. return $this->transaction(function () {
  765. // 订单是否已支付
  766. $isPay = $this['pay_status'] == PayStatusEnum::SUCCESS;
  767. // 订单取消事件
  768. $isPay == false && OrderService::cancelEvent($this);
  769. // 更新订单状态: 已付款的订单设置为"待取消", 等待后台审核
  770. return $this->save(['order_status' => $isPay ? OrderStatusEnum::APPLY_CANCEL : OrderStatusEnum::CANCELLED]);
  771. });
  772. }
  773. /**
  774. * 删除指定订单记录
  775. * @return bool
  776. * @throws BaseException
  777. */
  778. public function clear()
  779. {
  780. // 验证订单是否合法
  781. // 条件1: 订单必须已取消
  782. // 条件2: 订单必须已完成
  783. // 条件3: 订单必须已关闭
  784. if ($this['order_status'] != 20 && $this['order_status'] != 30 && $this['order_status'] != 40) {
  785. $this->error = '该订单不能删除';
  786. return false;
  787. }
  788. // 获取当前用户ID
  789. $userId = UserService::getCurrentLoginUserId();
  790. // 设置更新条件
  791. $where = [['user_id', '=', $userId], ['order_id', '=', $this['order_id']]];
  792. // 更新记录
  793. return static::updateBase(['is_delete'=>1],$where);
  794. }
  795. /**
  796. * 确认收货
  797. * @return bool|mixed
  798. */
  799. public function receipt()
  800. {
  801. // 验证订单是否合法
  802. // 条件1: 订单必须已发货
  803. // 条件2: 订单必须未收货
  804. if ($this['delivery_status'] != 20 || $this['receipt_status'] != 10) {
  805. $this->error = '该订单不合法';
  806. return false;
  807. }
  808. return $this->transaction(function () {
  809. // 更新订单状态
  810. $status = $this->save([
  811. 'receipt_status' => 20,
  812. 'receipt_time' => time(),
  813. 'order_status' => $this['order_status']==10 ? 30 : $this['order_status'],
  814. ]);
  815. // 执行订单完成后的操作
  816. // $OrderCompleteService = new OrderCompleteService(OrderTypeEnum::ORDER);
  817. // $OrderCompleteService->complete([$this], static::$storeId);
  818. return $status;
  819. });
  820. }
  821. /**
  822. * 确认核销并确认收货
  823. * @return bool|mixed
  824. */
  825. public function writeOff()
  826. {
  827. // 验证订单是否合法
  828. // 条件1: 订单必须未过提货截止时间
  829. if ($this['pickup_deadline'] < date('Y-m-d H:i:s')) {
  830. $this->error = '该订单已超过提货截止时间';
  831. return false;
  832. }
  833. // 条件1: 订单必须未核销
  834. // 条件2: 订单必须未收货
  835. if ($this['hx_status'] != 10 || $this['receipt_status'] != 10) {
  836. $this->error = '该订单已核销';
  837. return false;
  838. }
  839. if ($this['refund'] && $this['refund']['status'] == 0) {
  840. $this->error = '该订单在售后中';
  841. return false;
  842. }
  843. if ($this['order_status'] != 10) {
  844. $this->error = '该订单已取消或已退款';
  845. return false;
  846. }
  847. return $this->transaction(function () {
  848. // 更新订单状态
  849. $status = $this->save([
  850. 'receipt_status' => ReceiptStatusEnum::RECEIVED,//收货状态(10未收货 20已收货)
  851. 'receipt_time' => time(),//收货时间
  852. 'delivery_status' => DeliveryStatusEnum::DELIVERED, // 发货状态(10未发货 20已发货)
  853. 'delivery_time' => time(), // 发货时间
  854. 'order_status' => 30,//订单状态(10进行中 20取消 21待取消 30已完成)
  855. 'hx_status' => 20,//核销状态(10未核销 20已核销)',
  856. 'pickup_time' => time(),//提货时间
  857. 'hx_user_id' => UserService::getCurrentLoginUserId(),//核销人用户ID
  858. ]);
  859. $orderGoodsIds = helper::getArrayColumn($this['goods'],'order_goods_id');
  860. static::setSignTime($orderGoodsIds,$this['order_id']);
  861. return $status;
  862. });
  863. }
  864. /**
  865. * 核销后结算时间
  866. * @param $orderGoodsIds
  867. * @param $orderId
  868. * @throws \think\db\exception\DataNotFoundException
  869. * @throws \think\db\exception\DbException
  870. * @throws \think\db\exception\ModelNotFoundException
  871. * @author: zjwhust
  872. * @Time: 2021/12/10 14:48
  873. */
  874. public static function setSignTime($orderGoodsIds,$orderId){
  875. // 自动关闭订单的分钟数
  876. $provider_days = SettingModel::getItem('provider_settlement')['provider_days'];//供应商结算时间
  877. $refund = SettingModel::getItem('shops');//门店自提订单配置
  878. $data = [
  879. 'provider_settlement_time' => time()+$provider_days*86400,
  880. 'commission_settlement_time' => time()+$refund['commission_days']*86400,
  881. 'refund_time' => time()+$refund['refund_days']*86400,
  882. 'auto_receipt_time' => time(),
  883. 'sign_time' => time(),
  884. 'receipt_status' => ReceiptStatusEnum::RECEIVED,//收货状态(10未收货 20已收货)
  885. 'receipt_time' => time(),//收货时间
  886. 'delivery_status' => DeliveryStatusEnum::DELIVERED, // 发货状态(10未发货 20已发货)
  887. 'delivery_time' => time(), // 发货时间
  888. ];
  889. $dataOrder = [
  890. 'commission_settlement_time' => time()+$refund['commission_days']*86400,
  891. 'refund_time' => time()+$refund['refund_days']*86400,
  892. ];
  893. //添加测试的时间
  894. if(env('SERVE_ENV')=='test') {
  895. $data = [
  896. 'provider_settlement_time' => time() + 300,//供应商结算开始时间5分钟后
  897. 'commission_settlement_time' => time() + 600,//分佣结算开始时间10分钟后
  898. 'refund_time' => time() + 300,//关闭售后时间5分钟
  899. 'auto_receipt_time' => time(),//自动收货最晚时间5分钟后
  900. 'sign_time' => time(),//记录签到时间
  901. 'receipt_status' => 20,//收货状态(10未收货 20已收货)
  902. 'receipt_time' => time(),//收货时间
  903. 'delivery_status' => DeliveryStatusEnum::DELIVERED, // 发货状态(10未发货 20已发货)
  904. 'delivery_time' => time(), // 发货时间
  905. //售后退款用户退货发货超时5分钟
  906. ];
  907. $dataOrder = [
  908. 'commission_settlement_time' => time() + 600,//分佣结算开始时间10分钟后
  909. 'refund_time' => time() + 300,//关闭售后时间5分钟
  910. ];
  911. }
  912. OrderGoodsModel::updateBase($data, [['order_goods_id', 'in', $orderGoodsIds]]);
  913. self::updateBase($dataOrder,['order_id'=>$orderId]);
  914. }
  915. /**
  916. * 获取当前用户订单数量
  917. * @param string $type 订单类型 (all全部 payment待付款 received待发货 deliver待收货 comment待评价)
  918. * @return int
  919. * @throws BaseException
  920. */
  921. public function getCount($type = 'all')
  922. {
  923. // 筛选条件
  924. $filter = [];
  925. // 订单数据类型
  926. switch ($type) {
  927. case 'all':
  928. break;
  929. case 'payment':
  930. $filter['pay_status'] = PayStatusEnum::PENDING;
  931. break;
  932. case 'received':
  933. $filter['pay_status'] = PayStatusEnum::SUCCESS;
  934. $filter['delivery_status'] = DeliveryStatusEnum::DELIVERED;
  935. $filter['receipt_status'] = ReceiptStatusEnum::NOT_RECEIVED;
  936. break;
  937. case 'delivery':
  938. $filter['pay_status'] = PayStatusEnum::SUCCESS;
  939. $filter['delivery_status'] = DeliveryStatusEnum::NOT_DELIVERED;
  940. $filter['order_status'] = OrderStatusEnum::NORMAL;
  941. break;
  942. case 'comment':
  943. $filter['is_comment'] = 0;
  944. $filter['order_status'] = OrderStatusEnum::COMPLETED;
  945. break;
  946. }
  947. // 当前用户ID
  948. $userId = UserService::getCurrentLoginUserId();
  949. // 查询数据
  950. return $this->where('user_id', '=', $userId)
  951. ->where('order_status', '<>', 20)
  952. ->where($filter)
  953. ->where('is_delete', '=', 0)
  954. ->count();
  955. }
  956. /**
  957. * 获取分享链接的用户ID
  958. * @param int $staffUserId
  959. * @return mixed
  960. * @author: zjwhust
  961. * @Time: 2021/9/30 13:32
  962. */
  963. private function getStaffUserId( int $staffUserId)
  964. {
  965. // 获取当前用户ID
  966. $user = UserService::getCurrentLoginUser(true);
  967. $is_staff = 1;
  968. if($staffUserId<=0 || $staffUserId==$user['user_id']){
  969. if(in_array($user['role'],[1,99])){
  970. $staffUserId = $user['upper_user_id'];
  971. $is_staff = 0;
  972. }else{
  973. $staffUserId = 0;
  974. }
  975. }
  976. $data['staffUserId'] = $staffUserId;
  977. $data['shopId'] = 0;
  978. $data['distributorRadio'] = 0;
  979. if ($staffUserId>0) {
  980. // 获取分享链接的用户信息
  981. $user_staff = User::detail($staffUserId);
  982. if($user_staff){
  983. $data['shopId'] = !in_array($user_staff['role'],[1,99]) ? $user_staff['shop_id'] : $user_staff['bind_shop_id'];//获取分享链接用户的shop_id
  984. if($user['role']==99){
  985. $data['distributorRadio'] = SettingModel::getItem(SettingEnum::DISTRIBUTOR)['shopping_discount'];
  986. }else{
  987. if($user_staff['role'] == 99 && $is_staff){
  988. $data['distributorRadio'] = SettingModel::getItem(SettingEnum::DISTRIBUTOR)['shopping_discount'];
  989. }
  990. }
  991. }else{
  992. if($user['role']==99){
  993. $data['distributorRadio'] = SettingModel::getItem(SettingEnum::DISTRIBUTOR)['shopping_discount'];
  994. }
  995. }
  996. }else{
  997. if($user['role']==99){
  998. $data['distributorRadio'] = SettingModel::getItem(SettingEnum::DISTRIBUTOR)['shopping_discount'];
  999. }
  1000. }
  1001. return $data;
  1002. }
  1003. /**
  1004. * 获取用户订单详情(含关联数据)
  1005. * @param int $orderId 订单ID
  1006. * @return Order|array|null
  1007. * @throws BaseException
  1008. * @throws \think\db\exception\DataNotFoundException
  1009. * @throws \think\db\exception\DbException
  1010. * @throws \think\db\exception\ModelNotFoundException
  1011. */
  1012. public static function getUserOrderDetail(int $orderId)
  1013. {
  1014. // 关联查询
  1015. $with = [
  1016. 'goods' => ['image', 'refund', 'package'],
  1017. 'address', 'express', 'shops', 'hxUser'
  1018. ];
  1019. // 查询订单记录
  1020. $order = static::getDetail($orderId, $with);
  1021. //重整订单列表结构
  1022. // static::restructureGoods($order);
  1023. //添加订单商品售后状态
  1024. static::refundStatus($order);
  1025. // 订单商品总数量
  1026. $order['orderTotalNum'] = helper::getArrayColumnSum($order['goods'], 'total_num');
  1027. // 该订单是否允许申请售后
  1028. // $order['isAllowRefund'] = static::isAllowRefund($order);
  1029. // 订单是否允许申请开票
  1030. $order['isAllowInvoice'] = static::isAllowInvoice($order);
  1031. return $order;
  1032. }
  1033. // 订单是否允许申请开票
  1034. public static function isAllowInvoice(self $order) {
  1035. if($order['order_source']==OrderSourceEnum::ZA&&$order['pay_type']==OrderPayTypeEnum::ACTIVITY){
  1036. return false;
  1037. }
  1038. if ($order['invoice_deadline'] > 0 && ($order['invoice_deadline'] - time()) > 0) {
  1039. return true;
  1040. }
  1041. return false;
  1042. }
  1043. //重构订单列表逻辑
  1044. public static function restructureGoods(self $order){
  1045. $mj_send_goods_list = [];
  1046. foreach($order['goods'] as $key=>$goods){
  1047. if($goods['master_order_goods_id']>0){
  1048. $mj_send_goods_list[$goods['master_order_goods_id']][] = $goods;
  1049. unset($order['goods'][$key]);
  1050. }
  1051. }
  1052. foreach ($order['goods'] as $good){
  1053. $good['mj_send_goods_list'] = [];
  1054. foreach ($mj_send_goods_list as $key => $list){
  1055. if($good['order_goods_id']==$key){
  1056. $good['mj_send_goods_list'] = $list;
  1057. }
  1058. }
  1059. }
  1060. }
  1061. //处理订单商品当前的售后状态
  1062. public static function refundStatus(self $order){
  1063. $order['is_full_refund'] = true;
  1064. $order['total_amount'] = helper::bcadd($order['total_price'],$order['express_price']);
  1065. foreach($order['goods'] as $goods){
  1066. $goods['order_refund_status_text'] = '';
  1067. $goods['order_refund_status'] = 0;
  1068. if($order['pay_status']==PayStatusEnum::SUCCESS && in_array($order['order_status'],[OrderStatusEnum::NORMAL,OrderStatusEnum::COMPLETED]) && $goods['goods_type']!=20) { //已支付并且不是赠品
  1069. if($goods['is_export'] || $goods['delivery_status'] == DeliveryStatusEnum::DELIVERED){
  1070. $order['is_full_refund'] = false;
  1071. }
  1072. if(($order['is_full_send']==1||$order['is_qc_send_send']==1) && $goods['delivery_status'] == DeliveryStatusEnum::NOT_DELIVERED) {//如果是满就送订单或者全场满件送订单,并且订单商品未发货
  1073. }else{
  1074. $order_refund_status_text = $goods['delivery_status'] == DeliveryStatusEnum::DELIVERED ? '申请售后' : '申请退款';
  1075. if (empty($goods['refund_time']) || $goods['refund_time'] > time()) {//申请售后的时间未过期
  1076. if ($goods['refund']) {
  1077. $order['is_full_refund'] = false;//有了退款申请就不能在全部退款了
  1078. // if ($goods['is_export'] && $goods['refund']['status'] == 0){//导出并且在已退款中
  1079. // $goods['order_refund_status_text'] = '退款中';
  1080. // $goods['order_refund_status'] = 2;
  1081. // }elseif($goods['is_export']){//导出不显示退款按钮
  1082. // $goods['order_refund_status'] = 0;
  1083. // }else
  1084. if ($goods['refund']['status'] == RefundStatusEnum::CANCELLED || $goods['refund']['status'] == RefundStatusEnum::CLOSE) {
  1085. //导出未发货时不显示申请退款状态
  1086. if($goods['is_export'] && $goods['delivery_status'] == DeliveryStatusEnum::NOT_DELIVERED ) continue;
  1087. $goods['order_refund_status_text'] = $order_refund_status_text;
  1088. $goods['order_refund_status'] = 1;
  1089. } elseif($goods['refund']['status'] == RefundStatusEnum::COMPLETED ) {//已完成 不在给第二次申请的机会
  1090. $goods['order_refund_status_text'] = '退款成功';
  1091. $goods['order_refund_status'] = 3;
  1092. }else{
  1093. $goods['order_refund_status_text'] = '退款中';
  1094. $goods['order_refund_status'] = 2;
  1095. }
  1096. } else {
  1097. //导出未发货时不显示申请退款状态
  1098. if($goods['is_export'] && $goods['delivery_status'] == DeliveryStatusEnum::NOT_DELIVERED ) {
  1099. $order['is_full_refund'] = false;
  1100. continue;
  1101. }
  1102. // 门店自提订单未核销时不显示申请退款状态
  1103. if ($order['delivery_type'] == 20 && $order['hx_status'] == 10 && count($order['goods']) > 1) {
  1104. continue;
  1105. }
  1106. $goods['order_refund_status_text'] = $order_refund_status_text;
  1107. $goods['order_refund_status'] = 1;
  1108. }
  1109. } else { //不在申请售后时间内
  1110. $order['is_full_refund'] = false;
  1111. if ($goods['refund']) {
  1112. if ($goods['refund']['status'] == RefundStatusEnum::CANCELLED || $goods['refund']['status'] == RefundStatusEnum::CLOSE) {
  1113. $goods['order_refund_status_text'] = '已关闭';
  1114. $goods['order_refund_status'] = 3;
  1115. } elseif($goods['refund']['status'] == RefundStatusEnum::COMPLETED ) {//已完成 不在给第二次申请的机会
  1116. $goods['order_refund_status_text'] = '退款成功';
  1117. $goods['order_refund_status'] = 3;
  1118. } else {
  1119. $goods['order_refund_status_text'] = '退款中';
  1120. $goods['order_refund_status'] = 2;
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. //
  1127. if($order['order_source']==OrderSourceEnum::ZA&&$order['pay_type']==OrderPayTypeEnum::ACTIVITY){
  1128. $goods['order_refund_status_text'] = '';
  1129. $goods['order_refund_status'] = 0;
  1130. }
  1131. }
  1132. return $order;
  1133. }
  1134. /**
  1135. * 获取用户订单详情(仅订单记录)
  1136. * @param int $orderId
  1137. * @param array $with
  1138. * @return Order|array|null
  1139. * @throws BaseException
  1140. */
  1141. public static function getDetail(int $orderId, $with = [])
  1142. {
  1143. // var_dump(UserService::getCurrentLoginUserId());
  1144. // die();
  1145. // 查询订单记录
  1146. $order = static::detail([
  1147. 'order_id' => $orderId,
  1148. 'user_id' => UserService::getCurrentLoginUserId(),
  1149. ], $with);
  1150. empty($order) && throwError('订单不存在');
  1151. return $order;
  1152. }
  1153. /**
  1154. * 当前订单是否允许申请售后
  1155. * @param Order $order
  1156. * @return bool
  1157. * @throws \think\db\exception\DataNotFoundException
  1158. * @throws \think\db\exception\DbException
  1159. * @throws \think\db\exception\ModelNotFoundException
  1160. */
  1161. private static function isAllowRefund(self $order)
  1162. {
  1163. // 必须是已发货的订单
  1164. if ($order['delivery_status'] != DeliveryStatusEnum::DELIVERED) {
  1165. return false;
  1166. }
  1167. // 允许申请售后期限(天)
  1168. $refundDays = SettingModel::getItem(SettingEnum::TRADE)['order']['refund_days'];
  1169. // 不允许售后
  1170. if ($refundDays == 0) {
  1171. return false;
  1172. }
  1173. // 当前时间超出允许申请售后期限
  1174. if (
  1175. $order['receipt_status'] == ReceiptStatusEnum::RECEIVED
  1176. && time() > ($order->getData('receipt_time') + ((int)$refundDays * 86400))
  1177. ) {
  1178. return false;
  1179. }
  1180. return true;
  1181. }
  1182. /**
  1183. * 获取当前用户待处理的订单数量
  1184. * @return array
  1185. * @throws BaseException
  1186. */
  1187. public function getTodoCounts()
  1188. {
  1189. return [
  1190. 'payment' => $this->getCount('payment'), // 待付款
  1191. 'delivery' => $this->getCount('received') + $this->getCount('delivery'), // 待收货(包括待发货
  1192. 'comment' => $this->getCount('comment'), // 待评价
  1193. 'refund' => (new OrderRefund())->getCount() // 售后/退款订单数
  1194. ];
  1195. }
  1196. /**
  1197. * 待支付订单倒计时时间戳
  1198. * @param $value
  1199. * @param $data
  1200. * @return int
  1201. * @author: zjwhust
  1202. * @Time: 2021/10/8 17:06
  1203. */
  1204. public function getDjsTimeAttr($value, $data){
  1205. if(isset($data['pay_status']) && $data['pay_status']==10){ //待支付
  1206. $now = time();
  1207. $djs_time = 60 * (int)SettingModel::getItem('order_cancel', $this->storeId)['close_minutes'];
  1208. // $delay_time = 60* (int)$this->getTradeSetting()['close_days'];
  1209. if($now-$data['create_time']<$djs_time){
  1210. return $data['create_time']+$djs_time-$now;
  1211. }
  1212. }
  1213. return 0;
  1214. }
  1215. /**
  1216. * 待收货订单倒计时时间戳
  1217. * @param $value
  1218. * @param $data
  1219. * @return int
  1220. * @author: zjwhust
  1221. * @Time: 2021/10/8 17:06
  1222. */
  1223. public function getDshTimeAttr($value,$data){
  1224. if(isset($data['delivery_status']) && $data['delivery_status']==20&&$data['receipt_status']==10){ //已发货待收货状态
  1225. $now = time();
  1226. $delay_time = 86400 * (int)SettingModel::getItem('refund', $this->storeId)['receive_days'];
  1227. // $delay_time = 60 * (int)$this->getTradeSetting()['receive_days'];
  1228. if(($now-$data['delivery_time'])<$delay_time){ //发货时间15天内
  1229. return $data['delivery_time']+$delay_time-$now;
  1230. }
  1231. }
  1232. return 0;
  1233. }
  1234. /**
  1235. * 设置错误信息
  1236. * @param $error
  1237. */
  1238. protected function setError($error)
  1239. {
  1240. empty($this->error) && $this->error = $error;
  1241. }
  1242. /**
  1243. * 是否存在错误
  1244. * @return bool
  1245. */
  1246. public function hasError()
  1247. {
  1248. return !empty($this->error);
  1249. }
  1250. public function dailySalesTj($shopId,$from,$to){
  1251. //统计前一天的数据
  1252. $res = $this->where('staff_shop_id',$shopId)
  1253. ->where('pay_status',20)
  1254. ->whereBetweenTime('create_time',$from,$to)//mysql 对int类型的 between and包含左右边界
  1255. ->field('sum(total_price + express_price) as total_price,sum(total_price) as total_goods_price,sum(pay_price + rice_card_money) as total_pay_price,sum(coupon_money) as coupon_money,count(order_id) as order_count,sum(express_price) as express_price')
  1256. ->find();
  1257. $res['total_price'] = $res['total_price']?:0;
  1258. $res['total_goods_price'] = $res['total_goods_price']?:0;
  1259. $res['total_pay_price'] = $res['total_pay_price']?:0;
  1260. $res['coupon_money'] = $res['coupon_money']?:0;
  1261. $res['express_price'] = $res['express_price']?:0;
  1262. //店老板基本分佣
  1263. $res['boss_comm_money'] = CommissionsDetailApi::sumUserCommission($shopId,User::SHOP_BOSS,$from,$to);
  1264. //店长基本分佣
  1265. $res['mg_comm_money'] = CommissionsDetailApi::sumUserCommission($shopId,User::SHOP_MG,$from,$to);
  1266. //店员基本分佣
  1267. $res['seller_comm_money'] = CommissionsDetailApi::sumUserCommission($shopId,User::SHOP_SELLER,$from,$to);
  1268. return $res->toArray();
  1269. }
  1270. /**
  1271. * 商城统计时间区间的销售额和订单数
  1272. * @param $from
  1273. * @param $to
  1274. * @return Order|array|\think\Model|null
  1275. * @throws \think\db\exception\DataNotFoundException
  1276. * @throws \think\db\exception\DbException
  1277. * @throws \think\db\exception\ModelNotFoundException
  1278. */
  1279. public function dailyStoreSaleVolumeSt($from,$to){
  1280. $res = $this->whereBetweenTime('create_time',$from,$to)//mysql 对int类型的 between and包含左右边界
  1281. ->where('pay_status',20)
  1282. ->field('sum(pay_price + rice_card_money) as sale_volume,count(order_id) as order_count')
  1283. ->find();
  1284. $res['sale_volume'] = $res['sale_volume']?:0;
  1285. $res['order_count'] = $res['order_count']?:0;
  1286. return $res;
  1287. }
  1288. /**
  1289. * 统计成功支付的订单数1.3.92,2022年5月11日 18:31:31
  1290. * @param $shopId
  1291. * @param $from
  1292. * @param $to
  1293. * @return int
  1294. */
  1295. public static function getUserOrderCount39($shopId,$from,$to,$monthly=false)
  1296. {
  1297. $model = CommissionsDetail::field( 'distinct order_id')
  1298. ->where('shop_id',$shopId)
  1299. ->where('commission_level',1);//6.推荐官直接推广的订单计入奖励金,间接推广的订单不计入。
  1300. if($monthly == true){
  1301. $model->where('clearing_status',1);
  1302. }else{
  1303. $model->where('clearing_status','<',2);
  1304. }
  1305. $orderIds = $model->whereBetweenTime('order_create_time', $from, $to)->column('order_id');
  1306. return count(array_unique($orderIds));
  1307. }
  1308. }