HappinessOrder.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. namespace addons\Happiness\common\models;
  3. use addons\Store\common\models\StoreGoodsAttr;
  4. use common\enums\OrderSourceEnum;
  5. use common\enums\OrderStatusEnum;
  6. use common\enums\RedisKeyEnum;
  7. use common\enums\StatusEnum;
  8. use common\events\order\OrderTakeDeliveryEvent;
  9. use common\helpers\LockHelper;
  10. use common\models\order\OrderDetail;
  11. use common\models\order\OrderExpress;
  12. use common\models\order\OrderExpressLog;
  13. use common\models\order\OrderReserve;
  14. use common\models\user\User;
  15. use Exception;
  16. use Yii;
  17. /**
  18. * This is the model class for table "qimall_addons_happiness_order".
  19. *
  20. * @property int $id id
  21. * @property int $mall_id 商城id
  22. * @property int $user_id 用户id
  23. * @property int $store_id 门店id
  24. * @property int $order_id 订单id
  25. * @property int|null $shipping_type 快递方式(1:快递配送,2:门店自提,3:送货上门)
  26. * @property string|null $order_no 订单编号
  27. * @property int $order_status 订单状态
  28. * @property int|null $created_at 创建时间
  29. * @property int|null $updated_at 修改时间
  30. * @property int $parent_id 推荐用户id
  31. */
  32. class HappinessOrder extends \common\models\base\BaseActiveRecord
  33. {
  34. /**
  35. * {@inheritdoc}
  36. */
  37. public static function tableName()
  38. {
  39. return 'qimall_addons_happiness_order';
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public function rules()
  45. {
  46. return [
  47. // [['id', 'mall_id', 'user_id', 'store_id', 'order_id'], 'required'],
  48. [['mall_id', 'user_id', 'store_id', 'order_id', 'shipping_type', 'created_at', 'updated_at','parent_id'], 'integer'],
  49. [['order_no'], 'string', 'max' => 255],
  50. [['price'], 'number']
  51. ];
  52. }
  53. /**
  54. * {@inheritdoc}
  55. */
  56. public function attributeLabels()
  57. {
  58. return [
  59. 'id' => 'ID',
  60. 'mall_id' => 'Mall ID',
  61. 'user_id' => 'User ID',
  62. 'parent_id' => 'Parent ID',
  63. 'store_id' => 'Store ID',
  64. 'order_id' => 'Order ID',
  65. 'shipping_type' => 'Shipping Type',
  66. 'order_no' => 'Order No',
  67. 'order_status' => 'Order Status',
  68. 'created_at' => 'Created At',
  69. 'updated_at' => 'Updated At',
  70. ];
  71. }
  72. public function getBase_user()
  73. {
  74. return $this->hasOne(User::class, ['id' => 'user_id'])->select(['id', 'username','nickname', 'avatar_url','mobile']);
  75. }
  76. public function getDetail()
  77. {
  78. return $this->hasMany(OrderDetail::class, ['order_id' => 'id']);
  79. }
  80. public function getOrderDetail()
  81. {
  82. return $this->hasMany(OrderDetail::class, ['order_id' => 'order_id']);
  83. }
  84. public function getReserve()
  85. {
  86. return $this->hasOne(OrderReserve::class, ['order_id' => 'id']);
  87. }
  88. public function getStore()
  89. {
  90. return $this->hasOne(HappinessStore::class, ['id' => 'store_id'])->asArray(true);
  91. }
  92. public static function setData(array $params)
  93. {
  94. try {
  95. if (!empty($params['mall_id']) && !empty($params['id'])) {
  96. $model = self::findOne(['mall_id' => $params['mall_id'], 'id' => $params['id']]);
  97. if (empty($model)) {
  98. $model = new self();
  99. $model->loadDefaultValues();
  100. }
  101. } else {
  102. $model = new self();
  103. $model->loadDefaultValues();
  104. }
  105. if (!$model->load($params, '')) throw new \Exception($model->getErrorMessage());
  106. if (!$model->save()) throw new \Exception($model->getErrorMessage());
  107. return $model;
  108. } catch (\Exception $e) {
  109. self::$static_error = $e->getMessage();
  110. return false;
  111. }
  112. }
  113. /**
  114. * @name:
  115. * @msg: 关闭订单
  116. * @param {*} $params
  117. * @param {*} $force
  118. * @return {*}
  119. */
  120. public static function close($params, $force = false)
  121. {
  122. $trans = Yii::$app->db->beginTransaction();
  123. $stock_locks = [];
  124. $close_lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_GOODS, $params['id']);
  125. try {
  126. // 加锁
  127. $close_identification = uniqid();
  128. $stock_locks[$close_lock_key] = $close_identification;
  129. // if (!LockHelper::lock($close_lock_key, $close_identification, 30, 60)) throw new \Exception('正在关闭订单');
  130. $cond = ['mall_id' => $params['mall_id'], 'id' => $params['id']];
  131. isset($params['user_id']) && $cond['user_id'] = $params['user_id'];
  132. isset($params['store_id']) && $cond['store_id'] = $params['store_id'];
  133. $model = self::findOne($cond);
  134. if (empty($model)) throw new Exception('订单不存在或已删除1');
  135. // 判断订单是否已经被关闭
  136. if ($model->order_status == OrderStatusEnum::REPEAL) throw new Exception('订单已经关闭');
  137. // 判断是否是未支付的订单
  138. if ($force == false && $model->order_status != OrderStatusEnum::NOT_PAY) throw new Exception('订单已经被处理');
  139. $order = Order::findOne(['order_no'=>$model['order_no']]);
  140. // $model->close_time = time();
  141. $model->order_status = OrderStatusEnum::REPEAL;
  142. if (!$model->save()) throw new Exception($model->getErrorMessage());
  143. // if(!empty($order)){
  144. // $order->close_time = $model->close_time;
  145. // $order->order_status = $model->order_status;
  146. // if (!$order->save()) throw new Exception($order->getErrorMessage());
  147. // }
  148. // $goods_attr_arr = array_column($model->detail, 'num', 'goods_attr_id');
  149. // //操作规格库存-回退
  150. // foreach ($goods_attr_arr as $goods_attr_id => $num) {
  151. // $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_GOODS_ATTR, $goods_attr_id);
  152. // $identification = uniqid();
  153. // if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new Exception('当前访问人数过多');
  154. // $stock_locks[$lock_key] = $identification;
  155. // //操作商品库存-回退
  156. // HappinessStoreGoodsAttr::handleStock($goods_attr_id, $num, $params['store_id']);
  157. // }
  158. $trans->commit();
  159. // 触发订单取消事件
  160. // 解锁
  161. // LockHelper::batchUlock($stock_locks);
  162. return $model;
  163. } catch (Exception $e) {
  164. $trans->rollback();
  165. // 解锁
  166. LockHelper::batchUlock($stock_locks);
  167. self::$static_error = $e->getMessage();
  168. return false;
  169. }
  170. }
  171. public static function searchParams($mall_id, $search)
  172. {
  173. // 查询参数
  174. $isReserve = $search['is_reserve'];
  175. $where[] = ['=', 'o.mall_id', $mall_id];
  176. $where[] = ['>=', 'o.status', StatusEnum::DISABLED];
  177. if ($isReserve) {
  178. $where[] = ['=', 'o.order_source', OrderSourceEnum::SOURCE_RESERVE];
  179. } else {
  180. $where[] = ['not in', 'o.order_source', [OrderSourceEnum::SOURCE_SELF_MALL, OrderSourceEnum::SOURCE_RESERVE]];
  181. }
  182. if (isset($search['order_id'])) $where[] = ['in', 'o.id', explode(',', $search['order_id'])];
  183. ($search['payment_type'] ?? false) && $where[] = ['=', 'o.payment_type', $search['payment_type']];
  184. ($search['shipping_type'] ?? false) && $where[] = ['=', 'o.shipping_type', $search['shipping_type']];
  185. if (isset($search['order_status']) && $search['order_status'] != 999) {
  186. $where[] = ['=', 'o.order_status', $search['order_status']];
  187. }
  188. ($search['order_no'] ?? false) && $where[] = ['=', 'o.order_no', $search['order_no']];
  189. ($search['start'] ?? false) && $where[] = ['>=', 'o.created_at', strtotime($search['start'])];
  190. ($search['end'] ?? false) && $where[] = ['<=', 'o.created_at', strtotime($search['end'])];
  191. if ($search['type_value'] ?? false) {
  192. switch ($search['type']) {
  193. case 'mobile':
  194. $uids = User::find()->select('id')->where(['like', 'mobile', $search['type_value'] . '%', false])->column();
  195. !empty($uids) && $where[] = ['in', 'yo.user_id', $uids];
  196. break;
  197. case 'user_id':
  198. $where[] = ['in', 'yo.user_id', $search['type_value']];
  199. break;
  200. default:
  201. }
  202. }
  203. if (!empty($search['store_name'])) {
  204. $store_ids = HappinessStore::find()->select('id')->where(['like', 'store_name', '%'.$search['store_name'].'%', false])->column();
  205. if (!empty($store_ids)) {
  206. $where[] = ['in', 'yo.store_id', $store_ids];
  207. } else {
  208. $where[] = ['yo.store_id' => 0];
  209. }
  210. }
  211. if (!empty($search['store_user_id'])) {
  212. $store_ids = HappinessStore::find()->select('id')->where(['user_id' => $search['store_user_id']])->column();
  213. if (!empty($store_ids)) {
  214. $where[] = ['in', 'yo.store_id', $store_ids];
  215. } else {
  216. $where[] = ['yo.store_id' => 0];
  217. }
  218. }
  219. return $where;
  220. }
  221. public static function OrderExpressDelivery($params,$trigger_event = true){
  222. try{
  223. $store_order = HappinessOrder::getOne([['mall_id' => $params['mall_id'], 'order_id' => $params['id'],'store_id'=>$params['store_id']]]);
  224. $order = Order::getOne([['mall_id' => $params['mall_id'], 'order_no' => $store_order['order_no'],'status'=>[StatusEnum::ENABLED]]]);
  225. if(empty($order)) throw new Exception('订单不存在或已删除');
  226. $trans = Yii::$app->db->beginTransaction();
  227. $model = new OrderExpress();
  228. $params['order_id'] = $order['id'];
  229. $params['buyer_id'] = $order['user_id'];
  230. $params['buyer_name'] = $order['receiver_name'];
  231. $params['operator_username'] = $params['operator_name'];
  232. if(!$model->load($params,'') || !$model->save()) throw new \Exception($model->getErrorMessage());
  233. //保存物流轨迹记录
  234. $params['order_express_id'] = $model->id;
  235. $res = OrderExpressLog::saveLog($params);
  236. if ($res == false) throw new Exception(OrderExpressLog::getStaticError());
  237. $condition['where'] = [['in', 'order_id', $order['id']],['is_feedback'=>[OrderStatusEnum::FEEDBACKING,OrderStatusEnum::FEEDBACKED]]];
  238. $res = OrderDetail::lists($condition);
  239. if(!empty($res)) throw new \Exception('订单申请售后中,请先处理售后问题');
  240. // 订单商品的物流状态改变
  241. OrderDetail::updateAll(['shipping_status' => StatusEnum::ENABLED], ['in', 'order_id', $order['id']]);
  242. // 自动维护订单状态
  243. $res = Order::autoUpdateStatus($order);
  244. if($res === false) throw new \Exception(Order::getStaticError());
  245. $trans->commit();
  246. if ($trigger_event) {
  247. // 发货成功触发事件,事务提交完成后触发
  248. $event = new \common\events\order\OrderDeliveryEvent($params['mall_id']);
  249. $data['id'] = $model->id;
  250. $data['operator_id'] = $params['operator_id'];
  251. $data['operator_name'] = $params['operator_name'];
  252. Yii::$app->services->events->dispatch($event,$data, $event->listeners);
  253. }
  254. return true;
  255. }catch(Exception $e){
  256. if(isset($trans)) $trans->rollback();
  257. self::$static_error = $e->getMessage().$e->getFile().$e->getLine();
  258. return false;
  259. }
  260. }
  261. public static function takeDelivery($params)
  262. {
  263. try {
  264. $cond = ['mall_id' => $params['mall_id'],'id' => $params['id'], 'status' => [StatusEnum::ENABLED]];
  265. // isset($params['user_id']) && $cond['user_id'] = $params['user_id'];
  266. // isset($params['store_id']) && $cond['store_id'] = $params['store_id'];
  267. $model = Order::findOne($cond);
  268. if (empty($model)) throw new Exception('订单不存在或已删除');
  269. if ($model->order_status == OrderStatusEnum::SING) throw new Exception('订单已经签收');
  270. if ($model->order_status != OrderStatusEnum::PAY) throw new Exception('订单已经被处理');
  271. if (OrderDetail::getAfterSaleCountByOrderId($model['id']) > 0) throw new Exception('请先处理或关闭订单售后');
  272. $model->order_status = OrderStatusEnum::SING;
  273. $model->sign_time = time();
  274. $model->consign_time = time();
  275. if (!$model->save()) throw new Exception($model->getErrorMessage());
  276. // 触发订单收货事件,事务提交完成后触发
  277. $event = new OrderTakeDeliveryEvent($params['mall_id']);
  278. $data['id'] = $model['id'];
  279. $data['operator_id'] = $params['operator_id'];
  280. $data['operator_name'] = $params['operator_name'];
  281. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  282. return $model;
  283. } catch (Exception $e) {
  284. self::$static_error = $e->getMessage();
  285. return false;
  286. }
  287. }
  288. }