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.
423 lines
14 KiB
423 lines
14 KiB
<?php
|
|
|
|
namespace app\api\controller;
|
|
|
|
use core\base\BaseApiController;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 市场统计数据API控制器
|
|
*/
|
|
class MarketStats extends BaseApiController
|
|
{
|
|
/**
|
|
* 获取个人统计数据
|
|
*/
|
|
public function getPersonalStats()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$startDate = $this->request->post('start_date');
|
|
$endDate = $this->request->post('end_date');
|
|
|
|
if (empty($staffId)) {
|
|
return fail('缺少员工ID');
|
|
}
|
|
|
|
try {
|
|
$stats = [
|
|
'resource_count' => $this->getResourceCount($staffId, $startDate, $endDate),
|
|
'converted_count' => $this->getConvertedCount($staffId, $startDate, $endDate),
|
|
'performance' => $this->getPerformance($staffId, $startDate, $endDate),
|
|
'commission' => $this->getCommission($staffId, $startDate, $endDate),
|
|
'bonus' => $this->getBonus($staffId, $startDate, $endDate)
|
|
];
|
|
|
|
return success($stats);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取团队统计数据
|
|
*/
|
|
public function getTeamStats()
|
|
{
|
|
$campusId = $this->request->post('campus_id');
|
|
$deptId = $this->request->post('dept_id');
|
|
$startDate = $this->request->post('start_date');
|
|
$endDate = $this->request->post('end_date');
|
|
|
|
if (empty($campusId) || empty($deptId)) {
|
|
return fail('缺少校区或部门信息');
|
|
}
|
|
|
|
try {
|
|
$stats = [
|
|
'team_members' => $this->getTeamMembers($campusId, $deptId),
|
|
'team_performance' => $this->getTeamPerformance($campusId, $deptId, $startDate, $endDate),
|
|
'ranking' => $this->getTeamRanking($campusId, $deptId, $startDate, $endDate)
|
|
];
|
|
|
|
return success($stats);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取渠道分布统计
|
|
*/
|
|
public function getChannelDistribution()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$startDate = $this->request->post('start_date');
|
|
$endDate = $this->request->post('end_date');
|
|
|
|
try {
|
|
$distribution = Db::table('school_customer_resources')
|
|
->field('source_channel, COUNT(*) as count')
|
|
->where('consultant', $staffId)
|
|
->where('deleted_at', 0)
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('created_at', '<=', $endDate);
|
|
})
|
|
->group('source_channel')
|
|
->select();
|
|
|
|
return success($distribution);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取来源分布统计
|
|
*/
|
|
public function getSourceDistribution()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$startDate = $this->request->post('start_date');
|
|
$endDate = $this->request->post('end_date');
|
|
|
|
try {
|
|
$distribution = Db::table('school_customer_resources')
|
|
->field('source, COUNT(*) as count')
|
|
->where('consultant', $staffId)
|
|
->where('deleted_at', 0)
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('created_at', '<=', $endDate);
|
|
})
|
|
->whereNotNull('source')
|
|
->where('source', '<>', '')
|
|
->group('source')
|
|
->select();
|
|
|
|
return success($distribution);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取转化漏斗数据
|
|
*/
|
|
public function getConversionFunnel()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$startDate = $this->request->post('start_date');
|
|
$endDate = $this->request->post('end_date');
|
|
|
|
try {
|
|
// 总资源数
|
|
$totalResources = Db::table('school_customer_resources')
|
|
->where('consultant', $staffId)
|
|
->where('deleted_at', 0)
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('created_at', '<=', $endDate);
|
|
})
|
|
->count();
|
|
|
|
// 成交客户数
|
|
$convertedResources = Db::table('school_customer_resources r')
|
|
->join('school_order_table o', 'r.id = o.resource_id')
|
|
->where('r.consultant', $staffId)
|
|
->where('r.deleted_at', 0)
|
|
->where('o.order_type', '1')
|
|
->where('o.order_status', 'paid')
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('r.created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('r.created_at', '<=', $endDate);
|
|
})
|
|
->count();
|
|
|
|
$funnel = [
|
|
'total_resources' => $totalResources,
|
|
'converted_resources' => $convertedResources,
|
|
'conversion_rate' => $totalResources > 0 ? round($convertedResources * 100 / $totalResources, 1) : 0
|
|
];
|
|
|
|
return success($funnel);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取月度趋势数据
|
|
*/
|
|
public function getMonthlyTrend()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$months = $this->request->post('months', 6);
|
|
|
|
try {
|
|
$results = Db::table('school_customer_resources')
|
|
->field("DATE_FORMAT(created_at, '%Y-%m') as month, COUNT(*) as count")
|
|
->where('consultant', $staffId)
|
|
->where('deleted_at', 0)
|
|
->group('month')
|
|
->order('month DESC')
|
|
->limit($months)
|
|
->select();
|
|
|
|
return success(array_reverse($results));
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取提成明细数据
|
|
*/
|
|
public function getCommissionBreakdown()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$startDate = $this->request->post('start_date');
|
|
$endDate = $this->request->post('end_date');
|
|
|
|
try {
|
|
$results = Db::table('school_performance_records')
|
|
->field('performance_type, SUM(performance_value) as total_amount, COUNT(*) as count')
|
|
->where('staff_id', $staffId)
|
|
->whereIn('performance_type', ['sales', 'marketing', 'consultant'])
|
|
->where('order_status', 'completed')
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('created_at', '<=', $endDate);
|
|
})
|
|
->group('performance_type')
|
|
->select();
|
|
|
|
return success($results);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取奖励历史数据
|
|
*/
|
|
public function getBonusHistory()
|
|
{
|
|
$staffId = $this->request->post('staff_id');
|
|
$months = $this->request->post('months', 6);
|
|
|
|
try {
|
|
$results = Db::table('school_salary')
|
|
->field('salary_month, other_subsidies as amount')
|
|
->where('staff_id', $staffId)
|
|
->where('other_subsidies', '>', 0)
|
|
->order('salary_month DESC')
|
|
->limit($months)
|
|
->select();
|
|
|
|
return success($results);
|
|
|
|
} catch (\Exception $e) {
|
|
return fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
// ========== 私有查询方法 ==========
|
|
|
|
/**
|
|
* 获取资源数量
|
|
*/
|
|
private function getResourceCount($staffId, $startDate = null, $endDate = null)
|
|
{
|
|
return Db::table('school_customer_resources')
|
|
->where('consultant', $staffId)
|
|
->where('deleted_at', 0)
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('created_at', '<=', $endDate);
|
|
})
|
|
->count();
|
|
}
|
|
|
|
/**
|
|
* 获取成交客户数量
|
|
*/
|
|
private function getConvertedCount($staffId, $startDate = null, $endDate = null)
|
|
{
|
|
return Db::table('school_customer_resources r')
|
|
->join('school_order_table o', 'r.id = o.resource_id')
|
|
->where('r.consultant', $staffId)
|
|
->where('r.deleted_at', 0)
|
|
->where('o.order_type', '1')
|
|
->where('o.order_status', 'paid')
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('r.created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('r.created_at', '<=', $endDate);
|
|
})
|
|
->count();
|
|
}
|
|
|
|
/**
|
|
* 获取业绩数据
|
|
*/
|
|
private function getPerformance($staffId, $startDate = null, $endDate = null)
|
|
{
|
|
$result = Db::table('school_order_table')
|
|
->where('staff_id', $staffId)
|
|
->where('order_type', '1')
|
|
->where('order_status', 'paid')
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('payment_time', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('payment_time', '<=', $endDate);
|
|
})
|
|
->sum('order_amount');
|
|
|
|
return $result ?: 0;
|
|
}
|
|
|
|
/**
|
|
* 获取提成数据
|
|
*/
|
|
private function getCommission($staffId, $startDate = null, $endDate = null)
|
|
{
|
|
$result = Db::table('school_performance_records')
|
|
->where('staff_id', $staffId)
|
|
->whereIn('performance_type', ['sales', 'marketing', 'consultant'])
|
|
->where('order_status', 'completed')
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('created_at', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('created_at', '<=', $endDate);
|
|
})
|
|
->sum('performance_value');
|
|
|
|
return $result ?: 0;
|
|
}
|
|
|
|
/**
|
|
* 获取奖励数据
|
|
*/
|
|
private function getBonus($staffId, $startDate = null, $endDate = null)
|
|
{
|
|
$result = Db::table('school_salary')
|
|
->where('staff_id', $staffId)
|
|
->where('other_subsidies', '>', 0)
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('salary_month', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('salary_month', '<=', $endDate);
|
|
})
|
|
->sum('other_subsidies');
|
|
|
|
return $result ?: 0;
|
|
}
|
|
|
|
/**
|
|
* 获取团队成员
|
|
*/
|
|
private function getTeamMembers($campusId, $deptId)
|
|
{
|
|
return Db::table('school_personnel p')
|
|
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
|
|
->where('cpr.campus_id', $campusId)
|
|
->where('cpr.dept_id', $deptId)
|
|
->where('p.status', 1)
|
|
->where('p.deleted_at', '0')
|
|
->field('p.id, p.name')
|
|
->select();
|
|
}
|
|
|
|
/**
|
|
* 获取团队业绩
|
|
*/
|
|
private function getTeamPerformance($campusId, $deptId, $startDate = null, $endDate = null)
|
|
{
|
|
$members = $this->getTeamMembers($campusId, $deptId);
|
|
$memberIds = array_column($members, 'id');
|
|
|
|
$result = Db::table('school_order_table')
|
|
->whereIn('staff_id', $memberIds)
|
|
->where('order_type', '1')
|
|
->where('order_status', 'paid')
|
|
->when($startDate, function($query) use ($startDate) {
|
|
return $query->whereTime('payment_time', '>=', $startDate);
|
|
})
|
|
->when($endDate, function($query) use ($endDate) {
|
|
return $query->whereTime('payment_time', '<=', $endDate);
|
|
})
|
|
->sum('order_amount');
|
|
|
|
return $result ?: 0;
|
|
}
|
|
|
|
/**
|
|
* 获取团队排名
|
|
*/
|
|
private function getTeamRanking($campusId, $deptId, $startDate = null, $endDate = null)
|
|
{
|
|
$members = $this->getTeamMembers($campusId, $deptId);
|
|
$memberIds = array_column($members, 'id');
|
|
|
|
$ranking = [];
|
|
foreach ($members as $member) {
|
|
$performance = $this->getPerformance($member['id'], $startDate, $endDate);
|
|
$ranking[] = [
|
|
'staff_id' => $member['id'],
|
|
'staff_name' => $member['name'],
|
|
'performance' => $performance
|
|
];
|
|
}
|
|
|
|
// 按业绩排序
|
|
usort($ranking, function($a, $b) {
|
|
return $b['performance'] <=> $a['performance'];
|
|
});
|
|
|
|
return $ranking;
|
|
}
|
|
}
|