Orders.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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\CustomAddr;
  9. use App\Models\CustomCoupon;
  10. use App\Models\OrdersAddr;
  11. use App\Models\OrdersProduct;
  12. use App\Models\ShopCart;
  13. use Illuminate\Support\Facades\DB;
  14. /**
  15. * 订单接口
  16. *
  17. * @author 刘相欣
  18. *
  19. * */
  20. class Orders extends Api{
  21. /**
  22. * 创建订单 /api/orders/create
  23. *
  24. * @param string $car_info 需要下单的产品ID
  25. * @param string $buyer_number 需要下单的数量
  26. *
  27. * */
  28. public function create(Request $request,Model $Model,OrdersAddr $OrdersAddr,OrdersProduct $OrdersProduct,Product $Product,ProductSkus $ProductSkus,CustomCoupon $CustomCoupon,ShopCart $ShopCart,CustomAddr $CustomAddr){
  29. // 接口验签
  30. // $this->verify_sign();
  31. // 验证参数
  32. $request->scene('create')->validate();
  33. // 检查登录
  34. $uid = $this->checkLogin();
  35. // 接收参数
  36. $isCart = request('is_cart',0);
  37. $productList = request('product_list','[]');
  38. $customCouponId = request('custom_coupon_id',1);
  39. $addr = $CustomAddr->getOne(request('addr_id',0));
  40. // 如果不存在数据
  41. if( !$addr ) return json_send(['code'=>'error','msg'=>'地址有误,请核对','data'=>['error'=>'没有找到对应的地址']]);
  42. // 重组数据
  43. $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']];
  44. // 解码购买信息
  45. $buyList = json_decode($productList,true);
  46. // 如果不存在数据
  47. if( empty($buyList) ) return json_send(['code'=>'error','msg'=>'没有需下单的产品','data'=>['error'=>'产品列表为空']]);
  48. // 商品购买数量
  49. $buyNum = [];
  50. // 循环购买信息
  51. foreach ($buyList as $key => $value) {
  52. // 获取每个商品的总量
  53. $buyNum[$value['product_id']] = isset($buyNum[$value['product_id']]) ? ($buyNum[$value['product_id']] + $value['buy_num']) : $value['buy_num'];
  54. }
  55. // 查询产品信息
  56. $productList = $Product->getListByIds(array_column($buyList,'product_id'));
  57. $skusList = $ProductSkus->getListByIds(array_column($buyList,'product_skuid'));
  58. // 当前时间
  59. $time = time();
  60. // 产品以商业公司分组,方便写入订单
  61. $orderProduct = [];
  62. // 产品价格同级,用于优惠券计算
  63. $productPrice = [];
  64. // 循环处理购买信息
  65. foreach ($buyList as $buyInfo) {
  66. // 如果产品不存在
  67. if( empty($productList[$buyInfo['product_id']]) ) return json_send(['code'=>'error','msg'=>'产品不存在或已下架','data'=>['error'=>'产品不存在或已下架=>'.$buyInfo['product_id']]]);
  68. // 获取产信息
  69. $productInfo = $productList[$buyInfo['product_id']];
  70. // 如果产品限购
  71. if( $productInfo['quota'] ) {
  72. // 是否在限购时间,当前时间大于开始时间,并且小于结束时间
  73. if( $productInfo['quota_start'] <= $time && $time <= $productInfo['quota_end'] ){
  74. // 通过时间查询商品的购买总数
  75. $total = $OrdersProduct->query()->where([['custom_uid','=',$uid],['product_id','=',$productInfo['id']],['insert_time','>=',$productInfo['quota_start']],['insert_time','<=',$productInfo['quota_end']]])->sum('buy_num');
  76. // 判断限购数量
  77. $total = $buyNum[$buyInfo['product_id']] + $total;
  78. // 如果超过数量
  79. if( $total > $productInfo['quota'] ) return json_send(['code'=>'error','msg'=>'已限购'.$productInfo['product_name'],'data'=>['error'=>'已超限=>'.($total - $productInfo['quota'])]]);
  80. }
  81. }
  82. // 如果存在SKU
  83. if( $buyInfo['product_skuid'] ) {
  84. // 判断SKU信息存不存在
  85. if( empty($skusList[$buyInfo['product_skuid']]) ) return json_send(['code'=>'error','msg'=>'该产品规格不存在或已下架','data'=>['error'=>'SKU不存在或已下架=>'.$buyInfo['product_skuid']]]);
  86. // 产品ID不匹配的话
  87. if( $skusList[$buyInfo['product_skuid']]['product_id'] != $buyInfo['product_id'] ) return json_send(['code'=>'error','msg'=>'该产品规格不存在或已下架','data'=>['error'=>'SKU不匹配=>'.$buyInfo['product_skuid']]]);
  88. // 如果SKU存在,合并产品信息
  89. $productInfo = array_merge($productInfo,$skusList[$buyInfo['product_skuid']]);
  90. // 扣除库存
  91. $skusList[$buyInfo['product_skuid']]['stock'] = $skusList[$buyInfo['product_skuid']]['stock'] - $buyInfo['buy_num'];
  92. }
  93. // 判断库存
  94. if( $productInfo['stock'] < $buyInfo['buy_num'] ) return json_send(['code'=>'error','msg'=>'产品库存不足','data'=>['error'=>'产品库存不足=>'.$buyInfo['product_id']]]);
  95. // 扣除库存
  96. $productList[$buyInfo['product_id']]['stock'] = $productList[$buyInfo['product_id']]['stock'] - $buyInfo['buy_num'];
  97. // 计算价值
  98. $priceTotal = $buyInfo['buy_num'] * $productInfo['price'];
  99. // 购买信息
  100. $buyInfo = ['is_rebate'=>0,'custom_uid'=>$uid,'business_id'=>$productInfo['business_id'],'product_id'=>$buyInfo['product_id'],'buy_num'=>$buyInfo['buy_num'],'price_total'=>$priceTotal,'pay_total'=>$priceTotal,'coupon_total'=>0,'product_name'=>$productInfo['product_name'],'sku_attr_names'=>$productInfo['sku_attr_names'],'product_thumb'=>$productInfo['product_thumb']];
  101. // 获取信息
  102. 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'=>[]];
  103. // 订单产品
  104. $orderProduct[$buyInfo['business_id']]['price_total'] += $buyInfo['price_total'];
  105. $orderProduct[$buyInfo['business_id']]['pay_total'] += $buyInfo['price_total'];
  106. $orderProduct[$buyInfo['business_id']]['product_list'][] = $buyInfo;
  107. // 商品优惠信息不存在,创建
  108. if( !isset($productPrice[$buyInfo['product_id']]) ) $productPrice[$buyInfo['product_id']] = ['price_total'=>0,'rebate_price'=>0];
  109. // 计算总价
  110. $productPrice[$buyInfo['product_id']]['price_total'] = $productPrice[$buyInfo['product_id']]['price_total'] + $priceTotal;
  111. }
  112. // 优惠券数据
  113. $couponRebate = $CustomCoupon->getRebatePrice($customCouponId,$uid,$productPrice);
  114. // 判断是否使用了优惠券
  115. $usedCoupon = $couponRebate['is_used'];
  116. // 获取优惠券扣减金额
  117. $productPrice = $couponRebate['product_price'];
  118. // 获取优惠券赠品信息
  119. $rebateProduct = $couponRebate['rebate_product'];
  120. // 库存处理
  121. foreach ($productList as $key => $value) {
  122. $productList[$key] = ['id'=>$value['id'],'stock'=>$value['stock']];
  123. }
  124. foreach ($skusList as $key => $value) {
  125. $skusList[$key] = ['id'=>$value['sku_id'],'stock'=>$value['stock']];
  126. }
  127. // 组合订单数据
  128. foreach ($orderProduct as $key => $order) {
  129. // 判断哪一家的赠品
  130. if( isset($rebateProduct[$order['business_id']]) ){
  131. // 循环赠品
  132. foreach ( $rebateProduct[$order['business_id']] as $value) {
  133. // 没有对应的产品
  134. if( !isset($productList[$value['product_id']]) ) $productList[$value['product_id']] = ['id'=>$value['id'],'stock'=>$value['stock']];
  135. // 判断库存,如果库存不足,只赠送最后的库存
  136. if( $productList[$value['product_id']]['stock'] <= $value['buy_num'] ) $value['buy_num'] = $productList[$value['product_id']]['stock'];
  137. // 库存扣减
  138. $productList[$value['product_id']]['stock'] = $productList[$value['product_id']]['stock'] - $value['buy_num'];
  139. // 追加到订单表
  140. $order['product_list'][] = ['is_rebate'=>1,'custom_uid'=>$uid,'business_id'=>$value['business_id'],'product_id'=>$value['product_id'],'buy_num'=>$value['buy_num'],'price_total'=>$value['price_total'],'pay_total'=>$value['pay_total'],'coupon_total'=>$value['coupon_total'],'product_name'=>$value['product_name'],'sku_attr_names'=>$value['sku_attr_names'],'product_thumb'=>$value['product_thumb']];
  141. }
  142. }
  143. // 计算总价格
  144. foreach ($order['product_list'] as $k=>$product) {
  145. // 商品不存在,不进行扣减
  146. if( empty($productPrice[$product['product_id']]['rebate_price']) ) {
  147. // 重组
  148. $order['product_list'][$k] = $product;
  149. continue;
  150. }
  151. // 总优惠增加
  152. $order['coupon_total'] = $order['coupon_total'] + $productPrice[$product['product_id']]['rebate_price'];
  153. // 当前商品的优惠折扣计算
  154. $product['coupon_total'] = number_format( $productPrice[$product['product_id']]['rebate_price'] * ($product['price_total'] / $productPrice[$product['product_id']]['price_total']) , 2 , '.' ,'');
  155. // 成交小计
  156. $product['pay_total'] = $product['pay_total'] - $product['coupon_total'];
  157. // 重组
  158. $order['product_list'][$k] = $product;
  159. }
  160. // 成交总价
  161. $order['pay_total'] = $order['pay_total'] - $order['coupon_total'];
  162. // 成交总价
  163. $order['custom_uid'] = $uid;
  164. // 重组
  165. $orderProduct[$key] = $order;
  166. }
  167. // 组合数据,写入订单表,子表
  168. DB::beginTransaction();
  169. // 写入数据
  170. try {
  171. // 更新库存
  172. $Product->updateBatch(array_values($productList));
  173. // 更新库存
  174. $ProductSkus->updateBatch(array_values($skusList));
  175. // 循环订单数据
  176. foreach ($orderProduct as $order) {
  177. // 先获取产品列表,并去除key
  178. $productList = array_values($order['product_list']);
  179. // 删除非必要数据
  180. unset($order['product_list']);
  181. // 创建总订单
  182. $orderId = $Model->add($order);
  183. // 如果订单写入失败
  184. if( !$orderId ) {
  185. // 回退数据
  186. DB::rollBack();
  187. // 错误提示
  188. return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>'订单创建失败']]);
  189. }
  190. // 创建子订单
  191. foreach ($productList as $key=>$value) {
  192. // 增加订单ID
  193. $value['order_id'] = $orderId;
  194. // 增加订单ID
  195. $value['insert_time']= $time;
  196. $value['update_time']= $time;
  197. // 结果
  198. $productList[$key] = $value;
  199. }
  200. // 写入子表
  201. $result = $OrdersProduct->query()->insert($productList);
  202. // 如果扣减失败
  203. if( !$result ) {
  204. // 回退数据
  205. DB::rollBack();
  206. // 提示信息
  207. return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>'子订单创建失败']]);
  208. }
  209. // 写入订单地址表
  210. $addr['order_id'] = $orderId;
  211. // 写入订单地址表
  212. $result = $OrdersAddr->add($addr);
  213. // 地址写入失败
  214. if( !$result ) {
  215. // 回退数据
  216. DB::rollBack();
  217. // 提示信息
  218. return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>'地址写入失败']]);
  219. }
  220. // 如果使用了优惠券
  221. if( $usedCoupon ) $CustomCoupon->edit($usedCoupon,['status'=>1,'order_id'=>$orderId]);
  222. // 购物车
  223. if( $isCart ) $ShopCart->query()->where([['custom_uid','=',$uid]])->whereIn('skuid',array_column($buyList,'product_skuid'))->delete();
  224. }
  225. // 提交数据
  226. DB::commit();
  227. // 返回结果
  228. return json_send(['code'=>'success','msg'=>'下单成功','data'=>['id'=>null]]);
  229. // 返回结果
  230. } catch (\Throwable $th) {
  231. // 回退数据
  232. DB::rollBack();
  233. // 判断结果,如果库存扣减失败的话
  234. if( stripos($th->getMessage(),'UNSIGNED') ) return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>'产品库存扣减失败']]);
  235. // 下单失败提示
  236. return json_send(['code'=>'error','msg'=>'下单失败','data'=>['error'=>$th->getMessage().$th->getLine()]]);
  237. }
  238. }
  239. /**
  240. * 获取产品列表 /api/orders/get_list
  241. *
  242. * @param string $name 产品名称
  243. * @param int $page 页码,默认1
  244. * @param int $limit 每页条数,默认10条
  245. *
  246. * */
  247. public function get_list(Request $request,Model $Model,OrdersProduct $OrdersProduct,Business $Business){
  248. // 接口验签
  249. // $this->verify_sign();
  250. // 验证参数
  251. $request->scene('get_list')->validate();
  252. // 检查登录
  253. $uid = $this->checkLogin();
  254. // 接收参数
  255. $status = request('status',0);
  256. $limit = request('limit',10);
  257. // 显示
  258. $map = [['custom_uid','=',$uid]];
  259. // 查询状态
  260. if( $status ) $map[] = ['status','=',$status];
  261. // 查询
  262. $Paginator = $Model->query()->where($map)->orderByDesc('id')->paginate($limit,['id','pay_total','status','price_total','coupon_total','business_id','pay_total','insert_time']);
  263. // 订单产品
  264. $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();
  265. // 循环处理
  266. foreach ($Paginator as $key => $order) {
  267. // 商品列表
  268. $itemList = [];
  269. // 返回结果
  270. foreach ($productList as $item) {
  271. // 产品图路径
  272. $item['product_thumb'] = path_compat($item['product_thumb']);
  273. // 如果是订单的
  274. if( $item['order_id'] == $order['id'] ) $itemList[] = $item;
  275. }
  276. // 获取子列表
  277. $order['state'] = (string) $Model->getState($order['status'],'state');
  278. // 获取子列表
  279. $order['business_name'] = (string) $Business->getOne($order['business_id'],'name');
  280. // 获取子列表
  281. $order['contents_class']= 0;
  282. // 获取子列表
  283. $order['product_list'] = $itemList;
  284. // 重组
  285. $Paginator[$key] = $order;
  286. }
  287. // 获取数据
  288. $data['total'] = $Paginator->total();
  289. $data['current_page'] = $Paginator->currentPage();
  290. $data['per_page'] = $Paginator->perPage();
  291. $data['last_page'] = $Paginator->lastPage();
  292. $data['data'] = $Paginator->items();
  293. // 返回结果
  294. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$data]);
  295. }
  296. }