| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <?php
- namespace common\models\order;
- use addons\ReservationService\common\enums\ReservationServiceEnum;
- use addons\ReservationService\common\models\ReservationServiceOrder;
- use addons\SecondaryCard\common\models\SecondaryCard;
- use addons\Store\common\models\StoreOrderReserve;
- use common\enums\ClerkEnum;
- use common\enums\OrderStatusEnum;
- use common\enums\StatusEnum;
- use common\models\goods\Goods;
- use common\models\goods\GoodsReserve;
- use common\models\goods\GoodsReserveSku;
- use common\models\goods\GoodsReserveTime;
- use common\models\goods\GoodsReserveTimeSpec;
- use common\models\user\UserAddress;
- use Exception;
- use phpDocumentor\Reflection\Types\Static_;
- use Yii;
- /**
- * This is the model class for table "{{%order_reserve}}".
- * @property int $id ID
- * @property int $order_id 主订单id
- * @property int $store_id 门店id
- * @property int $mall_id 商城ID
- * @property int $user_id 用户id
- * @property int $time_id 预约时间id
- * @property int $time_spec_id 预约时间id
- * @property string $reserve_date_time 预约时间
- * @property int $reserve_time_range_type 预约模式(1按天预约 2按时间段预约)
- * @property int $province_id 省ID
- * @property int $city_id 市ID
- * @property int $district_id 区县ID
- * @property string $detail 详细地址
- * @property string $lat 纬度
- * @property string $lng 经度
- * @property int $service_type 服务方式(1上门 2到店)
- * @property int $order_status 订单状态
- * @property int $pay_status 订单付款状态
- * @property int $reserve_status 订单预约状态
- * @property int $feedback_status 售后状态
- * @property string $reserve_code 预约码
- * @property int $created_at 创建时间
- * @property int $updated_at 更新时间
- * @property int $reserve_type 更新时间
- * @property int $tech_id 更新时间
- * @property int $attr_id 更新时间
- * @property int $service_start_at 服务开始时间
- * @property int $service_end_at 服务结束时间
- * @property int $goods_id 商品id
- * @property int $reservation_service_order_id 预约服务订单id
- */
- class OrderReserve extends \common\models\base\BaseActiveRecord
- {
- const RESERVE_STATUS_WAIT = 0;
- const RESERVE_STATUS_PENDDING = 1;
- const RESERVE_STATUS_FINISH = 2;
- const CANCEL_TYPE_NOT = 1;
- const CANCEL_TYPE_TIME = 2;
- const CANCEL_TYPE_RATE = 3;
- /**
- * {@inheritdoc}
- */
- public static function tableName()
- {
- return '{{%order_reserve}}';
- }
- /**
- * {@inheritdoc}
- */
- public function rules()
- {
- return [
- [['order_id'], 'required'],
- [['order_id', 'store_id', 'mall_id', 'user_id', 'time_id', 'time_spec_id', 'reserve_time_range_type',
- 'province_id', 'city_id', 'district_id', 'service_type', 'order_status', 'pay_status', 'reserve_status', 'feedback_status',
- 'cancel_type', 'created_at', 'updated_at', 'reserve_type', 'tech_id', 'attr_id',
- 'service_start_at', 'service_end_at', 'goods_id', 'reservation_service_order_id'], 'integer'],
- [['lat', 'lng'], 'number'],
- [['reserve_date_time', 'detail', 'region_name', 'reserve_code','cancel_rule'], 'string', 'max' => 255]
- ];
- }
- /**
- * {@inheritdoc}
- */
- public function attributeLabels()
- {
- return [
- 'id' => 'ID',
- 'order_id' => '主订单id',
- 'store_id' => '门店id',
- 'mall_id' => '商城ID',
- 'user_id' => '用户id',
- 'time_id' => '预约时间id',
- 'time_spec_id' => '预约时间id',
- 'reserve_date_time' => '预约时间',
- 'reserve_time_range_type' => '预约模式(1按天预约 2按时间段预约)',
- 'province_id' => '省ID',
- 'city_id' => '市ID',
- 'district_id' => '区县ID',
- 'detail' => '详细地址',
- 'lat' => '纬度',
- 'lng' => '经度',
- 'region_name' => '地区字符串',
- 'service_type' => '服务方式(1上门 2到店)',
- 'order_status' => '订单状态',
- 'pay_status' => '订单付款状态',
- 'reserve_status' => '订单预约状态',
- 'feedback_status' => '售后状态',
- 'cancel_rule' => '取消退款规则',
- 'cancel_type' => '取消类型(1不允许取消 2服务开始前取消 3订单类型取消)',
- 'reserve_code' => '预约码',
- 'created_at' => '创建时间',
- 'updated_at' => '更新时间',
- 'reservation_service_order_id' => 'reservation_service_order_id',
- ];
- }
- /**
- * 预约商品订单处理
- * @param [type] $order
- * @param [type] $form
- * @return void
- */
- public static function create($order, $form)
- {
- try {
- $timeId = $form['data']['time_id'];
- $serviceType = $form['data']['service_type'];
- $latitude = $form['data']['latitude'];
- $longitude = $form['data']['longitude'];
- $address_id = $form['data']['address_id'] ?? 0;
- $timeSpecId = $form['data']['time_spec_id'];
- $tech_id = intval($form['data']['tech_id'] ?? 0);
- $orderDetail = $order->detail[0];
- $goodsId = $orderDetail['goods_id'];
- $skuId = $orderDetail['goods_attr_id'];
- $num = $orderDetail['num'];
- if (!empty($address_id)) {
- $user_address = UserAddress::findOne(['id' => $address_id]);
- if (!empty($user_address['latitude'])) {
- $latitude = $user_address['latitude'];
- }
- if (!empty($user_address['longitude'])) {
- $longitude = $user_address['longitude'];
- }
- }
- // 扣减时间或时间段的库存
- /**
- * @var $reserve GoodsReserve
- */
- $reserve = GoodsReserve::findOne(['goods_id' => $goodsId]);
- if (empty($reserve)) throw new \Exception('找不到该预约商品');
- $reserveSku = GoodsReserveSku::findOne(['id' => $skuId, 'goods_id' => $goodsId]);
- if (empty($reserveSku)) throw new \Exception('找不到该预约商品SKU');
- $goods = Goods::findOne(['id' => $goodsId]);
- $service_start_at = 0;
- $service_end_at = 0;
- if ($reserve->reserve_type == StatusEnum::DISABLED) {
- // 预约模式(1按天预约 2按时间段预约)
- $reserveTimeRangeType = $reserveSku->reserve_time_range_type;
- // 预约时间处理
- $time = GoodsReserveTime::findOne($timeId);
- if (empty($time)) throw new \Exception('找不到该预约时间日期');
- $date = $time->reserve_time;
- // if (empty($goods->is_attr)) {
- // if ($time->stock < $num) throw new \Exception('该预约时间日期已超过最大预约数量');
- // $time->stock -= $num;
- // $time->save();
- // }
- if ($reserveTimeRangeType == 2) {
- $timeSpec = GoodsReserveTimeSpec::findOne(['reserve_time_id' => $timeId, 'id' => $timeSpecId]);
- if (empty($timeSpec)) throw new \Exception('找不到该预约时间分片');
- $startHis = $timeSpec->start;
- $endHis = $timeSpec->end;
- $start = implode(' ', [$date, $startHis]);
- if ($timeSpec->is_next) $date = date('Y-m-d', strtotime('+1 day', strtotime($date)));
- $end = implode(' ', [$date, $endHis]);
- $reserveDateTime = implode(',', [$start, $end]);
- if ($timeSpec->stock < $num) throw new \Exception('该预约时间段已超过最大预约数量');
- $timeSpec->stock -= $num;
- $timeSpec->save();
- } else {
- $reserveDateTime = implode(',', [$date . ' 00:00:00', $date . '23:59:59']);
- }
- } else {
- $reserveTimeRangeType = 2; // 技师默认是按时间段预约的
- $reserveDateTime = $form['data']['select_time'] ?? '';
- if (!empty($reserveDateTime)) {
- $reserveDateTime .= ','.date('Y-m-d H:i', strtotime($reserveDateTime) + ($reserveSku->service_min * 60));
- $reserve_date_time_arr = explode(',', $reserveDateTime);
- if (!empty($reserve_date_time_arr)) {
- $service_start_at = strtotime($reserve_date_time_arr[0]);
- $service_end_at = strtotime($reserve_date_time_arr[1]);
- $res = OrderReserve::find()->where(['attr_id' => $skuId, 'service_start_at' => $service_start_at])
- ->andWhere(['tech_id' => $tech_id])
- ->andWhere(['!=', 'order_status', -4])
- ->select('tech_id')->one();
- if (!empty($res)) {
- throw new \Exception('该技师该时间已有预约');
- }
- }
- if (empty($goods->is_attr)) {
- // 查询今天有多少单
- $reserve_max_buy = $reserve->reserve_max_buy;
- } else {
- $reserve_max_buy = $reserveSku->reserve_max_buy;
- }
- $date = date('Y-m-d', $service_start_at);
- $start_time = strtotime($date . ' 00:00:00');
- $end_time = strtotime($date . ' 23:59:59');
- if (!empty($reserve_max_buy) && $reserve_max_buy <= self::find()->where(['attr_id' => $skuId])
- ->andWhere(['>=', 'service_start_at', $start_time])
- ->andWhere(['<=', 'service_start_at', $end_time])
- ->andWhere(['>=', 'order_status', 0])->count()) {
- throw new \Exception('今天已达到最大预约数');
- }
- }
- // 取出商品的结束时间
- }
- // 预约商品服务地址
- // service_type服务方式(1上门 2到店 3两者都兼容)
- if ($serviceType == GoodsReserve::RESERVE_SERVICE_TO) {
- // 上门服务使用订单地址
- $province = $order->province;
- $city = $order->city;
- $area = $order->area;
- $address = $order->address;
- $lat = $latitude;
- $lng = $longitude;
- $regionName = $order->region_name;
- } else {
- // 到店使用商品地址
- $province = $reserve->province_id;
- $city = $reserve->city_id;
- $area = $reserve->district_id;
- $address = $reserve->detail;
- $lat = $reserve->lat;
- $lng = $reserve->lng;
- $regionName = '';
- }
- if (empty($province) || empty($city) || empty($area) || empty($address) || empty($lat) || empty($lng)) {
- throw new \Exception('服务地址或定位信息错误');
- }
- $model = new OrderReserve();
- $model->loadDefaultValues();
- $model->isNewRecord = true;
- $model->order_id = $order->id;
- $model->store_id = $order->store_id;
- $model->mall_id = $order->mall_id;
- $model->user_id = $order->user_id;
- $model->time_id = $timeId ?? 0;
- $model->time_spec_id = $timeSpecId ?? 0;
- $model->reserve_date_time = !empty($reserveDateTime) ? $reserveDateTime : '';
- $model->reserve_time_range_type = !empty($reserveTimeRangeType) ? $reserveTimeRangeType : 0;
- $model->province_id = $province;
- $model->city_id = $city;
- $model->district_id = $area;
- $model->detail = $address;
- $model->lat = $lat;
- $model->lng = $lng;
- $model->region_name = $regionName;
- $model->service_type = $serviceType;
- $model->order_status = $order->order_status;
- $model->pay_status = $order->pay_status;
- $model->cancel_type = $reserve->cancel_type;
- $model->cancel_rule = $reserve->cancel_rule;
- $model->reserve_type = $reserve->reserve_type;
- $model->tech_id = $tech_id;
- $model->attr_id = $skuId;
- $model->service_start_at = $service_start_at;
- $model->service_end_at = $service_end_at;
- $model->goods_id = $goodsId;
- if (!$model->save()) throw new Exception($model->getErrorMessage());
- return true;
- } catch (Exception $e) {
- if (isset($trans)) $trans->rollback();
- self::$static_error = $e->getMessage();
- return false;
- }
- }
- /**
- * 同步订单状态
- * @param [type] $order
- * @return void
- */
- public static function syncOrderStatus($order, $tech_id = null)
- {
- $orderDetail = $order->detail[0];
- $num = $orderDetail['num'];
- if (empty($order['store_id'])) {
- $model = self::findOne(['order_id' => $order->id]);
- } else {
- $model = StoreOrderReserve::findOne(['main_order_id' => $order->id]);
- }
- $oldStatus = $model->order_status;
- $model->order_status = $order->order_status;
- $model->feedback_status = $order->is_feedback;
- $model->pay_status = $order->pay_status;
- $timeId = $model->time_id;
- $timeSpecId = $model->time_spec_id;
- $reserveTimeRangeType = $model->reserve_time_range_type;
- if (!empty($tech_id) && empty($model->tech_id)) $model->tech_id = $tech_id;
- if ($model->order_status === OrderStatusEnum::SHIPMENTS) {
- // 预约商品订单支付后,直接变成已发货状态
- // 订单支付,时订单处于关闭状态的话,重新扣减可预约数量
- // 生成预约码
- // $model->reserve_code = date('YmdHis') . $model->id;
- if(empty($model->reserve_code)){
- if($order->clerk_code){
- $reserve_code = $order->clerk_code;
- $model->reserve_code = $reserve_code;
- }else{
- if($order->marketing_type!='SecondaryCard' && $order->order_source=='Reserve'){
- $model->reserve_code = self::getClerkCode($order['mall_id'],ClerkEnum::RESERVATION_SERVICE_CLERK_CODE_PRE);
- }
- }
- }
- if ($oldStatus === OrderStatusEnum::REPEAL) {
- self::handleTimeStock($timeId, $timeSpecId, $reserveTimeRangeType, $num * -1);
- }
- }
- if ($model->order_status === OrderStatusEnum::SING) {
- // 预约商品核销订单
- $model->reserve_status = self::RESERVE_STATUS_PENDDING;
- }
- if ($model->order_status === OrderStatusEnum::REPEAL) {
- // 订单关闭,归还可预约数量
- self::handleTimeStock($timeId, $timeSpecId, $reserveTimeRangeType, $num);
- }
- if ($model->order_status === OrderStatusEnum::ACCOMPLISH) {
- // 订单完成
- $model->reserve_status = self::RESERVE_STATUS_FINISH;
- }
- if (!empty($order['store_id'])) {
- $where = [
- ['mall_id' => $order['mall_id']],
- ['order_id' => $order->id],
- ['status' => StatusEnum::ENABLED],
- ['store_id' => $order['store_id']]
- ];
- $reservation_service_order_model = ReservationServiceOrder::getOne($where);
- if (!empty($reservation_service_order_model)) {
- if (empty($reservation_service_order_model['secondary_card_id'])) {
- $reservation_service_order_model->server_status = ReservationServiceEnum::COMPLETED;
- $reservation_service_order_model->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH;
- $reservation_service_order_model->save();
- } else {
- $secondary_card_model = SecondaryCard::find()->where(['id' => $reservation_service_order_model['secondary_card_id']])->one();
- if (!empty($secondary_card_model)) {
- if ($secondary_card_model['reservation_model'] == 2) {
- if (in_array($reservation_service_order_model->server_status, [ReservationServiceEnum::ARRIVED_AT_STORE, ReservationServiceEnum::ALREADY_BOOKED])) {
- $reservation_service_order_model->server_status = ReservationServiceEnum::TO_BE_ACCEPTED;
- $reservation_service_order_model->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER;
- $reservation_service_order_model->save();
- } elseif ($reservation_service_order_model->server_status == ReservationServiceEnum::TO_BE_ACCEPTED) {
- $reservation_service_order_model->server_status = ReservationServiceEnum::COMPLETED;
- $reservation_service_order_model->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH;
- $reservation_service_order_model->save();
- }
- } else if ($secondary_card_model['reservation_model'] == 1) {
- if ($reservation_service_order_model->service_status == ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER) {
- $reservation_service_order_model->server_status = ReservationServiceEnum::COMPLETED;
- $reservation_service_order_model->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH;
- $reservation_service_order_model->save();
- }
- }
- }
- }
- }
- }
- if (!$model->save()) throw new Exception($model->getErrorMessage());
- return true;
- }
- public static function handleTimeStock($timeId, $timeSpecId, $reserveTimeRangeType, $num)
- {
- $time = GoodsReserveTime::findOne($timeId);
- if (empty($time)) return;
- $time->stock += $num;
- $time->save();
- if ($reserveTimeRangeType == 2) {
- $timeSpec = GoodsReserveTimeSpec::findOne(['reserve_time_id' => $timeId, 'id' => $timeSpecId]);
- if (empty($timeSpec)) return;
- $timeSpec->stock += $num;
- $timeSpec->save();
- }
- }
- public static function getClerkCode($mall_id,$pre)
- {
- while (true) {
- $clerk_code = ClerkEnum::getCode($pre);
- $res = self::findOne(['mall_id' => $mall_id, 'reserve_code' => $clerk_code]);
- if (empty($res)) break;
- }
- if (empty($clerk_code)) throw new \Exception('核销码生成失败');
- return $clerk_code;
- }
- }
|