This commit is contained in:
mzl
2025-12-12 09:47:34 +00:00
parent 909f169aae
commit f99b2a84ca
6 changed files with 404 additions and 120 deletions
+80 -12
View File
@@ -12,17 +12,24 @@ class InquiryAssignService
/**
* 按渠道分配 inquiry_log 中待分配的记录,轮询业务员,并推送到 CRM 队列
*
* @param int[] $salesUserIds 参与轮询的业务员ID列表
* @param string $roundRobinKey 轮询分组key(Redis记指针)
* @param int $channelId 渠道ID(对应 inquiry_log.channel)
* @param int $limit 每次最多分配多少条
* @param int[] $salesUserIds 默认参与轮询的业务员ID列表(该渠道默认池)
* @param string $roundRobinKey 默认轮询分组key(Redis记指针)
* @param int $channelId 渠道ID(对应 inquiry_log.channel)
* @param array $assignRules 渠道内规则:按国家切换业务员池(可选)
* @param int $limit 每次最多分配多少条
*
* @return int 实际分配的条数
*/
public function assignBatch(array $salesUserIds, string $roundRobinKey, int $channelId, int $limit = 100): int
{
$userIds = array_values(array_filter(array_map('intval', $salesUserIds), fn($v) => $v > 0));
if (empty($userIds)) {
public function assignBatch(
array $salesUserIds,
string $roundRobinKey,
int $channelId,
array $assignRules = [],
int $limit = 100
): int {
// 默认池(渠道默认业务员列表)
$defaultUserIds = $this->normalizeUserIds($salesUserIds);
if (empty($defaultUserIds)) {
throw new BusinessException('分配失败:业务员列表为空');
}
@@ -42,8 +49,18 @@ class InquiryAssignService
$count = 0;
foreach ($inquiries as $row) {
$inquiryId = (int)$row->id;
$recipientUserId = $this->nextRecipientId($userIds, $roundRobinKey);
$inquiryId = (int)$row->id;
// ✅ 关键:按规则选业务员池(命中规则就用规则池,否则用默认池)
[$poolUserIds, $rrKey] = $this->pickSalesPoolByRules(
(int)($row->country ?? 0),
$defaultUserIds,
$roundRobinKey,
$assignRules
);
// ✅ 用“对应池子自己的 rrKey”轮询拿业务员
$recipientUserId = $this->nextRecipientId($poolUserIds, $rrKey);
Db::transaction(function () use ($inquiryId, $recipientUserId, $now, &$count) {
$affected = Db::table('inquiry_log')
@@ -68,7 +85,6 @@ class InquiryAssignService
'source' => 'fb_leads_inquiry',
];
// 队列推送 —— 用你原来的写法
RedisQueueRedis::send('inquiry-to-crm-new', $res);
$count++;
@@ -83,7 +99,7 @@ class InquiryAssignService
*/
protected function nextRecipientId(array $userIds, string $groupKey): int
{
$userIds = array_values(array_filter(array_map('intval', $userIds), fn($v) => $v > 0));
$userIds = $this->normalizeUserIds($userIds);
if (empty($userIds)) {
throw new BusinessException('轮询分配失败:业务员列表为空');
}
@@ -96,4 +112,56 @@ class InquiryAssignService
return $userIds[$index];
}
/**
* 按国家规则挑选“业务员池 + 轮询key”
* 命中 rules 则返回规则池,否则返回默认池
*
* rules 示例:
* [
* [
* 'countries' => [1,2,3],
* 'sales_user_ids' => [63,64],
* 'round_robin_key' => 'fb_xxx_ru',
* ],
* ]
*
* @return array{0:int[], 1:string} [userIds, rrKey]
*/
protected function pickSalesPoolByRules(
int $countryId,
array $defaultUserIds,
string $defaultRrKey,
array $rules
): array {
foreach ($rules as $rule) {
if (!is_array($rule)) continue;
$countries = $rule['countries'] ?? [];
if (!is_array($countries) || empty($countries)) continue;
if (!in_array($countryId, array_map('intval', $countries), true)) {
continue;
}
$userIds = $this->normalizeUserIds($rule['sales_user_ids'] ?? []);
if (!empty($userIds)) {
// 规则池必须使用自己的 rrKey,否则会和默认池“抢指针”
$rrKey = (string)($rule['round_robin_key'] ?? ($defaultRrKey . '_rule_' . md5(json_encode($countries))));
return [$userIds, $rrKey];
}
}
return [$this->normalizeUserIds($defaultUserIds), $defaultRrKey];
}
/**
* 统一清洗业务员ID数组:转 int、去重、过滤 <=0
*/
protected function normalizeUserIds(array $ids): array
{
$ids = array_values(array_filter(array_map('intval', $ids), fn($v) => $v > 0));
$ids = array_values(array_unique($ids));
return $ids;
}
}