data = $data = is_array($form->data) ? $form->data : Json::decode($form->data, true); $skuId = $data['attr_id']; $timeId = $data['time_id'] ?? 0; //商品预约:时间ID $timeSpecId = $data['time_spec_id'] ?? 0;//商品预约:时间ID $buyNum = $data['num']; $serviceType = $data['service_type']; //服务类型 1上门 2到店 $address_id = $data['address_id']; $lat = $data['latitude']; $lng = $data['longitude']; $tech_id = $data['tech_id'] ?? 0 ; //项目服务预约:技师ID $select_time = $data['select_time'] ?? '' ; //项目服务预约:选择时间【2023-10-24 12:00】 if(empty($lat) || empty($lng)) throw new \Exception('请选择定位'); $form->data['order_source'] = OrderSourceEnum::SOURCE_RESERVE; $user = User::getOne([['id' => $form->user_id, 'mall_id' => $form->mall_id]]); if (empty($user)) throw new Exception('下单用户不存在'); if (!isset($data['num']) || (int)$data['num'] < 1) throw new Exception('请设置正确的下单数量'); $sku = GoodsReserveSku::getOne([['id' => $skuId, 'mall_id' => $form->mall_id]], true, ['goods', 'reserve', 'goods.extra']); if(empty($sku) || empty($sku['goods'])) throw new Exception('找不到产品信息或者产品已删除'); if (empty($sku['goods']['is_on_sale'])) throw new Exception('商品' . $sku['goods']['goods_name'] . '已下架! '); $goods = $sku['goods']; if($goods['goods_type'] != GoodsTypeEnum::GoodsTypeReserved) throw new Exception('商品类型错误'); if (!empty($sku['reserve'])) { !empty($sku['reserve_date']) && $sku['reserve_date'] = json_decode($sku['reserve_date'], true); !empty($sku['reserve_week']) && $sku['reserve_week'] = explode(',', $sku['reserve_week']); !empty($sku['reserve_time_slot']) && $sku['reserve_time_slot'] = json_decode($sku['reserve_time_slot'], true); !empty($sku['reserve_time_slot_price']) && $sku['reserve_time_slot_price'] = json_decode($sku['reserve_time_slot_price'], true); $reserve = &$sku['reserve']; !empty($reserve['reserve_date']) && $reserve['reserve_date'] = json_decode($reserve['reserve_date'], true); !empty($reserve['reserve_time_slot']) && $reserve['reserve_time_slot'] = json_decode($reserve['reserve_time_slot'], true); !empty($reserve['reserve_time_slot_price']) && $reserve['reserve_time_slot_price'] = json_decode($reserve['reserve_time_slot_price'], true); !empty($reserve['service_type']) && $reserve['service_type'] = json_decode($reserve['service_type'], true); !empty($reserve['reserve_week']) && $reserve['reserve_week'] = explode(',', $reserve['reserve_week']); } $goodsId = $sku['goods_id']; // 扣减时间或时间段的库存 $reserve = GoodsReserve::findOne(['goods_id' => $goodsId]); if (empty($reserve)) throw new \Exception('找不到该预约商品' . __METHOD__); $res = (new OrderService())->checkReserveFull($skuId, 0, $select_time); if ($res == false) { throw new \Exception('该商品预约已满'); } $reserve_type = $reserve['reserve_type']; //0商品预约,1项目服务预约 if($reserve_type){ //项目服务预约 只有在有选择技师的情况下才需要校验时间 if (!empty($tech_id)) $this->checkReservationService($sku,$tech_id,$select_time,$lat,$lng); $serviceType = StatusEnum::ENABLED; // 技师一定是上门服务 }else{ // 预约模式(1按天预约 2按时间段预约) $reserveTimeRangeType = $sku['reserve_time_range_type']; // 预约时间处理 $time = GoodsReserveTime::findOne($timeId); if (empty($time)) throw new \Exception('找不到该预约时间日期'); $date = $time->reserve_time; //if ($time->stock < $buyNum) throw new \Exception('该预约时间日期已超过最大预约数量'); 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 < $buyNum) throw new \Exception('该预约时间段已超过最大预约数量'); } // 仅限上门/创建订单 if($form->action == AppEnum::ACTION_CREATE && $form->data['service_type'] == StatusEnum::ENABLED) { $distance = bcmul((new LocationHelper())->getDistanceByGeo($reserve->lat, $reserve->lng, $form->data['latitude'], $form->data['longitude']), 0.001, 2); // 距离检测 if ($distance > $reserve->distance) throw new \Exception('超出项目服务范围,请重新选择'); } } if ($serviceType === 1 && $form->action == AppEnum::ACTION_CREATE) { //1上门 $address= UserAddress::findOne(['user_id'=>$form->user_id,'id'=> $address_id]); $province = $address->province_id; $city = $address->city_id; $district = $address->district_id; if (empty($province) || empty($city) || empty($district) || empty($address) || empty($lat) || empty($lng)) { throw new \Exception('服务地址或定位信息错误.'); } } // if ($buyNum > $sku['stock']) throw new Exception('商品' . $sku['goods']['goods_name'] . '超过可预约数量! '); $order_goods = new OrderDetail(); $order_goods = $order_goods->loadDefaultValues(); $order_goods->goods_id = $goodsId; $order_goods->goods_name = $sku['goods']['goods_name']; $order_goods->goods_attr_id = $sku['id']; $order_goods->sign_id = $sku['sign_id']; $order_goods->goods_attr_name = $sku['name']; $order_goods->num = $buyNum; $order_goods->cost_price = $sku['cost_price']; $order_goods->price = $sku['price']; $order_goods->goods_price = BcHelper::mul($order_goods->num, $order_goods->price); $order_goods->original_goods_price = $order_goods->goods_price; $order_goods->pic_url = !empty($sku['pic_url']) ? $sku['pic_url'] : $sku['goods']['cover_pic']; $order_goods->user_id = $form->user_id; $order_goods->mch_id = $sku['goods']['mch_id']; $order_goods->mall_id = $form->mall_id; $order_goods->marketing_type = $data['marketing_type'] ?? '0'; $order_goods->marketing_id = $data['marketing_id'] ?? 0; // 默认数据带下单数量方便计算 $goods = $sku['goods']; $goods['number'] = $buyNum; $form->order_goods[] = ArrayHelper::toArray($order_goods); // unset($sku['product']); $form->sku[$goodsId] = $sku; $form->user = $user; return $form; } catch (Exception $e) { $this->setError($e->getMessage()); return false; } } /** * 项目服务预约--检测 * @param $sku * @param $tech_id * @param $select_time * @param $lat * @param $lng * @return bool * @throws Exception */ private function checkReservationService($sku,$tech_id,$select_time,$lat,$lng) { $mall_id = $sku['mall_id']; if (!MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_RESERVATION_SERVICE)) { throw new \Exception('您还未安装当前插件'); } $time = strtotime($select_time); if($time <= time()) throw new \Exception('选择时间错误'); if(!$tech_id) throw new \Exception('请选择对应技师'); //检测技师 $check = TechniciansService::checkCanOrder($mall_id,$tech_id,$select_time,$sku['goods_id'],$sku['id'],$lat,$lng); if(!$check) throw new Exception(TechniciansService::getStaticError()); return true; } /** * 获取下单类型 * @Author bing * @DateTime 2021-09-23 09:48:45 * @copyright: Copyright (c) 2020 广东七件事集团 * @return string */ public static function getType(): string { return 'reserve_now'; } }