Orders.php 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. <?php namespace App\Http\Controllers\Api;
  2. use App\Http\Controllers\Api\Api;
  3. use App\Models\Orders as Model;
  4. use App\Models\Product;
  5. use App\Models\Product\Skus as ProductSkus;
  6. use App\Http\Requests\Api\Orders as Request;
  7. use App\Models\Business;
  8. use App\Models\Custom;
  9. use App\Models\StudentAddr;
  10. use App\Models\CustomCoupon;
  11. use App\Models\CustomScore;
  12. use App\Models\OrdersAddr;
  13. use App\Models\OrdersProduct;
  14. use App\Models\Regiment;
  15. use App\Models\RegimentActive;
  16. use App\Models\RegimentRecord;
  17. use App\Models\ShopCart;
  18. use Illuminate\Support\Facades\DB;
  19. use App\Models\Work\Tag as WorkTag;
  20. use App\Models\PromoProduct as PromoProduct;
  21. use Kra8\Snowflake\Snowflake;
  22. /**
  23. * 订单接口
  24. *
  25. * @author 刘相欣
  26. *
  27. * */
  28. class Orders extends Api{
  29. /**
  30. * 创建订单 /api/orders/create
  31. *
  32. * */
  33. public function create(Request $request,Custom $Custom,Model $Model,WorkTag $WorkTag,OrdersAddr $OrdersAddr,OrdersProduct $OrdersProduct,Product $Product,ProductSkus $ProductSkus,CustomCoupon $CustomCoupon,ShopCart $ShopCart,StudentAddr $StudentAddr,CustomScore $CustomScore,PromoProduct $PromoProduct){
  34. // 接口验签
  35. // $this->verify_sign();
  36. // 验证参数
  37. $request->scene('create')->validate();
  38. // 检查登录
  39. $uid = $this->checkLogin();
  40. // 接收参数
  41. $isCart = request('is_cart',0);
  42. $productList = request('product_list','[]');
  43. $customCouponId = request('custom_coupon_id',0);
  44. $addrId = request('addr_id',0);
  45. // 如果不存在数据
  46. if( !$addrId ) return json_send(['code'=>'error','msg'=>'请选择收货地址','data'=>['error'=>'请选择收货地址']]);
  47. // 解码购买信息
  48. $buyList = json_decode($productList,true);
  49. // 如果不存在数据
  50. if( empty($buyList) ) return json_send(['code'=>'error','msg'=>'没有需下单的产品','data'=>['error'=>'产品列表为空']]);
  51. // 选择地址
  52. $addr = $StudentAddr->getOne($addrId);
  53. // 如果不存在数据
  54. if( !$addr ) return json_send(['code'=>'error','msg'=>'地址有误,请核对','data'=>['error'=>'没有找到对应的地址']]);
  55. // 重组数据
  56. $addr = [
  57. 'contact_area'=>$addr['contact_area'],
  58. 'contact_school'=>$addr['contact_school'],
  59. 'contact_grade'=>$addr['contact_grade'],
  60. 'contact_class'=>$addr['contact_class'],
  61. 'contact_name'=>$addr['contact_name'],
  62. 'contact_phone'=>$addr['contact_phone'],
  63. ];
  64. // 获取客户城市ID
  65. $custom = $Custom->getOne($uid);
  66. // 如果不存在的话
  67. if( !$custom ) return json_send(['code'=>'no_login','msg'=>'用户不存在,请重新登录','data'=>['error'=>'用户不存在,请重新登录']]);
  68. // 商品购买数量
  69. $buyNum = [];
  70. // 循环购买信息
  71. foreach ($buyList as $key => $value) {
  72. // 获取每个商品的总量
  73. $buyNum[$value['product_id']] = isset($buyNum[$value['product_id']]) ? ($buyNum[$value['product_id']] + $value['buy_num']) : $value['buy_num'];
  74. }
  75. // 查询用户标签
  76. $tags = $WorkTag->getListByExtid($custom['external_userid']);
  77. // 查询产品信息
  78. $productList = $Product->getListByIds(array_column($buyList,'product_id'));
  79. $skusList = $ProductSkus->getListByIds(array_column($buyList,'product_skuid'));
  80. // 当前时间
  81. $time = time();
  82. // 产品以商业公司分组,方便写入订单
  83. $orderProduct = [];
  84. // 产品价格同级,用于优惠券计算
  85. $productPrice = [];
  86. $Snowflake = new Snowflake();
  87. $SnowflakeId = $Snowflake->next();
  88. // 循环处理购买信息
  89. foreach ($buyList as $buyInfo) {
  90. // 如果产品不存在
  91. if( empty($productList[$buyInfo['product_id']]) ) return json_send(['code'=>'error','msg'=>'产品不存在或已下架','data'=>['error'=>'产品不存在或已下架=>'.$buyInfo['product_id']]]);
  92. // 获取产信息
  93. $productInfo = $productList[$buyInfo['product_id']];
  94. // 判断是不是可以参与
  95. if( $productInfo['tag_scope'] ) {
  96. // 解析数组
  97. $productInfo['tag_scope'] = explode(',',$productInfo['tag_scope']);
  98. // 标签范围限定时,默认不能参与
  99. $allowJoin = 0;
  100. // 判断标签是不是存在
  101. foreach ($tags as $value) {
  102. // 标签范围内,允许参加
  103. if( in_array($value['name'],$productInfo['tag_scope']) ) $allowJoin = 1;
  104. }
  105. // 如果不能参与
  106. if( !$allowJoin ) return json_send(['code'=>'error','msg'=>'不在 '.$productInfo['product_name'].' 参与范围','data'=>['error'=>'不在标签范围内']]);
  107. }
  108. // 判断是不是可以参与
  109. if( $productInfo['tag_exclude'] ) {
  110. // 解析数组
  111. $productInfo['tag_exclude'] = explode(',',$productInfo['tag_exclude']);
  112. // 判断标签是不是存在
  113. foreach ($tags as $value) {
  114. // 标签排除范围内,不允许参加
  115. if( in_array($value['name'],$productInfo['tag_exclude']) ) return json_send(['code'=>'error','msg'=>'不在 '.$productInfo['product_name'].' 可参与范围','data'=>['error'=>'用户在标签排除范围']]);
  116. }
  117. }
  118. // 如果产品限购
  119. if( $productInfo['quota'] ) {
  120. // 是否在限购时间,当前时间大于开始时间,并且小于结束时间
  121. if( $productInfo['quota_start'] <= $time && $time <= $productInfo['quota_end'] ){
  122. // 通过时间查询商品的购买总数
  123. $total = $OrdersProduct->query()->where([['custom_uid','=',$uid],['product_id','=',$productInfo['id']],['insert_time','>=',$productInfo['quota_start']],['insert_time','<=',$productInfo['quota_end']]])->sum('buy_num');
  124. // 判断限购数量
  125. $total = $buyNum[$buyInfo['product_id']] + $total;
  126. // 如果超过数量
  127. if( $total > $productInfo['quota'] ) return json_send(['code'=>'error','msg'=>'限购'.$productInfo['quota'].'套-'.$productInfo['product_name'],'data'=>['error'=>'已超限=>'.($total - $productInfo['quota'])]]);
  128. }
  129. }
  130. // 如果存在SKU
  131. if( $buyInfo['product_skuid'] ) {
  132. // 判断SKU信息存不存在
  133. if( empty($skusList[$buyInfo['product_skuid']]) ) return json_send(['code'=>'error','msg'=>'该产品规格不存在或已下架','data'=>['error'=>'SKU不存在或已下架=>'.$buyInfo['product_skuid']]]);
  134. // 产品ID不匹配的话
  135. if( $skusList[$buyInfo['product_skuid']]['product_id'] != $buyInfo['product_id'] ) return json_send(['code'=>'error','msg'=>'该产品规格不存在或已下架','data'=>['error'=>'SKU不匹配=>'.$buyInfo['product_skuid']]]);
  136. // 如果SKU存在,合并产品信息
  137. $productInfo = array_merge($productInfo,$skusList[$buyInfo['product_skuid']]);
  138. // 需要扣除的库存
  139. $skusList[$buyInfo['product_skuid']]['decr'] = empty($skusList[$buyInfo['product_skuid']]['decr']) ? $buyInfo['buy_num'] : $skusList[$buyInfo['product_skuid']]['decr'] + $buyInfo['buy_num'];
  140. }
  141. // 需要扣除的库存
  142. $productList[$buyInfo['product_id']]['decr'] = empty($productList[$buyInfo['product_id']]['decr']) ? $buyInfo['buy_num'] : $productList[$buyInfo['product_id']]['decr'] + $buyInfo['buy_num'];
  143. // 判断库存
  144. if( $productInfo['stock'] < $productList[$buyInfo['product_id']]['decr'] ) return json_send(['code'=>'error','msg'=>$productInfo['product_name'].'-库存不足','data'=>['error'=>'产品库存不足=>'.$buyInfo['product_id']]]);
  145. // 计算价值
  146. $priceTotal = $buyInfo['buy_num'] * $productInfo['price'];
  147. $courseTotal = $buyInfo['buy_num'] * $productInfo['course_number'];
  148. // 购买信息
  149. $buyInfo = [
  150. 'is_rebate'=>0,
  151. 'custom_uid'=>$uid,
  152. 'business_id'=>$productInfo['business_id'],
  153. 'product_id'=>$buyInfo['product_id'],
  154. 'buy_num'=>$buyInfo['buy_num'],
  155. 'price_total'=>$priceTotal,
  156. 'pay_total'=>$priceTotal,
  157. 'coupon_total'=>0,
  158. 'product_name'=>$productInfo['product_name'],
  159. 'sku_attr_names'=>$productInfo['sku_attr_names'],
  160. 'product_thumb'=>$productInfo['product_thumb'],
  161. 'course_id'=>$productInfo['course_id'],
  162. 'course_number'=>$courseTotal,
  163. ];
  164. // 获取信息
  165. if( !isset($orderProduct[$buyInfo['business_id']]) ) $orderProduct[$buyInfo['business_id']] = ['business_id'=>$buyInfo['business_id'],'custom_uid'=>$buyInfo['custom_uid'],'price_total'=>0,'pay_total'=>0,'coupon_total'=>0,'product_list'=>[]];
  166. // 订单产品
  167. $orderProduct[$buyInfo['business_id']]['price_total'] += $buyInfo['price_total'];
  168. $orderProduct[$buyInfo['business_id']]['pay_total'] += $buyInfo['price_total'];
  169. $orderProduct[$buyInfo['business_id']]['product_list'][] = $buyInfo;
  170. // 商品优惠信息不存在,创建
  171. if( !isset($productPrice[$buyInfo['product_id']]) ) $productPrice[$buyInfo['product_id']] = ['price_total'=>0,'rebate_price'=>0];
  172. // 计算总价
  173. $productPrice[$buyInfo['product_id']]['price_total'] = $productPrice[$buyInfo['product_id']]['price_total'] + $priceTotal;
  174. }
  175. // 优惠券数据
  176. $couponRebate = $CustomCoupon->getRebatePrice($customCouponId,$uid,$productPrice);
  177. // 判断是否使用了优惠券
  178. $usedCoupon = $couponRebate['is_used'];
  179. // 获取优惠券扣减金额
  180. $productPrice = $couponRebate['product_price'];
  181. // 获取优惠券赠品信息
  182. $rebateProduct = $couponRebate['rebate_product'];
  183. /*活动优惠数据*/
  184. $promoList = $PromoProduct->getRebatePrice(array_column($buyList,'product_id'),$productPrice,$tags);
  185. $promoProductPrice = $promoList['product_price'];
  186. $promoRebateProduct = $promoList['rebate_product'];
  187. //订单支付总价
  188. $orderPayTotal = 0;
  189. // 组合订单数据
  190. foreach ($orderProduct as $key => $order) {
  191. // 判断哪一家的赠品
  192. if( isset($rebateProduct[$order['business_id']]) ){
  193. // 循环赠品
  194. foreach ( $rebateProduct[$order['business_id']] as $value) {
  195. // 没有对应的产品
  196. if( !isset($productList[$value['product_id']]) ) $productList[$value['product_id']] = ['id'=>$value['id'],'stock'=>$value['stock']];
  197. // 判断库存,如果库存不足,只赠送最后的库存
  198. if( $productList[$value['product_id']]['stock'] <= $value['buy_num'] ) $value['buy_num'] = $productList[$value['product_id']]['stock'];
  199. // 库存扣减
  200. $productList[$value['product_id']]['decr'] = empty($productList[$value['product_id']]['decr']) ? $value['buy_num'] : $productList[$value['product_id']]['decr'] + $value['buy_num'];
  201. // 追加到订单表
  202. $order['product_list'][] = ['is_rebate'=>1,
  203. 'custom_uid'=>$uid,
  204. 'business_id'=>$value['business_id'],
  205. 'product_id'=>$value['product_id'],
  206. 'buy_num'=>$value['buy_num'],
  207. 'price_total'=>$value['price_total'],
  208. 'pay_total'=>$value['pay_total'],
  209. 'coupon_total'=>$value['coupon_total'],
  210. 'product_name'=>$value['product_name'],
  211. 'sku_attr_names'=>$value['sku_attr_names'],
  212. 'product_thumb'=>$value['product_thumb'],
  213. 'course_id'=>$value['course_id'],
  214. 'course_number'=>$value['course_number'],
  215. ];
  216. }
  217. }
  218. // 促销活动判断哪一家的赠品
  219. if( isset($promoRebateProduct[$order['business_id']]) ){
  220. // 循环赠品
  221. foreach ( $promoRebateProduct[$order['business_id']] as $value) {
  222. // 没有对应的产品
  223. if( !isset($productList[$value['product_id']]) ) $productList[$value['product_id']] = ['id'=>$value['product_id'],'stock'=>$value['stock']];
  224. // 判断库存,如果库存不足,只赠送最后的库存
  225. if( $productList[$value['product_id']]['stock'] <= $value['buy_num'] ) $value['buy_num'] = $productList[$value['product_id']]['stock'];
  226. // 库存扣减
  227. $productList[$value['product_id']]['decr'] = empty($productList[$value['product_id']]['decr']) ? $value['buy_num'] : $productList[$value['product_id']]['decr'] + $value['buy_num'];
  228. // 追加到订单表
  229. $order['product_list'][] = ['is_rebate'=>1,
  230. 'custom_uid'=>$uid,
  231. 'business_id'=>$value['business_id'],
  232. 'product_id'=>$value['product_id'],
  233. 'buy_num'=>$value['buy_num'],
  234. 'price_total'=>$value['price_total'],
  235. 'pay_total'=>$value['pay_total'],
  236. 'coupon_total'=>$value['coupon_total'],
  237. 'sku_attr_names'=>$value['sku_attr_names'],
  238. 'product_name'=>$value['name'],
  239. 'product_thumb'=>$value['thumb'],
  240. 'course_id'=>$value['course_id'],
  241. 'course_number'=>$value['course_number'],
  242. ];
  243. }
  244. }
  245. // 计算总价格
  246. foreach ($order['product_list'] as $k=>$product) {
  247. //促销活动扣减
  248. if (isset($promoProductPrice[$product['product_id']]['promo_rebate_price']) && $promoProductPrice[$product['product_id']]['promo_rebate_price']> 0){
  249. // 总优惠增加
  250. $order['coupon_total'] = $order['coupon_total'] + $promoProductPrice[$product['product_id']]['promo_rebate_price'];
  251. // 当前商品的优惠折扣计算
  252. $product['coupon_total'] = number_format( $promoProductPrice[$product['product_id']]['rebate_price'] * ($product['price_total'] / $promoProductPrice[$product['product_id']]['price_total']) , 2 , '.' ,'');
  253. // 成交小计
  254. $product['pay_total'] = $product['pay_total'] - $product['coupon_total'];
  255. }
  256. // 商品不存在,不进行扣减
  257. if( !empty($productPrice[$product['product_id']]['rebate_price']) ) {
  258. // 总优惠增加
  259. $order['coupon_total'] = $order['coupon_total'] + $productPrice[$product['product_id']]['rebate_price'];
  260. // 当前商品的优惠折扣计算
  261. $product['coupon_total'] = number_format( $productPrice[$product['product_id']]['rebate_price'] * ($product['price_total'] / $productPrice[$product['product_id']]['price_total']) , 2 , '.' ,'');
  262. // 成交小计
  263. $product['pay_total'] = $product['pay_total'] - $product['coupon_total'];
  264. }
  265. // 重组
  266. $order['product_list'][$k] = $product;
  267. }
  268. // 成交总价
  269. $order['pay_total'] = $order['pay_total'] - $order['coupon_total'];
  270. $orderPayTotal += $order['pay_total'];
  271. // 赠送积分
  272. $order['order_score'] = (config('order_score_send',0) && floor( $order['pay_total'] * 1 ) > 0 ) ? floor( $order['pay_total'] * 1 ) : 0;
  273. // 成交总价
  274. $order['custom_uid'] = $uid;
  275. // 重组
  276. $orderProduct[$key] = $order;
  277. }
  278. //获取学期
  279. $semester = '';
  280. $year = date("Y");
  281. $month = date("m");
  282. if ($month <= 6){
  283. $semester = $year.'上学期';
  284. }else{
  285. $semester = $year.'下学期';
  286. }
  287. // 组合数据,写入订单表,子表
  288. DB::beginTransaction();
  289. // 写入数据
  290. try {
  291. // 扣减商品库存
  292. foreach ($productList as $key => $value) {
  293. // 扣减库存
  294. $result = $Product->edit($value['id'],['stock'=>DB::raw('stock+-'.$value['decr'])]);
  295. // 判断结果
  296. if( !$result ) {
  297. // 回退数据
  298. DB::rollBack();
  299. // 错误提示
  300. return json_send(['code'=>'error','msg'=>'库存扣减失败','data'=>['error'=>'库存扣减失败']]);
  301. }
  302. }
  303. // 扣减商品库存
  304. foreach ($skusList as $key => $value) {
  305. // 扣减库存
  306. $result = $ProductSkus->edit($value['sku_id'],['stock'=>DB::raw('stock+-'.$value['decr'])]);
  307. // 判断结果
  308. if( !$result ) {
  309. // 回退数据
  310. DB::rollBack();
  311. // 错误提示
  312. return json_send(['code'=>'error','msg'=>'库存扣减失败','data'=>['error'=>'库存扣减失败']]);
  313. }
  314. }
  315. // 循环订单数据
  316. foreach ($orderProduct as $order) {
  317. // 先获取产品列表,并去除key
  318. $productItem = array_values($order['product_list']);
  319. // 删除非必要数据
  320. unset($order['product_list']);
  321. $order['snowflake_id'] = $SnowflakeId;
  322. // 创建总订单
  323. $orderId = $Model->add($order);
  324. // 如果订单写入失败
  325. if( !$orderId ) {
  326. // 回退数据
  327. DB::rollBack();
  328. // 错误提示
  329. return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>'订单创建失败']]);
  330. }
  331. // 创建子订单
  332. foreach ($productItem as $key=>$value) {
  333. // 增加订单ID
  334. $value['order_id'] = $orderId;
  335. $value['semester'] = $semester;
  336. // 增加订单ID
  337. $value['insert_time']= $time;
  338. $value['update_time']= $time;
  339. // 结果
  340. $productItem[$key] = $value;
  341. }
  342. // 写入子表
  343. $result = $OrdersProduct->query()->insert($productItem);
  344. // 如果扣减失败
  345. if( !$result ) {
  346. // 回退数据
  347. DB::rollBack();
  348. // 提示信息
  349. return json_send(['code'=>'error','msg'=>'子订单创建失败','data'=>['error'=>'子订单创建失败']]);
  350. }
  351. // 写入订单地址表
  352. $addr['order_id'] = $orderId;
  353. // 写入订单地址表
  354. $result = $OrdersAddr->add($addr);
  355. // 地址写入失败
  356. if( !$result ) {
  357. // 回退数据
  358. DB::rollBack();
  359. // 提示信息
  360. return json_send(['code'=>'error','msg'=>'地址写入失败','data'=>['error'=>'地址写入失败']]);
  361. }
  362. // 赠送积分
  363. if( $order['order_score'] > 0 ) $CustomScore->trade($order['custom_uid'],$orderId,$order['order_score'],5,1);
  364. // 如果使用了优惠券
  365. if( $usedCoupon ) $CustomCoupon->edit($usedCoupon,['status'=>1,'order_id'=>$orderId]);
  366. // 购物车
  367. if( $isCart ) $ShopCart->query()->where([['custom_uid','=',$uid]])->whereIn('skuid',array_column($buyList,'product_skuid'))->delete();
  368. }
  369. // 自动发放优惠券
  370. $this->autoCoupon($uid);
  371. // 提交数据
  372. DB::commit();
  373. $data = [
  374. 'order_id' =>$orderId,
  375. 'pay_total' =>$orderPayTotal,
  376. 'snowflake_id' =>$SnowflakeId,
  377. ];
  378. // 返回结果
  379. return json_send(['code'=>'success','msg'=>'下单成功','data'=>$data]);
  380. // 返回结果
  381. } catch (\Throwable $th) {
  382. // 回退数据
  383. DB::rollBack();
  384. // 判断结果,如果库存扣减失败的话
  385. if( stripos($th->getMessage(),'UNSIGNED') ) return json_send(['code'=>'error','msg'=>'库存不足','data'=>['error'=>'产品库存扣减失败']]);
  386. // 下单失败提示
  387. return json_send(['code'=>'error','msg'=>'系统异常,请稍后再试','data'=>['error'=>$th->getMessage().$th->getLine()]]);
  388. }
  389. }
  390. /**
  391. * 获取列表 /api/orders/get_list
  392. *
  393. * @param string $name 产品名称
  394. * @param int $page 页码,默认1
  395. * @param int $limit 每页条数,默认10条
  396. *
  397. * */
  398. public function get_list(Request $request,Model $Model,OrdersProduct $OrdersProduct,Business $Business){
  399. // 接口验签
  400. // $this->verify_sign();
  401. // 验证参数
  402. $request->scene('get_list')->validate();
  403. // 检查登录
  404. $uid = $this->checkLogin();
  405. // 接收参数
  406. $status = request('status',0);
  407. $limit = request('limit',10);
  408. // 显示
  409. $map = [['custom_uid','=',$uid]];
  410. // 查询状态
  411. if( $status ) $map[] = ['status','=',$status];
  412. // 查询
  413. $Paginator = $Model->query()->where($map)->orderByDesc('id')->paginate($limit,['id','pay_total','status','price_total','coupon_total','business_id','pay_total','weizan_orderid','insert_time']);
  414. // 订单产品
  415. $productList = $OrdersProduct->query()->whereIn('order_id', array_column($Paginator->items(),'id'))->select(['id as item_id','order_id','product_id','buy_num','is_rebate','sku_attr_names as product_spec','product_name','product_thumb'])->get()->toArray();
  416. // 循环处理
  417. foreach ($Paginator as $key => $order) {
  418. // 商品列表
  419. $itemList = [];
  420. // 返回结果
  421. foreach ($productList as $item) {
  422. // 产品图路径
  423. $item['product_thumb'] = path_compat($item['product_thumb']);
  424. // 如果是订单的
  425. if( $item['order_id'] == $order['id'] ) $itemList[] = $item;
  426. }
  427. // 获取子列表
  428. $order['state'] = (string) $Model->getState($order['status'],'state');
  429. // 获取子列表
  430. $order['business_name'] = (string) ($order['business_id'] ? $Business->getOne($order['business_id'],'name') : ($order['weizan_orderid'] ? '微赞订单' : ''));
  431. // 获取子列表
  432. $order['contents_class']= 0;
  433. // 获取子列表
  434. $order['product_list'] = $itemList;
  435. // 重组
  436. $Paginator[$key] = $order;
  437. }
  438. // 获取数据
  439. $data['total'] = $Paginator->total();
  440. $data['current_page'] = $Paginator->currentPage();
  441. $data['per_page'] = $Paginator->perPage();
  442. $data['last_page'] = $Paginator->lastPage();
  443. $data['data'] = $Paginator->items();
  444. // 返回结果
  445. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$data]);
  446. }
  447. /**
  448. * 自动发放优惠券
  449. *
  450. */
  451. private function autoCoupon($uid){
  452. // 模型实例
  453. $Rule = new \App\Models\CouponRewardRule();
  454. // 获取配置列表
  455. $ruleList = $Rule->getList();
  456. // 如果没有信息的话
  457. if( !$ruleList ) return ['success'=>'暂无活动'];
  458. // 其他实例
  459. $RuleProduct = new \App\Models\CouponRewardProduct();
  460. $OrdersProduct = new \App\Models\OrdersProduct();
  461. $Custom = new \App\Models\Custom();
  462. $Coupon = new \App\Models\Coupon();
  463. $CustomCoupon = new \App\Models\CustomCoupon();
  464. // 获取客户城市ID
  465. $customCityId = (int) $Custom->getValue($uid,'city_id');
  466. // 循环配置列表
  467. foreach ( $ruleList as $value ) {
  468. // 如果存在城市范围,并且不在城市范围,不参与这个活动
  469. if( $value['city_ids'] && !in_array($customCityId,explode(',',$value['city_ids'])) ) continue;
  470. // 未到开始时间
  471. if( $value['start_time'] > time() ) continue;
  472. // 通过配置ID获取对应的商品范围
  473. $productList = $RuleProduct->getListByRule($value['id']);
  474. // 如果不存在产品范围,跳过
  475. if( !$productList ) continue;
  476. // 获取客户 规定时段内订单的商品ID以及购买数量
  477. $orderList = $OrdersProduct->query()->where([['custom_uid','=',$uid],['status','=',1],['insert_time','>=',$value['start_time']],['insert_time','<=',$value['end_time']]])->get(['product_id','buy_num'])->toArray();
  478. // 如果没有订单总数
  479. if( !$orderList ) continue;
  480. // 计算商品总量
  481. $total = 0;
  482. // 循环商品范围
  483. foreach ($productList as $scope) {
  484. // 循环订单产品
  485. foreach ($orderList as $order) {
  486. // 如果产品不相等
  487. if( $scope['product_id'] != $order['product_id'] ) continue;
  488. // 相等的计算总量
  489. $total += $scope['product_units'] * $order['buy_num'];
  490. }
  491. }
  492. // 判断总数是不是达标
  493. if( $total < $value['std_num'] ) continue;
  494. // 达标的是否已经发送过优惠券
  495. $havaCoupon = $CustomCoupon->query()->where([['custom_uid','=',$uid],['coupon_id','=',$value['coupon_id']]])->first(['status']);
  496. // 已经发过优惠券的,不发
  497. if( $havaCoupon ) continue;
  498. // 获取优惠券的可用时间
  499. $expTime = $Coupon->query()->where([['id','=',$value['coupon_id']]])->value('exp_time');
  500. // 时间转时间
  501. $expTime = $Coupon->getExpTime($expTime);
  502. // 发送优惠券
  503. $CustomCoupon->add(['coupon_id'=>$value['coupon_id'],'custom_uid'=>$uid,'exp_time'=>$expTime]);
  504. }
  505. // 返回成功
  506. return ['success'=>'操作成功'];
  507. }
  508. /**
  509. * 取消 /api/orders/cancel
  510. *
  511. * */
  512. public function cancel( Request $request, Model $Model,OrdersProduct $OrdersProduct,CustomScore $CustomScore){
  513. // 验证参数
  514. $request->scene('cancel')->validate();
  515. // 检查登录
  516. $uid = $this->checkLogin();
  517. // 接收参数
  518. $id = request('id',0);
  519. $status = 4;
  520. // 获取产品和数量
  521. $oldData = $Model->query()->where([['id','=',$id],['custom_uid','=',$uid]])->first(['id','order_score','status','custom_uid','insert_time']);
  522. // 如果用户不存在
  523. if( !$oldData ) return json_send(['code'=>'error','msg'=>'订单不存在']);
  524. // 如果已经取消
  525. if( $oldData['status'] == 4 ) return json_send(['code'=>'error','msg'=>'订单已取消']);
  526. // 组合数据,写入订单表,子表
  527. DB::beginTransaction();
  528. try{
  529. // 查询数据
  530. $result = $Model->setOrderStatus($id,$status,$OrdersProduct);
  531. // 提示新增失败
  532. if( isset($result['error']) ) {
  533. // 回退数据
  534. DB::rollBack();
  535. // 提示信息
  536. return json_send(['code'=>'error','msg'=>$result['error'],'data'=>['error'=>$result['error']]]);
  537. }
  538. if( $status == 4 ){
  539. // 取消积分
  540. if( $oldData['order_score'] > 0 ) {
  541. // 如果扣减失败
  542. $result = $CustomScore->trade($oldData['custom_uid'],$oldData['id'],($oldData['order_score']*-1),6,1);
  543. // 提示新增失败
  544. if( isset($result['error']) ) {
  545. // 回退数据
  546. DB::rollBack();
  547. // 提示信息
  548. return json_send(['code'=>'error','msg'=>'取消赠送积分失败','data'=>['error'=>$result['error']]]);
  549. }
  550. }
  551. // 取消关联订单
  552. $result = $Model->cancelRelate($oldData['insert_time'],$oldData['custom_uid'],$OrdersProduct,$CustomScore);
  553. // 提示新增失败
  554. if( isset($result['error']) ) {
  555. // 回退数据
  556. DB::rollBack();
  557. // 提示信息
  558. return json_send(['code'=>'error','msg'=>'取消关联订单失败','data'=>['error'=>$result['error']]]);
  559. }
  560. }
  561. // 提交数据
  562. DB::commit();
  563. // 告知结果
  564. return json_send(['code'=>'success','msg'=>'取消成功']);
  565. // 返回结果
  566. } catch (\Throwable $th) {
  567. // 回退数据
  568. DB::rollBack();
  569. // 下单失败提示
  570. return json_send(['code'=>'error','msg'=>'取消失败','data'=>['error'=>$th->getMessage().$th->getLine()]]);
  571. }
  572. }
  573. /**
  574. * 获取订单子数据 /api/orders/get_item
  575. *
  576. * @param string $name 产品名称
  577. * @param int $page 页码,默认1
  578. * @param int $limit 每页条数,默认10条
  579. *
  580. * */
  581. public function get_item(Request $request,Model $Model,OrdersProduct $OrdersProduct,Business $Business){
  582. // 接口验签
  583. // $this->verify_sign();
  584. // 验证参数
  585. $request->scene('get_item')->validate();
  586. // 检查登录
  587. $uid = $this->checkLogin();
  588. // 接收参数
  589. $id = request('id',0);
  590. // 查询
  591. $orderInfo = $Model->query()->where([['id','=',$id],['custom_uid','=',$uid]])->first(['id','pay_total','status','price_total','coupon_total','business_id','pay_total','weizan_orderid','insert_time']);
  592. // 如果用户不存在
  593. if( !$orderInfo ) return json_send(['code'=>'error','msg'=>'订单不存在']);
  594. // 转数组
  595. $orderInfo = $orderInfo->toArray();
  596. // 订单产品
  597. $orderInfo['product_list'] = $OrdersProduct->query()->where([['order_id','=',$id]])->select(['id as item_id','order_id','product_id','buy_num','is_rebate','sku_attr_names as product_spec','product_name','product_thumb'])->get()->toArray();
  598. // 循环处理
  599. foreach ($orderInfo['product_list'] as $key => $item) {
  600. // 产品图路径
  601. $item['product_thumb'] = path_compat($item['product_thumb']);
  602. // 重组
  603. $orderInfo['product_list'][$key] = $item;
  604. }
  605. // 获取子列表
  606. $orderInfo['state'] = (string) $Model->getState($orderInfo['status'],'state');
  607. // 获取子列表
  608. $orderInfo['business_name'] = (string) ($orderInfo['business_id'] ? $Business->getOne($orderInfo['business_id'],'name') : ($orderInfo['weizan_orderid'] ? '微赞订单' : ''));
  609. // 返回结果
  610. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$orderInfo]);
  611. }
  612. /**
  613. * 创建拼团订单 /api/orders/create_regiment
  614. *
  615. * */
  616. public function create_regiment(Request $request,Custom $Custom,Model $Model,WorkTag $WorkTag,OrdersAddr $OrdersAddr,OrdersProduct $OrdersProduct,Product $Product,ProductSkus $ProductSkus,CustomCoupon $CustomCoupon,ShopCart $ShopCart,StudentAddr $StudentAddr,CustomScore $CustomScore){
  617. // 接口验签
  618. // $this->verify_sign();
  619. // 验证参数
  620. $request->scene('create')->validate();
  621. // 检查登录
  622. $uid = $this->checkLogin();
  623. // 接收参数
  624. $productList = request('product_list','[]');
  625. $addrId = request('addr_id',0);
  626. $regimentId = request('regiment_id',0);
  627. $regimentActiveId = request('regiment_active_id',0);
  628. $btnType = request('btn_type',0);
  629. $Snowflake = new Snowflake();
  630. $SnowflakeId = $Snowflake->next();
  631. // 如果不存在数据
  632. if( !$addrId ) return json_send(['code'=>'error','msg'=>'请选择收货地址','data'=>['error'=>'请选择收货地址']]);
  633. // 解码购买信息
  634. $buyList = json_decode($productList,true);
  635. // 如果不存在数据
  636. if( empty($buyList) ) return json_send(['code'=>'error','msg'=>'没有需下单的产品','data'=>['error'=>'产品列表为空']]);
  637. $time = time();
  638. // 选择地址
  639. $addr = $StudentAddr->getOne($addrId);
  640. // 如果不存在数据
  641. if( !$addr ) return json_send(['code'=>'error','msg'=>'地址有误,请核对','data'=>['error'=>'没有找到对应的地址']]);
  642. // 重组数据
  643. $addr = [
  644. 'contact_area'=>$addr['contact_area'],
  645. 'contact_school'=>$addr['contact_school'],
  646. 'contact_grade'=>$addr['contact_grade'],
  647. 'contact_class'=>$addr['contact_class'],
  648. 'contact_name'=>$addr['contact_name'],
  649. 'contact_phone'=>$addr['contact_phone'],
  650. ];
  651. // 获取客户城市ID
  652. $custom = $Custom->getOne($uid);
  653. // 如果不存在的话
  654. if( !$custom ) return json_send(['code'=>'no_login','msg'=>'用户不存在,请重新登录','data'=>['error'=>'用户不存在,请重新登录']]);
  655. //获取团活动信息
  656. $regimentActiveInfo = RegimentActive::query()
  657. ->where([['id','=',$regimentActiveId],['status','=',1],['start_time','<=',$time],['end_time','>=',$time]])
  658. ->first();
  659. if (!$regimentActiveInfo) return json_send(['code'=>'error','msg'=>'拼团活动不存在','data'=>['error'=>'拼团活动不存在']]);
  660. //是否符合开团条件
  661. if($btnType == 3){
  662. if ($regimentActiveInfo['open_people'] == 1){
  663. if ($custom['insert_time'] > $regimentActiveInfo['start_time']) return json_send(['code'=>'error','msg'=>'此活动只允许老用户开团','data'=>['error'=>'此活动只允许老用户开团']]);
  664. }
  665. if ($regimentActiveInfo['open_people'] == 2){
  666. if ($custom['insert_time'] < $regimentActiveInfo['start_time']) return json_send(['code'=>'error','msg'=>'此活动只允许新用户开团','data'=>['error'=>'此活动只允许新用户开团']]);
  667. }
  668. }
  669. //是否符合参团条件
  670. if($btnType == 4){
  671. if ($regimentActiveInfo['partake_people'] == 1){
  672. if ($custom['insert_time'] > $regimentActiveInfo['start_time']) return json_send(['code'=>'error','msg'=>'此活动只允许老用户参与','data'=>['error'=>'此活动只允许老用户开团']]);
  673. }
  674. if ($regimentActiveInfo['partake_people'] == 2){
  675. if ($custom['insert_time'] < $regimentActiveInfo['start_time']) return json_send(['code'=>'error','msg'=>'此活动只允许新用户参与','data'=>['error'=>'此活动只允许新用户开团']]);
  676. }
  677. //查询团信息
  678. $regimentInfo = Regiment::query()
  679. ->where([['id','=',$regimentId],['status','=',0],['start_time','<=',$time],['end_time','>=',$time]])
  680. ->first();
  681. if (!$regimentInfo) return json_send(['code'=>'error','msg'=>'拼团活动不存在','data'=>['error'=>'拼团活动不存在']]);
  682. $regimentRecordres = RegimentRecord::query()
  683. ->where([['custom_uid','=',$uid],['regiment_id','=',$regimentId]])
  684. ->first();
  685. if ($regimentRecordres) return json_send(['code'=>'error','msg'=>'您已参与此拼团','data'=>['error'=>'您已参与此拼团']]);
  686. }
  687. //查询用户参团记录
  688. $regimentRecordCount = RegimentRecord::query()
  689. ->where([['custom_uid','=',$uid],['active_id','=',$regimentActiveInfo['id']]])
  690. ->count('id');
  691. if ($regimentRecordCount >= $regimentActiveInfo['participation_number']) return json_send(['code'=>'error','msg'=>'该活动每人仅限参与'.$regimentActiveInfo['participation_number'].'次','data'=>['error'=>'该活动每人仅限参与'.$regimentActiveInfo['participation_number'].'次']]);
  692. $tags = $WorkTag->getListByExtid($custom['external_userid']);
  693. // 查询产品信息
  694. $productList = $Product->getListByIds(array_column($buyList,'product_id'));
  695. // 当前时间
  696. $time = time();
  697. // 产品以商业公司分组,方便写入订单
  698. $orderProduct = [];
  699. // 产品价格同级,用于优惠券计算
  700. $productPrice = [];
  701. $priceTotal = 0;
  702. $payTotal = 0;
  703. $buyInfo = $buyList[0];
  704. $courseTotal = 0;
  705. if ($buyInfo){
  706. if( empty($productList[$buyInfo['product_id']]) ) return json_send(['code'=>'error','msg'=>'产品不存在或已下架','data'=>['error'=>'产品不存在或已下架=>'.$buyInfo['product_id']]]);
  707. // 获取产信息
  708. $productInfo = $productList[$buyInfo['product_id']];
  709. // 判断是不是可以参与
  710. if( $productInfo['tag_scope'] ) {
  711. // 解析数组
  712. $productInfo['tag_scope'] = explode(',',$productInfo['tag_scope']);
  713. // 标签范围限定时,默认不能参与
  714. $allowJoin = 0;
  715. // 判断标签是不是存在
  716. foreach ($tags as $value) {
  717. // 标签范围内,允许参加
  718. if( in_array($value['name'],$productInfo['tag_scope']) ) $allowJoin = 1;
  719. }
  720. // 如果不能参与
  721. if( !$allowJoin ) return json_send(['code'=>'error','msg'=>'不在 '.$productInfo['product_name'].' 参与范围','data'=>['error'=>'不在标签范围内']]);
  722. }
  723. // 判断是不是可以参与
  724. if( $productInfo['tag_exclude'] ) {
  725. // 解析数组
  726. $productInfo['tag_exclude'] = explode(',',$productInfo['tag_exclude']);
  727. // 判断标签是不是存在
  728. foreach ($tags as $value) {
  729. // 标签排除范围内,不允许参加
  730. if( in_array($value['name'],$productInfo['tag_exclude']) ) return json_send(['code'=>'error','msg'=>'不在 '.$productInfo['product_name'].' 可参与范围','data'=>['error'=>'用户在标签排除范围']]);
  731. }
  732. }
  733. //拼团活动限购
  734. if ($regimentActiveInfo['quota']){
  735. if ($buyInfo['buy_num'] > $regimentActiveInfo['quota']) return json_send(['code'=>'error','msg'=>'超过拼团限购','data'=>['error'=>'拼团限购=>'.$buyInfo['product_id']]]);
  736. }
  737. // 如果产品限购
  738. if( $productInfo['quota'] ) {
  739. // 是否在限购时间,当前时间大于开始时间,并且小于结束时间
  740. if( $productInfo['quota_start'] <= $time && $time <= $productInfo['quota_end'] ){
  741. // 通过时间查询商品的购买总数
  742. $total = $OrdersProduct->query()->where([['custom_uid','=',$uid],['product_id','=',$productInfo['id']],['insert_time','>=',$productInfo['quota_start']],['insert_time','<=',$productInfo['quota_end']]])->sum('buy_num');
  743. // 判断限购数量
  744. $total = $buyInfo['buy_num'] + $total;
  745. // 如果超过数量
  746. if( $total > $productInfo['quota'] ) return json_send(['code'=>'error','msg'=>'限购'.$productInfo['quota'].'套-'.$productInfo['product_name'],'data'=>['error'=>'已超限=>'.($total - $productInfo['quota'])]]);
  747. }
  748. }
  749. // 需要扣除的库存
  750. $productList[$buyInfo['product_id']]['decr'] = $buyInfo['buy_num'];
  751. // 判断库存
  752. if( $productInfo['stock'] < $productList[$buyInfo['product_id']]['decr'] ) return json_send(['code'=>'error','msg'=>$productInfo['product_name'].'-库存不足','data'=>['error'=>'产品库存不足=>'.$buyInfo['product_id']]]);
  753. // 计算价值
  754. $priceTotal = $buyInfo['buy_num'] * $productInfo['price'];
  755. $payTotal = $buyInfo['buy_num'] * $regimentActiveInfo['regiment_price'];
  756. $courseTotal = $buyInfo['buy_num'] * $productInfo['course_number'];
  757. }
  758. $orderInfo = [
  759. 'custom_uid' => $uid,
  760. 'status' => 1,
  761. 'insert_time' => $time,
  762. 'update_time' => $time,
  763. 'pay_total' => $payTotal,
  764. 'price_total' => $priceTotal,
  765. 'business_id' => $productList[$buyInfo['product_id']]['business_id'],
  766. 'snowflake_id' => $SnowflakeId,
  767. ];
  768. // 赠送积分
  769. $orderInfo['order_score'] = (config('order_score_send',0) && floor( $orderInfo['pay_total'] * 1 ) > 0 ) ? floor( $orderInfo['pay_total'] * 1 ) : 0;
  770. $orderProductInfo = [
  771. 'product_name' => $productList[$buyInfo['product_id']]['product_name'],
  772. 'sku_attr_names' => $productList[$buyInfo['product_id']]['sku_attr_names'],
  773. 'product_thumb' => $productList[$buyInfo['product_id']]['product_thumb'],
  774. 'buy_num' => $buyInfo['buy_num'],
  775. 'price_total' => $priceTotal,
  776. 'pay_total' => $buyInfo['buy_num'] * $productList[$buyInfo['product_id']]['price'],
  777. 'product_id' => $buyInfo['product_id'],
  778. 'custom_uid' => $uid,
  779. 'business_id' => $productList[$buyInfo['product_id']]['business_id'],
  780. 'insert_time' => $time,
  781. 'update_time' => $time,
  782. 'status' => 1,
  783. 'course_id' => $productList[$buyInfo['product_id']]['course_id'],
  784. 'course_number' => $courseTotal,
  785. ];
  786. // 组合数据,写入订单表,子表
  787. DB::beginTransaction();
  788. // 写入数据
  789. try {
  790. // 扣减商品库存
  791. foreach ($productList as $key => $value) {
  792. // 扣减库存
  793. $result = $Product->edit($value['id'],['stock'=>DB::raw('stock+-'.$value['decr'])]);
  794. // 判断结果
  795. if( !$result ) {
  796. // 回退数据
  797. DB::rollBack();
  798. // 错误提示
  799. return json_send(['code'=>'error','msg'=>'库存扣减失败','data'=>['error'=>'库存扣减失败']]);
  800. }
  801. }
  802. //创建拼团
  803. if($btnType == 3){
  804. $regimentInfoData = [
  805. 'custom_uid' => $uid,
  806. 'active_id' => $regimentActiveInfo['id'],
  807. 'product_id' => $buyInfo['product_id'],
  808. 'people_number' => 0,
  809. 'start_time' => $time,
  810. 'end_time' => $time + $regimentActiveInfo['expiration']*3600,
  811. 'update_time' => $time,
  812. 'insert_time' => $time,
  813. ];
  814. $regimentId = Regiment::query()->insertGetId($regimentInfoData);
  815. if( !$regimentId ) {
  816. // 回退数据
  817. DB::rollBack();
  818. // 提示信息
  819. return json_send(['code'=>'error','msg'=>'创建拼团失败','data'=>['error'=>'创建拼团失败']]);
  820. }
  821. }
  822. $orderInfo['regiment_id'] = $regimentId;
  823. // 创建总订单
  824. $orderId = $Model->add($orderInfo);
  825. // 如果订单写入失败
  826. if( !$orderId ) {
  827. // 回退数据
  828. DB::rollBack();
  829. // 错误提示
  830. return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>'订单创建失败']]);
  831. }
  832. $orderProductInfo['order_id'] = $orderId;
  833. // 写入子表
  834. $result = $OrdersProduct->query()->insert($orderProductInfo);
  835. // 如果扣减失败
  836. if( !$result ) {
  837. // 回退数据
  838. DB::rollBack();
  839. // 提示信息
  840. return json_send(['code'=>'error','msg'=>'子订单创建失败','data'=>['error'=>'子订单创建失败']]);
  841. }
  842. // 写入订单地址表
  843. $addr['order_id'] = $orderId;
  844. // 写入订单地址表
  845. $result = $OrdersAddr->add($addr);
  846. // 地址写入失败
  847. if( !$result ) {
  848. // 回退数据
  849. DB::rollBack();
  850. // 提示信息
  851. return json_send(['code'=>'error','msg'=>'地址写入失败','data'=>['error'=>'地址写入失败']]);
  852. }
  853. //拼团记录
  854. $regimentRecordInfo = [
  855. 'custom_uid' => $uid,
  856. 'regiment_id' => $regimentId,
  857. 'active_id' => $regimentActiveInfo['id'],
  858. 'product_id' => $buyInfo['product_id'],
  859. 'order_id' => $orderId,
  860. 'update_time' => $time,
  861. 'insert_time' => $time,
  862. ];
  863. $result = RegimentRecord::query()->insert($regimentRecordInfo);
  864. if( !$result ) {
  865. // 回退数据
  866. DB::rollBack();
  867. // 提示信息
  868. return json_send(['code'=>'error','msg'=>'创建拼团记录失败','data'=>['error'=>'创建拼团记录失败']]);
  869. }
  870. // 提交数据
  871. DB::commit();
  872. $data = [
  873. 'order_id' =>$orderId,
  874. 'pay_total' =>$orderInfo['pay_total'],
  875. 'snowflake_id' =>$orderInfo['snowflake_id'],
  876. ];
  877. // 返回结果
  878. return json_send(['code'=>'success','msg'=>'下单成功','data'=>$data]);
  879. // 返回结果
  880. } catch (\Throwable $th) {
  881. // 回退数据
  882. DB::rollBack();
  883. // 判断结果,如果库存扣减失败的话
  884. if( stripos($th->getMessage(),'UNSIGNED') ) return json_send(['code'=>'error','msg'=>'库存不足','data'=>['error'=>'产品库存扣减失败']]);
  885. // 下单失败提示
  886. return json_send(['code'=>'error','msg'=>'系统异常,请稍后再试','data'=>['error'=>$th->getMessage().$th->getLine()]]);
  887. }
  888. }
  889. /**
  890. * 取消拼团 /api/orders/cancel_regiment
  891. *
  892. * */
  893. public function cancel_regiment( Request $request, Model $Model,OrdersProduct $OrdersProduct,CustomScore $CustomScore){
  894. // 验证参数
  895. $request->scene('cancel')->validate();
  896. // 检查登录
  897. $uid = $this->checkLogin();
  898. // 接收参数
  899. $id = request('id',0);
  900. $status = 12;
  901. // 获取产品和数量
  902. $oldData = $Model->query()->where([['id','=',$id],['custom_uid','=',$uid]])->first(['id','order_score','status','custom_uid','insert_time','regiment_id']);
  903. // 如果用户不存在
  904. if( !$oldData ) return json_send(['code'=>'error','msg'=>'订单不存在']);
  905. // 如果已经取消
  906. if( $oldData['status'] == 12 ) return json_send(['code'=>'error','msg'=>'订单已取消']);
  907. // 如果团不存在
  908. if( !$oldData['regiment_id'] ) return json_send(['code'=>'error','msg'=>'拼团不存在']);
  909. //查询团信息
  910. $regimentInfo = Regiment::query()->find($oldData['regiment_id']);
  911. if( !$regimentInfo ) return json_send(['code'=>'error','msg'=>'拼团不存在']);
  912. // 组合数据,写入订单表,子表
  913. DB::beginTransaction();
  914. try{
  915. // 查询数据
  916. $result = $Model->setOrderStatus($id,$status,$OrdersProduct);
  917. // 提示新增失败
  918. if( isset($result['error']) ) {
  919. // 回退数据
  920. DB::rollBack();
  921. // 提示信息
  922. return json_send(['code'=>'error','msg'=>$result['error'],'data'=>['error'=>$result['error']]]);
  923. }
  924. //开团用户取消团订单
  925. if ($regimentInfo['people_number'] > 1 && $regimentInfo['custom_uid'] == $uid){
  926. //查询团记录
  927. $regimentRecordInfo = RegimentRecord::query()->where([['order_id','<>',$oldData['id']],['regiment_id','=',$regimentInfo['id']],['status','=',0]])->first();
  928. if ($regimentRecordInfo){
  929. //将参团成员中的第一个用户变成开团人
  930. $result = Regiment::query()->where('id','=',$regimentRecordInfo['regiment_id'])->update(['custom_uid'=>$regimentRecordInfo['custom_uid']]);
  931. if (!$result) {
  932. DB::rollBack();
  933. return json_send(['code'=>'error','msg'=>'取消拼团,改变开团人失败']);
  934. }
  935. }
  936. //扣减加入团人数
  937. $regimentRes = Regiment::query()->where('id','=',$oldData['regiment_id'])->decrement('people_number',1);
  938. if( !$regimentRes ) {
  939. // 回退数据
  940. DB::rollBack();
  941. // 提示信息
  942. return json_send(['code'=>'error','msg'=>'取消拼团失败']);
  943. }
  944. }else{
  945. $regimentRes = Regiment::query()->where('id','=',$oldData['regiment_id'])->update(['status'=>1]);
  946. if (!$regimentRes){
  947. DB::rollBack();
  948. return json_send(['code'=>'error','msg'=>'取消拼团失败']);
  949. }
  950. }
  951. //修改拼团记录
  952. $regimentRes = RegimentRecord::query()->where([['order_id','=',$oldData['id'],]])->update(['status'=>'1']);
  953. if( !$regimentRes ) {
  954. // 回退数据
  955. DB::rollBack();
  956. // 提示信息
  957. return json_send(['code'=>'error','msg'=>'取消拼团失败']);
  958. }
  959. // 提交数据
  960. DB::commit();
  961. // 告知结果
  962. return json_send(['code'=>'success','msg'=>'取消成功']);
  963. // 返回结果
  964. } catch (\Throwable $th) {
  965. // 回退数据
  966. DB::rollBack();
  967. // 下单失败提示
  968. return json_send(['code'=>'error','msg'=>'取消失败','data'=>['error'=>$th->getMessage().$th->getLine()]]);
  969. }
  970. }
  971. /**
  972. * 订单详情 /api/orders/create
  973. *
  974. * @pamam int $id 订单ID
  975. *
  976. * */
  977. public function get_detail( Request $request, Model $Model,OrdersProduct $OrdersProduct,Business $Business,OrdersAddr $OrdersAddr){
  978. // 验证参数
  979. $request->scene('get_detail')->validate();
  980. // 接受参数
  981. $id = request('id',0);
  982. // 查询数据
  983. $order = $Model->query()->find($id,['id','snowflake_id as order_code','pay_total','status','price_total','coupon_total','business_id','pay_total','weizan_orderid','insert_time']);
  984. // 查询不到订单
  985. if( !$order ) return json_send(['code'=>'error','msg'=>'订单不存在']);
  986. // 数据转换
  987. $order = $order->toArray();
  988. // id转编号
  989. $order['insert_time'] = date('Y-m-d H:i:s',$order['insert_time']);
  990. $order['business_name'] = (string) $Business->getOne($order['business_id'],'name');
  991. $order['state'] = $Model->getState($order['status'],'state');
  992. $order['order_code'] = (string)$order['order_code'];
  993. // 查询子订单数据
  994. $order['order_items'] = $OrdersProduct->query()->where([['order_id','=',$id]])->select(['id as item_id','order_id','product_id','buy_num','pay_total','is_rebate','sku_attr_names as product_spec','product_name','product_thumb'])->get()->toArray();
  995. // 处理缩略图
  996. foreach ($order['order_items'] as $key => $value) {
  997. $value['product_thumb'] = $value['product_thumb'] ? path_compat($value['product_thumb']) : '';
  998. $order['order_items'][$key] = $value;
  999. }
  1000. // 地址
  1001. $order['order_addr'] = $OrdersAddr->query()->where([['order_id','=',$id]])->first(['contact_area','contact_school','contact_grade','contact_class','contact_name','contact_phone']);
  1002. // 加载模板
  1003. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$order]);
  1004. }
  1005. }