Orders.php 48 KB

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