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.

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