feat: 询盘导入改为公平分配——按近10天窗口实际分到数排序(三脚本共用)

新增 InquiryFairAssigner:统计 crm_customer(合塑谷歌/导入/未删/近10天)
中名单内每人的已有条数,按 少者优先 -> 最久未分到优先 -> 名单顺序 排序,
三个导入命令分配前统一调用并打印排序结果(含各人窗口内条数)。
解决:日询盘量少于人数时固定只分给名单前几人的问题;
名单增删(离职/暂停回归)自适应,跨脚本/跨天共享,无额外状态。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
mzl
2026-08-20 15:40:45 +08:00
parent 89b9162f09
commit 6fa80336a6
4 changed files with 90 additions and 9 deletions
@@ -3,6 +3,7 @@
namespace app\command;
use app\common\model\CrmCustomer;
use app\common\utils\InquiryFairAssigner;
use app\common\utils\email\InquiryDigestMail;
use app\common\utils\email\MailSend;
use app\crm\model\Country;
@@ -324,10 +325,14 @@ class HesuGoogleAiInquiryImportCommand extends Command
$output->writeln('<comment>未匹配到国家(将留空): ' . implode('、', array_keys($countryMiss)) . '</comment>');
}
// 轮询分配(按行序 i % n)
$n = count($targetUserIds);
// 公平分配:按近10天窗口内实际分到数升序(少者优先、最久未分到优先),再按序轮询
$fair = InquiryFairAssigner::fairOrder($targetUserIds);
$orderedUsers = $fair['ordered'];
$output->writeln('<info>分配顺序(近' . $fair['window_days'] . '天已有条数):'
. implode('、', array_map(fn($u) => $u . '(' . ($fair['counts'][$u] ?? 0) . ')', $orderedUsers)) . '</info>');
$n = count($orderedUsers);
foreach ($keep as $i => &$row) {
$row['new_user_id'] = $targetUserIds[$i % $n];
$row['new_user_id'] = $orderedUsers[$i % $n];
}
unset($row);
$groups = [];
@@ -3,6 +3,7 @@
namespace app\command;
use app\common\model\CrmCustomer;
use app\common\utils\InquiryFairAssigner;
use app\common\utils\email\InquiryDigestMail;
use app\common\utils\email\MailSend;
use PhpOffice\PhpSpreadsheet\IOFactory;
@@ -191,10 +192,14 @@ class HesuGoogleInquiryImportCommand extends Command
$output->writeln('<comment> 无联系方式 行' . $row['excel_row'] . ' ' . $row['contacts'] . '</comment>');
}
// 轮询分配(按行序 i % n)
$n = count($targetUserIds);
// 公平分配:按近10天窗口内实际分到数升序(少者优先、最久未分到优先),再按序轮询
$fair = InquiryFairAssigner::fairOrder($targetUserIds);
$orderedUsers = $fair['ordered'];
$output->writeln('<info>分配顺序(近' . $fair['window_days'] . '天已有条数):'
. implode('、', array_map(fn($u) => $u . '(' . ($fair['counts'][$u] ?? 0) . ')', $orderedUsers)) . '</info>');
$n = count($orderedUsers);
foreach ($keep as $i => &$row) {
$row['new_user_id'] = $targetUserIds[$i % $n];
$row['new_user_id'] = $orderedUsers[$i % $n];
}
unset($row);
$groups = [];
@@ -4,6 +4,7 @@ namespace app\command;
use app\common\model\CrmCustomer;
use app\common\service\OssService;
use app\common\utils\InquiryFairAssigner;
use app\common\utils\email\InquiryDigestMail;
use app\common\utils\email\MailSend;
use PhpOffice\PhpSpreadsheet\IOFactory;
@@ -219,10 +220,14 @@ class HesuGoogleWhatsAppImportCommand extends Command
}
$output->writeln('<info>截图: 找到 ' . $shotFound . ' / 缺失 ' . $shotMissing . '(目录: ' . $imagesDir . ')</info>');
// 轮询分配(按行序 i % n)
$n = count($targetUserIds);
// 公平分配:按近10天窗口内实际分到数升序(少者优先、最久未分到优先),再按序轮询
$fair = InquiryFairAssigner::fairOrder($targetUserIds);
$orderedUsers = $fair['ordered'];
$output->writeln('<info>分配顺序(近' . $fair['window_days'] . '天已有条数):'
. implode('、', array_map(fn($u) => $u . '(' . ($fair['counts'][$u] ?? 0) . ')', $orderedUsers)) . '</info>');
$n = count($orderedUsers);
foreach ($keep as $i => &$row) {
$row['new_user_id'] = $targetUserIds[$i % $n];
$row['new_user_id'] = $orderedUsers[$i % $n];
}
unset($row);
$groups = [];