Order.php 55 KB

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