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.
wkcrm/application/common/command/PoolCommand.php

445 lines
19 KiB

4 years ago
<?php
/**
* 使用定时器将符合条件的用户回收到公海池
*
* @author fanqi
* @since 2021-03-31
*/
namespace app\common\command;
use think\Config;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\Db;
use think\response\Json;
use Workerman\Lib\Timer;
use Workerman\Worker;
class PoolCommand extends Command
{
protected $timer;
protected $interval = 10;
4 years ago
protected function configure()
{
$this->setName('pool')
->addArgument('status', Argument::REQUIRED, 'start/stop/reload/status/connections')
->addOption('d', null, Option::VALUE_NONE, 'daemon守护进程方式启动')
->setDescription('公海回收定时器');
4 years ago
// 读取数据库配置文件
3 years ago
$filename = ROOT_PATH . 'config' . DS . 'database.php';
4 years ago
// 重新加载数据库配置文件
Config::load($filename, 'database');
}
4 years ago
/**
* 初始化
*
* @param Input $input
* @param Output $output
*/
protected function init(Input $input, Output $output)
{
global $argv;
3 years ago
$argv[1] = $input->getArgument('status') ?: 'start';
4 years ago
if ($input->hasOption('d')) {
$argv[2] = '-d';
} else {
unset($argv[2]);
}
}
4 years ago
/**
* 停止定时器
*/
public function stop()
{
Timer::del($this->timer);
}
4 years ago
/**
* 启动定时器
*/
public function start()
{
$this->timer = Timer::add($this->interval, function () {
# 只在凌晨12点至6点间执行
if ((int)date('H') >= 0 && (int)date('H') < 6) {
$this->poolRecover();
4 years ago
}
});
}
public function poolRecover()
{
# 公海规则
$ruleList = db('crm_customer_pool_rule')->alias('rule')->field('rule.*')
->join('__CRM_CUSTOMER_POOL__ pool', 'pool.pool_id = rule.pool_id', 'LEFT')->field("pool.customer_type")->where('pool.status', 1)->select();
if (!empty($ruleList)) {
# 符合公海条件的客户IDS
$customerIds = PoolCommand::getQueryCondition($ruleList);
# 整理客户公海关联数据
$poolRelationData = PoolCommand::getCustomerPoolRelationData($customerIds);
# 整理修改客户数据的条件(进入公海时间,前负责人...
$customerWhere = PoolCommand::getCustomerQueryCondition($customerIds);
Db::startTrans();
try {
# 将客户退回公海
if (!empty($poolRelationData)) Db::name('crm_customer_pool_relation')->insertAll($poolRelationData);
# 修改客户数据
if (!empty($customerWhere)) {
Db::name('crm_customer')->whereIn('customer_id', $customerWhere)->exp('before_owner_user_id', 'owner_user_id')->update([
'ro_user_id' => '',
'rw_user_id' => '',
'owner_user_id' => 0,
'into_pool_time' => time()
]);
}
PoolCommand::updateInfo($ruleList, $customerWhere);
# 删除联系人的负责人
Db::name('crm_contacts')->whereIn('customer_id', $customerWhere)->update(['owner_user_id' => '']);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
}
}
}
3 years ago
/**
* 自动入公海操作记录
* @param $ruleList
* @param $customerWhere
*
* @author alvin guogaobo
* @version 1.0 版本号
* @since 2021/6/3 0003 10:38
*/
private function updateInfo($ruleList, $customerWhere)
{
foreach ($ruleList as $k => $v) {
$levels = json_decode($v['level'], true);
foreach ($levels as $k1 => $v1) {
if (!empty($v1['limit_day'])) {
$time = $v1['limit_day'];
} else {
$time = PoolCommand::getMinDay($levels);
}
}
foreach ($customerWhere as $val) {
if ($v['type'] == 1) updateActionLog(0, 'crm_customer', $val, '', '', '超过' . $time . '天无新建跟进记录自动进入公海');
if ($v['type'] == 2) updateActionLog(0, 'crm_customer', $val, '', '', '超过' . $time . '天无新建商机自动进入公海');
if ($v['type'] == 3) updateActionLog(0, 'crm_customer', $val, '', '', '超过' . $time . '天未成交自动进入公海');
}
}
}
4 years ago
protected function execute(Input $input, Output $output)
{
# 动态修改运行时参数
set_time_limit(0);
ini_set('memory_limit', '512M');
4 years ago
$this->init($input, $output);
4 years ago
# 创建定时器任务
$task = new Worker();
$task->name = 'pool';
$task->count = 1;
$task->onWorkerStart = [$this, 'start'];
$task->runAll();
}
4 years ago
/**
* 整理修改客户数据的条件
*
* @param array $customerIds 客户ID
* @return array
3 years ago
* @since 2021-04-01
* @author fanqi
4 years ago
*/
private function getCustomerQueryCondition($customerIds)
{
$result = [];
3 years ago
foreach ($customerIds as $k1 => $v1) {
foreach ($v1 as $k2 => $v2) {
4 years ago
$result[] = $v2;
}
}
4 years ago
return array_unique($result);
}
4 years ago
/**
* 客户公海关联数据
*
* @param array $customerIds 客户ID
* @return array
3 years ago
* @since 2021-04-01
* @author fanqi
4 years ago
*/
private function getCustomerPoolRelationData($customerIds)
{
$result = [];
4 years ago
# 用于排重
$repeat = [];
3 years ago
foreach ($customerIds as $k1 => $v1) {
4 years ago
$customerArray = array_unique($v1);
3 years ago
foreach ($customerArray as $k2 => $v2) {
4 years ago
if (!empty($repeat[$k1][$v2])) continue;
4 years ago
$result[] = [
'pool_id' => $k1,
'customer_id' => $v2
];
4 years ago
$repeat[$k1][$v2] = $v2;
}
}
4 years ago
return $result;
}
4 years ago
/**
* 获取符合公海条件的客户
*
* @param array $rules 公海规则数据
* @return array
3 years ago
* @since 2021-04-01
* @author fanqi
4 years ago
*/
private function getQueryCondition($rules)
{
$result = [];
3 years ago
foreach ($rules as $k => $v) {
4 years ago
if (!isset($result[$v['pool_id']])) $result[$v['pool_id']] = [];
if ($v['type'] == 1) $result[$v['pool_id']] = array_merge($result[$v['pool_id']], PoolCommand::getFollowUpQueryResult($v['level_conf'], $v['level'], $v['deal_handle'], $v['business_handle'], $v['customer_type']));
if ($v['type'] == 2) $result[$v['pool_id']] = array_merge($result[$v['pool_id']], PoolCommand::getBusinessQueryResult($v['level_conf'], $v['level'], $v['deal_handle'], $v['customer_type']));
if ($v['type'] == 3) $result[$v['pool_id']] = array_merge($result[$v['pool_id']], PoolCommand::getDealQueryResult($v['level_conf'], $v['level'], $v['business_handle'], $v['customer_type']));
4 years ago
}
4 years ago
return $result;
}
4 years ago
/**
* N天内无新建跟进记录的客户
*
* @param int $type 类型1 所有用户不分级别2 根据用户级别区分
* @param Json $levels 级别数据
* @param int $dealStatus 是否排除成交用户1 排除0 不排除
* @param int $businessStatus 是否排除有商机用户1 排除0 不排除
* @return array
3 years ago
* @since 2021-04-01
* @author fanqi
4 years ago
*/
private function getFollowUpQueryResult($type, $levels, $dealStatus, $businessStatus, $customerType)
4 years ago
{
# 转换格式
$levels = json_decode($levels, true);
4 years ago
# 默认条件
$where = "`customer`.`owner_user_id` > 0";
4 years ago
# 所有用户,不区分级别
if ($type == 1) {
3 years ago
foreach ($levels as $k1 => $v1) {
4 years ago
if (!empty($v1['limit_day'])) {
$time = time() - 24 * 60 * 60 * $v1['limit_day'];
3 years ago
$where .= " AND ((`customer`.`last_time` < " . $time . " AND `customer`.`last_time` > `customer`.`obtain_time`) OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `customer`.`last_time`) OR (`customer`.`obtain_time` < " . $time . " AND ISNULL(`customer`.`last_time`)))";
4 years ago
}
}
}
4 years ago
# 根据用户级别设置条件
if ($type == 2) {
3 years ago
foreach ($levels as $k1 => $v1) {
4 years ago
if (!empty($v1['level']) && !empty($v1['limit_day'])) {
$time = (time() - 24 * 60 * 60 * $v1['limit_day']);
if ($k1 == 0) {
3 years ago
$where .= " AND ( ((`customer`.`level` = '" . $v1['level'] . "' AND `customer`.`last_time` < " . $time . " AND `customer`.`last_time` > `customer`.`obtain_time`) OR (`customer`.`level` = '" . $v1['level'] . "' AND `customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `customer`.`last_time`) OR (`customer`.`level` = '" . $v1['level'] . "' AND `customer`.`obtain_time` < " . $time . " AND ISNULL(`customer`.`last_time`)))";
4 years ago
} else {
3 years ago
$where .= " OR ((`customer`.`level` = '" . $v1['level'] . "' AND `customer`.`last_time` < " . $time . " AND `customer`.`last_time` > `customer`.`obtain_time`) OR (`customer`.`level` = '" . $v1['level'] . "' AND `customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `customer`.`last_time`) OR (`customer`.`level` = '" . $v1['level'] . "' AND `customer`.`obtain_time` < " . $time . " AND ISNULL(`customer`.`last_time`)))";
4 years ago
}
}
}
4 years ago
# 获取最小天数,对于没有设置级别的客户数据使用
$minLimit = PoolCommand::getMinDay($levels);
4 years ago
$minTime = (time() - 24 * 60 * 60 * $minLimit);
3 years ago
$where .= " OR ((!`customer`.`level` AND `customer`.`last_time` < " . $minTime . " AND `customer`.`last_time` > `customer`.`obtain_time`) OR (!`customer`.`level` AND `customer`.`obtain_time` < " . $minTime . " AND `customer`.`obtain_time` > `customer`.`last_time`) OR (!`customer`.`level` AND `customer`.`obtain_time` < " . $minTime . " AND ISNULL(`customer`.`last_time`))) )";
4 years ago
}
4 years ago
# 选择不进入公海的客户(已成交客户)
if (!empty($dealStatus)) $where .= " AND (`customer`.`deal_status` <> '已成交' OR ISNULL(`customer`.`deal_status`))";
4 years ago
# 选择不进入公海的客户(有商机客户)
if (!empty($businessStatus)) $where .= " AND ISNULL(`business`.`customer_id`)";
4 years ago
# 锁定的客户不提醒
$where .= " AND `customer`.`is_lock` = 0";
4 years ago
# 查询符合条件的客户
return db('crm_customer')
->alias('customer')->join('__CRM_BUSINESS__ business', 'business.customer_id = customer.customer_id', 'LEFT')
->where($where)->where(['customer.crm_lthugd' => array('in', $customerType)])->column('customer.customer_id');
4 years ago
}
4 years ago
/**
* N天内无新建商机的客户
*
* @param int $type 类型1 所有用户不分级别2 根据用户级别区分
* @param Json $levels 级别数据
* @param int $dealStatus 是否排除成交用户1 排除0 不排除
* @return array|false|string
3 years ago
* @since 2021-04-01
* @author fanqi
4 years ago
*/
private function getBusinessQueryResult($type, $levels, $dealStatus, $customerType)
4 years ago
{
# 转换格式
$levels = json_decode($levels, true);
4 years ago
# 默认条件
$where = "`customer`.`owner_user_id` > 0";
4 years ago
# 所有用户,不区分级别
if ($type == 1) {
3 years ago
foreach ($levels as $k1 => $v1) {
4 years ago
if (!empty($v1['limit_day'])) {
$time = time() - 24 * 60 * 60 * $v1['limit_day'];
3 years ago
$where .= " AND ( (ISNULL(`business`.`customer_id`) AND `customer`.`obtain_time` < " . $time . ") OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `business`.`create_time`) OR (`business`.`create_time` < " . $time . " AND `business`.`create_time` > `customer`.`obtain_time`) )";
4 years ago
}
}
}
4 years ago
# 根据用户级别设置条件
if ($type == 2) {
3 years ago
foreach ($levels as $k1 => $v1) {
4 years ago
if (!empty($v1['level']) && !empty($v1['limit_day'])) {
$time = time() - 24 * 60 * 60 * $v1['limit_day'];
if ($k1 == 0) {
3 years ago
$where .= " AND ( ((ISNULL(`business`.`customer_id`) AND `customer`.`obtain_time` < " . $time . " AND `customer`.`level` = '" . $v1['level'] . "') OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `business`.`create_time` AND `customer`.`level` = '" . $v1['level'] . "') OR (`business`.`create_time` < " . $time . " AND `business`.`create_time` > `customer`.`obtain_time` AND `customer`.`level` = '" . $v1['level'] . "'))";
4 years ago
} else {
3 years ago
$where .= " OR ((ISNULL(`business`.`customer_id`) AND `customer`.`obtain_time` < " . $time . " AND `customer`.`level` = '" . $v1['level'] . "') OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `business`.`create_time` AND `customer`.`level` = '" . $v1['level'] . "') OR (`business`.`create_time` < " . $time . " AND `business`.`create_time` > `customer`.`obtain_time` AND `customer`.`level` = '" . $v1['level'] . "'))";
4 years ago
}
}
}
4 years ago
# 获取最小天数,对于没有设置级别的客户数据使用
$minLimit = PoolCommand::getMinDay($levels);
4 years ago
$minTime = (time() - 24 * 60 * 60 * $minLimit);
3 years ago
$where .= " OR ((ISNULL(`business`.`customer_id`) AND `customer`.`obtain_time` < " . $minTime . " AND !`customer`.`level`) OR (`customer`.`obtain_time` < " . $minTime . " AND `customer`.`obtain_time` > `business`.`create_time` AND !`customer`.`level`) OR (`business`.`create_time` < " . $minTime . " AND `business`.`create_time` > `customer`.`obtain_time` AND !`customer`.`level`)) )";
4 years ago
}
4 years ago
# 选择不进入公海的客户(已成交客户)
if (!empty($dealStatus)) $where .= " AND (`customer`.`deal_status` <> '已成交' OR ISNULL(`customer`.`deal_status`))";
4 years ago
# 锁定的客户不提醒
$where .= " AND `customer`.`is_lock` = 0";
4 years ago
# 查询匹配条件的客户
return db('crm_customer')->alias('customer')
->join('__CRM_BUSINESS__ business', 'business.customer_id = customer.customer_id', 'LEFT')
->where($where)->where(['customer.crm_lthugd' => array('in', $customerType)])->column('customer.customer_id');
4 years ago
}
4 years ago
/**
* N天内没有成交的客户
*
* @param int $type 类型1 所有用户不分级别2 根据用户级别区分
* @param Json $levels 级别数据
* @param int $businessStatus 是否排除有商机用户1 排除0 不排除
* @return array|false|string
3 years ago
* @since 2021-04-01
* @author fanqi
4 years ago
*/
private function getDealQueryResult($type, $levels, $businessStatus, $customerType)
4 years ago
{
# 转换格式
$levels = json_decode($levels, true);
4 years ago
# 默认条件
$where = "`customer`.`owner_user_id` > 0";
4 years ago
# 所有用户,不区分级别
if ($type == 1) {
3 years ago
foreach ($levels as $k1 => $v1) {
4 years ago
if (!empty($v1['limit_day'])) {
$time = time() - 24 * 60 * 60 * $v1['limit_day'];
3 years ago
$where .= " AND ( (ISNULL(`contract`.`customer_id`) AND `customer`.`obtain_time` < " . $time . ") OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `contract`.`create_time`) OR (`contract`.`create_time` < " . $time . " AND `contract`.`create_time` > `customer`.`obtain_time`) )";
4 years ago
}
}
}
4 years ago
# 根据用户级别设置条件
if ($type == 2) {
3 years ago
foreach ($levels as $k1 => $v1) {
4 years ago
if (!empty($v1['level']) && !empty($v1['limit_day'])) {
$time = time() - 24 * 60 * 60 * $v1['limit_day'];
if ($k1 == 0) {
3 years ago
$where .= " AND ( ((ISNULL(`contract`.`customer_id`) AND `customer`.`obtain_time` < " . $time . " AND `customer`.`level` = '" . $v1['level'] . "') OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `contract`.`create_time` AND `customer`.`level` = '" . $v1['level'] . "') OR (`contract`.`create_time` < " . $time . " AND `contract`.`create_time` > `customer`.`obtain_time` AND `customer`.`level` = '" . $v1['level'] . "'))";
4 years ago
} else {
3 years ago
$where .= " OR ((ISNULL(`contract`.`customer_id`) AND `customer`.`obtain_time` < " . $time . " AND `customer`.`level` = '" . $v1['level'] . "') OR (`customer`.`obtain_time` < " . $time . " AND `customer`.`obtain_time` > `contract`.`create_time` AND `customer`.`level` = '" . $v1['level'] . "') OR (`contract`.`create_time` < " . $time . " AND `contract`.`create_time` > `customer`.`obtain_time` AND `customer`.`level` = '" . $v1['level'] . "'))";
4 years ago
}
}
}
4 years ago
# 获取最小天数,对于没有设置级别的客户数据使用
$minLimit = PoolCommand::getMinDay($levels);
4 years ago
$minTime = (time() - 24 * 60 * 60 * $minLimit);
3 years ago
$where .= " OR ((ISNULL(`contract`.`customer_id`) AND `customer`.`obtain_time` < " . $minTime . " AND !`customer`.`level`) OR (`customer`.`obtain_time` < " . $minTime . " AND `customer`.`obtain_time` > `contract`.`create_time` AND !`customer`.`level`) OR (`contract`.`create_time` < " . $minTime . " AND `contract`.`create_time` > `customer`.`obtain_time` AND !`customer`.`level`)) )";
4 years ago
}
4 years ago
# 选择不进入公海的客户(有商机客户)
if (!empty($businessStatus)) $where .= " AND ISNULL(`business`.`customer_id`)";
4 years ago
# 锁定的客户不提醒
$where .= " AND `customer`.`is_lock` = 0";
4 years ago
# 查询符合条件的客户
return db('crm_customer')->alias('customer')
->join('__CRM_BUSINESS__ business', 'business.customer_id = customer.customer_id', 'LEFT')
->join('__CRM_CONTRACT__ contract', 'contract.customer_id = customer.customer_id', 'LEFT')
->where($where)->where(['customer.crm_lthugd' => array('in', $customerType)])->column('customer.customer_id');
4 years ago
}
4 years ago
/**
* 获取公海规则最小数字(最快进入公海天数)
*
* @param $data
* @return int
3 years ago
* @since 2021-04-19
* @author fanqi
4 years ago
*/
private function getMinDay($data)
{
$number = 1;
3 years ago
foreach ($data as $k1 => $v1) {
4 years ago
if (empty($number) || $v1['limit_day'] < $number) $number = $v1['limit_day'];
}
4 years ago
return $number;
}
}