| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- <?php
- namespace addons\ReservationService\common\services;
- use addons\ReservationService\common\enums\ReservationServiceEnum;
- use addons\ReservationService\common\models\ReservationServiceGoods;
- use addons\ReservationService\common\models\ReservationServiceGoodsSetting;
- use addons\ReservationService\common\models\ReservationServiceLevel;
- use addons\ReservationService\common\models\ReservationServiceOccupy;
- use addons\ReservationService\common\models\ReservationServiceOrder;
- use addons\ReservationService\common\models\ReservationServiceStoreSecondaryCard;
- use addons\ReservationService\common\models\ReservationServiceUser;
- use addons\SecondaryCard\common\models\SecondaryCard;
- use common\enums\ClerkEnum;
- use common\enums\GoodsTypeEnum;
- use common\enums\OrderSourceEnum;
- use common\enums\StatusEnum;
- use common\models\goods\Goods;
- use common\models\goods\GoodsReserveSku;
- use common\models\mall\Mall;
- use common\models\order\Order;
- use common\models\order\OrderReserve;
- use common\models\user\User;
- use services\common\UserWalletService;
- use Yii;
- use yii\console\ExitCode;
- class ReservationServiceOrderService
- {
- public static function orderProcess(string $action, string $config_key, array $order_wheres = null) : int
- {
- $action_info_map = [
- 'complete' => [
- 'task_name' => '自动验收',
- 'time_radix' => 86400, // 时间节点计算的基数,订单自动自动过售后的时间单位是天,转换为秒的基数是86400
- 'method' => 'complete',
- 'time_field' => 'service_end_at',
- 'default' => 7, // 自动过售后默认时间 7 天
- ],
- ];
- try {
- $mall_list = Mall::getEnableMallList(true);
- $mall_ids = array_column($mall_list, 'id');
- if (empty($mall_ids)) {
- echo '没有可用商城,不做处理 ... ' . PHP_EOL;
- return ExitCode::UNSPECIFIED_ERROR;
- }
- foreach ($mall_ids as $mall_id) {
- // 订单自动处理时间
- $order_auto_handle_time = \Yii::$app->services->setting->mall->get($mall_id, $config_key);
- // 如果自动处理时间没有配置,则取默认值
- if (empty($order_auto_handle_time)) $order_auto_handle_time = $action_info_map[$action]['default'];
- // 订单自动处理时间节点,延后两分钟处理,避免支付回调尚未回来订单已经被取消s
- $time_node = time() - $order_auto_handle_time * $action_info_map[$action]['time_radix'] - 120;
- $time_field = $action_info_map[$action]['time_field'];
- $where = [
- 'and',
- ['mall_id' => $mall_id],
- ['<', $time_field, $time_node]
- ];
- if (!empty($order_wheres)) {
- foreach ($order_wheres as $order_where) {
- array_push($where, $order_where);
- }
- }
- foreach (ReservationServiceOrder::find()->where($where)->each(500) as $order) {
- var_dump($order['order_id']);
- $data = [];
- $data['id'] = $order['order_id'];
- $data['mall_id'] = $order['mall_id'];
- $data['user_id'] = $order['user_id'];
- $data['operator_id'] = 0;
- $data['operator_name'] = '';
- $data['from'] = OrderSourceEnum::SOURCE_RESERVE;
- Order::complete($data);
- }
- }
- return ExitCode::OK;
- } catch (\Exception $e) {
- echo ' 订单' . $action_info_map[$action]['task_name'] . ' 任务处理出错:' . $e->getMessage() . PHP_EOL;
- return ExitCode::UNSPECIFIED_ERROR;
- }
- }
- public static function getSkuList(int $mall_id)
- {
- $goods_list = Goods::lists([
- 'where' => [
- ['mall_id' => $mall_id],
- ['status' => StatusEnum::ENABLED],
- ['check_status' => StatusEnum::ENABLED],
- ['is_on_sale' => StatusEnum::ENABLED],
- ['goods_type' => GoodsTypeEnum::GoodsTypeReserved],
- ],
- 'select' => 'id,goods_name',
- 'index' => 'id'
- ]);
- $goods_ids = array_column($goods_list, 'id');
- $sku_list = GoodsReserveSku::lists([
- 'where' => [
- ['goods_id' => $goods_ids],
- ],
- 'select' => 'id,goods_id,service_min,name',
- ]);
- foreach ($sku_list as &$sku) {
- $sku['goods_name'] = $goods_list[$sku['goods_id']]['goods_name'] . ':' . $sku['name'];
- }
- return $sku_list;
- }
- public static function getReserveDay(int $mall_id)
- {
- $config = BackendService::getSetting($mall_id);
- $range_end = $config['range_end'];
- $range_end_arr = ReservationServiceEnum::RANGE_END_ARR_MAP;
- $days = $range_end_arr[$range_end] ?? 7;
- $day_arr = [];
- $time = strtotime(date('Y-m-d'));
- $end_time = $time + $days * 24 * 3600;
- for ($i = $time; $i < $end_time; $i += 24 * 60 * 60) {
- $day_arr[] = $i * 1000;;
- }
- return ['day_arr' => $day_arr];
- }
- /**
- * 后台添加预约/预约看板添加预约,获取可以预约的时间段
- * @param $params
- * @return array
- */
- public function getReserveTimes($params)
- {
- $date_time = strtotime($params['date']);
- $staff_user_id = $params['staff_user_id'] ?? 0;
- if (!empty($params['staff_user_id'])) {
- $scheduling = ReserveTechnicianScheduling::getOne([
- ['user_id' => $staff_user_id],
- ['date_time' => $date_time],
- ['status' => StatusEnum::ENABLED]
- ], true, ['schedulingTime']);
- if (empty($scheduling)) {
- return [];
- }
- }
- $buff = [];
- $sku = StoreGoodsReserveSku::findOne(['id' => $params['sku_id']]);
- $date_day = date('Y-m-d', strtotime($params['date']));
- $time = time();
- $service_min = $sku['service_min'];
- $obj = new StoreReserveSettingService(['mall_id' => $mall_id, 'store_id' => $this->store_id]);
- $store_reserve_setting = $obj->detail();
- if (strtotime(date('Y-m-d')) == $date_time) {
- $range_start_time = $obj->getRangeStartTime($store_reserve_setting['range_start']);
- $time += $range_start_time;
- }
- $reservation_service_order_list = ReservationServiceOrder::lists([
- 'where' => [
- ['mall_id' => $mall_id],
- ['store_id' => $this->store_id],
- ['staff_user_id' => $staff_user_id],
- ['>=', 'service_start_at', strtotime($date_day . ' 00:00:00')],
- ['<=', 'service_end_at', strtotime($date_day . ' 23:59:59')],
- ['!=', 'server_status', ReservationServiceEnum::CANCELED]
- ]
- ]);//已预约
- $reservation_service_order_arr = [];
- foreach ($reservation_service_order_list as $value) {
- $reservation_service_order_arr[$value['service_start_at']] = $value;
- }
- $occupy_list = ReservationServiceOccupy::lists([
- 'where' => [
- ['mall_id' => $mall_id],
- ['store_id' => $this->store_id],
- ['staff_user_id' => $staff_user_id],
- ['status' => StatusEnum::ENABLED]
- ]
- ]
- );//已占用时间
- if (!empty($staff_user_id)) {
- if (!empty($scheduling['is_all_day'])) {
- //全天
- $store = Store::findOne(['id' => $this->store_id]);
- $time1 = $date_day . " " . $store['business_time_start'] . ":00";
- $time2 = $date_day . " " . $store['business_time_end'] . ":59";
- $start = strtotime($time1);
- $end = strtotime($time2);
- $this->getBuff($start, $end, $service_min, $reservation_service_order_arr, $occupy_list, $time, $buff);
- } else {
- if (!empty($scheduling['schedulingTime'])) {
- foreach ($scheduling['schedulingTime'] as $val) {
- $start = $val['start_time'];
- $end = $val['end_time'];
- $this->getBuff($start, $end, $service_min, $reservation_service_order_arr, $occupy_list, $time, $buff);
- }
- }
- }
- } else {
- $store = Store::findOne(['id' => $this->store_id]);
- $time1 = $date_day . " " . $store['business_time_start'] . ":00";
- $time2 = $date_day . " " . $store['business_time_end'] . ":59";
- $start = strtotime($time1);
- $end = strtotime($time2);
- $this->getBuff($start, $end, $service_min, $reservation_service_order_arr, $occupy_list, $time, $buff);
- }
- return $buff;
- }
- public static function getReserveTime(int $mall_id)
- {
- $step = '00:01';
- $picker_options_time = [
- 'start' => "00:00",
- 'end' => "23:59",
- 'step' => $step,
- ];
- return ['picker_options_time' => $picker_options_time];
- }
- public static function getStaffUserList(int $mall_id, $params)
- {
- if (empty($params['goods_id'])) {
- $sku = GoodsReserveSku::findOne(['id' => $params['sku_id']]);
- if ($sku === null) throw new \Exception('商品不存在.');
- $goods_id = $sku['goods_id'];
- } else {
- $goods_id = $params['goods_id'];
- }
- $reservation_ervice_store_goods_list = ReservationServiceGoods::lists(['where' => [
- ['goods_id' => $goods_id],
- ['status' => StatusEnum::ENABLED],
- ['mall_id' => $mall_id]
- ]]);
- $user_ids = array_column($reservation_ervice_store_goods_list, 'user_id');
- $list = ReservationServiceUser::lists([
- 'where' => [
- ['mall_id' => $mall_id],
- ['user_id' => $user_ids],
- ['status' => StatusEnum::ENABLED]
- ],
- 'select' => 'user_id,name'
- ]);
- return $list;
- }
- public static function getUser(int $mall_id, $params)
- {
- $user = User::findOne(['mall_id' => $mall_id, 'mobile' => $params['mobile'], 'status' => [StatusEnum::ENABLED]]);
- $name = '';
- if ($user !== null) {
- if (!empty($user['nickname'])) {
- $name = $user['nickname'];
- } else {
- $name = $user['mobile'];
- }
- }
- return $name;
- }
- public static function getEditData(int $mall_id, $params)
- {
- $goods_list = Goods::lists([
- 'where' => [
- ['mall_id' => $mall_id],
- ['status' => StatusEnum::ENABLED],
- ['check_status' => StatusEnum::ENABLED],
- ['is_on_sale' => StatusEnum::ENABLED],
- ['goods_type' => GoodsTypeEnum::GoodsTypeReserved],
- ],
- 'select' => 'id,goods_name',
- 'with' => ['reserve' => function ($q) {
- $q->select('id,goods_id,service_min');
- }],
- ]);
- $config = BackendService::getSetting($mall_id);
- $ret['goods_list'] = $goods_list;
- $ret['range_start'] = $config['range_start'] ?? 1;
- $ret['range_end'] = $config['range_end'] ?? 1;
- $order = [];
- $goods_name = '';
- $service_type_arr = [];
- if (!empty($params['id'])) {
- $order = ReservationServiceOrder::getOne([
- ['id' => $params['id'], 'mall_id' => $mall_id]
- ],
- true
- );
- $user = User::findOne(['id' => $order['user_id']]);
- if ($user === null) throw new \Exception('用户不存在');
- $order['mobile'] = $user['mobile'];
- $order['nickname'] = !empty($user['nickname']) ? $user['nickname'] : $user['mobile'];
- $order['at_date'] = date('Y-m-d', $order['service_start_at']);
- $order['at_time'] = date('H:i', $order['service_start_at']);
- $params['goods_id'] = $order['goods_id'];
- $params['sku_id'] = $order['goods_reserve_sku_id'];
- $order['sku_id'] = $order['goods_reserve_sku_id'];
- if (empty($order['staff_user_id'])) {
- $order['staff_user_id'] = '';
- }
- if (empty($order['secondary_card_id'])) {
- $sku = GoodsReserveSku::findOne(['id' => $order['sku_id']]);
- if ($sku === null) throw new \Exception('商品不存在');
- if (empty($sku['name'])) {
- $store_goods = Goods::findOne(['id' => $order['goods_id']]);
- if ($store_goods === null) throw new \Exception('商品不存在!');
- $goods_name = $store_goods['goods_name'];
- } else {
- $goods_name = $sku['name'];
- }
- $ret['staff_user_list'] = self::getStaffUserList($mall_id, $params);
- $order['master'] = [
- ['sku_id' => $order['sku_id'], 'staff_user_id' => $order['staff_user_id'], 'service_min' => $sku['service_min'] ?? 0]
- ];
- } else {
- $params['secondary_card_id'] = $order['secondary_card_id'];
- $secondary_card = SecondaryCard::getOne([['id' => $order['secondary_card_id']]]);
- $goods_name = $secondary_card['name'] ?? '';
- $ret['staff_user_list'] = self::getStaffUserListBySecondaryCard($mall_id, $params);
- $order['master'] = [
- ['sku_id' => $order['secondary_card_id'], 'staff_user_id' => $order['staff_user_id'], 'service_min' => $secondary_card['appointment_interval_duration'] ?? 0]
- ];
- switch ($secondary_card['reservation_service_type']) {
- case 1:
- $service_type_arr[] = ['value' => 1, 'label' => '上门服务'];
- break;
- case 2:
- $service_type_arr[] = ['value' => 2, 'label' => '到店服务'];
- break;
- case 3:
- $service_type_arr[] = ['value' => 1, 'label' => '上门服务'];
- $service_type_arr[] = ['value' => 2, 'label' => '到店服务'];
- break;
- }
- }
- }
- $ret['service_type_arr'] = $service_type_arr;
- $ret['reserve_order'] = $order;
- $ret['goods_name'] = $goods_name;
- $store = $params['store'];
- $business_time_start = strtotime(date('Y-m-d') . ' ' . $store['business_time_start'] . ':00');
- $business_time_end = strtotime(date('Y-m-d') . ' ' . $store['business_time_end'] . ':00');
- $H = date('H', $business_time_start);
- $start_time = $H * 60;
- $H = date('H', $business_time_end);
- $minute = date('i', $business_time_end);
- $end_time = $H * 60 + $minute;
- $ret['start_time'] = $start_time;
- $ret['end_time'] = $end_time;
- return $ret;
- }
- public static function getStaffUserListBySecondaryCard(int $mall_id, $params)
- {
- $reservation_service_store_secondary_card_list = ReservationServiceStoreSecondaryCard::lists(['where' => [
- ['secondary_card_id' => $params['secondary_card_id']],
- ['status' => StatusEnum::ENABLED],
- ['mall_id' => $mall_id]
- ]]);
- $user_ids = array_column($reservation_service_store_secondary_card_list, 'user_id');
- return ReservationServiceUser::lists([
- 'where' => [
- ['mall_id' => $mall_id],
- ['user_id' => $user_ids],
- ['status' => StatusEnum::ENABLED]
- ],
- 'select' => 'user_id,name'
- ]);
- }
- /**
- * 后台添加预约
- * @param $params
- * @return array
- * @throws \yii\base\Exception
- * @throws \yii\db\Exception
- */
- public static function setEditData(int $mall_id, $params)
- {
- $t = Yii::$app->db->beginTransaction();
- try {
- $user = User::findOne(['mobile' => $params['mobile'], 'mall_id' => $mall_id]);
- if (!empty($user)) {
- if ($user['status'] != StatusEnum::ENABLED) {
- throw new \Exception('用户状态异常');
- } else {
- $params['user_id'] = $user['id'];
- }
- } else {
- //注册用户
- $user = self::setUser($mall_id, $params);
- $params['user_id'] = $user['id'];
- }
- $service_start_at = strtotime(date('Y-m-d', strtotime($params['at_date'])) . ' ' . $params['at_time'] . ':00');
- $config = BackendService::getSetting($mall_id);
- if (!empty($params['id'])) {
- $model = ReservationServiceOrder::findOne(['id' => $params['id'], 'mall_id' => $mall_id]);
- if ($model === null) {
- throw new \Exception('数据不存在');
- }
- $params['secondary_card_id'] = $model['secondary_card_id'];
- }
- $params['staff_user_id'] = !empty($params['master'][0]['staff_user_id']) ? $params['master'][0]['staff_user_id'] : 0;
- if (empty($params['secondary_card_id'])) {
- $params['sku_id'] = $params['master'][0]['sku_id'];;
- $store_goods_reserve_sku = GoodsReserveSku::findOne(['id' => $params['sku_id']]);
- if (empty($store_goods_reserve_sku)) {
- throw new \Exception('预约商品规格不存在');
- }
- $service_min = TechniciansService::getServiceMin(1, $store_goods_reserve_sku['service_min'] ?? 0);
- $goods_id = $store_goods_reserve_sku['goods_id'];
- } else {
- $secondary_card = SecondaryCard::getOne([['id' => $params['secondary_card_id']]]);
- $service_min = TechniciansService::getServiceMin(1, $secondary_card['appointment_interval_duration'] ?? 0);
- $goods_id = 0;
- $params['sku_id'] = 0;
- }
- $service_end_at = $service_start_at + $service_min * 60;
- self::checkEdit($params['staff_user_id'], $service_start_at, $service_end_at);
- if (!empty($params['create_type'])) {
- $update['create_type'] = $params['create_type'];
- }
- if (!empty($params['id'])) {
- if ($params['staff_user_id'] != $model['staff_user_id']) {
- $staff = ReservationServiceUser::findOne(['user_id' => $params['staff_user_id'], 'status' => StatusEnum::ENABLED]);
- }
- } else {
- throw new \Exception('预约订单不存在');
- }
- $model->user_id = $params['user_id'];
- $model->staff_user_id = $params['staff_user_id'];
- $model->goods_id = $goods_id;
- $model->service_start_at = $service_start_at;
- $model->service_end_at = $service_end_at;
- $model->reservation_model = $params['reservation_model'];
- $model->goods_reserve_sku_id = $params['sku_id'];
- $model->commission = self::calcCommission($mall_id, $params['staff_user_id'], $goods_id, $store_goods_reserve_sku['price'] ?? 0);
- $model->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_NORMAL;
- if (!empty($params['create_type'])) {
- $model->create_type = $params['create_type'];
- }
- if (!empty($params['service_type'])) {
- $model->service_type = $params['service_type'];
- }
- $res = $model->save();
- $reserve_date_time = date('Y-m-d H:i', $model->service_start_at) . ',' . date('Y-m-d H:i', $model->service_end_at);
- $update['reserve_date_time'] = $reserve_date_time;
- $update['service_start_at'] = $model->service_start_at;
- $update['service_end_at'] = $model->service_end_at;
- $update['service_type'] = $model->service_type;
- $update['reservation_service_order_id'] = $model['id'];
- $update['reserve_code'] = OrderReserve::getClerkCode($mall_id, ClerkEnum::RESERVATION_SERVICE_CLERK_CODE_PRE);
- if (isset($staff)) {
- $update['tech_id'] = $staff['id'];
- }
- unset($update['create_type']);
- OrderReserve::updateAll($update, ['order_id' => $model['order_id']]);
- // 核销码
- Order::updateAll(['clerk_code' => $update['reserve_code']], ['id' => $model->order_id]);
- if ($res == false) {
- throw new \Exception($model->getErrorMessage());
- }
- $t->commit();
- return ['id' => $model['id']];
- } catch (\Exception $e) {
- $t->rollBack();
- throw new \Exception($e->getMessage());
- }
- }
- public static function calcCommission(int $mall_id, $tech_id, $goods_id, $goods_price)
- {
- $staff = ReservationServiceUser::findOne(['mall_id' => $mall_id, 'user_id' => $tech_id,
- 'status' => StatusEnum::ENABLED, 'check_status' => ReservationServiceEnum::CHECK_ADOPT]);
- if ($staff === null) throw new \Exception('技师不存在');
- /**
- * @var $level ReservationServiceLevel
- */
- $level = $staff->getLevel()->andWhere(['mall_id' => $mall_id])->one();
- $commission = $level->item_commission;
- if (empty($level->item_commission_type)) {
- $commission = bcmul(bcmul($commission, $goods_price, 2), 0.01, 2);
- }
- /**
- * @var $goodsSetting ReservationServiceGoodsSetting
- */
- $goodsSetting = ReservationServiceGoodsSetting::getOne([
- ['mall_id' => $mall_id],
- ['status' => StatusEnum::ENABLED],
- ['item_id' => $goods_id],
- ['item_type' => 'goods'],
- ['is_enable' => StatusEnum::ENABLED],
- ['commission_type' => UserWalletService::WALLET_TYPE_COMMISSION]
- ]);
- if (!empty($goodsSetting)) {
- $commission = $goodsSetting->commission;
- if (!empty($goodsSetting->is_percent)) {
- $commission = bcmul(bcmul($commission, $goods_price, 2), 0.01, 2);
- }
- }
- if ($commission < 0) $commission = 0;
- return $commission;
- }
- /**
- * 注册用户
- * @param $params
- * @return bool|User
- * @throws \yii\base\Exception
- * @throws \yii\db\Exception
- */
- protected static function setUser(int $mall_id, $params)
- {
- $password = substr($params['mobile'], -6, 6);
- $params['mall_id'] = $mall_id;
- if (empty($params['username'])) {
- $params['username'] = $params['mobile'];
- }
- $params['parent_id'] = 0;
- $params['level'] = 0;
- $params['source'] = User::SOURCE_ADD_PLATFORM;
- $params['platform'] = User::TYPE_MANUAL;
- $params['password'] = Yii::$app->getSecurity()->generatePasswordHash($password);
- return User::setData($params);
- }
- /**
- * 检查该时间段是否被预约或者被占用
- * @param $staff_user_id
- * @param $service_start_at
- * @param $service_end_at
- * @param $reservation_service_order_id
- * @return void
- * @throws \Exception
- */
- protected static function checkEdit($staff_user_id, $service_start_at, $service_end_at, $reservation_service_order_id = null, $create_type = 2)
- {
- $list = ReservationServiceOccupy::lists([
- 'where' => [
- ['staff_user_id' => $staff_user_id],
- ['status' => StatusEnum::ENABLED],
- ]
- ]);
- foreach ($list as $item) {
- if ($service_start_at >= $item['start_at'] && $service_start_at < $item['end_at']) {
- throw new \Exception('该时间段已被占用');
- }
- if ($service_end_at >= $item['start_at'] && $service_end_at < $item['end_at']) {
- throw new \Exception('该时间段已被占用');
- }
- }
- }
- }
|