You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1268 lines
47 KiB
1268 lines
47 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\api\apiService;
|
|
|
|
use app\model\campus_person_role\CampusPersonRole;
|
|
use app\model\customer_resource_changes\CustomerResourceChanges;
|
|
use app\model\customer_resources\CustomerResources;
|
|
use app\model\dict\Dict;
|
|
use app\model\member\Member;
|
|
use app\model\personnel\Personnel;
|
|
use app\model\resource_sharing\ResourceSharing;
|
|
use app\model\six_speed\SixSpeed;
|
|
use app\model\six_speed_modification_log\SixSpeedModificationLog;
|
|
use app\model\school\SchoolStudent;
|
|
use core\base\BaseApiService;
|
|
use think\facade\Db;
|
|
use think\facade\Event;
|
|
use think\facade\Log;
|
|
|
|
/**
|
|
* 客户资源服务层
|
|
* Class MemberService
|
|
* @package app\service\api\member
|
|
*/
|
|
class CustomerResourcesService extends BaseApiService
|
|
{
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
}
|
|
|
|
//获取客户资源详情
|
|
public function getInfo(array $where, string $field = '*')
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
$model = new CustomerResources();
|
|
if (!empty($where['member_id'])) {
|
|
$model = $model->where('member_id', $where['member_id']);
|
|
}
|
|
if (!empty($where['phone_number'])) {
|
|
$model = $model->where('phone_number', $where['phone_number']);
|
|
}
|
|
$data = $model->field($field)
|
|
->with([
|
|
'memberHasOne',
|
|
'resourceSharingHasMany'
|
|
])
|
|
->append([
|
|
'gender_name',
|
|
'initial_intent_name'
|
|
])
|
|
->find();
|
|
if ($data) {
|
|
$data = $data->toArray();
|
|
$res['code'] = 1;
|
|
$res['data'] = $data;
|
|
} else {
|
|
$res['msg'] = '暂无数据';
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
//获取全部客户资源数据
|
|
public function getAll(array $where, string $field = '*')
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
if (!$where) {
|
|
$res['msg'] = '查询条件不能为空';
|
|
return $res;
|
|
}
|
|
$model = new CustomerResources();
|
|
if (!empty($where['name'])) {
|
|
$model = $model->where('name', 'like', "%{$where['name']}%");
|
|
}
|
|
if(!empty($where['phone_number'])){
|
|
$model = $model->where('phone_number', 'like', "%{$where['phone_number']}%");
|
|
}
|
|
$data = $model->field($field)
|
|
->with([
|
|
'resourceSharingHasMany'
|
|
])
|
|
->append([
|
|
'initial_intent_name',
|
|
])
|
|
->select()->toArray();
|
|
if (!$data) {
|
|
$res['msg'] = '暂无数据';
|
|
return $res;
|
|
}
|
|
$res['code'] = 1;
|
|
$res['msg'] = '操作成功';
|
|
$res['data'] = $data;
|
|
return $res;
|
|
|
|
|
|
}
|
|
|
|
//添加数据
|
|
public function addData(array $customer_resources_data, array $six_speed_data, array $student_data = [], $staff_id = 0, $role_id = 0)
|
|
{
|
|
$date = date('Y-m-d H:i:s');
|
|
$customer_resources_data['updated_at'] = $date;
|
|
$six_speed_data['updated_at'] = $date;
|
|
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败'
|
|
];
|
|
//开启事物
|
|
Db::startTrans();
|
|
try {
|
|
$resource_id = CustomerResources::insertGetId($customer_resources_data);//客户资源表
|
|
if (!$resource_id) {
|
|
Db::rollback();
|
|
return $res;
|
|
}
|
|
$six_speed_data['resource_id'] = $resource_id;
|
|
$sixSpeedAdd = SixSpeed::create($six_speed_data);
|
|
if (!$sixSpeedAdd) {
|
|
Db::rollback();
|
|
return $res;
|
|
}
|
|
// 写入资源分配表
|
|
$assignee_id = $staff_id ?: 56; // 使用传入的staff_id,如果没有则使用默认值56
|
|
try {
|
|
Db::table('school_resource_assignment')->insert([
|
|
'resource_id' => $resource_id,
|
|
'assignee_type' => 'user',
|
|
'assignee_id' => $assignee_id,
|
|
'is_primary' => 1,
|
|
'assigned_by' => 0,
|
|
'assigned_at' => date("Y-m-d H:i:s"),
|
|
'campus_id' => $customer_resources_data['campus'],
|
|
'assigned_source' => 'api'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
// 如果插入失败,记录日志但不影响主流程
|
|
Log::error("资源分配记录写入失败:" . $e->getMessage());
|
|
}
|
|
// 转介绍奖励逻辑:当source=3且有referral_resource_id时发放奖励
|
|
if ($customer_resources_data['source'] == '3' && !empty($customer_resources_data['referral_resource_id'])) {
|
|
$this->grantReferralReward($customer_resources_data['referral_resource_id'], $resource_id);
|
|
}
|
|
|
|
// 添加school_student表记录
|
|
if (!empty($student_data)) {
|
|
$student_data['user_id'] = $resource_id; // 设置user_id为新添加的客户资源ID
|
|
$student_data['updated_at'] = $date;
|
|
$student_data['created_at'] = $date;
|
|
|
|
$studentAdd = SchoolStudent::create($student_data);
|
|
if (!$studentAdd) {
|
|
Db::rollback();
|
|
$res['msg'] = '添加学员记录失败';
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
Db::commit();
|
|
$res = [
|
|
'code' => 1,
|
|
'msg' => '操作成功'
|
|
];
|
|
$event_data = [
|
|
'customer_resources_id' => $resource_id,//客户资源表id
|
|
'event_type' => 'add'//事件类型"add=添加,edit=修改
|
|
];//事件类型"add=添加,edit=修改
|
|
|
|
Event::trigger('CalculatePerformance', $event_data, true);
|
|
return $res;
|
|
} catch (\Exception $exception) {
|
|
Db::rollback();
|
|
$res['msg'] = $exception->getMessage();
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
//客户资源-编辑
|
|
public function editData(array $where, array $customer_resources_data, array $six_speed_data)
|
|
{
|
|
$operator_id = $this->member_id;//当前登录用户的id(日志操作人的id)
|
|
$campus_id = 0;//日志操作人校区的id
|
|
$campus_id_arr = CampusPersonRole::where('person_id', $operator_id)->column('campus_id');
|
|
if (count($campus_id_arr)) {
|
|
if (count($campus_id_arr) > 1) {
|
|
$campus_id = 0;
|
|
} else {
|
|
$campus_id = $campus_id_arr[0];
|
|
}
|
|
}
|
|
|
|
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
|
|
if (!$where) {
|
|
$res['msg'] = '查询条件不能为空';
|
|
return $res;
|
|
}
|
|
|
|
$date = date('Y-m-d H:i:s');
|
|
$customer_resources_data['updated_at'] = $date;
|
|
$six_speed_data['updated_at'] = $date;
|
|
|
|
|
|
try {
|
|
$customer_resources = CustomerResources::where('id', $where['id'])->find();
|
|
|
|
$six_speed = SixSpeed::where('resource_id', $where['id'])->find();
|
|
if ($customer_resources) {
|
|
$customer_resources = $customer_resources->toArray();
|
|
|
|
if (!$customer_resources['member_id'] && $six_speed) {
|
|
$sex = 0;
|
|
switch ($customer_resources_data['gender']) {
|
|
case 'male'://男
|
|
$sex = 1;
|
|
break;
|
|
case 'female'://女
|
|
$sex = 2;
|
|
break;
|
|
default://其他
|
|
$sex = 0;
|
|
break;
|
|
}
|
|
$password = create_password($customer_resources_data['phone_number']);//创建密码
|
|
//开启事物
|
|
// Db::startTrans();
|
|
//给用户创建member账号
|
|
$member_id = Member::insertGetId([
|
|
'username' => $customer_resources_data['phone_number'],//会员用户名
|
|
'mobile' => $customer_resources_data['phone_number'],//手机号
|
|
'password' => $password,//会员密码
|
|
'nickname' => $customer_resources_data['name'],//会员昵称
|
|
'sex' => $sex,//性别 0保密 1男 2女
|
|
'member_time' => time(),//成为会员时间
|
|
]);
|
|
|
|
if ($member_id) {
|
|
$customer_resources_data['member_id'] = $member_id;
|
|
} else {
|
|
Db::rollback();
|
|
$res['msg'] = '创建用户账号失败';
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
}
|
|
$update_1 = CustomerResources::where('id', $where['id'])->update($customer_resources_data);//客户资源表
|
|
if (!$update_1) {
|
|
// Db::rollback();
|
|
return $res;
|
|
}
|
|
|
|
|
|
//更近客户资源日志表
|
|
$compareData = (new CommonService)->compareData($customer_resources, $customer_resources_data);
|
|
if ($compareData['changed_fields']) {
|
|
$data = [
|
|
"customer_resource_id" => $where['id'],//客户资源的ID
|
|
"operator_id" => $operator_id,//操作人的ID
|
|
"campus_id" => $campus_id,//操作人校区的ID|如果这人有2校区就填0
|
|
"modified_fields" => $compareData['changed_fields_json'],//修改的哪些字段
|
|
"old_values" => $compareData['old_values_json'],//修改前的值
|
|
"new_values" => $compareData['new_values_json'],//修改后的值
|
|
];
|
|
|
|
$id = CustomerResourceChanges::insertGetId($data);
|
|
if (!$id) {
|
|
// Db::rollback();
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
|
|
$six_speed_data['resource_id'] = $where['id'];
|
|
|
|
//查六要素是否存在
|
|
if ($six_speed) {
|
|
$six_speed = $six_speed->toArray();
|
|
//更新六要素
|
|
$sixSpeedUpdate = SixSpeed::where('id', $six_speed['id'])->update($six_speed_data);
|
|
if (!$sixSpeedUpdate) {
|
|
// Db::rollback();
|
|
return $res;
|
|
}
|
|
|
|
//更近六要素日志表
|
|
$compareData = (new CommonService)->compareData($six_speed, $six_speed_data);
|
|
if ($compareData['changed_fields']) {
|
|
$data = [
|
|
"operator_id" => $operator_id,//操作人的ID
|
|
"campus_id" => $campus_id,//操作人校区的ID|如果这人有2校区就填0
|
|
"customer_resource_id" => $where['id'],//客户资源的ID
|
|
"modified_field" => $compareData['changed_fields_json'],//修改的哪些字段
|
|
"old_value" => $compareData['old_values_json'],//修改前的值
|
|
"new_value" => $compareData['new_values_json'],//修改后的值
|
|
];
|
|
|
|
$id = SixSpeedModificationLog::insertGetId($data);
|
|
if (!$id) {
|
|
// Db::rollback();
|
|
return $res;
|
|
}
|
|
}
|
|
} else {
|
|
//创建六要素
|
|
$sixSpeedUpdate = SixSpeed::create($six_speed_data);
|
|
if (!$sixSpeedUpdate) {
|
|
// Db::rollback();
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
// Db::commit();
|
|
$res = [
|
|
'code' => 1,
|
|
'msg' => '操作成功'
|
|
];
|
|
return $res;
|
|
} catch (\Exception $exception) {
|
|
Db::rollback();
|
|
dd($exception);
|
|
Log::error(print_r($exception, true));
|
|
return $exception->getMessage();
|
|
}
|
|
}
|
|
|
|
//客户资源(学生个人资料)-编辑
|
|
public function editInfo(array $where, array $data)
|
|
{
|
|
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
|
|
if (!$where) {
|
|
$res['msg'] = '查询条件不能为空';
|
|
return $res;
|
|
}
|
|
|
|
$customer_resources_data = [
|
|
'name' => $data['name'], // 姓名
|
|
'gender' => $data['gender'], // 性别(male:男, female:女)
|
|
'age' => $data['age'], // 年龄
|
|
'phone_number' => $data['phone_number'], // 手机号
|
|
];
|
|
|
|
$date = date('Y-m-d H:i:s');
|
|
$customer_resources_data['updated_at'] = $date;
|
|
|
|
//开启事物
|
|
Db::startTrans();
|
|
try {
|
|
$customer_resources = CustomerResources::where('member_id', $where['member_id'])->find();
|
|
|
|
if ($customer_resources) {
|
|
$customer_resources = $customer_resources->toArray();
|
|
}
|
|
$update_1 = CustomerResources::where('id', $customer_resources['id'])->update($customer_resources_data);//客户资源表
|
|
if (!$update_1) {
|
|
Db::rollback();
|
|
return $res;
|
|
}
|
|
|
|
//更新学生账户登录表
|
|
$member_data = [
|
|
'username' => $data['phone_number'],
|
|
'mobile' => $data['phone_number'],
|
|
'update_time' => time()
|
|
];
|
|
if (!empty($data['headimg'])) {
|
|
$member_data['headimg'] = $data['headimg'];
|
|
}
|
|
$update_member = Member::where('member_id', $where['member_id'])->update($member_data);
|
|
if (!$update_member) {
|
|
Db::rollback();
|
|
return $res;
|
|
}
|
|
|
|
|
|
//更近客户资源日志表
|
|
$compareData = (new CommonService)->compareData($customer_resources, $customer_resources_data);
|
|
if ($compareData['changed_fields']) {
|
|
$data = [
|
|
"customer_resource_id" => $customer_resources['id'],//客户资源的ID
|
|
"operator_id" => 0,//操作人的ID
|
|
"campus_id" => 0,//操作人校区的ID|如果这人有2校区就填0
|
|
"modified_fields" => $compareData['changed_fields_json'],//修改的哪些字段
|
|
"old_values" => $compareData['old_values_json'],//修改前的值
|
|
"new_values" => $compareData['new_values_json'],//修改后的值
|
|
];
|
|
|
|
$id = CustomerResourceChanges::insertGetId($data);
|
|
if (!$id) {
|
|
Db::rollback();
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
Db::commit();
|
|
$res = [
|
|
'code' => 1,
|
|
'msg' => '操作成功'
|
|
];
|
|
return $res;
|
|
} catch (\Exception $exception) {
|
|
Db::rollback();
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
//客户资源-获取客户资源修改记录列表
|
|
public function getCustomerResourceChangesEditLog(array $where)
|
|
{
|
|
$page_params = $this->getPageParam();//获取请求参数中的页码+分页数
|
|
$page = $page_params['page'];
|
|
$limit = $page_params['limit'];
|
|
|
|
//客户资源修改记录表
|
|
$data = CustomerResourceChanges::where('customer_resource_id', $where['customer_resource_id'])
|
|
->order('created_at', 'desc')
|
|
->with([
|
|
'personnel' => function ($query) {
|
|
}
|
|
])
|
|
->paginate([
|
|
'list_rows' => $limit,
|
|
'page' => $page,
|
|
])
|
|
->toArray();
|
|
|
|
|
|
$fieldZhArr = CustomerResources::FieldZh;//字段中文映射常量
|
|
//需要获取字段与字典key的映射关系数组
|
|
$fieldDictArr = [
|
|
'source_channel' => 'SourceChannel',//field=>dict_key(来源渠道)
|
|
'source' => 'source',//field=>dict_key(来源)
|
|
'gender' => 'zy_sex',//field=>dict_key(性别)
|
|
'purchasing_power' => 'customer_purchasing_power',//field=>dict_key(购买力)
|
|
'cognitive_idea' => 'cognitive_concept',//field=>dict_key(认知理念)
|
|
'initial_intent' => 'preliminarycustomerintention',//field=>dict_key(客户初步意向度)
|
|
'status' => 'kh_status',//field=>dict_key(客户状态)
|
|
];
|
|
$dict_arr = $this->getFieldDictionary($fieldDictArr);//字段与字典值列表的映射关系
|
|
|
|
$consultant_id_arr = [];
|
|
foreach ($data['data'] as $v) {
|
|
$modified_fields_arr = json_decode($v['modified_fields'], true);
|
|
$old_values_arr = json_decode($v['old_values'], true);
|
|
$new_values_arr = json_decode($v['new_values'], true);
|
|
|
|
//判断有没有修改过"顾问"字段
|
|
if (in_array('consultant', $modified_fields_arr)) {
|
|
$consultant_id_arr[] = $old_values_arr['consultant'];
|
|
$consultant_id_arr[] = $new_values_arr['consultant'];
|
|
}
|
|
}
|
|
$consultant_id_arr = array_unique($consultant_id_arr);//去重
|
|
$dict_arr['consultant'] = [];//获取员工信息列表
|
|
if ($consultant_id_arr) {
|
|
$personnel = Personnel::whereIn('id', $consultant_id_arr)->field('id,name')->select()->toArray();
|
|
foreach ($personnel as $v) {
|
|
$dict_arr['consultant'][] = [
|
|
"name" => $v['name'],
|
|
"value" => $v['id'],
|
|
"sort" => 0,
|
|
"memo" => "",
|
|
];
|
|
}
|
|
}
|
|
|
|
|
|
$fieldDictKeyArr = array_keys($fieldDictArr);
|
|
$list = [];
|
|
foreach ($data['data'] as $v) {
|
|
$modified_fields_arr = json_decode($v['modified_fields'], true);
|
|
$old_values_arr = json_decode($v['old_values'], true);
|
|
$new_values_arr = json_decode($v['new_values'], true);
|
|
|
|
|
|
$update_arr = [];
|
|
foreach ($modified_fields_arr as $m_v) {
|
|
$old_value = $old_values_arr[$m_v] ?? '';
|
|
$new_value = $new_values_arr[$m_v] ?? '';
|
|
|
|
if (in_array($m_v, $fieldDictKeyArr)) {
|
|
$dict = $dict_arr[$m_v];
|
|
foreach ($dict as $d_v) {
|
|
if ($d_v['value'] == $old_value) {
|
|
$old_value = $d_v['name'];
|
|
}
|
|
if ($d_v['value'] == $new_value) {
|
|
$new_value = $d_v['name'];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//一些字典和外键相关的字段值处理
|
|
$update_arr[] = [
|
|
'field_name_en' => $m_v,
|
|
'field_name_zh' => $fieldZhArr[$m_v] ?? $m_v,
|
|
'old_value' => $old_value,
|
|
'new_value' => $new_value,
|
|
];
|
|
}
|
|
|
|
$list[] = [
|
|
'id' => $v['id'],//日志id
|
|
'modification_time' => $v['modification_time'],//修改时间
|
|
'staff_id_name' => $v['staff_id_name'],//修改人的名字
|
|
'update_arr' => $update_arr,//数据变更数组
|
|
];
|
|
}
|
|
|
|
|
|
$data['data'] = $list;
|
|
return $data;
|
|
}
|
|
|
|
//客户资源-获取六要素修改记录列表
|
|
public function getSixSpeedModificationEditLog(array $where)
|
|
{
|
|
$page_params = $this->getPageParam();//获取请求参数中的页码+分页数
|
|
$page = $page_params['page'];
|
|
$limit = $page_params['limit'];
|
|
|
|
//六要素修改记录表
|
|
$data = SixSpeedModificationLog::where('operator_id', $where['customer_resource_id'])
|
|
->order('created_at', 'desc')
|
|
->with([
|
|
'personnel' => function ($query) {
|
|
}
|
|
])
|
|
->paginate([
|
|
'list_rows' => $limit,
|
|
'page' => $page,
|
|
])
|
|
->toArray();
|
|
|
|
|
|
$fieldZhArr = SixSpeed::FieldZh;//字段中文映射常量
|
|
//需要获取字段与字典key的映射关系数组
|
|
$fieldDictArr = [
|
|
'purchase_power' => 'customer_purchasing_power',//field=>dict_key(需求购买力)
|
|
'concept_awareness' => 'cognitive_concept',//field=>dict_key(认知理念)
|
|
'call_intent' => 'preliminarycustomerintention',//field=>dict_key(电话后的意向程度)
|
|
'is_closed' => 'global_true_or_false',//field=>dict_key(是否关单: 1-是, 0-否)
|
|
];
|
|
$dict_arr = $this->getFieldDictionary($fieldDictArr);//字段与字典值列表的映射关系
|
|
|
|
$consultant_id_arr = [];//顾问(人员)id数组
|
|
foreach ($data['data'] as $v) {
|
|
$modified_fields_arr = json_decode($v['modified_field'], true);
|
|
$old_values_arr = json_decode($v['old_value'], true);
|
|
$new_values_arr = json_decode($v['new_value'], true);
|
|
|
|
//判断有没有修改过"顾问(人员)"字段
|
|
if (in_array('staff_id', $modified_fields_arr)) {
|
|
$consultant_id_arr[] = $old_values_arr['staff_id'];
|
|
$consultant_id_arr[] = $new_values_arr['staff_id'];
|
|
}
|
|
}
|
|
$consultant_id_arr = array_unique($consultant_id_arr);//去重
|
|
$dict_arr['consultant'] = [];//获取员工信息列表
|
|
if ($consultant_id_arr) {
|
|
$personnel = Personnel::whereIn('id', $consultant_id_arr)->field('id,name')->select()->toArray();
|
|
foreach ($personnel as $v) {
|
|
$dict_arr['consultant'][] = [
|
|
"name" => $v['name'],
|
|
"value" => $v['id'],
|
|
"sort" => 0,
|
|
"memo" => "",
|
|
];
|
|
}
|
|
}
|
|
|
|
|
|
$fieldDictKeyArr = array_keys($fieldDictArr);
|
|
$list = [];
|
|
foreach ($data['data'] as $v) {
|
|
$modified_fields_arr = json_decode($v['modified_field'], true);
|
|
$old_values_arr = json_decode($v['old_value'], true);
|
|
$new_values_arr = json_decode($v['new_value'], true);
|
|
|
|
|
|
$update_arr = [];
|
|
foreach ($modified_fields_arr as $m_v) {
|
|
$old_value = $old_values_arr[$m_v] ?? '';
|
|
$new_value = $new_values_arr[$m_v] ?? '';
|
|
|
|
if (in_array($m_v, $fieldDictKeyArr)) {
|
|
$dict = $dict_arr[$m_v];
|
|
foreach ($dict as $d_v) {
|
|
if ($d_v['value'] == $old_value) {
|
|
$old_value = $d_v['name'];
|
|
}
|
|
if ($d_v['value'] == $new_value) {
|
|
$new_value = $d_v['name'];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//一些字典和外键相关的字段值处理
|
|
$update_arr[] = [
|
|
'field_name_en' => $m_v,
|
|
'field_name_zh' => $fieldZhArr[$m_v] ?? $m_v,
|
|
'old_value' => $old_value,
|
|
'new_value' => $new_value,
|
|
];
|
|
}
|
|
|
|
$list[] = [
|
|
'id' => $v['id'],//日志id
|
|
'modification_time' => $v['updated_at'],//修改时间
|
|
'staff_id_name' => $v['staff_id_name'],//修改人的名字
|
|
'update_arr' => $update_arr,//数据变更数组
|
|
];
|
|
}
|
|
|
|
|
|
$data['data'] = $list;
|
|
return $data;
|
|
}
|
|
|
|
|
|
/**
|
|
* 根据字段和字典键映射关系,获取字段对应字典项
|
|
*
|
|
* @param array $fieldDictMapping 字段 => 字典 key 映射数组
|
|
* @return array 字段 => 字典列表
|
|
*/
|
|
public function getFieldDictionary(array $fieldDictMapping): array
|
|
{
|
|
// 获取所有需要的字典 key 列表
|
|
$dictKeys = array_values($fieldDictMapping);
|
|
|
|
if (empty($dictKeys)) {
|
|
return [];
|
|
}
|
|
|
|
// 查询字典数据 - 使用正确的表名
|
|
$dictData = \think\facade\Db::table('school_sys_dict')->whereIn('key', $dictKeys)->select()->toArray();
|
|
|
|
//使用 array_column 构建 key => dict 的映射
|
|
$dictMap = array_column($dictData, null, 'key'); // 以 key 字段为索引
|
|
|
|
|
|
// 构建字段 => 字典项的映射
|
|
$result = [];
|
|
foreach ($fieldDictMapping as $field => $key) {
|
|
$dictionary = [];
|
|
if (isset($dictMap[$key]['dictionary']) && !empty($dictMap[$key]['dictionary'])) {
|
|
// 数据库中的字段是双层JSON编码,需要两次解码
|
|
$jsonString = json_decode($dictMap[$key]['dictionary'], true);
|
|
if (is_string($jsonString)) {
|
|
$dictionary = json_decode($jsonString, true) ?: [];
|
|
} else {
|
|
$dictionary = $jsonString ?: [];
|
|
}
|
|
}
|
|
$result[$field] = $dictionary;
|
|
//判断是不是获取的"来源渠道"的字典
|
|
if ($field == 'source_channel') {
|
|
$append_arr = [
|
|
"name" => "线下",
|
|
"value" => "0",
|
|
"sort" => 0,
|
|
"memo" => "",
|
|
];
|
|
//插入到数组头部
|
|
array_unshift($result[$field], $append_arr);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
/**
|
|
* 发放转介绍奖励
|
|
* @param int $referral_resource_id 推荐人资源ID
|
|
* @param int $new_resource_id 新客户资源ID
|
|
* @return void
|
|
*/
|
|
private function grantReferralReward($referral_resource_id, $new_resource_id)
|
|
{
|
|
try {
|
|
// 查找推荐人信息
|
|
$referralResource = CustomerResources::where('id', $referral_resource_id)->find();
|
|
if (!$referralResource) {
|
|
Log::error("转介绍奖励发放失败:推荐人资源不存在,ID: $referral_resource_id");
|
|
return;
|
|
}
|
|
|
|
// 奖励配置(可以后续移到配置文件中)
|
|
$rewardConfig = [
|
|
'gift_name' => '转介绍奖励',
|
|
'gift_type' => 'referral_reward',
|
|
'reward_amount' => 100, // 奖励金额,可配置
|
|
];
|
|
|
|
// 插入奖励记录到shcool_resources_gift表
|
|
$giftData = [
|
|
'gift_name' => $rewardConfig['gift_name'],
|
|
'gift_type' => $rewardConfig['gift_type'],
|
|
'gift_time' => time(),
|
|
'giver_id' => $new_resource_id, // 新客户作为赠送来源
|
|
'resource_id' => $referral_resource_id, // 推荐人作为接收者
|
|
'order_id' => 0, // 非订单相关奖励
|
|
'gift_status' => 1, // 已发放状态
|
|
'use_time' => 0,
|
|
'create_time' => time(),
|
|
'update_time' => time(),
|
|
'delete_time' => 0,
|
|
];
|
|
|
|
Db::table('shcool_resources_gift')->insert($giftData);
|
|
|
|
Log::info("转介绍奖励发放成功:推荐人ID $referral_resource_id,新客户ID $new_resource_id");
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error("转介绍奖励发放异常:" . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function updateUserCourseInfo($data)
|
|
{
|
|
// 验证必要参数
|
|
if (empty($data['id'])) {
|
|
return ['code' => false, 'msg' => '缺少必要参数id'];
|
|
}
|
|
|
|
try {
|
|
// 更新school_student_courses表中的字段
|
|
$update_data = [];
|
|
|
|
// 更新主教练ID
|
|
if (isset($data['main_coach_id'])) {
|
|
$update_data['main_coach_id'] = $data['main_coach_id'];
|
|
}
|
|
|
|
// 更新助教IDs
|
|
if (isset($data['assistant_ids'])) {
|
|
$update_data['assistant_ids'] = $data['assistant_ids'];
|
|
}
|
|
|
|
// 更新教务ID
|
|
if (isset($data['education_id'])) {
|
|
$update_data['education_id'] = $data['education_id'];
|
|
}
|
|
|
|
// 如果没有需要更新的数据,直接返回成功
|
|
if (empty($update_data)) {
|
|
return ['code' => true, 'msg' => '更新成功'];
|
|
}
|
|
|
|
// 执行更新操作
|
|
$res = \think\facade\Db::name('student_courses')
|
|
->where('id', $data['id'])
|
|
->update($update_data);
|
|
|
|
if ($res !== false) {
|
|
return ['code' => true, 'msg' => '更新成功'];
|
|
} else {
|
|
return ['code' => false, 'msg' => '更新失败'];
|
|
}
|
|
} catch (\Exception $e) {
|
|
return ['code' => false, 'msg' => '更新失败:' . $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取客户赠品记录列表
|
|
* @param array $where 查询条件
|
|
* @return array
|
|
*/
|
|
public function getGiftRecordList(array $where)
|
|
{
|
|
try {
|
|
$resource_id = $where['resource_id'] ?? 0;
|
|
|
|
if (empty($resource_id)) {
|
|
return ['code' => false, 'msg' => '缺少客户资源ID'];
|
|
}
|
|
|
|
// 查询赠品记录,同时关联查询赠送人信息
|
|
$gift_records = Db::table('shcool_resources_gift')
|
|
->alias('g')
|
|
->leftJoin('customer_resources cr', 'g.giver_id = cr.id')
|
|
->where('g.resource_id', $resource_id)
|
|
->where('g.delete_time', 0)
|
|
->where('g.gift_status', 1)
|
|
->where('g.order_id', 0)
|
|
->field([
|
|
'g.*',
|
|
'cr.name as giver_name',
|
|
'cr.phone_number as giver_phone'
|
|
])
|
|
->order('g.create_time', 'desc')
|
|
->select()
|
|
->toArray();
|
|
|
|
// 处理数据格式
|
|
$formatted_records = [];
|
|
foreach ($gift_records as $record) {
|
|
$formatted_records[] = [
|
|
'id' => $record['id'],
|
|
'gift_name' => $record['gift_name'],
|
|
'gift_type' => $record['gift_type'],
|
|
'gift_type_text' => $this->getGiftTypeText($record['gift_type']),
|
|
'gift_time' => $record['gift_time'],
|
|
'gift_time_formatted' => date('Y-m-d H:i:s', $record['gift_time']),
|
|
'giver_id' => $record['giver_id'],
|
|
'giver_name' => $record['giver_name'] ?: '系统赠送',
|
|
'giver_phone' => $record['giver_phone'] ?: '',
|
|
'order_id' => $record['order_id'],
|
|
'gift_status' => $record['gift_status'],
|
|
'gift_status_text' => $this->getGiftStatusText($record['gift_status']),
|
|
'use_time' => $record['use_time'],
|
|
'use_time_formatted' => $record['use_time'] ? date('Y-m-d H:i:s', $record['use_time']) : '',
|
|
'create_time' => date('Y-m-d H:i:s', $record['create_time'])
|
|
];
|
|
}
|
|
|
|
return [
|
|
'code' => true,
|
|
'msg' => '获取成功',
|
|
'data' => $formatted_records
|
|
];
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('获取赠品记录失败:' . $e->getMessage());
|
|
return [
|
|
'code' => false,
|
|
'msg' => '获取赠品记录失败:' . $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取赠品类型文本
|
|
* @param string $gift_type
|
|
* @return string
|
|
*/
|
|
private function getGiftTypeText($gift_type)
|
|
{
|
|
$type_map = [
|
|
'referral_reward' => '转介绍奖励',
|
|
'sign_reward' => '签到奖励',
|
|
'course_reward' => '课程奖励',
|
|
'activity_reward' => '活动奖励',
|
|
'other' => '其他'
|
|
];
|
|
|
|
return $type_map[$gift_type] ?? $gift_type;
|
|
}
|
|
|
|
/**
|
|
* 获取赠品状态文本
|
|
* @param int $gift_status
|
|
* @return string
|
|
*/
|
|
private function getGiftStatusText($gift_status)
|
|
{
|
|
$status_map = [
|
|
0 => '已失效',
|
|
1 => '可使用',
|
|
2 => '已使用'
|
|
];
|
|
|
|
return $status_map[$gift_status] ?? '未知状态';
|
|
}
|
|
|
|
/**
|
|
* 获取学生标签信息
|
|
* @param array $where
|
|
* @return array
|
|
*/
|
|
public function getStudentLabel($where)
|
|
{
|
|
try {
|
|
$label_id = $where['label_id'] ?? '';
|
|
if (empty($label_id)) {
|
|
return [
|
|
'code' => false,
|
|
'msg' => '标签ID不能为空'
|
|
];
|
|
}
|
|
|
|
// 查询学生标签信息
|
|
$label_info = Db::table('school_student_label')
|
|
->where('label_id', $label_id)
|
|
->field('label_id, label_name, memo')
|
|
->find();
|
|
return [
|
|
'code' => true,
|
|
'msg' => '获取成功',
|
|
'data' => $label_info
|
|
];
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('获取学生标签失败:' . $e->getMessage());
|
|
return [
|
|
'code' => false,
|
|
'msg' => '获取学生标签失败:' . $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取所有学生标签列表
|
|
* @return array
|
|
*/
|
|
public function getAllStudentLabels()
|
|
{
|
|
try {
|
|
// 查询所有学生标签信息
|
|
$label_list = Db::table('school_student_label')
|
|
->field('label_id, label_name, memo, sort')
|
|
->order('sort asc, label_id asc')
|
|
->select();
|
|
|
|
// 确保返回数组格式
|
|
$result = [];
|
|
if ($label_list) {
|
|
foreach ($label_list as $label) {
|
|
$result[] = [
|
|
'label_id' => (int)$label['label_id'],
|
|
'label_name' => $label['label_name'],
|
|
'memo' => $label['memo'],
|
|
'sort' => (int)$label['sort']
|
|
];
|
|
}
|
|
}
|
|
|
|
return [
|
|
'code' => true,
|
|
'msg' => '获取成功',
|
|
'data' => $result
|
|
];
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('获取学生标签列表失败:' . $e->getMessage());
|
|
return [
|
|
'code' => false,
|
|
'msg' => '获取学生标签列表失败:' . $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 搜索学员(用于课程安排)
|
|
* @param array $where 搜索条件
|
|
* @param string $field 返回字段
|
|
* @return array
|
|
*/
|
|
public function searchStudents(array $where, string $field = '*')
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
|
|
try {
|
|
// 构建查询条件
|
|
$query = Db::table('school_student')
|
|
->alias('s')
|
|
->leftJoin('school_student_courses sc', 's.id = sc.student_id')
|
|
->where('s.deleted_at', 0)
|
|
->where('s.status', 1); // 只查询状态正常的学员
|
|
|
|
// 按姓名搜索
|
|
if (!empty($where['name'])) {
|
|
$query->where('s.name', 'like', "%{$where['name']}%");
|
|
}
|
|
|
|
// 按手机号搜索
|
|
if (!empty($where['phone_number'])) {
|
|
$query->where('s.contact_phone', 'like', "%{$where['phone_number']}%");
|
|
}
|
|
|
|
// 获取学员基本信息和课程信息
|
|
$students = $query
|
|
->field([
|
|
's.id as student_id',
|
|
's.name',
|
|
's.age',
|
|
's.contact_phone',
|
|
's.gender',
|
|
's.birthday',
|
|
's.campus_id',
|
|
's.class_id',
|
|
's.trial_class_count',
|
|
's.headimg',
|
|
's.first_come',
|
|
's.second_come',
|
|
's.user_id as resource_id',
|
|
'sc.id as student_course_id',
|
|
'sc.total_hours',
|
|
'sc.use_total_hours',
|
|
'sc.gift_hours',
|
|
'sc.use_gift_hours',
|
|
'sc.start_date',
|
|
'sc.end_date',
|
|
'sc.course_id'
|
|
])
|
|
->group('s.id')
|
|
->order('s.created_at DESC')
|
|
->select();
|
|
|
|
if (!$students) {
|
|
$res['msg'] = '暂无学员数据';
|
|
return $res;
|
|
}
|
|
|
|
// 处理数据格式,计算课程进度
|
|
$result = [];
|
|
foreach ($students as $student) {
|
|
$totalHours = intval($student['total_hours'] ?: 0) + intval($student['gift_hours'] ?: 0);
|
|
$usedHours = intval($student['use_total_hours'] ?: 0) + intval($student['use_gift_hours'] ?: 0);
|
|
$remainingHours = $totalHours - $usedHours;
|
|
|
|
// 判断是否为体验课学员
|
|
$isTrialStudent = empty($student['student_course_id']);
|
|
|
|
// 判断是否需要续费
|
|
$needsRenewal = false;
|
|
if (!$isTrialStudent) {
|
|
// 检查到期时间
|
|
if ($student['end_date']) {
|
|
$daysUntilExpiry = (strtotime($student['end_date']) - time()) / (24 * 3600);
|
|
if ($daysUntilExpiry <= 10) {
|
|
$needsRenewal = true;
|
|
}
|
|
}
|
|
// 检查剩余课时
|
|
if ($remainingHours < 4) {
|
|
$needsRenewal = true;
|
|
}
|
|
}
|
|
|
|
$result[] = [
|
|
'id' => $student['student_id'],
|
|
'student_id' => $student['student_id'],
|
|
'name' => $student['name'],
|
|
'age' => floatval($student['age'] ?: 0),
|
|
'phone_number' => $student['contact_phone'],
|
|
'contact_phone' => $student['contact_phone'],
|
|
'gender' => $student['gender'],
|
|
'birthday' => $student['birthday'],
|
|
'campus_id' => $student['campus_id'],
|
|
'class_id' => $student['class_id'],
|
|
'trial_class_count' => intval($student['trial_class_count'] ?: 0),
|
|
'headimg' => $student['headimg'],
|
|
'first_come' => $student['first_come'],
|
|
'second_come' => $student['second_come'],
|
|
'resource_id' => intval($student['resource_id'] ?: 0), // 客户资源表ID
|
|
'person_type' => 'student', // 标识为学员类型
|
|
'courseStatus' => $isTrialStudent ? '体验课' : '正式课',
|
|
'isTrialStudent' => $isTrialStudent,
|
|
'is_formal_student' => !$isTrialStudent, // 有付费课程记录的为正式学员,可以选固定课
|
|
'needsRenewal' => $needsRenewal,
|
|
'student_course_info' => [
|
|
'id' => $student['student_course_id'],
|
|
'total_hours' => $student['total_hours'],
|
|
'use_total_hours' => $student['use_total_hours'],
|
|
'gift_hours' => $student['gift_hours'],
|
|
'use_gift_hours' => $student['use_gift_hours'],
|
|
'start_date' => $student['start_date'],
|
|
'end_date' => $student['end_date'],
|
|
'course_id' => $student['course_id']
|
|
],
|
|
'course_progress' => [
|
|
'total' => $totalHours,
|
|
'used' => $usedHours,
|
|
'remaining' => $remainingHours,
|
|
'percentage' => $totalHours > 0 ? round(($usedHours / $totalHours) * 100, 1) : 0
|
|
],
|
|
'remainingHours' => $remainingHours,
|
|
'totalHours' => $totalHours,
|
|
'usedHours' => $usedHours,
|
|
'expiryDate' => $student['end_date']
|
|
];
|
|
}
|
|
|
|
$res['code'] = 1;
|
|
$res['msg'] = '操作成功';
|
|
$res['data'] = $result;
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('搜索学员失败:' . $e->getMessage());
|
|
$res['msg'] = '搜索学员失败:' . $e->getMessage();
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* 根据资源ID和学员ID获取预设学员信息(不受状态限制)
|
|
* @param array $where 查询条件
|
|
* @return array
|
|
*/
|
|
public function getPresetStudentInfo(array $where)
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
|
|
try {
|
|
$resourceId = $where['resource_id'] ?? 0;
|
|
$studentId = $where['student_id'] ?? 0;
|
|
|
|
if (!$resourceId && !$studentId) {
|
|
$res['msg'] = '缺少必要参数';
|
|
return $res;
|
|
}
|
|
|
|
// 构建查询条件 - 不限制status状态
|
|
$query = Db::table('school_student')
|
|
->alias('s')
|
|
->leftJoin('school_student_courses sc', 's.id = sc.student_id')
|
|
->leftJoin('school_customer_resources cr', 's.user_id = cr.id')
|
|
->where('s.deleted_at', 0)
|
|
->where('s.id', $studentId);
|
|
|
|
// 获取学员基本信息和课程信息
|
|
$student = $query
|
|
->field([
|
|
's.id as student_id',
|
|
's.name',
|
|
's.age',
|
|
's.contact_phone',
|
|
's.gender',
|
|
's.birthday',
|
|
's.campus_id',
|
|
's.class_id',
|
|
's.trial_class_count',
|
|
's.headimg',
|
|
's.first_come',
|
|
's.second_come',
|
|
's.user_id as resource_id',
|
|
's.status as student_status',
|
|
'cr.phone_number',
|
|
'cr.member_id',
|
|
'sc.id as student_course_id',
|
|
'sc.total_hours',
|
|
'sc.use_total_hours',
|
|
'sc.gift_hours',
|
|
'sc.use_gift_hours',
|
|
'sc.start_date',
|
|
'sc.end_date',
|
|
'sc.course_id'
|
|
])
|
|
->find();
|
|
|
|
if (!$student) {
|
|
$res['msg'] = '学员不存在';
|
|
return $res;
|
|
}
|
|
|
|
// 计算课程进度和状态
|
|
$totalHours = intval($student['total_hours'] ?: 0) + intval($student['gift_hours'] ?: 0);
|
|
$usedHours = intval($student['use_total_hours'] ?: 0) + intval($student['use_gift_hours'] ?: 0);
|
|
$remainingHours = $totalHours - $usedHours;
|
|
|
|
// 判断是否为体验课学员
|
|
$isTrialStudent = empty($student['student_course_id']);
|
|
|
|
// 判断是否需要续费
|
|
$needsRenewal = false;
|
|
if (!$isTrialStudent) {
|
|
// 检查到期时间
|
|
if ($student['end_date']) {
|
|
$daysUntilExpiry = (strtotime($student['end_date']) - time()) / (24 * 3600);
|
|
if ($daysUntilExpiry <= 10) {
|
|
$needsRenewal = true;
|
|
}
|
|
}
|
|
// 检查剩余课时
|
|
if ($remainingHours < 4) {
|
|
$needsRenewal = true;
|
|
}
|
|
}
|
|
|
|
$result = [
|
|
'id' => $student['student_id'],
|
|
'student_id' => $student['student_id'],
|
|
'name' => $student['name'],
|
|
'age' => floatval($student['age'] ?: 0),
|
|
'phone_number' => $student['contact_phone'] ?: $student['phone_number'],
|
|
'contact_phone' => $student['contact_phone'] ?: $student['phone_number'],
|
|
'gender' => $student['gender'],
|
|
'birthday' => $student['birthday'],
|
|
'campus_id' => $student['campus_id'],
|
|
'class_id' => $student['class_id'],
|
|
'trial_class_count' => intval($student['trial_class_count'] ?: 0),
|
|
'headimg' => $student['headimg'],
|
|
'first_come' => $student['first_come'],
|
|
'second_come' => $student['second_come'],
|
|
'resource_id' => $student['resource_id'],
|
|
'member_id' => $student['member_id'],
|
|
'student_status' => $student['student_status'],
|
|
'person_type' => 'student',
|
|
'courseStatus' => $isTrialStudent ? '体验课' : '正式课',
|
|
'isTrialStudent' => $isTrialStudent,
|
|
'is_formal_student' => !$isTrialStudent, // 有付费课程记录的为正式学员,可以选固定课
|
|
'needsRenewal' => $needsRenewal,
|
|
'student_course_info' => [
|
|
'id' => $student['student_course_id'],
|
|
'total_hours' => $student['total_hours'],
|
|
'use_total_hours' => $student['use_total_hours'],
|
|
'gift_hours' => $student['gift_hours'],
|
|
'use_gift_hours' => $student['use_gift_hours'],
|
|
'start_date' => $student['start_date'],
|
|
'end_date' => $student['end_date'],
|
|
'course_id' => $student['course_id']
|
|
],
|
|
'course_progress' => [
|
|
'total' => $totalHours,
|
|
'used' => $usedHours,
|
|
'remaining' => $remainingHours,
|
|
'percentage' => $totalHours > 0 ? round(($usedHours / $totalHours) * 100, 1) : 0
|
|
],
|
|
'remainingHours' => $remainingHours,
|
|
'totalHours' => $totalHours,
|
|
'usedHours' => $usedHours,
|
|
'expiryDate' => $student['end_date']
|
|
];
|
|
|
|
$res['code'] = 1;
|
|
$res['msg'] = '操作成功';
|
|
$res['data'] = $result;
|
|
|
|
} catch (\Exception $exception) {
|
|
$res['msg'] = '获取预设学员信息失败:' . $exception->getMessage();
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
}
|
|
|