Orders.php 12 KB

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