Merge branch 'develop'
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use support\Db;
|
||||
use support\Redis;
|
||||
use support\exception\BusinessException;
|
||||
use Webman\RedisQueue\Redis as RedisQueueRedis;
|
||||
|
||||
/**
|
||||
* 轮询分配 inquiry_log 里的询盘给业务员,并推送到 CRM 队列
|
||||
*/
|
||||
class InquiryAssignInquiryCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'iq-assign';
|
||||
protected static $defaultDescription = '轮询分配询盘给业务员,并推送到 CRM 队列';
|
||||
|
||||
/**
|
||||
* 参与轮询的业务员 ID 列表(请按你想要的顺序填写)
|
||||
* 比如:销售1=186,销售2=233...
|
||||
*/
|
||||
protected const SALES_USER_IDS = [
|
||||
63,
|
||||
64,
|
||||
67,
|
||||
93,
|
||||
108,
|
||||
132,
|
||||
143,
|
||||
145,
|
||||
157,
|
||||
160,
|
||||
168,
|
||||
172,
|
||||
173,
|
||||
191,
|
||||
193,
|
||||
194,
|
||||
195,
|
||||
196,
|
||||
197
|
||||
];
|
||||
|
||||
/**
|
||||
* 轮询分配的分组 key(同一分组共用一个轮询指针)
|
||||
*/
|
||||
protected const ROUND_ROBIN_GROUP_KEY = 'fb_inquiry';
|
||||
|
||||
/**
|
||||
* 每次脚本最多分配多少条
|
||||
*/
|
||||
protected const BATCH_LIMIT = 10;
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
// 业务员列表检查
|
||||
$userIds = array_values(array_filter(
|
||||
array_map('intval', static::SALES_USER_IDS),
|
||||
fn($v) => $v > 0
|
||||
));
|
||||
|
||||
if (empty($userIds)) {
|
||||
throw new BusinessException('SALES_USER_IDS 业务员列表不能为空,请先在命令中配置.');
|
||||
}
|
||||
|
||||
// 取出“待分配”的询盘(你可以根据自己系统调整条件)
|
||||
// 当前策略:status = 0 且 recipient = 0 的视为未分配
|
||||
$inquiries = Db::table('inquiry_log')
|
||||
->where('enter_user_id', 186)
|
||||
->where('channel', 10)
|
||||
->where('status', 0)
|
||||
->where('recipient', 0)
|
||||
->where('id', '>', 34426)
|
||||
->orderBy('id')
|
||||
->limit(static::BATCH_LIMIT)
|
||||
->get();
|
||||
|
||||
if ($inquiries->isEmpty()) {
|
||||
$output->writeln('<comment>没有需要分配的询盘(status=0 且 recipient=0)</comment>');
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$count = 0;
|
||||
|
||||
foreach ($inquiries as $row) {
|
||||
$inquiryId = (int)$row->id;
|
||||
sleep(1);
|
||||
// 轮询取出一个业务员 ID
|
||||
$recipientUserId = $this->nextRecipientId($userIds, static::ROUND_ROBIN_GROUP_KEY);
|
||||
|
||||
// 对每一条记录单独事务,避免单条异常拖垮全部
|
||||
Db::transaction(function () use ($inquiryId, $recipientUserId, $now, $output, &$count) {
|
||||
// 1)更新 inquiry_log
|
||||
$affected = Db::table('inquiry_log')
|
||||
->where('id', $inquiryId)
|
||||
->update([
|
||||
'recipient' => $recipientUserId,
|
||||
'status' => 2,
|
||||
'r_time' => $now,
|
||||
't_time' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
if ($affected === 0) {
|
||||
// 被其他进程抢先更新也有可能,这里只打印提示不中断整个批次
|
||||
$output->writeln("<comment>询盘 {$inquiryId} 未更新(可能已被处理)</comment>");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2)构造队列 payload(后续 CRM 消费时至少知道 ID)
|
||||
$res = [
|
||||
'id' => $inquiryId,
|
||||
'recipient' => $recipientUserId,
|
||||
'dispatched_at' => $now,
|
||||
'source' => 'fb_leads_inquiry',
|
||||
];
|
||||
|
||||
// 3)推送到 CRM 队列
|
||||
RedisQueueRedis::send('inquiry-to-crm-new', $res);
|
||||
|
||||
$count++;
|
||||
$output->writeln("<info>已分配询盘 {$inquiryId} 给业务员 {$recipientUserId},并推送到队列</info>");
|
||||
});
|
||||
}
|
||||
|
||||
$output->writeln("<info>本次共分配成功 {$count} 条询盘</info>");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询获取“下一位业务员 ID”
|
||||
*
|
||||
* @param int[] $userIds
|
||||
* @param string $groupKey
|
||||
* @return int
|
||||
* @throws BusinessException
|
||||
*/
|
||||
protected function nextRecipientId(array $userIds, string $groupKey = 'default'): int
|
||||
{
|
||||
$userIds = array_values(array_filter(array_map('intval', $userIds), fn($v) => $v > 0));
|
||||
if (empty($userIds)) {
|
||||
throw new BusinessException('轮询分配失败:业务员列表为空');
|
||||
}
|
||||
|
||||
$count = count($userIds);
|
||||
$key = 'inquiry:assign:round_robin:' . $groupKey;
|
||||
|
||||
// Redis INCR 是原子操作,适合并发下使用
|
||||
$val = Redis::incr($key); // 第一次会从 0 变成 1
|
||||
|
||||
// 换算为从 0 开始的下标
|
||||
$index = ($val - 1) % $count;
|
||||
|
||||
return $userIds[$index];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user