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' => '更新时间', 'create_type' => 'create_type', 'reservation_service_order_id' => 'reservation_service_order_id', ]; } /** * 预约商品订单处理 * @param [type] $order * @param [type] $form * @return void */ public static function create($order, $form, $main_order_id = 0) { try { $timeId = $form['data']['time_id'] ?? 0; $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'] ?? 0; $tech_id = $form['data']['tech_id'] ?? 0; $create_type = $form['data']['create_type'] ?? null; $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']; } } // 扣减时间或时间段的库存 $reserve = StoreGoodsReserve::findOne(['goods_id' => $goodsId]); if (empty($reserve)) throw new \Exception('找不到该预约商品' . __METHOD__); $reserveSku = StoreGoodsReserveSku::findOne(['id' => $skuId, 'goods_id' => $goodsId]); if (empty($reserveSku)) throw new \Exception('找不到该预约商品SKU'); $goods = StoreGoods::findOne(['id' => $goodsId]); // 预约模式(1按天预约 2按时间段预约) $reserveTimeRangeType = $reserveSku->reserve_time_range_type; // 家政 $service_start_at = 0; $service_end_at = 0; if ($reserve->reserve_type == StatusEnum::DISABLED) { // 预约时间处理 $time = GoodsReserveTime::findOne($timeId); if (empty($time)) throw new \Exception('找不到该预约时间日期' . __METHOD__); $date = $time->reserve_time; // 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 { $reserveDateTime = $form['data']['select_time']; $reserveTimeRangeType = 2; // 技师默认是按时间段预约的 if (!empty($reserveDateTime)) { $reserveDateTime .= ','.date('Y-m-d H:i', strtotime($reserveDateTime) + ($reserveSku->service_min * 60)); $reserve_date_time_arr = explode(',', $reserveDateTime); $service_start_at = strtotime($reserve_date_time_arr[0]); $service_end_at = strtotime($reserve_date_time_arr[1]); if (isset($create_type) && $create_type == 1) { if (!empty($reserve_date_time_arr) && !empty($tech_id)) { $res = StoreOrderReserve::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('该技师该时间已有预约'); } } $date = date('Y-m-d', $service_start_at); $start_time = strtotime($date . ' 00:00:00'); $end_time = strtotime($date . ' 23:59:59'); $counts = ReservationServiceOrder::find()->where( [ 'and', ['mall_id' => $reserveSku['mall_id']], ['store_id' => $reserveSku['store_id']], ['goods_reserve_sku_id' => $reserveSku['id']], ['!=', 'server_status', ReservationServiceEnum::CANCELED], ['>=', 'created_at', $start_time], ['<=', 'created_at', $end_time], ] )->count(); if (!empty($reserveSku->reserve_max_buy) && $reserveSku->reserve_max_buy <= $counts) { 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 { // 到店使用商品地址 - 使用门店地址 $store = Store::findOne(['id' => $order->store_id]); $province = $store->province_id; $city = $store->city_id; $area = $store->district_id; $address = $store->address; $lat = $store->latitude; $lng = $store->longitude; $regionName = ""; } if (empty($province) || empty($city) || empty($area) || empty($address) || empty($lat) || empty($lng)) { throw new \Exception('服务地址或定位信息错误'); } $model = new StoreOrderReserve(); $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->main_order_id = $main_order_id; $model->service_start_at = $service_start_at; $model->service_end_at = $service_end_at; $model->goods_id = $goodsId; $model->attr_id = $skuId; if (!$model->save()) throw new Exception($model->getErrorMessage()); return $model; } catch (Exception $e) { if (isset($trans)) $trans->rollback(); self::$static_error = $e->getMessage(); return false; } } /** * 同步订单状态 * @param [type] $order * @return void * @throws Exception */ public static function syncOrderStatus($order, $tech_id = 0) { $orderDetail = $order->detail[0]; $num = $orderDetail['num']; $model = self::findOne(['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 ($model->order_status === OrderStatusEnum::PAY) { // 预约商品订单支付后,直接变成已发货状态 // 订单支付,时订单处于关闭状态的话,重新扣减可预约数量 // 生成预约码 // $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 == OrderSourceEnum::SOURCE_STORE_RESERVE){ $model->reserve_code = OrderReserve::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 (!$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(); } } }