$params['mall_id']]; $params['where'][] = ['sco.status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]; $params['where'][] = ['>', 'sco.open_time', 0]; if (!empty($params['open_type'])) { $params['where'][] = ['sco.open_type' => $params['open_type']]; } if (!empty($params['order_no'])) { $params['where'][] = ['like', 'sco.order_no', trim($params['order_no'])]; } if (!empty($params['user_id'])) { $params['where'][] = ['sco.user_id' => trim($params['user_id'])]; } if (!empty($params['secondary_card_name'])) { $secondary_card_list = SecondaryCard::lists([ 'where' => [ ['like', 'name', trim($params['secondary_card_name'])], ['mall_id' => $params['mall_id']] ] ]); $params['where'][] = ['sco.secondary_card_id' => array_column($secondary_card_list, 'id')]; } if (!empty($params['secondary_card_id'])) { $params['where'][] = ['sco.secondary_card_id' => $params['secondary_card_id']]; } if (!empty($params['date_time'][0])) { $params['where'][] = ['>=', 'sco.created_at', strtotime($params['date_time'][0])]; } if (!empty($params['date_time'][1])) { $params['where'][] = ['<=', 'sco.created_at', strtotime($params['date_time'][1])]; } if (!empty($params['create_source_id'])) { $params['where'][] = [ 'or', ['sco.use_type' => 0], ['scrs.store_id' => $params['create_source_id'], 'scrs.store_type' => $params['store_type']] ]; $params['join'] = [['left join', SecondaryCardRelateStore::tableName() . ' as scrs', 'sco.secondary_card_id = scrs.secondary_card_id']]; } $params['order'] = 'sco.id DESC'; $params['with'] = ['user', 'secondaryCard']; if (!empty($params['sort_column']) && !empty($params['sort_order'])) { $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc'; $params['order'] = 'sco.' . $params['sort_column'] . ' ' . $sort_order; } $params['alias'] = 'sco'; $pageData = SecondaryCardOrder::listPage($params, false); if (!empty($pageData['list'])) { foreach ($pageData['list'] as &$item) { $item['nickname'] = $item['user']['nickname'] ?? ''; $item['avatar_url'] = $item['user']['avatar_url'] ?? ''; $item['mobile'] = $item['user']['mobile'] ?? ''; unset($item['user']); } } $pageData['export_list'] = SecondaryCardOrder::getExportFields(); return $pageData; } public static function getMySecondaryCard($params) { $params['where'][] = ['mall_id' => $params['mall_id']]; $params['where'][] = ['user_id' => $params['user_id']]; $params['where'][] = ['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]; $params['where'][] = ['>', 'open_time', 0]; if (isset($params['order_status'])) { $order_status[] = $params['order_status']; if ($params['order_status'] == 1) { $order_status[] = 3; } $params['where'][] = ['order_status' => $order_status]; } $params['order'] = 'id DESC'; $params['with'] = [ 'secondaryCard' => function ($query) { $query->select('id,name,background,background_type,font_color,reservation_type,reservation_model,reservation_cancel_deduct,reservation_cancel_type,reservation_service_type'); }]; $params['select'] = 'id,secondary_card_id,order_no,verifiable_times,start_time,expire_time as end_time,order_status,clerk_code'; $pageData = SecondaryCardOrder::listPage($params, false); if (!empty($pageData['list'])) { $secondary_card_order_ids = array_column($pageData['list'], 'id'); $where = [ ['marketing_id' => $secondary_card_order_ids], ['marketing_type' => 'SecondaryCard'], ['order_source' => 'Reserve'], ]; $order_list = Order::lists([ 'where' => $where, 'order' => 'id desc' ]); $order_arr = []; $order_ids = []; foreach ($order_list as $val) { if (isset($order_arr[$val['marketing_id']])) { continue; } $order_arr[$val['marketing_id']] = $val; $order_ids[] = $val['id']; } $where = [ ['order_id' => $order_ids], ['!=', 'service_status', ReservationServiceEnum::RESERVE_ORDER_STATUS_CLOSED], ['!=', 'server_status', ReservationServiceEnum::CANCELED], ]; $reservation_service_order_list = ReservationServiceOrder::lists([ 'where' => $where, 'index' => 'order_id' ]); foreach ($pageData['list'] as &$item) { $item['end_time_u'] = $item['end_time']; $item['start_time'] = date('Y-m-d', $item['start_time']); $item['end_time'] = date('Y-m-d', $item['end_time']); if ($item['secondaryCard']['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { if (!MallAddons::isInstall($params['mall_id'], 'ReservationService')) { throw new \Exception('没有安装预约服务插件'); } $item['reservation']['reservation_service_order_id'] = 0; $item['reservation']['service_status'] = 0; $item['reservation']['remark'] = ''; $item['reservation']['main_order_id'] = 0; $item['reservation']['service_start_at'] = ''; $item['reservation']['service_end_at'] = ''; if (!isset($order_arr[$item['id']])) { continue; } $order = $order_arr[$item['id']]; if (!isset($reservation_service_order_list[$order['id']])) { continue; } $reservation_service_order = $reservation_service_order_list[$order['id']]; $item['reservation']['reservation_service_order_id'] = $reservation_service_order['id']; $item['reservation']['service_status'] = $reservation_service_order['service_status']; $item['reservation']['remark'] = $reservation_service_order['remark']; $item['reservation']['main_order_id'] = $reservation_service_order['order_id']; $item['reservation']['service_start_at'] = date('Y-m-d H:i', $reservation_service_order['service_start_at']); $item['reservation']['service_end_at'] = date('Y-m-d H:i', $reservation_service_order['service_end_at']); } } } return $pageData; } /** * 生成次卡订单 * @Author:hua * @Date:2024-03-08 18:23 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return array */ public static function createOrder($params) { $id = $params['secondary_card_id']; $lock_key = RedisKeyEnum::suffix(SecondaryCardEnum::LOCK_SECONDARY_CARD, $id); $identification = uniqid(); try { if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new \Exception('正在关闭订单'); $mall_id = $params['mall_id']; $user_id = $params['user_id']; $secondary_card = SecondaryCard::getOne([['id' => $id, 'mall_id' => $mall_id]], false); if (empty($secondary_card)) throw new \Exception('次卡不存在'); if (empty($secondary_card['is_on_sales'])) throw new \Exception('次卡已下架'); $time = time(); if (!empty($secondary_card['sell_time_start']) && $time < $secondary_card['sell_time_start']) { throw new \Exception('次卡售卖时间还没开始'); } if (!empty($secondary_card['sell_time_end']) && $time > $secondary_card['sell_time_end']) { $secondary_card->is_on_sales = 0; $secondary_card->save(); throw new \Exception('次卡售卖时间已结束'); } if ($secondary_card['expire_type'] == SecondaryCardEnum::EXPIRE_TYPE_APPOINT) { if (strtotime($secondary_card['end_at'] . ' 23:59:59') <= $secondary_card['sell_time_start']) { throw new \Exception('次卡的有效期结束时间小于次卡售卖的开始时间'); } } if ($secondary_card['max_times'] <= 0) { $secondary_card->is_on_sales = 0; $secondary_card->save(); throw new \Exception('次卡库存不足'); } if ($secondary_card['expire_type'] == 2) { $end_time = strtotime($secondary_card['end_at'] . ' 23:59:59'); if ($time > $end_time) { $secondary_card->is_on_sales = 0; $secondary_card->save(); throw new \Exception('该次卡已过有效期'); } } if ($secondary_card['limit_type'] == SecondaryCardEnum::LIMIT_YES) { $query = SecondaryCardOrder::find()->where(['mall_id' => $mall_id, 'user_id' => $user_id, 'secondary_card_id' => $id, 'open_type' => SecondaryCardEnum::OPEN_TYPE_BUY]) ->andWhere(['>', 'pay_type', 0]) ->andWhere(['>', 'open_time', 0]); $counts = $query->count(); if (!empty($secondary_card['limit_times']) && $counts >= $secondary_card['limit_times']) { throw new \Exception('每人只能限开' . $secondary_card['limit_times'] . '张'); } } $order_no = SecondaryCardOrder::getOrderNo(); if ($order_no == false) { throw new \Exception('生成卡号失败'); } $params['order_no'] = $order_no; $params['clerk_code'] = self::getClerkCode($mall_id); $params['open_type'] = SecondaryCardEnum::OPEN_TYPE_BUY; $params['pay_money'] = $secondary_card['price']; $params['start_time'] = self::getStartTime($secondary_card['expire_type'], $time, $secondary_card['begin_at']); $params['expire_time'] = self::getExpireTime($secondary_card['expire_type'], $time, $secondary_card['end_at'], $secondary_card['expire_day']); $params['verifiable_times'] = $secondary_card['verifiable_times']; $params['use_type'] = $secondary_card['use_type']; $params['create_source_type'] = $secondary_card['create_source_type']; $params['create_source_id'] = $secondary_card['create_source_id']; $model = SecondaryCardOrder::setData($params); $order_trade_info[] = [ 'order_id' => $model->id, 'order_type' => 'secondary_card_order', 'order_no' => $model->order_no, 'amount' => $secondary_card['price'], 'title' => self::getOrderTitle($secondary_card['name']), 'notify_class' => 'addons\SecondaryCard\common\logic\notify\Notify', ]; $res = \Yii::$app->services->pay->createTrade($mall_id, $user_id, $order_trade_info); if ($res == false) throw new \Exception('生成支付流水失败'); $model->trade_id = $res['trade_id']; $model->save(); $arr['transaction'] = $res; $arr['pay_success_page'] = \Yii::$app->services->setting->mall->get($mall_id, 'order.pay_after_link');// 支付成功后跳转的地址 $arr['order_id'] = $model->id; LockHelper::uLock($lock_key, $identification); return $arr; } catch (\Exception $e) { LockHelper::uLock($lock_key, $identification); throw new \Exception($e->getMessage()); } } public static function getClerkCode($mall_id) { while (true) { $clerk_code = ClerkEnum::getCode(ClerkEnum::SECONDARY_CARD_CLERK_CODE_PRE); $res = SecondaryCardOrder::findOne(['mall_id' => $mall_id, 'clerk_code' => $clerk_code, 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); if (empty($res)) break; } if (empty($clerk_code)) throw new \Exception('核销码生成失败'); return $clerk_code; } public static function getOrderTitle($title) { return mb_strlen($title) > 32 ? mb_substr($title, 0, 32) : $title; } /** * 支付后的处理 * @Author:hua * @Date:2024-03-08 11:33 * @Copyright:copyright(c)2024 广东七件事集团 * @param SecondaryCardOrder $order * @param $pay_type * @return bool */ public static function pay(SecondaryCardOrder $order, $pay_type) { if ($order->open_time > 0) throw new \Exception('订单已被处理'); $secondary_card_model = SecondaryCard::findOne(['id' => $order['secondary_card_id']]); if (!empty($secondary_card_model)) { $secondary_card_model->max_times -= 1; if ($secondary_card_model->max_times < 0) { $secondary_card_model->max_times = 0; $secondary_card_model->is_on_sales = 0; } $secondary_card_model->total_sales += 1; $secondary_card_model->total_sales_price += $order->pay_money; $secondary_card_model->save(); } $order->order_status = 0; $order->pay_type = $pay_type; $order->open_time = time(); if ($secondary_card_model['expire_type'] == SecondaryCardEnum::EXPIRE_TYPE_BUY) { $order->start_time = time(); } $res = $order->save(); if (empty($res)) throw new \Exception('更新次卡订单表失败'); return true; } public static function getExpireTime($expire_type, $time, $end_at, $expire_day) { $expire_time = 0; switch ($expire_type) { case SecondaryCardEnum::EXPIRE_TYPE_BUY: $expire_time = $time + 3600 * 24 * $expire_day; break; case SecondaryCardEnum::EXPIRE_TYPE_APPOINT: $expire_time = strtotime($end_at . ' 23:59:59'); break; } return $expire_time; } public static function getStartTime($expire_type, $time, $begin_at) { $start_time = 0; switch ($expire_type) { case SecondaryCardEnum::EXPIRE_TYPE_BUY: $start_time = $time; break; case SecondaryCardEnum::EXPIRE_TYPE_APPOINT: $start_time = strtotime($begin_at . ' 00:00:00'); break; } return $start_time; } public static function getMySecondaryCardDetailByH5($params) { $secondary_card_order = SecondaryCardOrder::findOne(['id' => $params['id'], 'mall_id' => $params['mall_id'], 'user_id' => $params['user_id']]); $params['id'] = $secondary_card_order['secondary_card_id']; $select = 'id,name,price,original_price,virtual_sales,total_sales,service,rule,expire_type,begin_at,end_at,expire_day,store_type,use_type,reservation_type,reservation_model, reservation_cancel_type,reservation_cancel_hour,reservation_cancel_deduct,background,font_color,refund_type,background_type,reservation_service_type'; $params['select'] = $select; $detail = SecondaryCardService::getDetailByH5($params); // $detail['clerk_code'] = $secondary_card_order['clerk_code']; // $detail['order_no'] = (string)$secondary_card_order['order_no']; $detail['verifiable_times'] = $secondary_card_order['verifiable_times']; $detail['secondary_card_id'] = $secondary_card_order['secondary_card_id']; unset($detail['price']); unset($detail['original_price']); unset($detail['virtual_sales']); unset($detail['total_sales']); unset($detail['store_type']); unset($detail['use_type']); //todo $where = [ 'marketing_id' => $secondary_card_order['id'], 'marketing_type' => 'SecondaryCard', 'order_source' => 'Reserve', // 'status' => StatusEnum::ENABLED ]; $order = Order::find()->where($where)->orderBy('id desc')->one(); if ($detail['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { if (!MallAddons::isInstall($params['mall_id'], 'ReservationService')) { throw new \Exception('没有安装预约服务插件'); } } if (!empty($order)) { $reservation_service_order = ReservationServiceOrder::find()->where(['order_id' => $order['id']]) ->andWhere(['!=', 'service_status', ReservationServiceEnum::RESERVE_ORDER_STATUS_CLOSED]) ->andWhere(['!=', 'server_status', ReservationServiceEnum::CANCELED])->one(); } $service_start_at = 0; $service_end_at = 0; $name = 0; $reservation_service_order_id = 0; $main_order_id = 0; if (!empty($reservation_service_order)) { $reservation_service_order_id = $reservation_service_order['id']; $main_order_id = $reservation_service_order['order_id']; $service_start_at = $reservation_service_order['service_start_at']; $service_end_at = $reservation_service_order['service_end_at']; $store = Store::findOne(['id' => $reservation_service_order['store_id']]); $name = $store['store_name']; if ($reservation_service_order['staff_user_id']) { $reservation_service_user = ReservationServiceUser::findOne(['user_id' => $reservation_service_order['staff_user_id'], 'status' => StatusEnum::ENABLED]); $name = $reservation_service_user['name'] ?? ''; } } $data['id'] = $secondary_card_order['id']; $data['secondaryCard'] = $detail; $data['reservation'] = [ 'reservation_service_order_id' => $reservation_service_order_id, 'main_order_id' => $main_order_id, 'name' => $name, 'service_start_at' => date('Y-m-d H:i', $service_start_at), 'service_end_at' => date('Y-m-d H:i', $service_end_at), 'service_status' => $reservation_service_order['service_status'], 'remark' => $reservation_service_order['remark'], ]; $data['status'] = $reservation_service_order['service_status'] ?? -1; $data['order_status'] = $secondary_card_order['order_status']; $data['open_type'] = $secondary_card_order['open_type']; $data['end_time_u'] = $secondary_card_order['expire_time']; $data['pay_money'] = $secondary_card_order['pay_money']; $data['order_no'] = $secondary_card_order['order_no']; $data['clerk_code'] = $secondary_card_order['clerk_code']; $data['verifiable_times'] = $secondary_card_order['verifiable_times']; $data['start_time'] = date('Y-m-d', $secondary_card_order['start_time']); $data['end_time'] = date('Y-m-d', $secondary_card_order['expire_time']); return $data; } /** * 获取个人次卡数量 * @Author:hua * @Date:2024-02-29 18:12 * @Copyright:copyright(c)2024 广东七件事集团 * @param $mall_id * @param $user_id * @param $secondary_card_id * @return bool|int|string */ public static function getMySecondaryCardCounts($mall_id, $user_id, $secondary_card_id) { $counts = SecondaryCardOrder::find() ->where([ 'mall_id' => $mall_id, 'user_id' => $user_id, 'secondary_card_id' => $secondary_card_id, 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED], 'order_status' => [SecondaryCardEnum::WAIT_VERIFIED, SecondaryCardEnum::STOPPED] ]) ->andWhere(['>', 'open_time', 0]) ->count(); return $counts ?? 0; } public static function exportHandle($data) { $download_id = $data['download_id'] ?? 0; $download = Download::findOne(['id' => $download_id]); if ($download) { try { $params = json_decode($download->params, true); $filename = $download->name; $type = $download->type; $fields = $params['fields']; $fields_arr = SecondaryCardOrder::getExportFields(); $have_select_field_arr = []; foreach ($fields as $value) { $have_select_field_arr[] = $fields_arr[$value]; } $csv = new CsvTool(); $csv->filename = $filename; $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type); $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC; $csv->header = $have_select_field_arr; $model = SecondaryCardOrder::find(); $model->where(['sco.mall_id' => $params['mall_id'], 'sco.status' => StatusEnum::ENABLED]) ->andWhere(['>', 'sco.open_time', 0]); if (!empty($params['open_type'])) { $model->andWhere(['sco.open_type' => $params['open_type']]); } if (!empty($params['order_no'])) { $model->andWhere(['like', 'sco.order_no', $params['order_no']]); } if (!empty($params['secondary_card_name'])) { $secondary_card_list = SecondaryCard::lists([ 'where' => [ ['like', 'name', trim($params['secondary_card_name'])], ['mall_id' => $params['mall_id']] ] ]); $model->andWhere(['sco.secondary_card_id' => array_column($secondary_card_list, 'id')]); } if (!empty($params['secondary_card_id'])) { $model->andWhere(['sco.secondary_card_id' => $params['secondary_card_id']]); } if (!empty($params['date_time'][0])) { $model->andWhere(['>=', 'sco.created_at', strtotime($params['date_time'][0])]); } if (!empty($params['date_time'][1])) { $model->andWhere(['<=', 'sco.created_at', strtotime($params['date_time'][1])]); } if (!empty($params['create_source_id'])) { $model->andWhere([ 'or', ['sco.use_type' => SecondaryCardEnum::USE_TYPE_ALL], ['scrs.store_id' => $params['create_source_id'], 'scrs.store_type' => $params['store_type']] ]); $model->leftJoin(SecondaryCardRelateStore::tableName() . ' as scrs', 'sco.secondary_card_id = scrs.secondary_card_id'); } $model->with(['user']); $model->orderBy('sco.id DESC'); if (!empty($params['sort_column']) && !empty($params['sort_order'])) { $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc'; $model->orderBy('sco.' . $params['sort_column'] . ' ' . $sort_order); } $model->alias('sco'); $order_status_map = SecondaryCardEnum::getOrderStatusMap(); $order_type_map = SecondaryCardEnum::getOpenTypeMap(); foreach ($model->batch() as $list) { $csv->data = array_map(function ($order) use ($fields, $order_status_map, $order_type_map) { $row = []; //遍历所选字段 foreach ($fields as $field) { if (in_array($field, ['open_time', 'expire_time', 'refund_time'])) { $row[] = !empty($order[$field]) ? date('Y-m-d H:i:s', $order[$field]) : ''; } elseif (in_array($field, ['order_status'])) { $row[] = $order_status_map[$order['order_status']] ?? ''; } elseif (in_array($field, ['nickname'])) { $row[] = $order['user']['nickname'] ?? ''; } elseif (in_array($field, ['open_type'])) { $row[] = $order_type_map[$order['open_type']] ?? ''; } else { $row[] = !empty($order[$field]) ? $order[$field] : ''; } } return $row; }, $list); $csv->export(); } $csv->updateDown($download, $params['mall_id']); return true; } catch (\Exception $e) { $download->status = 3; $res = $download->save(); self::setStaticError($e->getMessage()); return false; } } } public static function exportHandleSync($data) { try { $params = $data; $fields = $data['fields']; $fields_arr = SecondaryCardOrder::getExportFields(); $have_select_field_arr = []; $post_fields_arr = explode(',', $fields); foreach ($post_fields_arr as $value) { $have_select_field_arr[] = $fields_arr[$value]; } $csv = new CsvTool(); $csv->export_mode = $data['export_mode']; $csv->filename = $data['filename']; $csv->export_mode = $data['export_mode']; $csv->header = $have_select_field_arr; $model = SecondaryCardOrder::find(); $model->where(['sco.mall_id' => $params['mall_id'], 'sco.status' => StatusEnum::ENABLED]) ->andWhere(['>', 'sco.open_time', 0]); if (!empty($params['open_type'])) { $model->andWhere(['sco.open_type' => $params['open_type']]); } if (!empty($params['order_no'])) { $model->andWhere(['sco.order_no' => $params['order_no']]); } if (!empty($params['secondary_card_name'])) { $secondary_card_list = SecondaryCard::lists([ 'where' => [ ['like', 'name', trim($params['secondary_card_name'])], ['mall_id' => $params['mall_id']] ] ]); $model->andWhere(['sco.secondary_card_id' => array_column($secondary_card_list, 'id')]); } if (!empty($params['date_time'][0])) { $model->andWhere(['>=', 'sco.created_at', strtotime($params['date_time'][0])]); } if (!empty($params['date_time'][1])) { $model->andWhere(['<=', 'sco.created_at', strtotime($params['date_time'][1])]); } if (!empty($params['create_source_id'])) { $model->andWhere([ 'or', ['sco.use_type' => SecondaryCardEnum::USE_TYPE_ALL], ['scrs.store_id' => $params['create_source_id'], 'scrs.store_type' => $params['store_type']] ]); $model->leftJoin(SecondaryCardRelateStore::tableName() . ' as scrs', 'sco.secondary_card_id = scrs.secondary_card_id'); } $model->with(['user']); $model->orderBy('sco.id DESC'); if (!empty($params['sort_column']) && !empty($params['sort_order'])) { $sort_order = $params['sort_order'] == 'ascending' ? 'asc' : 'desc'; $model->orderBy('sco.' . $params['sort_column'] . ' ' . $sort_order); } $model->alias('sco'); $order_status_map = SecondaryCardEnum::getOrderStatusMap(); $order_type_map = SecondaryCardEnum::getOpenTypeMap(); $list = $model->all(); foreach ($list as $order) { $row = []; foreach ($post_fields_arr as $field) { if (in_array($field, ['open_time', 'expire_time', 'refund_time'])) { $row[] = !empty($order[$field]) ? date('Y-m-d H:i:s', $order[$field]) : ''; } elseif (in_array($field, ['order_status'])) { $row[] = $order_status_map[$order['order_status']] ?? ''; } elseif (in_array($field, ['nickname'])) { $row[] = $order['user']['nickname'] ?? ''; } elseif (in_array($field, ['open_type'])) { $row[] = $order_type_map[$order['open_type']] ?? ''; } else { $row[] = !empty($order[$field]) ? $order[$field] : ''; } } $data[] = $row; } $csv->data = $data; $res = $csv->export(); return true; } catch (\Exception $e) { self::setStaticError($e->getMessage()); return false; } } public static function changeOrderStatus($id, $mall_id, $order_status) { $secondary_card_order = SecondaryCardOrder::findOne(['id' => $id, 'mall_id' => $mall_id, 'status' => [StatusEnum::ENABLED]]); if (empty($secondary_card_order)) { throw new \Exception('记录不存在'); } $secondary_card = $secondary_card_order['secondaryCard']; if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES && $order_status == 4) { if (!MallAddons::isInstall($mall_id, 'ReservationService')) { throw new \Exception('请先安装预约服务插件'); } $res = ReservationServiceOrder::find()->where([ 'secondary_card_no' => $secondary_card_order['order_no'], 'service_status' => [ ReservationServiceEnum::RESERVE_ORDER_STATUS_NORMAL, ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING, ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER, ], ])->one(); if (!empty($res)) { throw new \Exception('该次卡有预约服务,不允许停卡'); } } $secondary_card_order->order_status = $order_status; return $secondary_card_order->save(); } /** * 次卡预约 * @Author:hua * @Date:2024-03-05 10:23 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return bool */ public static function secondaryCardReserve($params) { $t = \Yii::$app->db->beginTransaction(); try { $order_no = $params['secondary_card_no']; $mall_id = $params['mall_id']; $user_id = $params['user_id']; $store_id = 0; $staff_user_id = 0; $secondary_card_order = SecondaryCardOrder::getOne([['order_no' => $order_no, 'mall_id' => $mall_id, 'user_id' => $user_id]], true, ['secondaryCard']); $time = time(); if (empty($secondary_card_order['verifiable_times'])) { throw new \Exception('可核销次数已用完'); } if ($secondary_card_order['start_time'] > $time) { throw new \Exception('该次卡还未生效'); } if ($secondary_card_order['expire_time'] < $time) { throw new \Exception('该次卡已过期'); } if (!empty($secondary_card_order['order_status'])) { throw new \Exception('非待核销卡不能预约'); } if ($secondary_card_order['secondaryCard']['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_NO) { throw new \Exception('该次卡不需要预约'); } $start_at = strtotime($params['select_time']); $service_end_at = $start_at + ($secondary_card_order['secondaryCard']['appointment_interval_duration'] * 60); $time = time(); $select_time = strtotime($params['select_time']); if ($select_time < $time) { throw new \Exception('预约时间小于当前时间!'); } // $date = date('Y-m-d', $select_time); // if ($date == date('Y-m-d', $time)) { // if (($select_time - $time) < 3600) { // throw new \Exception('需提前1小时预约!'); // } // } $start = strtotime(date('Y-m-d', $time) . ' 00:00:00'); $end = strtotime(date('Y-m-d', $time) . ' 23:59:59'); if ($secondary_card_order['secondaryCard']['reservation_limit_repeat'] > 0) { $cancel_counts = ReservationServiceOrder::find() ->where(['mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::DISABLED, 'secondary_card_id' => $secondary_card_order['secondaryCard']['id']]) ->andWhere(['>=', 'created_at', $start]) ->andWhere(['<=', 'created_at', $end]) ->count(); if ($cancel_counts >= $secondary_card_order['secondaryCard']['reservation_limit_repeat']) { throw new \Exception('您的预约次数已达上限,无法再预约,请明日再试!'); } } $reservation_service_order = ReservationServiceOrder::find() ->where(['mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED, 'secondary_card_no' => $secondary_card_order['order_no'], 'service_status' => [ReservationServiceEnum::RESERVE_ORDER_STATUS_NORMAL, ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING]]) ->one(); if (!empty($reservation_service_order)) { throw new \Exception('您已预约了' . date('Y-m-d H:i', $reservation_service_order['service_start_at']) . '-' . date('H:i', $reservation_service_order['service_end_at'])); } switch ($secondary_card_order['secondaryCard']['reservation_model']) { case 1: if (empty($params['store_id'])) { throw new \Exception('门店id不能为空'); } $store_id = $params['store_id']; if ($secondary_card_order['secondaryCard']['reservation_limit_people'] > 0) { $counts = ReservationServiceOrder::find() ->where(['mall_id' => $mall_id, 'staff_user_id' => 0, 'status' => StatusEnum::ENABLED, 'service_status' => [ ReservationServiceEnum::RESERVE_ORDER_STATUS_NORMAL, ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING, ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER, ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH, ], 'secondary_card_id' => $secondary_card_order['secondaryCard']['id']]) ->andWhere(['>=', 'service_start_at', $start_at]) ->andWhere(['<=', 'service_end_at', $service_end_at]) ->count(); if ($counts >= $secondary_card_order['secondaryCard']['reservation_limit_people']) { throw new \Exception('该时间段已约满,请约去其他时间段!'); } } break; case 2: $employee_selection = SecondaryCardService::getEmployeeSelection($params['mall_id'], $params['store_id']);//技师必选 if ($employee_selection == 2 && empty($params['tech_id'])) { throw new \Exception('技师id不能为空'); } if (!empty($params['tech_id'])) {//门店分配时,不需要校验 $staff = ReservationServiceUser::findOne(['mall_id' => $params['mall_id'], 'id' => $params['tech_id'], 'status' => StatusEnum::ENABLED, 'check_status' => ReservationServiceEnum::CHECK_ADOPT]); if (empty($staff)) throw new \Exception('技师不存在'); $store_id = $staff['store_id']; $staff_user_id = $staff['user_id']; } else { $store_id = $params['store_id']; } if ($secondary_card_order['secondaryCard']['reservation_limit_people'] > 0) { $counts = ReservationServiceOrder::find() ->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'service_status' => [ ReservationServiceEnum::RESERVE_ORDER_STATUS_NORMAL, ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING, ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER, ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH, ], 'secondary_card_id' => $secondary_card_order['secondaryCard']['id']]) ->andWhere(['!=', 'staff_user_id', 0]) ->andWhere(['>=', 'service_start_at', $start_at]) ->andWhere(['<=', 'service_end_at', $service_end_at]) ->count(); if ($counts >= $secondary_card_order['secondaryCard']['reservation_limit_people']) { throw new \Exception('该时间段已约满,请约去其他时间段!'); } } break; } $params['store_id'] = $store_id; $params['staff_user_id'] = $staff_user_id; $params['start_at'] = $start_at; $params['service_end_at'] = $service_end_at; list($order, $order_detail_id) = self::createReserveOrder($params); $t->commit(); return true; } catch (\Exception $e) { $t->rollBack(); return $e->getMessage(); } } /** * 生成预约单 * @Author:hua * @Date:2024-03-05 11:05 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return array */ public static function createReserveOrder($params) { $mall_id = $params['mall_id']; $user_id = $params['user_id']; $secondary_card_no = $params['secondary_card_no']; $store_id = $params['store_id']; $staff_user_id = $params['staff_user_id']; $start_at = $params['start_at']; $service_end_at = $params['service_end_at']; $tech_id = $params['tech_id'] ?? 0; $service_type = $params['service_type'] ?? 1; $secondary_card_order = SecondaryCardOrder::findOne(['order_no' => $secondary_card_no, 'mall_id' => $mall_id, 'user_id' => $user_id]); if (!empty($secondary_card_order['order_status'])) { throw new \Exception('非待核销卡不能预约'); } $secondary_card = SecondaryCard::getOne([['id' => $secondary_card_order['secondary_card_id']]], true); if ($secondary_card['reservation_model'] == 1) { $service_type = 2; $service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_NORMAL; $order_status = OrderStatusEnum::PAY; } else { $service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING; $order_status = OrderStatusEnum::SHIPMENTS; } $params['secondary_card_order_id'] = $secondary_card_order['id']; $params['pay_type'] = $secondary_card_order['pay_type']; $params['store_id'] = $store_id; list($order, $order_detail_id) = self::createMallOrder($params, $secondary_card, $secondary_card_order); $model = new ReservationServiceOrder(); $model->loadDefaultValues(); $data = [ 'mall_id' => $mall_id, 'user_id' => $user_id, 'store_id' => $store_id, 'status' => StatusEnum::ENABLED, 'staff_user_id' => $staff_user_id, 'order_id' => $order['id'], 'order_no' => $order['order_no'], 'service_type' => $service_type, 'service_status' => $service_status, 'server_status' => ReservationServiceEnum::ALREADY_BOOKED, 'service_start_at' => $start_at, 'service_end_at' => $service_end_at, 'order_detail_id' => $order_detail_id, 'secondary_card_id' => $secondary_card_order['secondaryCard']['id'], 'secondary_card_no' => $secondary_card_no, 'reservation_model' => $secondary_card_order['secondaryCard']['reservation_model'], ]; if (!$model->load($data, '') || !$model->save()) throw new \Exception($model->getErrorMessage()); $cancel_type = $secondary_card_order['secondaryCard']['reservation_cancel_type']; self::orderReserveCreate($order, $params['latitude'], $params['longitude'], $tech_id, $params['select_time'], $service_type, $cancel_type, $secondary_card_order['clerk_code'], $secondary_card, $start_at, $service_end_at, $model['id']); switch ($secondary_card['store_type']) { case 1: $params['mall_order_no'] = $order['order_no']; list($store_order, $store_order_detail_id) = self::createO2oStoreOrder($params, $secondary_card); if ($secondary_card_order['secondaryCard']['store_type'] == SecondaryCardEnum::STORE_TYPE_O2O) { self::o2oStoreOrderReserveCreate($store_order, $params['latitude'], $params['longitude'], $tech_id, $params['select_time'], $service_type, $cancel_type, $secondary_card_order['clerk_code'], $order['id'], $secondary_card, $start_at, $service_end_at, $model['id']); } break; } Order::updateAll(['order_status' => $order_status, 'shipping_time' => time()], ['order_no' => $order['order_no']]); StoreOrder::updateAll(['order_status' => $order_status, 'shipping_time' => time()], ['order_no' => $order['order_no']]); return [$order, $order_detail_id]; } /** * 生成主订单 * @Author:hua * @Date:2024-03-11 15:28 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @param $secondary_card * @param $secondary_card_order * @return array */ public static function createMallOrder($params, $secondary_card, $secondary_card_order) { try { $mall_id = $params['mall_id']; $user_id = $params['user_id']; $store_id = $params['store_id']; $payment_type = $params['pay_type']; $marketing_id = $params['secondary_card_order_id']; $latitude = $params['latitude']; $longitude = $params['longitude']; $service_type = $params['reservation_service_type']; if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE && in_array($service_type, [GoodsReserve::RESERVE_SERVICE_TO])) { $user_address = UserAddress::findOne(['user_id' => $user_id, 'is_default' => 1, 'status' => StatusEnum::ENABLED]); if (empty($user_address)) { throw new \Exception('请到地址管理添加个默认地址2'); } //选择用户的默认的收货地址 $province = $user_address->province_id; $city = $user_address->city_id; $area = $user_address->district_id; $town_id = $user_address->town_id; $address = $user_address->detail; $lat = $latitude; $lng = $longitude; $region_name = $user_address['province'] . ' ' . $user_address['city'] . ' ' . $user_address['district'] . ' ' . $user_address['town'] . ' ' . $user_address['community']; $receiver_name = $user_address['name']; } else { // 到店使用商品地址 - 使用门店地址 $store = Store::findOne(['id' => $store_id]); if (empty($store)) { throw new \Exception('门店不存在'); } $province = $store->province_id; $city = $store->city_id; $area = $store->district_id; $address = $store->address; $lat = $store->latitude; $lng = $store->longitude; $region_list = Region::lists([ 'where' => [ ['id' => [$store->province_id, $store->city_id, $store->district_id]] ], 'index' => 'id' ]); $region_name = $region_list[$store->province_id]['name'] . ' ' . $region_list[$store->city_id]['name'] . ' ' . $region_list[$store->district_id]['name']; $receiver_name = $store['shop_owner']; } if (empty($province) || empty($city) || empty($area) || empty($address) || empty($lat) || empty($lng)) { throw new \Exception('服务地址或定位信息错误'); } $time = time(); $order = new Order(); $order->loadDefaultValues(); $order->mall_id = $mall_id; $order->mch_id = 0; $order->user_id = $user_id; $order->order_no = StringHelper::generateOrderNo('s'); $order->out_trade_no = ''; $order->mobile = ''; $order->province = $province; $order->city = $city; $order->area = $area; $order->town = $town_id ?? 0; $order->address = $address; $order->region_name = $region_name; $order->receiver_name = $receiver_name; $order->shipping_money = 0; $order->pay_money = $secondary_card['price']; $order->goods_price = $secondary_card['price']; $order->original_goods_price = $secondary_card['original_price']; $order->order_status = OrderStatusEnum::PAY; $order->marketing_id = $marketing_id; $order->marketing_type = 'SecondaryCard'; $order->pay_status = OrderStatusEnum::PAY; $order->payment_type = $payment_type; $order->pay_time = $time; $order->order_source = 'Reserve'; $order->store_id = $store_id; $order->clerk_code = $secondary_card_order['clerk_code']; $res = $order->save(); if ($res == false) throw new \Exception($order->getErrorMessage()); $order_detail_id = self::createMallOrderDetail($order, $secondary_card); return [$order, $order_detail_id]; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } /** * 生成o2o主订单 * @Author:hua * @Date:2024-03-05 10:46 * @Copyright:copyright(c)2024 广东七件事集团 * @param $mall_id * @param $user_id * @param $order_no * @param $marketing_id * @param $payment_type * @param $secondary_card * @param $store_id * @return array|false */ public static function createO2oStoreOrder($params, $secondary_card) { try { $mall_id = $params['mall_id']; $user_id = $params['user_id']; $store_id = $params['store_id']; $payment_type = $params['pay_type']; $marketing_id = $params['secondary_card_order_id']; $latitude = $params['latitude']; $longitude = $params['longitude']; $service_type = $secondary_card['reservation_service_type']; if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE && in_array($service_type, [GoodsReserve::RESERVE_SERVICE_TO])) { $user_address = UserAddress::findOne(['user_id' => $user_id, 'is_default' => 1, 'status' => StatusEnum::ENABLED]); if (empty($user_address)) { throw new \Exception('请到地址管理添加个默认地址'); } //选择用户的默认的收货地址 $province = $user_address->province_id; $city = $user_address->city_id; $area = $user_address->district_id; $town_id = $user_address->town_id; $address = $user_address->detail; $lat = $latitude; $lng = $longitude; $region_name = $user_address['province'] . ' ' . $user_address['city'] . ' ' . $user_address['district'] . ' ' . $user_address['town'] . ' ' . $user_address['community']; $receiver_name = $user_address['name']; } else { // 到店使用商品地址 - 使用门店地址 $store = Store::findOne(['id' => $store_id]); if (empty($store)) { throw new \Exception('门店不存在'); } $province = $store->province_id; $city = $store->city_id; $area = $store->district_id; $address = $store->address; $lat = $store->latitude; $lng = $store->longitude; $region_list = Region::lists([ 'where' => [ ['id' => [$store->province_id, $store->city_id, $store->district_id]] ], 'index' => 'id' ]); $region_name = $region_list[$store->province_id]['name'] . ' ' . $region_list[$store->city_id]['name'] . ' ' . $region_list[$store->district_id]['name']; $receiver_name = $store['shop_owner']; } if (empty($province) || empty($city) || empty($area) || empty($address) || empty($lat) || empty($lng)) { throw new \Exception('服务地址或定位信息错误'); } $time = time(); $order = new StoreOrder(); $order->loadDefaultValues(); $order->mall_id = $mall_id; $order->mch_id = 0; $order->user_id = $user_id; $order->order_no = $params['mall_order_no']; $order->out_trade_no = ''; $order->mobile = ''; $order->province = $province; $order->city = $city; $order->area = $area; $order->town = $town_id ?? 0; $order->address = $address; $order->region_name = $region_name; $order->receiver_name = $receiver_name; $order->shipping_money = 0; $order->pay_money = $secondary_card['price']; $order->goods_price = $secondary_card['price']; $order->original_goods_price = $secondary_card['original_price']; $order->order_status = OrderStatusEnum::PAY; $order->marketing_id = $marketing_id; $order->marketing_type = 'SecondaryCard'; $order->pay_status = OrderStatusEnum::PAY; $order->payment_type = $payment_type; $order->pay_time = $time; $order->order_source = 'Reserve'; $order->store_id = $store_id; $res = $order->save(); if ($res == false) throw new \Exception($order->getErrorMessage()); $order_detail_id = self::createO2oStoreOrderDetail($order, $secondary_card); return [$order, $order_detail_id]; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } /** * 生成主订单详情 * @Author:hua * @Date:2024-03-04 15:36 * @Copyright:copyright(c)2024 广东七件事集团 * @param $order * @param $secondary_card * @return mixed */ protected static function createMallOrderDetail($order, $secondary_card) { // 订单详情 $order_detail = new OrderDetail(); $order_detail->loadDefaultValues(); $order_detail->user_id = $order->user_id; $order_detail->mall_id = $order->mall_id; $order_detail->mch_id = $order->mch_id; $order_detail->order_id = $order->id; $order_detail->goods_id = 0; $order_detail->goods_attr_id = 0; $order_detail->goods_name = $secondary_card['name']; $order_detail->is_virtual = 0; $order_detail->goods_attr_name = ''; $order_detail->price = $secondary_card['price']; $order_detail->cost_price = 0; $order_detail->original_goods_price = $secondary_card['original_price']; //https://teststatic.qijianshigw.com/static//addons/SecondaryCard/default_card.png $static_url = \Yii::$app->services->setting->platform->get('system.static_url'); $order_detail->pic_url = $static_url . '/static/addons/SecondaryCard/default_card.png'; $order_detail->goods_price = $secondary_card['price']; $order_detail->num = 1; $order_detail->marketing_id = $order->marketing_id; $order_detail->marketing_type = $order->marketing_type; $order_detail->order_status = OrderStatusEnum::PAY; $order_detail->remark = ''; $res = $order_detail->save(); if ($res == false) throw new \Exception('生成订单详情失败'); return $order_detail['id']; } /** * 生成o2o订单详情 * @Author:hua * @Date:2024-03-05 10:46 * @Copyright:copyright(c)2024 广东七件事集团 * @param $store_order * @param $secondary_card * @return mixed */ protected static function createO2oStoreOrderDetail($store_order, $secondary_card) { // 订单详情 $order_detail = new StoreOrderDetail(); $order_detail->loadDefaultValues(); $order_detail->user_id = $store_order->user_id; $order_detail->mall_id = $store_order->mall_id; $order_detail->mch_id = $store_order->mch_id; $order_detail->order_id = $store_order->id; $order_detail->goods_id = 0; $order_detail->goods_attr_id = 0; $order_detail->goods_name = $secondary_card['name']; $order_detail->is_virtual = 0; $order_detail->goods_attr_name = ''; $order_detail->price = $secondary_card['price']; $order_detail->cost_price = 0; $order_detail->original_goods_price = $secondary_card['original_price']; // $order_detail->pic_url = $secondary_card['background']; $static_url = \Yii::$app->services->setting->platform->get('system.static_url'); $order_detail->pic_url = $static_url . '/static/addons/SecondaryCard/default_card.png'; $order_detail->goods_price = $secondary_card['price']; $order_detail->num = 1; $order_detail->marketing_id = $store_order->marketing_id; $order_detail->marketing_type = $store_order->marketing_type; $order_detail->order_status = OrderStatusEnum::PAY; $order_detail->remark = ''; $res = $order_detail->save(); if ($res == false) throw new \Exception('生成订单详情失败'); return $order_detail['id']; } public static function orderReserveCreate($order, $latitude, $longitude, $tech_id, $reserveDateTime, $service_type, $cancel_type, $reserve_code, $secondary_card, $start_at, $end_at, $reservation_service_order_id) { try { $reserveTimeRangeType = 2; // 技师默认是按时间段预约的 // service_type服务方式(1上门 2到店 3两者都兼容) if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE && in_array($service_type, [GoodsReserve::RESERVE_SERVICE_TO])) { $user_address = UserAddress::findOne(['user_id' => $order['user_id'], 'is_default' => 1, 'status' => StatusEnum::ENABLED]); if (empty($user_address)) { throw new \Exception('请到地址管理添加个默认地址'); } //选择用户的默认的收货地址 $province = $user_address->province_id; $city = $user_address->city_id; $area = $user_address->district_id; $address = $user_address->detail; $lat = $latitude; $lng = $longitude; $regionName = ''; } else { // 到店使用商品地址 - 使用门店地址 $store = Store::findOne(['id' => $order->store_id]); if (empty($store)) { throw new \Exception('门店不存在'); } $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 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 = $service_type; $model->order_status = $order->order_status; $model->pay_status = $order->pay_status; $model->cancel_type = $cancel_type; $model->cancel_rule = ''; $model->reserve_type = 1; $model->reserve_code = $reserve_code; $model->tech_id = $tech_id; $model->service_start_at = $start_at; $model->service_end_at = $end_at; $model->reservation_service_order_id = $reservation_service_order_id; 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; } } /** * 生成o2o门店预约单 * @Author:hua * @Date:2024-03-04 16:57 * @Copyright:copyright(c)2024 广东七件事集团 * @param $order * @param $latitude * @param $longitude * @param $tech_id * @param $reserveDateTime * @param $service_type * @param $cancel_type * @param $reserve_code * @param int $main_order_id * @return bool */ public static function o2oStoreOrderReserveCreate($order, $latitude, $longitude, $tech_id, $reserveDateTime, $service_type, $cancel_type, $reserve_code, $main_order_id, $secondary_card, $start_at, $end_at, $reservation_service_order_id) { try { $reserveTimeRangeType = 2; // 技师默认是按时间段预约的 // service_type服务方式(1上门 2到店 3两者都兼容) if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE && in_array($service_type, [GoodsReserve::RESERVE_SERVICE_TO])) { $user_address = UserAddress::findOne(['user_id' => $order['user_id'], 'is_default' => 1, 'status' => StatusEnum::ENABLED]); if (empty($user_address)) { throw new \Exception('请到地址管理添加个默认地址1'); } //选择用户的默认的收货地址 $province = $user_address->province_id; $city = $user_address->city_id; $area = $user_address->district_id; $address = $user_address->detail; $lat = $latitude; $lng = $longitude; $regionName = ''; } else { // 到店使用商品地址 - 使用门店地址 $store = Store::findOne(['id' => $order->store_id]); if (empty($store)) { throw new \Exception('门店不存在'); } $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 = $service_type; $model->order_status = $order->order_status; $model->pay_status = $order->pay_status; $model->cancel_type = $cancel_type; $model->cancel_rule = ''; $model->reserve_type = 1; $model->tech_id = $tech_id; $model->main_order_id = $main_order_id; $model->reserve_code = $reserve_code; $model->service_start_at = $start_at; $model->service_end_at = $end_at; $model->reservation_service_order_id = $reservation_service_order_id; 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; } } /** *取消预约 * @Author:hua * @Date:2024-03-05 10:46 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return bool|string */ public static function cancelReservation($params) { $t = \Yii::$app->db->beginTransaction(); try { $mall_id = $params['mall_id']; $user_id = $params['user_id']; if (!MallAddons::isInstall($mall_id, 'ReservationService')) { throw new \Exception('没有安装预约服务插件'); } if (!empty($params['reservation_service_order_id'])) { $reservation_service_order = ReservationServiceOrder::findOne(['id' => $params['reservation_service_order_id'], 'mall_id' => $mall_id, 'user_id' => $user_id]); } if (!empty($params['main_order_id'])) { $reservation_service_order = ReservationServiceOrder::findOne(['order_id' => $params['main_order_id'], 'mall_id' => $mall_id, 'user_id' => $user_id]); } if (empty($reservation_service_order)) { throw new \Exception('预约服务订单不存在'); } if ($reservation_service_order['status'] == StatusEnum::DISABLED) { throw new \Exception('该预约已取消过'); } $order = Order::findOne(['id' => $reservation_service_order['order_id'], 'mall_id' => $mall_id, 'user_id' => $user_id]); if (empty($order)) { throw new \Exception('预约订单不存在'); } $secondary_card_order = SecondaryCardOrder::findOne(['id' => $order['marketing_id'], 'mall_id' => $mall_id, 'user_id' => $user_id]); if (empty($secondary_card_order)) { throw new \Exception('开卡记录不存在'); } $secondary_card = SecondaryCard::findOne(['id' => $secondary_card_order['secondary_card_id'], 'mall_id' => $mall_id]); if ($secondary_card['reservation_cancel_type'] == SecondaryCardEnum::RESERVATION_CANCEL_TYPE_NO) { throw new \Exception('该次卡不允许取消预约'); } // if ($reservation_service_order['service_start_at'] < time()) { // throw new \Exception('服务时间已开始,不能取消'); // } $reservation_cancel_deduct = 0; if (!empty($secondary_card['reservation_cancel_hour']) && !empty($secondary_card['reservation_cancel_deduct']) && $reservation_service_order['service_status'] == ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING) { $service_start_at = $reservation_service_order['service_start_at']; $temp_time = $service_start_at - $secondary_card['reservation_cancel_hour'] * 3600; if (time() > $temp_time) { $reservation_cancel_deduct = $secondary_card['reservation_cancel_deduct']; } } $role = '用户'; $reservation_service_order->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_CANCEL; $reservation_service_order->status = StatusEnum::DISABLED; $reservation_service_order->remark = "{$reservation_service_order->remark} {$role} [$user_id] 取消了当前订单的预约 \n"; $reservation_service_order->save(); $order->status = StatusEnum::DISABLED; $order->save(); $secondary_card_order->verifiable_times -= $reservation_cancel_deduct; if ($secondary_card_order->verifiable_times <= 0) { $secondary_card_order->verifiable_times = 0; $secondary_card_order->order_status = 1; } $secondary_card_order->save(); ReservationServiceUserBookTime::updateAll(['status' => StatusEnum::DELETE], ['and', ['status' => StatusEnum::ENABLED], ['order_id' => $order->id]]); $order->sign_time = 0; $order->order_status = OrderStatusEnum::PAY; $order->shipping_status = StatusEnum::DISABLED; if (!$order->save()) throw new \Exception($order->getErrorMessage()); // 清除详情发货信息 OrderDetail::updateAll(['order_status' => OrderStatusEnum::PAY, 'shipping_status' => StatusEnum::DISABLED], ['in', 'id', OrderDetail::find()->where(['order_id' => $order->id])->select('id')->column()]); if ($secondary_card['store_type'] == SecondaryCardEnum::STORE_TYPE_O2O) { $storeOrder = StoreOrder::findOne(['order_no' => $reservation_service_order->order_no]); if (empty($storeOrder)) throw new \Exception("预约订单不存在"); $orderReserve = StoreOrderReserve::findOne(['order_id' => $storeOrder->id]); } if (empty($orderReserve)) throw new \Exception("预约订单不存在"); $orderReserve = OrderReserve::findOne(['order_id' => $order->id]); if (empty($orderReserve)) throw new \Exception("预约订单不存在"); $orderReserve->tech_id = 0; $orderReserve->reserve_status = 0; if (!$orderReserve->save()) throw new \Exception($orderReserve->getErrorMessage()); $t->commit(); return true; } catch (\Exception $e) { $t->rollBack(); return $e->getMessage(); } } /** * 次卡-核销-获取详情 * @Author:hua * @Date:2024-03-06 11:08 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return array */ public static function getSecondaryCardClerkData($params) { $mall_id = $params['mall_id']; $clerk_code = $params['clerk_code']; $where = [['clerk_code' => $clerk_code], ['mall_id' => $mall_id],]; $secondary_card_order = SecondaryCardOrder::getOne($where, true, ['secondaryCard']); if (empty($secondary_card_order)) { throw new \Exception('开卡记录不存在'); } $time = time(); if ($secondary_card_order['start_time'] > $time) { throw new \Exception('该次卡还未生效'); } if ($secondary_card_order['expire_time'] < $time) { throw new \Exception('该次卡已过期'); } $secondary_card = $secondary_card_order['secondaryCard']; $reservation_service_order_return = $order_return = []; switch ($secondary_card['store_type']) { case 1: if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_STORE) { self::checkO2oStore($params, $secondary_card); } break; } if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { list($reservation_service_order, $order) = self::getReservationServiceOrder($params['mall_id'], $secondary_card_order['id'], $secondary_card['store_type']); self::checkTechnician($secondary_card['reservation_model'], $params['user_id'], $reservation_service_order['staff_user_id'], $reservation_service_order['store_id']); $service_status_map = ReservationServiceEnum::RESERVE_ORDER_STATUS_MAP; $reservation_service_order_return = [ 'service_start_at' => date('Y-m-d H:i', $reservation_service_order['service_start_at']), 'service_end_at' => date('Y-m-d H:i', $reservation_service_order['service_end_at']), 'service_status' => $reservation_service_order['service_status'], 'service_status_text' => $service_status_map[$reservation_service_order['service_status']] ?? '未知状态', ]; $created_at = $reservation_service_order['created_at']; $order_return = [ 'mobile' => $order['mobile'], 'receiver_name' => $order['receiver_name'], 'address' => $order['region_name'] . $order['address'], ]; $service_type_text = ReservationServiceEnum::SERVICE_TYPE_MAP[$reservation_service_order['service_type']] ?? ''; } else { $created_at = $secondary_card_order['created_at']; $service_type_text = ''; } $service = json_decode($secondary_card['service'], true); if (empty($secondary_card)) { throw new \Exception('次卡不存在'); } $data = [ 'secondary_card' => [ 'name' => $secondary_card['name'], 'background' => $secondary_card['background'], 'font_color' => $secondary_card['font_color'], 'reservation_type' => $secondary_card['reservation_type'], 'appointment_interval_duration' => $secondary_card['appointment_interval_duration'], 'service' => $service ?? [], 'secondary_card_order_no' => $secondary_card_order['order_no'], 'verifiable_times' => $secondary_card_order['verifiable_times'], 'use_times' => $secondary_card['verifiable_times'] - $secondary_card_order['verifiable_times'], 'order_source' => SecondaryCardOrderService::getSourceName($secondary_card_order, $secondary_card['use_type']), 'service_type_text' => $service_type_text, 'service_times' => 1, 'order_money' => bcdiv($secondary_card_order['pay_money'], $secondary_card['verifiable_times'], 2), 'created_at' => $created_at, 'pay_time' => date('Y-m-d H:i:s', $secondary_card_order['open_time']), 'pay_money' => $secondary_card_order['pay_money'], ], 'order' => $order_return, 'reservation_service_order' => $reservation_service_order_return, 'user' => User::getOne([['id' => $secondary_card_order['user_id']]], true, [], false, 'id,nickname,mobile'), ]; return $data; } /** * 次卡-核销 * @Author:hua * @Date:2024-03-08 17:36 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return array|string */ public static function secondaryCardClerk($params) { $t = \Yii::$app->db->beginTransaction(); try { if (empty($params['clerk_nums'])) { throw new \Exception('核销次数不能为0'); } $secondary_card_order = SecondaryCardOrder::getOne([['clerk_code' => $params['clerk_code']], ['mall_id' => $params['mall_id']],], false, ['secondaryCard']); $time = time(); if ($secondary_card_order['start_time'] > $time) { throw new \Exception('该次卡还未生效'); } if ($secondary_card_order['expire_time'] < $time) { throw new \Exception('该次卡已过期'); } $secondary_card = $secondary_card_order['secondaryCard']; $params['order_id'] = $secondary_card_order['id']; $params['pay_money'] = $secondary_card_order['pay_money']; $params['payment_type'] = $secondary_card_order['pay_type']; $params['type'] = $secondary_card['store_type']; if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { list($reservation_service_order, $order) = self::getReservationServiceOrder($params['mall_id'], $secondary_card_order['id'], $secondary_card['store_type']); self::checkTechnician($secondary_card['reservation_model'], $params['user_id'], $reservation_service_order['staff_user_id'], $reservation_service_order['store_id']); $params['store_id'] = $reservation_service_order['store_id']; $params['order_no'] = $reservation_service_order['order_no']; $params['reservation_service_order_id'] = $reservation_service_order['id']; } else { $params['order_no'] = $secondary_card_order['order_no']; } if ($params['clerk_nums'] > $secondary_card_order['verifiable_times']) { throw new \Exception('可核销次数不足'); } if ($secondary_card_order['verifiable_times'] == $secondary_card['verifiable_times'] && $secondary_card_order['verifiable_times'] == $params['clerk_nums']) { $clerk_money = $secondary_card_order['pay_money']; } else { $unit_money = bcdiv($secondary_card_order['pay_money'], $secondary_card['verifiable_times'], 2); $clerk_money = $params['clerk_nums'] * $unit_money; if ($params['clerk_nums'] >= $secondary_card_order['verifiable_times']) { $use_times = $secondary_card['verifiable_times'] - $secondary_card_order['verifiable_times']; $clerk_money = bcsub($secondary_card_order['pay_money'] - $secondary_card_order['refund_money'], $use_times * $unit_money, 2); } } $params['r_pay_money'] = $clerk_money; $logo_img = ''; $store_name = ''; $service_income = 0; $total_commission = 0; if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { $store_order_reserve = StoreOrderReserve::findOne(['main_order_id' => $reservation_service_order['order_id']]); $order_reserve = OrderReserve::findOne(['order_id' => $reservation_service_order['order_id']]); if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_PEOPLE) { $user = User::findOne(['id' => $reservation_service_order['staff_user_id']]); $params['store_id'] = self::checkIsTechnician($params['mall_id'], $secondary_card['store_type'], $params['store_id'], $params['user_id'], $params['from'] ?? null); $reservation_service_order->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER; $staff = $reservation_service_order->getStaff()->one(); $data = []; $data['id'] = $reservation_service_order['order_id']; $data['mall_id'] = $reservation_service_order['mall_id']; $data['user_id'] = $reservation_service_order['user_id']; $data['operator_id'] = $reservation_service_order['staff_user_id']; $data['operator_name'] = $user->nickname ?? $user->mobile; $data['from'] = OrderSourceEnum::SOURCE_RESERVE; $data['tech_id'] = $staff['id']; $res = Order::takeDelivery($data); if ($res == false) { throw new \Exception(Order::getStaticError()); } $staff->order_num += 1; $staff->store_order_num += 1; if (!$staff->save()) throw new \Exception($staff->getErrorMessage()); $store_order_reserve = StoreOrderReserve::findOne(['main_order_id' => $reservation_service_order['order_id']]); if (!empty($store_order_reserve) && empty($store_order_reserve->tech_id)) { $store_order_reserve->tech_id = $staff->id;// 绑定技师ID } $order_reserve = OrderReserve::findOne(['order_id' => $reservation_service_order['order_id']]); if (!empty($order_reserve) && empty($order_reserve->tech_id)) { $order_reserve->tech_id = $staff->id; // 绑定技师ID } } else { $user = User::findOne(['id' => $params['user_id']]); $data = []; $data['id'] = $reservation_service_order['order_id']; $data['mall_id'] = $reservation_service_order['mall_id']; $data['user_id'] = $reservation_service_order['user_id']; $data['operator_id'] = $params['user_id']; $data['operator_name'] = $user->nickname ?? $user->mobile; $data['from'] = OrderSourceEnum::SOURCE_RESERVE; $data['tech_id'] = 0; $res = Order::takeDelivery($data); if ($res == false) { throw new \Exception(Order::getStaticError()); } $reservation_service_order->service_status = ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER; $reservation_service_order->server_status = ReservationServiceEnum::TO_BE_ACCEPTED; } $reservation_service_order->save(); if (!empty($store_order_reserve)) { $store_order_reserve->reserve_status = OrderReserve::RESERVE_STATUS_PENDDING; if (!$store_order_reserve->save()) { throw new \Exception($store_order_reserve->getErrorMessage()); } } if (!empty($order_reserve)) { $order_reserve->reserve_status = OrderReserve::RESERVE_STATUS_PENDDING; if (!$order_reserve->save()) { throw new \Exception($order_reserve->getErrorMessage()); } } } else { switch ($secondary_card['store_type']) { case 1: $store = self::checkO2oStore($params, $secondary_card); $params['store_id'] = $store['id']; break; } } $params['clerk_money'] = $clerk_money; $clerk_type = 1; if ($secondary_card['reservation_type'] && $secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE) { $clerk_type = 2; } $params['clerk_type'] = $clerk_type; $params['clerk_user_id'] = $params['user_id']; $params['order_user_id'] = $secondary_card_order['user_id']; $params['secondary_name'] = $secondary_card['name']; $add_use_log = $params; $add_use_log['order_no'] = $secondary_card_order['order_no']; $add_use_log['user_id'] = $secondary_card_order['user_id']; $add_use_log['secondary_card_id'] = $secondary_card_order['secondary_card_id']; $add_use_log['open_time'] = $secondary_card_order['open_time']; $add_use_log['clerk_user_id'] = $params['user_id']; $add_use_log['clerk_money'] = $clerk_money; $use_log_model = SecondaryCardUseLog::setData($add_use_log); if ($use_log_model == false) { throw new \Exception(SecondaryCardUseLog::getStaticError()); } if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES && $secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE) { $params['secondary_card_use_log_id'] = $use_log_model['id']; // list($total_commission, $insert_wallet, $service_income) = self::computeReservationServiceUserCommission($params); } $secondary_card_order->verifiable_times -= $params['clerk_nums']; if ($secondary_card_order->verifiable_times <= 0) { $secondary_card_order->verifiable_times = 0; $secondary_card_order->order_status = SecondaryCardEnum::LOSE; } $secondary_card_order->save(); $use_log_model->service_income = $service_income ?? 0; $use_log_model->save(); if (isset($reservation_service_order)) { $reservation_service_order->commission = $service_income; $reservation_service_order->save(); } switch ($secondary_card['store_type']) { case 1: if (empty($store)) { $store = self::checkO2oStore($params, $secondary_card); } $logo_img = $store['logo_img']; $store_name = $store['store_name']; if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { if ($secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_STORE) { $params['clerk_money'] -= $total_commission; $params['addons_bonus'] = $total_commission; self::addStoreCommission($store, $params); } else { switch ($secondary_card_order['open_type']) { case SecondaryCardEnum::OPEN_TYPE_BUY: if ($secondary_card['create_source_type'] == 1) { $params['clerk_money'] -= $total_commission; $params['addons_bonus'] = $total_commission; self::addStoreCommission($store, $params); } break; case SecondaryCardEnum::OPEN_TYPE_EXCHANGE: $redemption_code_model = SecondaryCardRedemptionCode::findOne(['order_no' => $secondary_card_order['order_no']]); if (!empty($redemption_code_model) && $redemption_code_model['create_source_type'] == 1) { $params['clerk_money'] -= $total_commission; $params['addons_bonus'] = $total_commission; self::addStoreCommission($store, $params); } break; } } } else { if (!empty($store)) { self::addStoreCommission($store, $params); } } break; } $service_type_text = ''; if (isset($reservation_service_order)) { $service_type_text = ReservationServiceEnum::SERVICE_TYPE_MAP[$reservation_service_order['service_type']] ?? ''; } $add_clerk_log_data = [ 'mall_id' => $params['mall_id'], 'user_id' => $params['user_id'], 'mall_logo' => $logo_img, 'mall_name' => $store_name, 'name' => $secondary_card['name'], 'pic' => $secondary_card['background'], 'clerk_code' => (string)$params['clerk_code'], 'type' => ClerkEnum::SECONDARY_CARD_CLERK_CODE_PRE, 'extra' => json_encode([ 'clerk_nums' => $params['clerk_nums'], 'verifiable_times' => $secondary_card_order['verifiable_times'], 'clerk_money' => $clerk_money, 'settled_money' => $clerk_money, 'order_money' => $secondary_card['price'], 'reservation_model' => $secondary_card['reservation_model'], 'unit_times' => 1, 'service_type_text' => $service_type_text, 'service_income' => $service_income, 'order_id' => $reservation_service_order['order_id'] ?? 0, ]), ]; $clerk_log_model = ClerkLog::setData($add_clerk_log_data); if ($clerk_log_model == false) { throw new \Exception(ClerkLog::getStaticError()); } $use_log_model->clerk_log_id = $clerk_log_model['id']; $use_log_model->save(); // if (!empty($insert_wallet)) { // $userService = new UserService(); // foreach ($insert_wallet as $item) { // if ($item['is_frozen'] == false) { // $userService->addCommission($item['user_id'], $item['money']); // } // } // } $t->commit(); // if (!empty($insert_wallet)) { // UserWalletService::batchHandleByQueue($insert_wallet); // } return ['clerk_code' => $params['clerk_code']]; } catch (\Exception $e) { $t->rollBack(); throw new \Exception($e->getMessage()); } } public static function checkTechnician($reservation_model, $user_id, $staff_user_id, $store_id) { if ($reservation_model == SecondaryCardEnum::RESERVATION_MODEL_PEOPLE && $user_id != $staff_user_id) { if (empty($staff_user_id)) { throw new \Exception('未分配技师'); } $store = Store::findOne(['id' => $store_id, 'user_id' => $user_id]); if (empty($store)) { throw new \Exception('该次卡预约的技师会员id:' . $staff_user_id); } } } public static function checkO2oStore($params, $secondary_card) { if (!empty($params['store_id'])) { $store = Store::findOne(['id' => $params['store_id']]); if (empty($store)) { throw new \Exception('门店不存在'); } $store_id = $store['id']; } else { if ($secondary_card['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_NO || $secondary_card['reservation_model'] == SecondaryCardEnum::RESERVATION_MODEL_STORE) { $store_clerk = StoreClerk::findOne(['user_id' => $params['user_id'], 'status' => StatusEnum::ENABLED]); if (empty($store_clerk)) { throw new \Exception('你不是核销员'); } $store = Store::findOne(['id' => $store_clerk['store_id']]); if (empty($store)) { throw new \Exception('门店不存在'); } $store_id = $store['id']; } } if ($secondary_card['use_type'] == SecondaryCardEnum::USE_TYPE_STORE) { $res = SecondaryCardRelateStore::find()->where(['store_id' => $store_id, 'secondary_card_id' => $secondary_card['id'], 'store_type' => $secondary_card['store_type'], 'status' => StatusEnum::ENABLED])->one(); if (empty($res)) { throw new \Exception('该次卡指定店铺核销,所以无法在本店铺核销!'); } } return $store; } /** * 获取预约服务订单 * @Author:hua * @Date:2024-03-13 16:36 * @Copyright:copyright(c)2024 广东七件事集团 * @param $mall_id * @param $secondary_card_order_id * @param $store_type * @return array */ public static function getReservationServiceOrder($mall_id, $secondary_card_order_id, $store_type) { switch ($store_type) { case 1: $store_order = StoreOrder::find()->where(['marketing_id' => $secondary_card_order_id, 'marketing_type' => 'SecondaryCard']) ->orderBy('id desc')->one(); if (empty($store_order)) { throw new \Exception('订单记录不存在'); } if ($store_order['order_status'] == 1) { throw new \Exception('订单未确认'); } if ($store_order['order_status'] == 3) { throw new \Exception('订单已核销'); } if ($store_order['order_status'] == 4) { throw new \Exception('订单已完成'); } $order = Order::findOne(['order_no' => $store_order['order_no']]); break; } if (empty($order)) { throw new \Exception('订单记录不存在'); } $reservation_service_order = ReservationServiceOrder::find()->where(['order_id' => $order['id'], 'mall_id' => $mall_id])->one(); if (empty($reservation_service_order)) { throw new \Exception('服务预约订单记录不存在'); } if (in_array($reservation_service_order['service_status'], [ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER, ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH])) { throw new \Exception('服务订单已核销'); } return [$reservation_service_order, $order]; } protected static function checkIsTechnician($mall_id, $store_type, $store_id, $user_id, $from) { $reservation_service_user = ReservationServiceUser::findOne(['mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED, 'check_status' => 1]); $store = Store::findOne(['id' => $store_id]); if (empty($reservation_service_user)) { if ($store['user_id'] != $user_id) { throw new \Exception('技师不存在'); } } switch ($store_type) { case 1: if (empty($store)) { throw new \Exception('o2o门店不存在'); } break; } if ($from == 'store_mobile_terminal') { return $store_id; } return $reservation_service_user['store_id']; } /** * 添加门店余额 * @Author:hua * @Date:2024-03-07 10:44 * @Copyright:copyright(c)2024 广东七件事集团 * @param $store * @param $params * @return false|mixed */ protected static function addStoreCommission($store, $params) { if (empty($params['store_id'])) return false; $set_data = [ 'mall_id' => $params['mall_id'], 'store_id' => $params['store_id'], 'user_id' => $params['order_user_id'], 'order_no' => $params['order_no'], 'order_money' => $params['pay_money'], 'pay_money' => $params['r_pay_money'], 'amount_received' => $params['clerk_money'], 'addons_bonus' => $params['addons_bonus'] ?? 0, 'type' => 4, 'settle_type' => 4, 'is_settlement' => 1, 'store_send_commission' => 0, ]; $store->total_num += 1; $store->total_order_money += $params['clerk_money']; $store->total_money += $params['clerk_money']; $store->total_settled_amount += $params['clerk_money']; StoreCommission::setData($set_data); if ($params['payment_type'] != 15) {//银典支付 $store->balance += $params['clerk_money']; } $store->save(); $temp_amount_received = $params['clerk_money']; $key = StoreEnum::STORE_REAL_PAY_AMOUNTS . ':' . $params['mall_id']; $res = Yii::$app->redis->get($key); $amount_received = $params['clerk_money']; if ($params['payment_type'] != 15) {//银典支付 if (!empty($res)) $amount_received = bcadd($params['clerk_money'], $res, 2); Yii::$app->redis->set($key, $amount_received);//实收金额 } $key = StoreEnum::STORE_SETTLE_AMOUNTS . ':' . $params['mall_id']; $res = Yii::$app->redis->get($key); return $temp_amount_received; } /** * 计算预约服务插件佣金-提成明细 * @Author:hua * @Date:2024-03-06 15:03 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params * @return array */ public static function computeReservationServiceUserCommission($params) { $mall_id = $params['mall_id']; $clerk_user_id = $params['clerk_user_id']; $user_id = $params['order_user_id']; $clerk_money = $params['clerk_money']; $secondary_card_use_log_id = $params['secondary_card_use_log_id']; $order_no = $params['order_no']; $secondary_name = $params['secondary_name']; $reservation_service_user = ReservationServiceUser::findOne(['user_id' => $clerk_user_id]); $reservation_service_level = ReservationServiceLevel::findOne(['mall_id' => $mall_id, 'level' => $reservation_service_user['level'], 'status' => StatusEnum::ENABLED]); $total_commission = 0; $service_income = 0; $insert_wallet = []; if (empty($reservation_service_level)) return [$total_commission, $insert_wallet, $service_income]; $from_type = 'ReservationService'; $wallet_type = 'commission'; $source_table = SecondaryCardUseLog::tableName(); if ($reservation_service_level['item_commission'] > 0) { $self_commission = $reservation_service_level['item_commission']; if ($reservation_service_level['item_commission_type'] == 0) { $self_commission = bcmul($clerk_money, $reservation_service_level['item_commission'] / 100, 2); } $service_income = $self_commission; $total_commission += $self_commission; if ($self_commission > 0) { $capital_type = ReservationServiceEnum::CAPITAL_TYPE_COMMISSION; $desc = "技师 [{$clerk_user_id}] 为用户 [{$user_id}] 完成订单 [{$order_no}] 提供 [{$secondary_name}] 服务获得 [{$self_commission}] " . ReservationServiceEnum::CAPITAL_TYPE_MAP[$capital_type]; $insert_wallet [] = ['mall_id' => $mall_id, 'user_id' => $clerk_user_id, 'is_frozen' => false, 'wallet_type' => $wallet_type, 'money' => $self_commission, 'desc' => $desc, 'source_table' => $source_table, 'source_table_id' => $secondary_card_use_log_id ?? '', 'from_type' => $from_type, 'capital_type' => $capital_type, 'order_no' => $order_no, 'contributor_name' => $secondary_name, 'contributor_id' => $user_id, 'contributor_money' => $clerk_money, 'extra1' => [], ]; } } if ($reservation_service_level['enable_distribution_commission']) { $user = User::findOne(['id' => $clerk_user_id]); if ($user['parent_id'] && $reservation_service_level['level1_commission'] > 0) { $parent_id = $user['parent_id']; $first_user_commission = $reservation_service_level['level1_commission']; if ($reservation_service_level['level1_commission_type'] == 0) { $first_user_commission = bcmul($clerk_money, $reservation_service_level['level1_commission'] / 100, 2); } $total_commission += $first_user_commission; if ($first_user_commission > 0) { $capital_type = ReservationServiceEnum::CAPITAL_TYPE_COMMISSION_FIRST; $desc = "用户 [{$parent_id}] 推荐技师 [{$clerk_user_id}] 完成订单 [{$order_no}] 服务获得 [$first_user_commission] " . ReservationServiceEnum::CAPITAL_TYPE_MAP[$capital_type]; $insert_wallet [] = ['mall_id' => $mall_id, 'user_id' => $parent_id, 'is_frozen' => false, 'wallet_type' => $wallet_type, 'money' => $first_user_commission, 'desc' => $desc, 'source_table' => $source_table, 'source_table_id' => $secondary_card_use_log_id ?? '', 'from_type' => $from_type, 'capital_type' => $capital_type, 'order_no' => $order_no, 'contributor_name' => $secondary_name, 'contributor_id' => $user_id, 'contributor_money' => $clerk_money, 'extra1' => [], ]; } } if ($user['second_parent_id'] && $reservation_service_level['level2_commission'] > 0) { $second_parent_id = $user['second_parent_id']; $second_user_commission = $reservation_service_level['level2_commission']; if ($reservation_service_level['level2_commission_type'] == 0) { $second_user_commission = bcmul($clerk_money, $reservation_service_level['level2_commission'] / 100, 2); } $total_commission += $second_user_commission; if ($second_user_commission > 0) { $capital_type = ReservationServiceEnum::CAPITAL_TYPE_COMMISSION_SECOND; $desc = "用户 [{$second_parent_id}] 推荐技师 [{$clerk_user_id}] 完成订单 [{$order_no}] 服务获得 [$second_user_commission] " . ReservationServiceEnum::CAPITAL_TYPE_MAP[$capital_type]; $insert_wallet [] = ['mall_id' => $mall_id, 'user_id' => $second_parent_id, 'is_frozen' => false, 'wallet_type' => $wallet_type, 'money' => $second_user_commission, 'desc' => $desc, 'source_table' => $source_table, 'source_table_id' => $secondary_card_use_log_id ?? '', 'from_type' => $from_type, 'capital_type' => $capital_type, 'order_no' => $order_no, 'contributor_name' => $secondary_name, 'contributor_id' => $user_id, 'contributor_money' => $clerk_money, 'extra1' => [], ]; } } } return [$total_commission, $insert_wallet, $service_income]; } /** * 次卡退款 * @Author:hua * @Date:2024-03-08 11:01 * @Copyright:copyright(c)2024 广东七件事集团 * @param $params ['id'=>'','mall_id'=>'','user_id'=>'','refund_money'=>''] * @return bool */ public static function orderRefund($params) { try { $id = $params['id']; $mall_id = $params['mall_id']; $user_id = $params['user_id'] ?? 0; $where = ['id' => $id, 'mall_id' => $mall_id]; if (!empty($user_id)) { $where['user_id'] = $user_id; } $secondary_card_order_model = SecondaryCardOrder::find()->where($where)->with(['secondaryCard'])->one(); if (empty($secondary_card_order_model)) { throw new \Exception('该次卡开卡记录不存在'); } if (empty($secondary_card_order_model['verifiable_times'])) { throw new \Exception('该次卡已被核销完,无法退款'); } if ($secondary_card_order_model['open_type'] == SecondaryCardEnum::OPEN_TYPE_EXCHANGE) { throw new \Exception('兑换的次卡不允许退款'); } if ($secondary_card_order_model->order_status == SecondaryCardEnum::REFUNDED) { throw new \Exception('该次卡已退款'); } $secondary_card_model = $secondary_card_order_model['secondaryCard']; if (!empty($user_id)) { if ($secondary_card_model['refund_type'] == SecondaryCardEnum::REFUND_TYPE_NO) { throw new \Exception('该次卡不允许退款'); } $refund_money = $secondary_card_order_model['pay_money']; if ($secondary_card_model['verifiable_times'] != $secondary_card_order_model['verifiable_times']) { $refund_money = bcmul($secondary_card_order_model['verifiable_times'], ($secondary_card_order_model['pay_money'] / $secondary_card_model['verifiable_times']), 2); } } else { $refund_money = $params['refund_money']; } if ($refund_money <= 0) { throw new \Exception('退款金额必须大于0'); } if ($refund_money > $secondary_card_order_model['pay_money']) { throw new \Exception('退款金额不能大于支付金额'); } if ($secondary_card_order_model['secondaryCard']['reservation_type'] == SecondaryCardEnum::RESERVATION_TYPE_YES) { ReservationServiceOrder::updateAll( ['service_status' => ReservationServiceEnum::RESERVE_ORDER_STATUS_CLOSED], ['secondary_card_no' => $secondary_card_order_model['order_no'] ]); Order::updateAll( ['order_status' => OrderStatusEnum::REPEAL], ['marketing_id' => $secondary_card_order_model['id'], 'marketing_type' => 'SecondaryCard', 'order_source' => 'Reserve']); StoreOrder::updateAll( ['order_status' => OrderStatusEnum::REPEAL], ['marketing_id' => $secondary_card_order_model['id'], 'marketing_type' => 'SecondaryCard', 'order_source' => 'Reserve']); } $secondary_card_order_model->refund_money = $refund_money; $secondary_card_order_model->refund_time = time(); $secondary_card_order_model->order_status = 3; $secondary_card_order_model->save(); return self::refundMoney($id, $secondary_card_order_model['order_no'], $secondary_card_order_model['trade_id'], $refund_money, $secondary_card_model['name']); } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } protected static function refundMoney($order_id, $order_no, $trade_id, $refund_money, $name) { try { $payment_trade = PaymentTrade::findOne(['id' => $trade_id]); return \Yii::$app->services->pay->commonRefund($refund_money, $payment_trade['out_trade_no'], $order_no, SecondaryCardOrder::tableName(), $order_id, $name, UserWalletEnum::REFUND, 'secondary_card_refund'); } catch (Exception $e) { throw new \Exception($e->getFile() . ',第' . $e->getLine() . '行,原因:' . $e->getMessage()); } } public static function getClerkLogDetail($params) { $clerk_log_model = ClerkLog::findOne(['id' => $params['clerk_log_id'], 'mall_id' => $params['mall_id'], 'user_id' => $params['user_id'], 'type' => $params['type']]); $mall_id = $clerk_log_model['mall_id']; $clerk_code = $clerk_log_model['clerk_code']; $where = [['clerk_code' => $clerk_code], ['mall_id' => $mall_id],]; $secondary_card_order = SecondaryCardOrder::getOne($where, true, ['secondaryCard']); $secondary_card = $secondary_card_order['secondaryCard']; $reservation_service_order_return = $order_return = []; if ($secondary_card['reservation_type'] == 1) { $extra = json_decode($clerk_log_model['extra'], true); $order = Order::findOne(['id' => $extra['order_id']]); if (empty($order)) { throw new \Exception('订单记录不存在'); } $reservation_service_order = ReservationServiceOrder::find()->where(['order_id' => $order['id'], 'mall_id' => $mall_id])->one(); if (empty($reservation_service_order)) { throw new \Exception('服务预约订单记录不存在'); } $service_status_map = ReservationServiceEnum::RESERVE_ORDER_STATUS_MAP; $reservation_service_order_return = [ 'service_start_at' => date('Y-m-d H:i', $reservation_service_order['service_start_at']), 'service_end_at' => date('Y-m-d H:i', $reservation_service_order['service_end_at']), 'service_status' => $reservation_service_order['service_status'], 'finish_at' => date('Y-m-d H:i:s', $reservation_service_order['updated_at']), 'service_status_text' => $service_status_map[$reservation_service_order['service_status']] ?? '未知状态', ]; $created_at = $reservation_service_order['created_at']; $order_return = [ 'mobile' => $order['mobile'], 'receiver_name' => $order['receiver_name'], 'address' => $order['region_name'] . $order['address'], ]; $service_type_text = ReservationServiceEnum::SERVICE_TYPE_MAP[$reservation_service_order['service_type']] ?? ''; } else { $service_type_text = ''; $created_at = $secondary_card_order['created_at']; } $service = json_decode($secondary_card['service'], true); $data = [ 'secondary_card' => [ 'name' => $secondary_card['name'], 'background' => $secondary_card['background'], 'font_color' => $secondary_card['font_color'], 'reservation_type' => $secondary_card['reservation_type'], 'appointment_interval_duration' => $secondary_card['appointment_interval_duration'], 'service' => $service ?? [], 'secondary_card_order_no' => $secondary_card_order['order_no'], 'verifiable_times' => $secondary_card_order['verifiable_times'], 'use_times' => $secondary_card['verifiable_times'] - $secondary_card_order['verifiable_times'], 'order_source' => SecondaryCardOrderService::getSourceName($secondary_card_order, $secondary_card['use_type']), 'service_type_text' => $service_type_text, 'service_times' => 1, 'order_money' => bcdiv($secondary_card_order['pay_money'], $secondary_card['verifiable_times'], 2), 'created_at' => $created_at, 'pay_time' => date('Y-m-d H:i:s', $secondary_card_order['open_time']), 'pay_money' => $secondary_card_order['pay_money'], 'service_income' => $extra['service_income'] ?? 0, 'clerk_money' => $extra['clerk_money'] ?? 0, 'clerk_time' => date('Y-m-d H:i:s', $clerk_log_model['created_at']), ], 'order' => $order_return, 'reservation_service_order' => $reservation_service_order_return, 'user' => User::getOne([['id' => $secondary_card_order['user_id']]], true, [], false, 'id,nickname,mobile'), ]; return $data; } public static function getSourceName($secondary_card_order, $use_type) { $order_source = \Yii::$app->services->setting->mall->get($secondary_card_order['mall_id'], 'basic.name'); switch ($secondary_card_order['create_source_type']) { case 1: if ($use_type == 1) { $store = Store::findOne(['id' => $secondary_card_order['create_source_id']]); $order_source = $store['store_name'] ?? ''; } break; } return $order_source; } }