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.

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