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.
238 lines
8.2 KiB
238 lines
8.2 KiB
<?php
|
|
|
|
namespace app\job\transfer\schedule;
|
|
|
|
use app\model\campus_person_role\CampusPersonRole;
|
|
use app\model\resource_sharing\ResourceSharing;
|
|
use core\base\BaseScheduleJob;
|
|
use think\facade\Db;
|
|
use think\facade\Log;
|
|
|
|
/**
|
|
* 自动分配资源
|
|
*/
|
|
class ResourceAutoAllocation extends BaseScheduleJob
|
|
{
|
|
/**
|
|
* 任务名称
|
|
* @var string
|
|
*/
|
|
protected $jobName = 'resource_allocation';
|
|
|
|
/**
|
|
* 锁定时间(5分钟)
|
|
* @var int
|
|
*/
|
|
protected $lockTimeout = 300;
|
|
|
|
/**
|
|
* 执行具体任务
|
|
* @return array
|
|
*/
|
|
protected function executeJob()
|
|
{
|
|
// 获取待分配的资源
|
|
$resources = $this->getResource();
|
|
if (empty($resources)) {
|
|
Log::write('没有可分配的资源');
|
|
return $this->getSuccessResult([
|
|
'allocated' => 0,
|
|
'message' => '没有可分配的资源'
|
|
]);
|
|
}
|
|
|
|
// 获取销售人员
|
|
$salesmen = $this->getSalesman();
|
|
if (empty($salesmen)) {
|
|
Log::write('没有可用的销售人员');
|
|
return $this->getSuccessResult([
|
|
'allocated' => 0,
|
|
'message' => '没有可用的销售人员'
|
|
]);
|
|
}
|
|
|
|
// 分配资源
|
|
$result = $this->allocateResource($resources, $salesmen);
|
|
|
|
return $this->getSuccessResult([
|
|
'allocated' => $result['allocated'] ?? 0,
|
|
'updated' => $result['updated'] ?? 0,
|
|
'created' => $result['created'] ?? 0,
|
|
'total_resources' => count($resources),
|
|
'total_salesmen' => count($salesmen)
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 获取销售人员(角色ID为6或7的人员)
|
|
* @return array 销售人员列表
|
|
*/
|
|
public function getSalesman()
|
|
{
|
|
Log::write('获取销售人员');
|
|
|
|
// 获取角色ID为6或7的人员ID
|
|
$salesmen = CampusPersonRole::where('role_id', 'in', [6, 7])
|
|
->where('deleted_at', 0) // 未删除的记录
|
|
->field('person_id, role_id')
|
|
->select()
|
|
->toArray();
|
|
|
|
if (empty($salesmen)) {
|
|
Log::write('未找到销售人员');
|
|
return [];
|
|
}
|
|
|
|
// 获取每个销售人员当前拥有的资源数量
|
|
foreach ($salesmen as &$salesman) {
|
|
$resourceCount = ResourceSharing::where('shared_by', $salesman['person_id'])
|
|
->count();
|
|
$salesman['resource_count'] = $resourceCount;
|
|
}
|
|
|
|
// 按资源数量升序排序,资源少的排在前面
|
|
array_multisort(array_column($salesmen, 'resource_count'), SORT_ASC, $salesmen);
|
|
|
|
Log::write('找到' . count($salesmen) . '个销售人员');
|
|
return $salesmen;
|
|
}
|
|
|
|
/**
|
|
* 获取待分配的资源
|
|
* @return array 待分配资源列表
|
|
*/
|
|
public function getResource()
|
|
{
|
|
Log::write('获取待分配资源');
|
|
|
|
// 获取role_id不是6,7的,shared_by是0的资源ID
|
|
$resources = ResourceSharing::where(function ($query) {
|
|
$query->where('role_id', 'not in', [6, 7])
|
|
->whereOr('role_id', 'null');
|
|
})
|
|
->where('shared_by', 0)
|
|
->field('id, resource_id')
|
|
->select()
|
|
->toArray();
|
|
|
|
Log::write('找到' . count($resources) . '个待分配资源');
|
|
return $resources;
|
|
}
|
|
|
|
/**
|
|
* 按照销售人员的资源拥有情况分配资源
|
|
* @param array $resources 待分配的资源列表
|
|
* @param array $salesmen 销售人员列表
|
|
*/
|
|
public function allocateResource($resources, $salesmen)
|
|
{
|
|
Log::write('按照销售人员的资源拥有情况分配资源');
|
|
|
|
if (empty($resources) || empty($salesmen)) {
|
|
Log::write('没有资源或销售人员,无法分配');
|
|
return;
|
|
}
|
|
|
|
// 记录分配结果
|
|
$allocations = [];
|
|
|
|
// 开始分配
|
|
foreach ($resources as $resource) {
|
|
// 重新获取销售人员的资源数量排序,确保每次分配都是给最少资源的人
|
|
$currentSalesmen = $this->refreshSalesmenResourceCount($salesmen);
|
|
|
|
if (empty($currentSalesmen)) {
|
|
Log::write('没有可用的销售人员');
|
|
break;
|
|
}
|
|
|
|
// 选择资源最少的销售人员
|
|
$targetSalesman = $currentSalesmen[0];
|
|
|
|
// 更新现有资源记录,而不是插入新记录
|
|
try {
|
|
Db::startTrans();
|
|
|
|
// 检查是否存在该资源的分配记录
|
|
$existingRecord = ResourceSharing::where('id', $resource['id'])->find();
|
|
|
|
if ($existingRecord) {
|
|
// 更新现有记录
|
|
$updateData = [
|
|
'user_id' => $targetSalesman['person_id'],
|
|
'role_id' => $targetSalesman['role_id'],
|
|
'shared_by' => $targetSalesman['person_id'],
|
|
'shared_at' => date('Y-m-d H:i:s'),
|
|
'updated_at' => time()
|
|
];
|
|
|
|
ResourceSharing::where('id', $resource['id'])->update($updateData);
|
|
|
|
Log::write('更新资源分配记录,资源ID:' . $resource['resource_id'] . ' 分配给销售人员ID:' . $targetSalesman['person_id']);
|
|
} else {
|
|
// 如果记录不存在,创建新记录
|
|
$insertData = [
|
|
'resource_id' => $resource['resource_id'],
|
|
'user_id' => $targetSalesman['person_id'],
|
|
'role_id' => $targetSalesman['role_id'],
|
|
'shared_by' => $targetSalesman['person_id'],
|
|
'shared_at' => date('Y-m-d H:i:s'),
|
|
'created_at' => time(),
|
|
'updated_at' => time()
|
|
];
|
|
|
|
ResourceSharing::create($insertData);
|
|
|
|
Log::write('创建新资源分配记录,资源ID:' . $resource['resource_id'] . ' 分配给销售人员ID:' . $targetSalesman['person_id']);
|
|
}
|
|
|
|
// 记录分配结果
|
|
$allocations[] = [
|
|
'resource_id' => $resource['resource_id'],
|
|
'salesman_id' => $targetSalesman['person_id'],
|
|
'action' => $existingRecord ? 'updated' : 'created'
|
|
];
|
|
|
|
Db::commit();
|
|
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
Log::write('资源分配失败:' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
$updatedCount = count(array_filter($allocations, function($a) { return $a['action'] == 'updated'; }));
|
|
$createdCount = count(array_filter($allocations, function($a) { return $a['action'] == 'created'; }));
|
|
|
|
Log::write('成功分配' . count($allocations) . '个资源,其中更新:' . $updatedCount . '个,新建:' . $createdCount . '个');
|
|
|
|
return [
|
|
'allocated' => count($allocations),
|
|
'updated' => $updatedCount,
|
|
'created' => $createdCount
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 刷新销售人员的资源数量并重新排序
|
|
* @param array $salesmen 销售人员列表
|
|
* @return array 更新后的销售人员列表
|
|
*/
|
|
private function refreshSalesmenResourceCount($salesmen)
|
|
{
|
|
if (empty($salesmen)) {
|
|
return [];
|
|
}
|
|
|
|
foreach ($salesmen as &$salesman) {
|
|
$resourceCount = ResourceSharing::where('shared_by', $salesman['person_id'])
|
|
->count();
|
|
$salesman['resource_count'] = $resourceCount;
|
|
}
|
|
|
|
// 按资源数量升序排序
|
|
array_multisort(array_column($salesmen, 'resource_count'), SORT_ASC, $salesmen);
|
|
|
|
return $salesmen;
|
|
}
|
|
}
|