You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

401 lines
12 KiB

  1. <?php
  2. namespace api\logic;
  3. use backend\modules\goods\models\ars\Goods;
  4. use backend\modules\goods\models\ars\GoodsSku;
  5. use backend\modules\shop\models\ars\Address;
  6. use backend\modules\shop\models\ars\Cart;
  7. use backend\modules\shop\models\ars\Order;
  8. use backend\modules\shop\models\ars\OrderGoods;
  9. use backend\modules\shop\models\ars\TakingSite;
  10. use yii\base\Component;
  11. use Throwable;
  12. use Yii;
  13. use yii\db\ActiveRecord;
  14. use yii\base\Exception;
  15. use yii\web\BadRequestHttpException;
  16. use yii\web\NotFoundHttpException;
  17. use yii\web\ServerErrorHttpException;
  18. /**
  19. * @author iron
  20. * @email weiriron@gmail.com
  21. * @package api\logic
  22. */
  23. class OrderLogic extends Component
  24. {
  25. public $viewAction = 'view';
  26. /*订单操作类型*/
  27. const TYPE_CONFIRM = 1;
  28. const TYPE_CANCEL = 2;
  29. const TYPE_TAKE = 3;
  30. const TYPE_CHANGE_SHIPPING_TYPE = 4;
  31. const TYPE_CHANGE_ADDRESS = 5;
  32. const TYPE_CHANGE_TAKING_SITE = 6;
  33. /*仓库类型*/
  34. const TYPE_ADD_STOCK = 1;
  35. const TYPE_SUB_STOCK = -1;
  36. /**
  37. * @return Order
  38. * @throws BadRequestHttpException
  39. * @throws Exception
  40. * 创建订单
  41. */
  42. public function create()
  43. {
  44. //立即购物需传参数
  45. $goodsId = Yii::$app->request->getBodyParam('goodsId');/*int 商品id*/
  46. $count = Yii::$app->request->getBodyParam('count');/*int 数量*/
  47. $skuId = Yii::$app->request->getBodyParam('skuId');/*int 商品sku id*/
  48. //购物车提交订单需传参数
  49. $cartIds = Yii::$app->request->getBodyParam('cartIds');/*array 购物车商品id*/
  50. if ((empty($cartIds) && empty($goodsId)) || ($goodsId && empty($count))) {
  51. throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS);
  52. }
  53. $tra = Yii::$app->db->beginTransaction();
  54. try {
  55. $order = new Order();
  56. if (!$order->save()) {
  57. throw new ServerErrorHttpException('服务器创建订单失败');
  58. }
  59. if ($goodsId && $count) {
  60. $this->addGoods($order->id, $goodsId, $skuId, $count);/*添加订单商品*/
  61. } else {
  62. $this->addGoodsByCart($cartIds, $order->id);/*通过购物车添加订单商品*/
  63. }
  64. $this->saveGoodsInfo($order);/*保存订单商品信息*/
  65. $tra->commit();
  66. Helper::createdResponse($order, $this->viewAction);
  67. return $order;
  68. } catch (Exception $e) {
  69. $tra->rollBack();
  70. throw $e;
  71. }
  72. }
  73. /**
  74. * @return bool
  75. * @throws Exception
  76. * @throws Throwable
  77. * @throws yii\base\InvalidConfigException
  78. * 根据操作类型更新订单
  79. */
  80. public function update()
  81. {
  82. $data = Yii::$app->request->getBodyParams();
  83. $type = Yii::$app->request->getBodyParam('type');
  84. $order = $this->findOrder();
  85. $tra = Yii::$app->db->beginTransaction();
  86. try {
  87. switch ($type) {
  88. case self::TYPE_CONFIRM :
  89. $this->confirm($order, $data);
  90. break;
  91. case self::TYPE_CANCEL:
  92. $this->cancel($order);
  93. break;
  94. case self::TYPE_TAKE:
  95. $this->take($order);
  96. break;
  97. case self::TYPE_CHANGE_SHIPPING_TYPE:
  98. $this->switchShippingType($order, $data);
  99. break;
  100. case self::TYPE_CHANGE_ADDRESS:
  101. $this->changeAddress($order, $data);
  102. break;
  103. case self::TYPE_CHANGE_TAKING_SITE:
  104. $this->changeTakingSite($order, $data);
  105. break;
  106. }
  107. if (!$order->save()) {
  108. throw new ServerErrorHttpException('服务器更新订单失败');
  109. }
  110. $tra->commit();
  111. return true;
  112. } catch (Exception $e) {
  113. $tra->rollBack();
  114. throw $e;
  115. }
  116. }
  117. /*----------------------------------------- 华丽的分割线 -----------------------------------------*/
  118. /**
  119. * @param Order $order
  120. * @param array $data
  121. * @throws BadRequestHttpException
  122. * @throws NotFoundHttpException
  123. * 添加地址到订单
  124. */
  125. private function changeAddress($order, $data)
  126. {
  127. if (!isset($data['address_id'])) {
  128. throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS);
  129. }
  130. if ($order->shipping_type !== Order::SHIPPING_TYPE_EXPRESS) {
  131. throw new BadRequestHttpException('配送方式异常');
  132. }
  133. $address = Address::findOne(['id' => $data['address_id'], 'user_id' => Yii::$app->user->getId()]);
  134. if (!$address) {
  135. throw new NotFoundHttpException('收货地址未找到');
  136. }
  137. $order->consignee = $address->consignee;
  138. $order->phone = $address->phone;
  139. $order->city = $address->city;
  140. $order->area = $address->area;
  141. $order->province = $address->province;
  142. $order->address = $address->address;
  143. }
  144. /**
  145. * @param Order $order
  146. * @param array $data
  147. * @throws BadRequestHttpException
  148. * @throws NotFoundHttpException
  149. * 修改自提点
  150. */
  151. private function changeTakingSite($order, $data)
  152. {
  153. if (!isset($data['taking_site_id']) || empty($data['taking_site_id'])) {
  154. throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS);
  155. }
  156. if ($order->shipping_type !== Order::SHIPPING_TYPE_PICKED_UP) {
  157. throw new BadRequestHttpException('配送方式异常');
  158. }
  159. $site = TakingSite::findOne($data['taking_site_id']);
  160. if (!$site) {
  161. throw new NotFoundHttpException('自提点未找到');
  162. }
  163. $order->taking_site = $data['taking_site_id'];
  164. }
  165. /**
  166. * @param Order $order
  167. * @param array $data
  168. * @throws BadRequestHttpException
  169. * 切换配送方式
  170. */
  171. private function switchShippingType($order, $data)
  172. {
  173. if (!isset($data['shipping_type'])) {
  174. throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS);
  175. }
  176. if ($order->status !== Order::STATUS_UNCONFIRMED) {
  177. throw new BadRequestHttpException('订单状态异常');
  178. }
  179. $order->shipping_type = $data['shipping_type'];
  180. }
  181. /**
  182. * @param Order $order
  183. * @param array $data
  184. * @throws BadRequestHttpException
  185. * @throws NotFoundHttpException
  186. * @throws ServerErrorHttpException
  187. * @throws Throwable
  188. * @throws yii\db\StaleObjectException
  189. * 确定订单
  190. */
  191. private function confirm($order, $data)
  192. {
  193. if ($order->status !== Order::STATUS_UNCONFIRMED) {
  194. throw new BadRequestHttpException('订单状态异常');
  195. }
  196. if ($order->shipping_type === Order::SHIPPING_TYPE_PICKED_UP) {
  197. if ($data['consignee'] ?? false || $data['phone'] ?? false) {
  198. throw new BadRequestHttpException(Helper::REQUEST_BAD_PARAMS);
  199. }
  200. $order->consignee = $data['consignee'];
  201. $order->phone = $data['phone'];
  202. }
  203. if (empty($order->consignee)) {
  204. throw new BadRequestHttpException('需先填写收件人信息');
  205. }
  206. if (isset($data['remarks'])) {
  207. $order->remarks = $data['remarks'];
  208. }
  209. Helper::delCarts($this->getCartsIds($order)); //删除购物车对应商品
  210. $order->status = Order::STATUS_NONPAYMENT;
  211. $this->updateStock($order, self::TYPE_SUB_STOCK);
  212. }
  213. /**
  214. * @param $order
  215. * @return array
  216. * 获取订单商品对应购物车商品id
  217. */
  218. private function getCartsIds($order)
  219. {
  220. $allGoods = $this->findOrderGoods($order->id);
  221. $ids = [];
  222. foreach ($allGoods as $goods) {
  223. $cart = Cart::findOne(['goods_id' => $goods->goods_id, 'user_id' => Yii::$app->user->getId()]);
  224. if ($cart) {
  225. $ids[] = $cart->id;
  226. }
  227. }
  228. return $ids;
  229. }
  230. /**
  231. * @param Order $order
  232. * @throws BadRequestHttpException
  233. * @throws NotFoundHttpException
  234. * @throws ServerErrorHttpException
  235. * 取消订单
  236. */
  237. private function cancel($order)
  238. {
  239. if ($order->status !== Order::STATUS_NONPAYMENT) {
  240. throw new BadRequestHttpException('订单状态异常');
  241. }
  242. $order->status = Order::STATUS_CANCEL;
  243. $this->updateStock($order, self::TYPE_ADD_STOCK);/*更新库存*/
  244. }
  245. /**
  246. * @param Order $order
  247. * @throws BadRequestHttpException
  248. * 确认收货
  249. */
  250. private function take($order)
  251. {
  252. if ($order->status !== Order::STATUS_SHIPMENT_ALL) {
  253. throw new BadRequestHttpException('订单状态异常');
  254. }
  255. $order->status = Order::STATUS_FINISH;
  256. }
  257. /**
  258. * @param $id
  259. * @param $type
  260. * @throws BadRequestHttpException
  261. * @throws NotFoundHttpException
  262. * @throws ServerErrorHttpException
  263. * 更新库存
  264. */
  265. private function updateStock($id, $type)
  266. {
  267. $allOrderGoods = $this->findOrderGoods($id);
  268. foreach ($allOrderGoods as $orderGoods) {
  269. /*检查库存*/
  270. Helper::checkStock($orderGoods->goods_id, $orderGoods->goods_count, $orderGoods->sku_id);
  271. if ($orderGoods->sku_id) {
  272. $goods = GoodsSku::findOne($orderGoods->sku_id);
  273. } else {
  274. $goods = Goods::findOne($orderGoods->goods_id);
  275. }
  276. if ($type) {
  277. $count = $orderGoods->goods_count;
  278. } else {
  279. $count = -$orderGoods->goods_count;
  280. }
  281. if (!$goods->updateCounters(['stock' => $count])) {
  282. throw new ServerErrorHttpException('更新库存失败');
  283. }
  284. }
  285. }
  286. /**
  287. * @param array $cartIds 购物车商品id
  288. * @param int $id 订单id
  289. * @throws Exception
  290. * @throws NotFoundHttpException
  291. * 通过购物车添加商品
  292. */
  293. private function addGoodsByCart($cartIds, $id)
  294. {
  295. foreach ($cartIds as $cartId) {
  296. $cart = Cart::findOne($cartId);
  297. if (!$cart) {
  298. throw new NotFoundHttpException('购物车未找到');
  299. }
  300. $this->addGoods($id, $cart->goods_id, $cart->sku_id, $cart->goods_count);
  301. }
  302. }
  303. /**
  304. * @param Order $order
  305. * @throws Exception
  306. * 保存商品总价格和总数量信息到
  307. */
  308. private function saveGoodsInfo($order)
  309. {
  310. $orderGoods = $this->findOrderGoods($order->id);
  311. foreach ($orderGoods as $goods) {
  312. $order->goods_amount += $goods->price;
  313. $order->goods_count += $goods->goods_count;
  314. }
  315. if (!$order->save()) {
  316. throw new Exception('服务器创建订单失败');
  317. }
  318. }
  319. /**
  320. * @param $id
  321. * @param int $goodsId
  322. * @param $skuId
  323. * @param $count
  324. * @throws Exception
  325. * @throws NotFoundHttpException
  326. * 添加商品到订单
  327. */
  328. private function addGoods($id, $goodsId, $skuId, $count)
  329. {
  330. $goods = Goods::findOne($goodsId);
  331. $orderGoods = new OrderGoods();
  332. $orderGoods->order_id = $id;
  333. $orderGoods->goods_id = $goodsId;
  334. $orderGoods->sku_id = $skuId ?: 0;
  335. $orderGoods->sku_value = Helper::skuValue($skuId);
  336. $orderGoods->weight = $skuId ? $this->skuWeight($skuId) : $goods->weight;
  337. $orderGoods->goods_count = $count;
  338. $orderGoods->goods_img = $goods->image;
  339. $orderGoods->goods_name = $goods->name;
  340. $orderGoods->price = Helper::goodsPrice($goodsId, $skuId);
  341. Helper::checkStock($goodsId, $count, $skuId); /*检查库存*/
  342. if (!$orderGoods->save()) {
  343. throw new Exception('服务器添加订单商品失败');
  344. }
  345. }
  346. private function skuWeight($skuId)
  347. {
  348. $sku = GoodsSku::findOne($skuId);
  349. if (!$sku) {
  350. throw new NotFoundHttpException('sku未找到');
  351. }
  352. return $sku->weight;
  353. }
  354. /**
  355. * @return array|Order|null
  356. * 根据id获取订单
  357. */
  358. private function findOrder()
  359. {
  360. $id = Yii::$app->request->getQueryParam('id');
  361. return Order::find()
  362. ->where(['id' => $id])
  363. ->andWhere(['user_id' => Yii::$app->user->getId()])
  364. ->one();
  365. }
  366. /**
  367. * @param $id
  368. * @return array|ActiveRecord[]|OrderGoods[]
  369. * 根据订单 id 获取所有订单商品
  370. */
  371. private function findOrderGoods($id)
  372. {
  373. return OrderGoods::find()
  374. ->where(['order_id' => $id])
  375. ->all();
  376. }
  377. }