Orders.php 13 KB

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