<?php
/**
  * @method 跑街令CRM基本操作
  * @author soul
  * @copyright 2016/3/31
  */
class CrmMain extends CrmBase
{
	public function __construct()
	{
		parent::__construct();
		LibFc::useMainDb();
	}

	/**
	  * @method 自动调整当前业务员和客户之间的关系
	  * @param  $ctrId 客户ID  ctrId/ctrUid二选一
	  * @param  $ctrUid 客户会员ID
	  * @param  $auUid 业务员ID
	  * @author soul
	  * @copyright 2021/4/13
	  * @return 
		规则1：最新成交的商家入驻，自动归属到成交人私海30天,自助入驻的进公海
		规则2：有填写邀请码到缴费页面，但未缴费的商家自动进入业务员私海7天
		规则3：公海客户，电话跟进后进入私海3天，其他的不进私海
		规则4：每个业务员每天进私海的客户最多40个
	  */
	public function changeCtrAutoStatus($ctrId = 0, $auUid, $ctrUid = 0)
	{
		//停止使用，已启用新CRM 2024/2/4
		return LibFc::ReturnData(true);
	}

	/**
	 * @param  int $uid 用户uid
	 * @method 通过uid添加crm活跃用户
	 * @author zhengweihua 
	 * @copyright 2023-05-22
	 */
	public function addCrmCustomerByUid($uid, $au_uid = 0)
	{
		$res =	$this->Get('crm_customer',['ctr_id'],sprintf(" AND ctr_uid = %d",$uid),true);
		if($res['data']) return	LibFc::ReturnData(true,$res['data']['ctr_id']);

		$fields = ['ua_uid, ua_score, ua_com_name, ua_com_style, ua_link_name, ua_link_tel, ua_pjl_shop_id, ua_pjl_shop_etime'];
		$YpwBase = new YpwBase();
		$res =	$YpwBase->Get('yp_user_act',$fields,sprintf(" AND ua_uid = %d",$uid),true);
		$temp = $res['data']?:[];
		$this->CrmDb->Begin();
		
		$PjlBase = new PjlBase();
		$table = 'pl_shop 
		LEFT JOIN pl_shop_addr ON sha_shop_id = shop_id and sha_main =1
		LEFT JOIN pl_user_vip_list ON uvl_uid=shop_pu_id and uvl_status = 2 AND uvl_pay_time >0';
		$fields = ['MAX(uvl_pay_time) as uvl_pay_time','shop_pu_id','shop_addr','shop_vip_etime','shop_enter_time','shop_apply_time','shop_style','shop_id','shop_tels','shop_name', 'shop_pct_ids','sha_name', 'sha_tel'];
		$res = $PjlBase->get($table,$fields,sprintf(" and shop_pu_id = %d group by shop_pu_id", $uid),true);
		$shopArr = $res['data'];
		$mobile = $shopArr['sha_tel'];
		$contact = $shopArr['sha_name'];
		if(!$mobile ||!$contact)
		{
			if($shopArr['shop_tels'])
			{
				$telsArr = json_decode($shopArr['shop_tels'],true);
				$mobile = $telsArr[0]['val'];
				$contact = $telsArr[0]['name'];
			}
			if(!$mobile || !$contact)
			{
				$res1 = $YpwBase->get('yp_user s join yp_user_ext on ui_uid=u_id', ['u_id', 'u_mobile', 'u_email', 'u_real_name'], sprintf(' and u_id=%d', $uid),true);
				if($res1['data'])
				{
					if($res1['data']['u_mobile'] && !$mobile ) $mobile = $res1['data']['u_mobile'];
					if($res1['data']['u_real_name'] && !$contact)  $contact= $res1['data']['u_real_name'];
				}
			}
		}
		$pctIds = explode(',',$shopArr['shop_pct_ids']);
		$addData = [];
		$addData = [
			'ctr_uid' => $uid,
			'ctr_score' => $temp['ua_score'] ?: 0.5,
			'ctr_pjl_shop_id' => (int) $shopArr['shop_pu_id'],
			'ctr_comname' =>	$temp['ua_com_name'] ? $temp['ua_com_name'] : $shopArr['shop_name'],
			'ctr_com_style' =>	$temp['ua_com_style'] ? $temp['ua_com_style'] : $shopArr['shop_style'],
			'ctr_contact' =>	$temp['ua_link_name'] ? $temp['ua_link_name'] : $contact,
			'ctr_tel' => $temp['ua_link_tel'] ? $temp['ua_link_tel'] : $mobile,
			'ctr_pjl_shop_applytime' => (int) $shopArr['shop_apply_time'],
			'ctr_pjl_shop_entertime' => (int) $shopArr['shop_enter_time'],
			'ctr_pjl_shop_lastpaytime' => (int) $shopArr['uvl_pay_time'],
			'ctr_pjl_shop_etime' => (int) $shopArr['shop_vip_etime'],
			'ctr_addr' => $shopArr['shop_addr'] ?: '',
			'ctr_atime'=>time(),
			'ctr_pct_ids'=>json_encode( 
				[
				'pid'=>(int) $pctIds[0],	
				'cid'=>(int) $pctIds[1],	
				'tid'=>(int) $pctIds[2]
				]
			)
		];
		if($au_uid) $addData['ctr_level_id'] = 1;

		if(empty($addData['ctr_comname'])){
			$res = $YpwBase->Get('yp_user', ['u_nickname'],sprintf(" and u_id=%d",$uid),true);
			$addData['ctr_comname'] = $res['data']['u_nickname'];
		}
		$res = $this->add('crm_customer',$addData);
		$ctr_id = $res['data'];
		$brands = $YpwBase->Get('yp_user_act_brand',['*'],sprintf(" AND uab_uid=%d",$uid));	
		if($brands['data']){
			$brandIds = array_column($brands['data'],'uab_brand_id');
			$brandArr =	$YpwBase->Get('ypb2c_common_a.bc_brand',['*'],sprintf(" AND brand_id in (%s)",implode(',',$brandIds)));
			$brandArr = array_column($brandArr['data'],'brand_id','brand_name');
	
			foreach ($brands['data'] as $val) {
				if(!$brandArr[$val['uab_brand']]) continue;
				$YpwBase->Set('yp_user_act_brand',['uab_brand_id'=>$brandArr[$val['uab_brand']]],sprintf(" AND uab_uid=%d AND uab_brand = '%s'",$uid,$val['uab_brand']));
			}
		}
		if($au_uid){
			//保护30天
			$now = time();
			$add = [
				'cca_ctr_id'=>$ctr_id,
				'cca_level_id'=>1,
				'cca_au_uid'=>$au_uid,
				'cca_begin_atime'=>$now,
				'cca_end_time'=>$now+3600*24*30,
				'cca_atime'=>$now,
				'cca_add_remark'=>'手工新增客户',
			];
			$this->add('crm_customer_admin', $add);
		}
		$this->CrmDb->End();
		return LibFc::ReturnData(true, $ctr_id);
	}

	/**
	  * @method 自动创建VIP会员的合同
	  * @param  $uvl_id pl_user_vip_list的订单ID
	  * @author soul
	  * @copyright 2024/1/30
	  * @return 
	  */
	public function addContractByPjlVipOrder($uvl_id, $autostatus = true)
	{
		$uvl_id = (int) $uvl_id;
		$PjlUser = new PjlUser();
		$table = 'pl_user_vip_list 
		JOIN pl_user_vip ON  uip_uvl_id = uvl_id AND uvl_status = 2
		LEFT JOIN pl_vip_level as l on uvl_now_vip_id = vip_id
		JOIN dl_order_list ON uvl_id = dml_order_id';
		$res = $PjlUser->get($table, ['uvl_id, uvl_uid u_id, uvl_style, vip_name, uvl_paymoney, uvip_btime, uvip_etime, dml_dwo_uid au_uid,dml_dwo_name au_name, dml_remark'], sprintf(" and uvl_id=%d AND uvl_paymoney > 0 limit 1", $uvl_id), true);
		if(empty($res['data'])) return LibFc::ReturnData(false, '订单不存在或者尚未完成，请稍后重试');
		$orderArr = $res['data'];
		$B2cBase = new B2cBase();
		$res = $B2cBase->get('an_user', ['au_uid, au_name, au_enter, au_out'], sprintf(" and au_uid=%d", $orderArr['au_uid']), true);
		if(empty($res['data'])){//非公司业务
			$orderArr['au_uid'] = 172999;
			$orderArr['dml_remark'] .= '[非公司业务员归属转跑街令]';
		}

		$res = $this->addCrmCustomerByUid($orderArr['u_id']);
		$ctr_id = $res['data'];
		$xufei = 0;
		if($orderArr['uvl_style'] == 'shop'){
			$sve_id = 1;
			$title = '商家入驻';
		}else{
			$sve_id = 2;
			$title = $orderArr['vip_name'];
		}
		$res = $PjlUser->get('pl_user_vip_list JOIN pl_user_vip ON  uip_uvl_id = uvl_id AND uvl_status = 2', ['uvl_id'], sprintf(" and uvl_uid=%d and uvl_style='%s' and uvip_btime < %d and uvl_id != %d limit 1", $orderArr['u_id'], $orderArr['uvl_style'], $orderArr['uvip_btime'], $orderArr['uvl_id']), true);
		if(!empty($res['data'])){
			$xufei = 1;
			$title .= '续费';
		}
		
		//检测是否已经存在
		$res = $this->get('fad_link_fct_sve join fad_contract on fct_id = fsl_fct_id', ['fct_id'], sprintf(" and fct_ctr_id=%d and fsl_sve_id=%d and fsl_des_id=%d", $ctr_id, $sve_id, $uvl_id), true);
		if(!empty($res['data'])) return LibFc::ReturnData(true,$res['data']['fct_id']);
		$now = time();
		
		$this->CrmDb->Begin();
		$conArr = [
			'fct_ctr_id'=>$ctr_id,
			'fct_title'=>$title,
			'fct_money'=>$orderArr['uvl_paymoney'],
			'fct_remark'=>'系统',
			'fct_status'=>2,
			'fct_remnew'=>$xufei,
			'fct_modified'=>$now,
			'fct_chk_user'=>'系统'
		];
		$res = $this->add('fad_contract', $conArr);
		$fct_id = $res['data'];
		
		//业务员
		$this->add('fad_link_fct_usr', ['duc_usr_id'=>$orderArr['au_uid'], 'duc_fct_id'=>$fct_id]);
		
		//项目
		$conSer = [
			'fsl_fct_id'=>$fct_id,
			'fsl_sve_id'=>$sve_id,
			'fsl_money'=>$orderArr['uvl_paymoney'],
			'fsl_remark'=>$title.' '.$orderArr['dml_remark'],
			'fsl_btime'=>$orderArr['uvip_btime'],
			'fsl_etime'=>$orderArr['uvip_etime'],
			'fsl_des_id'=>$orderArr['uvl_id']
		];
		$res = $this->add('fad_link_fct_sve', $conSer);
		$fsl_id = $res['data'];

		//付款计划
		$conPay = [
			'pay_status'=>1,	
			'pay_money'=>$orderArr['uvl_paymoney'],	
			'pay_pay_time'=>$now,	
			'pay_create_time'=>$now,	
			'pay_fct_id'=>$fct_id,
			'pay_remark'=>'系统'
		];
		$res = $this->add('fad_pay_money', $conPay);
		$pay_id = $res['data'];
		
		//付款
		$conPay = [
			'fae_status'=>1,	
			'fae_text'=>$title,	
			'fae_money'=>$orderArr['uvl_paymoney'],	
			'fae_create_usr_id'=>8,	
			'fae_create_usr'=>'系统',	
			'fae_create_time'=>$now,	
			'fae_ctr_id'=>$ctr_id,	
			'fae_fct_id'=>$fct_id
		];
		$res = $this->add('fad_finance', $conPay);
		$fae_id = $res['data'];

		//扣款
		$conPay = [
			'fff_fct_id'=>$fct_id,
			'fff_fae_id'=>$fae_id,
			'fff_pay_id'=>$pay_id,	
			'fff_pay_money'=>$orderArr['uvl_paymoney'],	
			'fff_pay_time'=>$now,	
			'fff_remark'=>'系统'
		];
		$this->add('fad_link_pay', $conPay);
		if($autostatus) $this->initCtrStatus($ctr_id);
		
		//删除无效的计划
		$res = $this->get('`crm_plan` JOIN `crm_customer_admin` ON cca_ctr_id = cp_ctr_id', ['cp_id'], " and cp_ok = 0 AND cp_au_uid != cca_au_uid
		AND cp_au_uid NOT IN (SELECT au_uid FROM `ypb2c`.`an_user_group_link` JOIN `ypb2c`.`an_user` ON ugl_uid = au_uid WHERE ugl_ugid = 33 AND au_status = 1)");
		if($res['data']){
			$this->del('crm_plan', sprintf(" and cp_id in (%s)", implode(',', array_column($res['data'], 'cp_id'))));
		}

		$this->CrmDb->End();
		return LibFc::ReturnData(true, $fct_id);
	}


	/**
	  * @method 历史补合同
	  * @param  $dataArr 
	  * @author soul
	  * @copyright 2024/1/30
	  * @return 
	  */
	public function addContractByOld($dataArr)
	{
		$res = $this->addCrmCustomerByUid($dataArr['u_id']);
		$ctr_id = $res['data'];
		$title = $dataArr['title'];
		$money = 0.00;
		foreach($dataArr['sves'] as $sve){
			$where = sprintf(" and fct_ctr_id=%d and fsl_sve_id=%d", $ctr_id, $sve['sve_id']);
			if($sve['des_id']){
				$where .= sprintf(" and fsl_des_id=%d", $sve['des_id']);
			}else{
				$where .= sprintf(" and fsl_btime=%d and fsl_etime=%d", $sve['btime'], $sve['etime']);
			}
			$res = $this->get('fad_link_fct_sve join fad_contract on fct_id = fsl_fct_id', ['fct_id'], $where, true);
			if(!empty($res['data'])) return LibFc::ReturnData(true,$res['data']['fct_id']);
			$money += $sve['money'];
		}
		$now = time();
		
		$this->CrmDb->Begin();
		$conArr = [
			'fct_ctr_id'=>$ctr_id,
			'fct_title'=>$title,
			'fct_money'=>$money,
			'fct_remark'=>'系统',
			'fct_status'=>2,
			'fct_modified'=>$now,
			'fct_chk_user'=>'系统'
		];
		$res = $this->add('fad_contract', $conArr);
		$fct_id = $res['data'];
		
		//业务员
		$this->add('fad_link_fct_usr', ['duc_usr_id'=>$dataArr['au_uid'], 'duc_fct_id'=>$fct_id]);
		
		//项目
		foreach($dataArr['sves'] as $sve){
			$conSer = [
				'fsl_fct_id'=>$fct_id,
				'fsl_sve_id'=>$sve['sve_id'],
				'fsl_money'=>$sve['money'],
				'fsl_remark'=>$sve['remark'],
				'fsl_btime'=>$sve['btime'],
				'fsl_etime'=>$sve['etime'],
				'fsl_des_id'=>(int) $sve['des_id']
			];
			$this->add('fad_link_fct_sve', $conSer);
		}
		if($money > 0){
			//付款计划
			$conPay = [
				'pay_status'=>1,	
				'pay_money'=>$money,	
				'pay_pay_time'=>$now,	
				'pay_create_time'=>$now,	
				'pay_fct_id'=>$fct_id,
				'pay_remark'=>'系统'
			];
			$res = $this->add('fad_pay_money', $conPay);
			$pay_id = $res['data'];
			
			//付款
			$conPay = [
				'fae_status'=>1,	
				'fae_text'=>$title,	
				'fae_money'=>$money,	
				'fae_create_usr_id'=>8,	
				'fae_create_usr'=>'系统',	
				'fae_create_time'=>$now,	
				'fae_ctr_id'=>$ctr_id,	
				'fae_fct_id'=>$fct_id
			];
			$res = $this->add('fad_finance', $conPay);
			$fae_id = $res['data'];

			//扣款
			$conPay = [
				'fff_fct_id'=>$fct_id,
				'fff_fae_id'=>$fae_id,
				'fff_pay_id'=>$pay_id,	
				'fff_pay_money'=>$money,	
				'fff_pay_time'=>$now,	
				'fff_remark'=>'系统'
			];
			$this->add('fad_link_pay', $conPay);
		}
		$this->CrmDb->End();
		return LibFc::ReturnData(true, $fct_id);
	}

	/**
	  * @method 自动调整当前业务员和客户之间的关系
	  * @param  $ctr_id 客户ID  
	  * @author soul
	  * @copyright 2021/4/13
	  * @return  0公海 1保护中 2已分配 5成交客户 6过期客户
	  */
	public function initCtrStatus($ctr_id)
	{
		$ctr_id = (int) $ctr_id;
		$res = $this->get('crm_customer left join crm_customer_admin on ctr_id=cca_ctr_id', ['ctr_id, ctr_level_id, cca_id, cca_level_id, cca_au_uid, cca_end_time'], sprintf(" and ctr_id=%d", $ctr_id));
		if(empty($res['data'])) return LibFc::ReturnData(false, '客户ID'.$ctr_id.'不存在');
		$hasLevelArr = $res['data'];
		$arr = ['level'=>0, 'au_uid'=>0, 'etime'=>0];
		$fenpei = ['flag'=>false, 'remark'=>'', 'new_au_id'=>0];//需要分配新业务员
		$now = time();
		$comAuUid = 172999;//公司会员ID
		$B2cBase = new B2cBase();

		//已审合同
		$table = 'fad_link_fct_sve
		JOIN fad_service ON sve_id = fsl_sve_id
		JOIN fad_contract ON  fsl_fct_id = fct_id
		JOIN fad_link_fct_usr ON duc_fct_id = fct_id';
		$res = $this->get($table, ['fct_id, fct_title, duc_usr_id au_uid, sve_id, sve_text, fsl_money, fsl_btime, fsl_etime'], sprintf(" and fct_ctr_id = %d and fct_status > 0 ORDER BY fsl_etime DESC", $ctr_id));
		if(!empty($res['data'])){//无合同的直接变更为公海
			$conArr = $res['data'];
			
			$arr['etime'] = $conArr[0]['fsl_etime'];
			if($arr['etime'] <= $now){//过期的
				$arr['level'] = 6;
				$arr['au_uid'] = 0;
			}else if($arr['etime'] > $now){//在服务期的
				$arr['level'] = 5;
				$arr['au_uid'] = $hasLevelArr[0]['ctr_level_id'] == $arr['level'] && $hasLevelArr[0]['cca_au_uid'] && $hasLevelArr[0]['cca_au_uid'] != 172999 ? $hasLevelArr[0]['cca_au_uid']: $conArr[0]['au_uid'];
				
				//已离职
				//1.业务员辞职后，按照其名下客户服务项目的最大单笔业绩来分配：
				//(1)客户服务项目最大一笔成交业绩≤5000元的：
				//①　客户最近到期的服务项目≤60天，则直接将客户自动平均分配给新业务员（入职两年内的）；
				//②　客户最近到期的服务项目＞60天，则在业务员离职30天后，平均分配给新业务员（入职两年内的）。
					//2025/6/6 改为上级手工分配
				//(2)客户服务项目最大一笔成交业绩＞5000元的，则业务员辞职时直接分配给跑街令客服；
				$res = $B2cBase->get('an_user', ['au_uid, au_name, au_enter, au_out'], sprintf(" and au_uid=%d", $arr['au_uid']), true);
				if(empty($res['data'])){//非公司业务
					$fenpei['flag'] = true;
					$fenpei['remark'] = '业务属于非公司业务员';
					$fenpei['new_au_id'] = 172999;
				}else if(!empty($res['data']['au_out']) && strtotime($res['data']['au_out']) > 0 && strtotime($res['data']['au_out']) < $now){
					$oldAuArr = $res['data'];
					$maxMoney = 0;
					foreach($conArr as $tv){
						if($tv['fsl_money'] >= $maxMoney) $maxMoney = $tv['fsl_money'];
					}
					if($maxMoney > 5000){
						$fenpei['flag'] = true;
						$fenpei['new_au_id'] = $comAuUid;
						$fenpei['remark'] = '最大一笔成交业绩＞5000元的，分配给跑街令客服';
					}/*else if($arr['etime'] <= strtotime('+60 day')){
						$fenpei['flag'] = true;
						$fenpei['remark'] = '客户最近到期的服务项目≤60天';
					}else if(strtotime($oldAuArr['au_out']) < strtotime('-30 day')){
						$fenpei['flag'] = true;
						$fenpei['remark'] = '客户最近到期的服务项目＞60天，则在业务员离职30天后';
					}*/
				}
				if(!$fenpei['flag']){
					//(仅)商家自助入驻(商家+PCVIP也允许)au_uid=172999后30天后，直接平均分配给新业务员
					$isAutoVip = true;
					$hasShop = false;
					foreach($conArr as $tv){
						if($tv['sve_id'] == 1) $hasShop = true;
						if(!in_array($tv['sve_id'], [1,2]) || $tv['au_uid'] != $comAuUid){
							$isAutoVip = false;
							break;
						}
					}

					if($hasShop && $isAutoVip && time() - $conArr[0]['fsl_btime'] >= 86400*30){//最晚时间
						//现有业务员一样
						if($hasLevelArr[0]['ctr_level_id'] != $arr['level'] || $arr['au_uid'] == $comAuUid){
							$fenpei['flag'] = true;
							$fenpei['remark'] = '商家自助入驻';
						}
					}
				}
			}
		}
		$this->CrmDb->Begin();
		
		if($fenpei['flag']){
			if(empty($fenpei['new_au_id'])){//为指定新业务员
				$table = 'an_user_group_link
				JOIN an_user_group ON ugl_ugid = ugp_id 
				JOIN an_user ON au_uid = ugl_uid';
				//分配给新业务员（入职两年内的）
				$res = $B2cBase->get($table, ['au_uid, ugp_name au_group,au_name, au_enter'], " and au_status = 1 AND au_pjcrmsys = 1 AND au_yewu=1 AND au_enter >= DATE_SUB(CURDATE(), INTERVAL 2 YEAR) group by au_uid");
				if(!empty($res['data']))
				{
					//一年内的权重2  其他的权重为1
					$auArr = [];
					$maxenter = 0;
					foreach($res['data'] as $uv){
						//业务员A权重是3，业务员B权重是2，业务员C权重是1
						$uv['weight'] = 1;
						$enter = strtotime($uv['au_enter']);
						if($enter > strtotime('-1 year')){
							$uv['weight'] = 2;
						}
						if($enter > $maxenter) $maxenter = $enter;
						$uv['ctr_count'] = 0;
						//平均权重
						$uv['avg_weight'] = 0;
						$auArr[$uv['au_uid']] = $uv;
					}
					//$maxenter 后已分配的人数
					$res = $this->get('crm_customer_fenpei', ['ccf_new_au_uid au_uid, count(*) ctr_count'], sprintf(" and ccf_new_au_uid in (%s) and ccf_atime >= %d and ccf_type='service' group by ccf_new_au_uid", implode(",", array_keys($auArr)), $maxenter));
					foreach($res['data'] as $uv){
						$auArr[$uv['au_uid']]['ctr_count'] = $uv['ctr_count'];
						$auArr[$uv['au_uid']]['avg_weight'] = $uv['ctr_count']/$auArr[$uv['au_uid']]['weight'];
					}

					//按平均权重升序、权重降序、入职时间降序
					$sort = [];
					foreach($auArr as $k=>$v){
						$sort['avg_weight'][$k] = $v['avg_weight'];
						$sort['weight'][$k] = $v['weight'];
						$sort['au_enter'][$k] = $v['au_enter'];
					}
					array_multisort($sort['avg_weight'], SORT_ASC, $sort['weight'], SORT_DESC, $sort['au_enter'], SORT_DESC, $auArr);
					//分配给第一个
					$temp = array_values($auArr);
					$fenpei['new_au_id'] = $temp[0]['au_uid'];
				}
			}
			if($fenpei['new_au_id']){
				$arr['au_old_uid'] = $arr['au_uid'];
				$arr['au_uid'] = $fenpei['new_au_id'];
				$add = [
					'ccf_type'=>'service',
					'ccf_ctr_id'=>$ctr_id,
					'ccf_old_au_uid'=>$arr['au_old_uid'],
					'ccf_new_au_uid'=>$arr['au_uid'],
					'ccf_remark'=>'系统分配:'.$fenpei['remark'],
					'ccf_reg'=>json_encode($auArr),
					'ccf_atime'=>$now,
				];
				$this->add('crm_customer_fenpei', $add);
			}
		}

		if($hasLevelArr[0]['ctr_level_id'] < 0 && $arr['level'] === 0) $arr['level'] = $hasLevelArr[0]['ctr_level_id'];

		if($hasLevelArr[0]['ctr_level_id'] != $arr['level']){
			$this->set('crm_customer', ['ctr_level_id'=>$arr['level']], sprintf(" and ctr_id=%d", $ctr_id));
		}
		if(in_array($arr['level'], [5])){//在服务期的
			$hasId = 0;
			if(!empty($hasLevelArr[0]['cca_id'])){
				foreach($hasLevelArr as $tv){
					if($tv['cca_au_uid'] == $arr['au_uid']){
						$hasId = $tv['cca_id'];
						if($tv['cca_level_id'] != $arr['level'] || $tv['cca_end_time'] != $arr['etime']){
							$this->set('crm_customer_admin', ['cca_level_id'=>$arr['level'], 'cca_end_time'=>$arr['etime']], sprintf(" and cca_ctr_id=%d and cca_id=%d", $ctr_id, $hasId));
						}
						break;
					}
				}
				//已存在，并且多条的删除剩余部分,或者不存在
				if(($hasId && count($hasLevelArr) > 1) || !$hasId){
					$this->del('crm_customer_admin', sprintf(" and cca_ctr_id=%d and cca_id in (%s) and cca_id != %d", $ctr_id, implode(',', array_column($hasLevelArr, 'cca_id')), $hasId));
				}
			}
			if(!$hasId){
				$add = [
					'cca_ctr_id'=>$ctr_id,
					'cca_level_id'=>$arr['level'],
					'cca_au_uid'=>$arr['au_uid'],
					'cca_begin_atime'=>$now,
					'cca_end_time'=>$arr['etime'],
					'cca_atime'=>$now,
					'cca_add_remark'=>'系统',
				];
				$this->add('crm_customer_admin', $add);
			}
		}else if(!empty($hasLevelArr[0]['cca_id']) && ($hasLevelArr[0]['cca_level_id'] != 1 || $hasLevelArr[0]['cca_end_time'] < $now)){//移除客户与业务员关联关系
			$this->del('crm_customer_admin', sprintf(" and cca_ctr_id=%d", $ctr_id));
		}
		$this->initCtrKefu($ctr_id);
		$this->CrmDb->End();
		return LibFc::ReturnData(true, $arr);
	}


	/**
	  * @method 归属公司的客户分配客服
	  * @param  $ctr_id 客户ID  为空则初始化所有
	  * @author soul
	  * @copyright 2024/7/10
	  * @return  
	  */
	public function initCtrKefu($ctrId = 0)
	{
		$where = $ctrId ? sprintf(" AND ctr_kefu = 0 and ctr_id=%d", $ctrId): ' AND ctr_kefu = 0';
		$table = 'crm_customer JOIN crm_customer_admin ON cca_ctr_id = ctr_id AND cca_au_uid = 172999';
 		$cres = $this->get($table, ['ctr_id'], $where);
		if(!empty($cres['data'])){
			$ctrArr = array_column($cres['data'], 'ctr_id');
			//当前分配状态
			$kefuArr = [];
			$res = $this->get($table, ['ctr_kefu', 'count(*) count'], " and ctr_kefu > 0 group by ctr_kefu");
			$hasArr = array_column($res['data'], 'count', 'ctr_kefu');
			$B2cBase = new B2cBase();
			$res = $B2cBase->get('an_user JOIN an_user_group_link ON ugl_uid=au_uid', ['au_uid', '0 count'], " and au_status = 1 AND ugl_ugid=33");
			foreach($res['data'] as $v){
				if($hasArr[$v['au_uid']]) $v['count'] = $hasArr[$v['au_uid']];
				$v['ctrids'] = [];
				$kefuArr[] = $v;
			}
			//开始分配
			foreach($ctrArr as $id){
				//找出最少的
				usort($kefuArr, function($a, $b) {
					return $a['count'] - $b['count'];
				});
				$kefuArr[0]['count']++;
				//$kefuArr[0]['ctrids'][] = $id;
				$this->set('crm_customer', ['ctr_kefu'=>$kefuArr[0]['au_uid']], sprintf(" and ctr_id=%d", $id));
			}
		}
		return LibFc::ReturnData(true);
	}

	/**
	  * @method 系统工作计划与提醒规则
	  * @author soul
	  * @copyright 2021/4/13
	  * @return  
	  （一）广告提醒：
		1．优先期续费（提醒2次）：
		（1）广告到期前37天，文字提醒：“广告”优先期剩余7天
		（2）到期前31天，文字提醒：“广告”优先期剩余1天
		2．服务期到期提醒：广告到期前最后1天，文字提醒：“广告”服务期剩余1天
		（二）商家入驻提醒：
		1．归属到业务员后，15天后启动第一次提醒，文字提醒：“商家入驻”客情服务
		2．日常客情提醒：90天/次，文字提醒：“商家入驻”客情服务
		（三）目录类、机器人、接口、资源包、其他服务项目提醒：
		1．归属到业务员后，15天后启动第一次提醒，文字提醒：客情服务：服务项目名称
		2．客情提醒：45天/次，文字提醒：客情服务：服务项目名称
		3．服务期提醒2次：
		（1）到期前30天，文字提醒：“服务项目名称”续费提醒，30天后到期；
		（2）到期前10天，文字提醒：“服务项目名称”续费提醒，10天后到期。
	  */
	public function initSysPlan()
	{
		$now = time();
		$ymdTime = strtotime(date('Y-m-d'));
		$B2cBase = new B2cBase();
		$res = $B2cBase->get('`an_user_group_link` JOIN `an_user` ON ugl_uid = au_uid', ['au_uid'], " and ugl_ugid = 33 AND au_status = 1");
		$kefuUids = array_column($res['data'], 'au_uid');
		$table = '`fad_link_fct_sve`
		JOIN `fad_service` ON sve_id = fsl_sve_id
		JOIN `fad_contract` ON fsl_fct_id = fct_id
		JOIN fad_link_fct_usr ON duc_fct_id = fct_id
		JOIN `crm_customer` ON fct_ctr_id = ctr_id
		JOIN `crm_customer_admin` ON ctr_id = cca_ctr_id';
		$serRes = $this->get($table, ['ctr_id, ctr_comname, cca_au_uid au_uid, duc_usr_id ser_au_uid,  fct_id, fsl_id, sve_id, sve_text, fsl_btime, fsl_etime'], sprintf(" and fsl_etime > %d", $ymdTime));
		$planArr = [];
		foreach($serRes['data'] as $sv){
			//已购买天数
			$sv['ymd_btime'] = strtotime(date('Y-m-d', $sv['fsl_btime']));
			$sv['bday_diff'] = ($ymdTime-$sv['ymd_btime'])/3600/24;
			
			//到期天数
			$sv['ymd_etime'] = strtotime(date('Y-m-d', $sv['fsl_etime']));
			$sv['eday_diff'] = ($sv['ymd_etime'] - $ymdTime)/3600/24;
			switch($sv['sve_id'])
			{
				case 7: //广告
					if($sv['eday_diff'] == 37){
						$temp = $sv;
						$temp['remark'] = '“广告”优先期剩余7天';
						$planArr[$sv['ctr_id']][] = $temp;
					}
					if($sv['eday_diff'] == 31){
						$temp = $sv;
						$temp['remark'] = '“广告”优先期剩余1天';
						$planArr[$sv['ctr_id']][] = $temp;
					}
					if($sv['eday_diff'] == 1){
						$temp = $sv;
						$temp['remark'] = '“广告”服务期剩余1天';
						$planArr[$sv['ctr_id']][] = $temp;
					}
				break;
				case 1: //商家入驻
					if($sv['bday_diff'] == 15 || ($sv['bday_diff'] > 0 && $sv['bday_diff']%90 === 0)){
						$temp = $sv;
						$temp['remark'] = '“商家入驻”客情服务';
						$planArr[$sv['ctr_id']][] = $temp;
					}
				break;
				default://目录类、机器人、接口、资源包、其他服务项目
					if($sv['bday_diff'] == 15 || ($sv['bday_diff'] > 0 && $sv['bday_diff']%45 === 0)){
						$temp = $sv;
						$temp['remark'] = '客情服务：'.$temp['sve_text'];
						$planArr[$sv['ctr_id']][] = $temp;
					}
					if($sv['eday_diff'] == 30){
						$temp = $sv;
						$temp['remark'] = $temp['sve_text'].'续费提醒，30天后到期';
						$planArr[$sv['ctr_id']][] = $temp;
					}
					if($sv['eday_diff'] == 10){
						$temp = $sv;
						$temp['remark'] = $temp['sve_text'].'续费提醒，10天后到期';
						$planArr[$sv['ctr_id']][] = $temp;
					}
				break;
			}
		}
		$this->CrmDb->Begin();
		$day = date('Ymd');

		$tmpkefu = [];
		foreach($planArr as $ctr_id=>$pvs){
			foreach($pvs as $pv){
				if($pv['au_uid'] == 172999){
					if(empty($tmpkefu)) $tmpkefu = $kefuUids;
					$key = array_keys($tmpkefu)[0];
					$pv['au_uid'] = $tmpkefu[$key];
					unset($tmpkefu[$key]);
				}
				$addArr = [
					'cp_date'=>$day,
					'cp_ctr_id'=>$pv['ctr_id'],
					'cp_au_uid'=>$pv['au_uid'],
					'cp_from'=>'service',
					'cp_from_id'=>$pv['fsl_id'],
					'cp_title'=>$pv['remark'],
					'cp_by_uid'=>8,
					'cp_atime'=>$now
				];
				$where = sprintf(" and cp_date=%d and cp_ctr_id=%d and cp_au_uid=%d and cp_from='%s' and cp_from_id='%s'", 
					$addArr['cp_date'],$addArr['cp_ctr_id'],$addArr['cp_au_uid'],$addArr['cp_from'], $addArr['cp_from_id']);
				$res = $this->get('crm_plan', ['cp_id'], $where);
				if(empty($res['data'])) $this->add('crm_plan', $addArr);
			}
		}
		$this->CrmDb->End();
		return LibFc::ReturnData(true);
	}


	/**
	  * @method 通过手机号码创建客户
	  * @param  $mobile 手机号码
	  * @param  $au_uid 业务员ID
	  * @author soul
	  * @copyright 2024/2/19
	  * @return 
	  */
	public function addCtrByMobile($mobile, $au_uid = 0)
	{
		if(!preg_match('/^1\d{10}$/', $mobile)) return LibFc::ReturnData(false, '手机号码不正确，请重新输入！');
		$ctr_id = 0;
		$YpwUser = new YpwUser();
		$res = $YpwUser->get('yp_user', ['u_id'], sprintf(" and u_mobile_check='Y' and u_mobile='%s'", $mobile), true);
		$this->CrmDb->Begin();
		if(!empty($res['data'])){
			$uid = $res['data']['u_id'];
		}else{
			$code = '100000';
			$addSms = [
				'smc_mobile'=>$mobile,
				'smc_style'=>'bind',
				'smc_from'=>'system',
				'smc_code'=>$code,
				'smc_send_time'=>time(),	
				'smc_expire_time'=>time()+600,
				'smc_sms'=>0
			];
			$SendSms = new SendSms();
			$SendSms->Add('sc_mobile_code', $addSms);
			$addUser = [
				'u_mobile'=>$mobile,
				'mobile_code'=>$code,
				'u_from'=>'system',
				'au_uid'=>$au_uid
			];
			$res = $YpwUser->Register($addUser);
			$uid = $res['data'];
		}
		$res = $this->addCrmCustomerByUid($uid, $au_uid);
		$ctr_id = $res['data'];
		$this->CrmDb->End();
		return LibFc::ReturnData(true, $ctr_id);
	}


	/**
	 * @param  int $uid 用户uid
	 * @method 分配新注册用户
	 * @author soul 
	 * @copyright 2024/9/19
	  2025/11/13
	 （1）数量分配规则：
		①参与分配人员：按入职时长，分三个阶段，0-1年：入职1-3年：入职3年以上=2：1：0
		②上个自然月跟进完成率>90%：下个月正常100%分配
		③上个自然月跟进完成率60-89%：分配70%
		④上个自然月跟进完成率<60%：不分配，如需重新分配需要申请并通过人工评估才可再开通   ypdb_write.keyval  pjdcrm_feipei202511(年月):业务员ID逗号分隔	
		⑤下个月的分配量按上个月的考核完成率执行
	（2）跟进记录考核标准：
		①考核内容：按上个自然月的“跟进完成率”进行考核，只要有保存成功的跟进，都算完成。
		②无论是通过任意入口写的跟进记录（公海或日计划入口），只要是同一个客户ID，跟进记录关联，在日计划中均显示为完成状态。
	 */
	public function fenpeiNewUser($uid, $au_uid = 0)
	{
		$res = $this->addCrmCustomerByUid($uid, $au_uid);
		$ctr_id = $res['data'];
		if(!empty($ctr_id)){
			$now = time();
			$res = $this->get('crm_customer_admin', ['*'], sprintf(" and cca_ctr_id=%d", $ctr_id), true);
			if(empty($res['data'])){
				if(empty($au_uid) && time() < strtotime('2025-12-01')){
					//每个业务员均衡分配
					$table = 'an_user_group_link
					JOIN an_user_group ON ugl_ugid = ugp_id 
					JOIN an_user ON au_uid = ugl_uid';
					$B2cBase = new B2cBase();
					$res = $B2cBase->get($table, ['au_uid, ugp_name au_group,au_name'], " and au_status = 1 AND au_pjcrmsys = 1 AND au_fenpei = 1 group by au_uid");
					if(!empty($res['data']))
					{
						$auArr = [];
						foreach($res['data'] as $uv){
							//后期支持权重
							$uv['weight'] = 1;
							$uv['ctr_count'] = 0;
							//平均权重
							$uv['avg_weight'] = 0;
							$auArr[$uv['au_uid']] = $uv;
						}
						//已分配的人数
						$res = $this->get('crm_customer_fenpei', ['ccf_new_au_uid au_uid, count(*) ctr_count'], sprintf(" and ccf_new_au_uid in (%s) and ccf_atime >= %d and ccf_type='register' group by ccf_new_au_uid", implode(",", array_keys($auArr)), strtotime(date('Y-m-d'))));
						foreach($res['data'] as $uv){
							$auArr[$uv['au_uid']]['ctr_count'] = $uv['ctr_count'];
							$auArr[$uv['au_uid']]['avg_weight'] = $uv['ctr_count']/$auArr[$uv['au_uid']]['weight'];
						}

						//按平均权重升序、权重降序
						$sort = [];
						foreach($auArr as $k=>$v){
							$sort['avg_weight'][$k] = $v['avg_weight'];
							$sort['weight'][$k] = $v['weight'];
						}
						array_multisort($sort['avg_weight'], SORT_ASC, $sort['weight'], $auArr);
						//分配给第一个
						$temp = array_values($auArr);
						$au_uid = $temp[0]['au_uid'];
					}
				}else if(empty($au_uid)){
					//每个业务员均衡分配
					$B2cBase = new B2cBase();
					$mintime = strtotime('-3 years');
					$res = $B2cBase->get('an_user', ['au_uid, au_name, au_enter'], sprintf(" and au_status = 1 AND au_pjcrmsys = 1 AND au_fenpei = 1 and UNIX_TIMESTAMP(au_enter) >%d group by au_uid", $mintime));
					if(!empty($res['data']))
					{
						$auArr = array_column($res['data'], null, 'au_uid');
						//上个自然月的跟进率
						$lastm_btime = strtotime('first day of last month 00:00:00');
						$lastm_etime   = strtotime('last day of last month 23:59:59');
						$table = sprintf("(
						SELECT ccf_new_au_uid au_uid, cfo_ctr_id ctr_id, ccf_id, cfo_id FROM `crm_customer_fenpei`
						LEFT JOIN `crm_follow` ON cfo_ctr_id = ccf_ctr_id AND ccf_new_au_uid = cfo_au_uid and cfo_atime BETWEEN %d AND %d
						WHERE ccf_type='register' AND ccf_atime BETWEEN %d AND %d and ccf_new_au_uid in (%s) 
						 GROUP BY ccf_new_au_uid, cfo_ctr_id
						 ) t", $lastm_btime, $lastm_etime, $lastm_btime, $lastm_etime, implode(',', array_keys($auArr)));
						$res = $this->get($table, ['au_uid, COUNT(*) fp_count, SUM(CASE WHEN cfo_id > 0 THEN 1 ELSE 0 END) ok_count'], " GROUP BY au_uid");
						foreach($res['data'] as $tv){
							$tv['follow_rate'] = round($tv['ok_count']/$tv['fp_count'], 2);
							$auArr[$tv['au_uid']] = array_merge($auArr[$tv['au_uid']], $tv);
						}

						//今日已分配的人数
						$res = $this->get('crm_customer_fenpei', ['ccf_new_au_uid au_uid, count(*) ctr_count'], sprintf(" and ccf_new_au_uid in (%s) and ccf_atime >= %d and ccf_type='register' group by ccf_new_au_uid", implode(",", array_keys($auArr)), strtotime('today -3 days')));
						foreach($res['data'] as $tv){
							$auArr[$tv['au_uid']] = array_merge($auArr[$tv['au_uid']], $tv);
						}
						
						//如需重新分配需要申请并通过人工评估才可再开通
						$YpwBase = new YpwBase();
						$res = $YpwBase->getKeyVal('pjdcrm_feipei'.date('Ym'));
						$allowUids = $res['data']? explode(',', $res['data']): [];

						foreach($auArr as $uid=>$uv){
							//后期支持权重
							$year1 = strtotime('-1 years');
							$uv['weight'] = strtotime($uv['au_enter']) >= $year1? 2 : 1;
							if(empty($uv['ctr_count'])) $uv['ctr_count'] = 0;
							if(in_array($uid, $allowUids) || strtotime($uv['au_enter']) > $lastm_btime){
								//人工评估开通或者新入职
							}else{
								//修正权重
								if($uv['follow_rate'] < 0.6){
									$uv['weight'] = 0;
								}else if($uv['follow_rate'] <= 0.9){
									$uv['weight'] = $uv['weight'] * 0.7;
								}
							}
							//权重越高、客户越少，越低
							$uv['avg_weight'] = $uv['weight'] > 0? $uv['ctr_count'] / $uv['weight']: 999999;
							$auArr[$uid] = $uv;
						}
						//按平均权重升序、权重降序
						$sort = [];
						foreach($auArr as $k=>$v){
							$sort['avg_weight'][$k] = $v['avg_weight'];
							$sort['weight'][$k] = $v['weight'];
						}
						array_multisort($sort['avg_weight'], SORT_ASC, $sort['weight'], $auArr);
						//分配给第一个
						$temp = array_values($auArr);
						$au_uid = $temp[0]['au_uid'];
					}
				}
				//var_dump($auArr);exit;

				$this->CrmDb->Begin();
				$add = [
					'ccf_type'=>'register',
					'ccf_ctr_id'=>$ctr_id,
					'ccf_old_au_uid'=>0,
					'ccf_new_au_uid'=>$au_uid,
					'ccf_remark'=>'系统分配:新会员',
					'ccf_reg'=>json_encode($auArr),
					'ccf_atime'=>$now,
				];
				$this->add('crm_customer_fenpei', $add);
				
				//保护30天
				$add = [
					'cca_ctr_id'=>$ctr_id,
					'cca_level_id'=>1,
					'cca_au_uid'=>$au_uid,
					'cca_begin_atime'=>$now,
					'cca_end_time'=>$now+3600*24*30,
					'cca_atime'=>$now,
					'cca_add_remark'=>'系统分配新会员',
				];
				$this->add('crm_customer_admin', $add);

				$this->set('crm_customer', ['ctr_level_id'=>1], sprintf(" and ctr_id=%d and ctr_level_id = 0", $ctr_id));
				
				//计划任务
				$add = [
					'cp_ctr_id'=>$ctr_id,
					'cp_date'=>date('Ymd'),
					'cp_au_uid'=>$au_uid,
					'cp_from'=>'register',
					'cp_title'=>'新注册用户',
					'cp_by_uid'=>8,
					'cp_atime'=>$now,
				];
				$this->add('crm_plan', $add);
				$this->CrmDb->End();
			}
		}
		return LibFc::ReturnData(true, $ctr_id);
	}

	/**
	 * @method  入驻商家归属
				填了邀请码的：保护起来不放入公海，30天内未成交，释放公海
				未填邀请码的：24小时先不分配，期间业务员可凭证据来认领并申请更改保护人；24小时内无人认领，平均分配给业务员；分配后30天内未成交，释放到公海
	 * @param  int $uid 用户uid
	 * @author soul 
	 * @copyright 2025/11/6
	 */
	public function initShopVipYewu($shopid)
	{
		//客户是否有保护
		$now = time();
		$res = $this->get('crm_customer left join crm_customer_admin on ctr_id=cca_ctr_id', ['ctr_id', 'cca_au_uid', 'cca_end_time', 'ctr_level_id'], sprintf(" and ctr_uid=%d", $shopid), true);
		if(empty($res['data'])) return LibFc::ReturnData(true, []);
		$ctrArr = $res['data'];
		$ctr_id = $ctrArr['ctr_id'];
		$sysuid = 172999;
		//已有归属不处理
		if(($ctrArr['ctr_level_id'] == 5 || $ctrArr['cca_au_uid'] != $sysuid) && $ctrArr['cca_end_time'] > $now) return LibFc::ReturnData(true, $ctrArr);

		$PjlShop = new PjlShop();
		$res = $PjlShop->get('pl_shop left join dl_worker_invcode on dwi_invcode = shop_dwi_invcode', ['shop_id', 'dwi_dwo_uid'], sprintf(" and shop_id=%d and shop_vip_etime<%d and shop_status != 2", $shopid, $now), true);
		if(empty($res['data'])) return LibFc::ReturnData(true, []);
		$shopArr = $res['data'];
		
		$this->CrmDb->Begin();
		//归属跑街令的，允许修改一次邀请码（如果没填写，在付款页面修改邀请码，以首次修改邀请码的为准）
		if($ctrArr['cca_au_uid'] == $sysuid){
			$this->del('crm_customer_admin', sprintf(" and cca_ctr_id=%d and cca_level_id = 1 and cca_au_uid=%d", $ctr_id, $sysuid));
		}

		if($shopArr['dwi_dwo_uid']){
			//填了邀请码的：保护起来不放入公海，30天内未成交，释放公海
			$au_uid = $shopArr['dwi_dwo_uid'];
			$totime = $now+3600*24*30;
			$remark = '邀请码保护';
		}else{
			$au_uid = $sysuid;
			$totime = $now+3600*24*2;//保护两天，每天定时分配
			$remark = '无邀请码';
		}
		
		$add = [
			'cca_ctr_id'=>$ctr_id,
			'cca_level_id'=>1,
			'cca_au_uid'=>$au_uid,
			'cca_begin_atime'=>$now,
			'cca_end_time'=>$totime,
			'cca_atime'=>$now,
			'cca_add_remark'=>$remark,
		];
		$this->add('crm_customer_admin', $add);
		$this->set('crm_customer', ['ctr_level_id'=>1], sprintf(" and ctr_id=%d and ctr_level_id = 0", $ctr_id));
		$this->CrmDb->End();
		$ctrArr['cca_au_uid'] = $au_uid;
		return LibFc::ReturnData(true, $ctrArr);
	}

	/**
	 * @method  未填邀请码的：24小时内无人认领，平均分配给业务员；分配后30天内未成交，释放到公海
	 * @author soul 
	 * @copyright 2025/11/6
	 */
	public function fenpeiShopNoInvcode()
	{
		//前一天分配到公司的
		$res = $this->get('crm_customer_admin', ['*'], sprintf(" and cca_au_uid=172999 and cca_add_remark ='无邀请码' and cca_level_id =1 and cca_begin_atime <%d", time()-3600*24));
		$ctrArr = $res['data'];
		$now = time();
		$B2cBase = new B2cBase();
		$ccfRemark = '系统分配:无邀请码'; 
		$this->CrmDb->Begin();
		foreach($ctrArr as $ctr){
			$ctr_id = $ctr['ccf_ctr_id'];
			$res = $B2cBase->get('an_user', ['au_uid, au_name'], " and au_status = 1 AND au_pjcrmsys = 1 AND au_yewu = 1");
			$auArr = [];
			foreach($res['data'] as $uv){
				//后期支持权重
				$uv['weight'] = 1;
				$uv['ctr_count'] = 0;
				//平均权重
				$uv['avg_weight'] = 0;
				$auArr[$uv['au_uid']] = $uv;
			}
			//最近30天 已分配的人数
			$res = $this->get('crm_customer_fenpei', ['ccf_new_au_uid au_uid, count(*) ctr_count'], sprintf(" and ccf_new_au_uid in (%s) and ccf_atime >= %d and ccf_type='general' and ccf_remark='%s' group by ccf_new_au_uid", implode(",", array_keys($auArr)), strtotime('-30 day'), $ccfRemark));
			foreach($res['data'] as $uv){
				$auArr[$uv['au_uid']]['ctr_count'] = $uv['ctr_count'];
				$auArr[$uv['au_uid']]['avg_weight'] = $uv['ctr_count']/$auArr[$uv['au_uid']]['weight'];
			}

			//按平均权重升序、权重降序
			$sort = [];
			foreach($auArr as $k=>$v){
				$sort['avg_weight'][$k] = $v['avg_weight'];
				$sort['weight'][$k] = $v['weight'];
			}
			array_multisort($sort['avg_weight'], SORT_ASC, $sort['weight'], $auArr);
			//分配给第一个
			$temp = array_values($auArr);
			$au_uid = $temp[0]['au_uid'];

			$this->CrmDb->Begin();
			$add = [
				'ccf_type'=>'general',
				'ccf_ctr_id'=>$ctr_id,
				'ccf_old_au_uid'=>$ctr['cca_au_uid'],
				'ccf_new_au_uid'=>$au_uid,
				'ccf_remark'=>$ccfRemark,
				'ccf_reg'=>json_encode($auArr),
				'ccf_atime'=>$now,
			];
			$this->add('crm_customer_fenpei', $add);
			
			//保护30天
			$add = [
				'cca_ctr_id'=>$ctr_id,
				'cca_au_uid'=>$au_uid,
				'cca_begin_atime'=>$now,
				'cca_end_time'=>$now+3600*24*30,
				'cca_atime'=>$now,
				'cca_add_remark'=>$ccfRemark,
			];
			$this->set('crm_customer_admin', $add, sprintf(" and cca_id=%d", $ctr['cca_id']));
		}
		$this->CrmDb->End();
		return LibFc::ReturnData(true);
	}
	

	/**
	  * @method 通过手机号码查找所属业务员
	  * @param  $mobile 手机号码
	  * @author soul
	  * @copyright 2025/11/22
	  * @return {"status":true,"data":{"org_ctr_id":"96477","ctr_id":"25396","cca_level_id":"5","au_uid":"334744","end_time":"1797004800"},"code":0,"runtime":209}
		org_ctr_id:手机号码对应的客户ID,  ctr_id:归属主客户
	  */
	public function checkMobileSales($mobile)
	{
		$mobile = trim($mobile);
		if(!preg_match('/^1\d{10}$/', $mobile)) return LibFc::ReturnData(false, '手机号码不正确，请重新输入！');
		$arr = [];
		$YpwUser = new YpwUser();
		$res = $YpwUser->get('yp_user', ['u_id'], sprintf(" and u_mobile_check='Y' and u_mobile='%s'", $mobile), true);
		if(empty($res['data'])) return LibFc::ReturnData(true, $arr);
		$uid = $res['data']['u_id'];
		$res =	$this->Get('crm_customer',['ctr_id'],sprintf(" AND ctr_uid = %d",$uid),true);
		if(empty($res['data'])){
			//广告系统反找
			$res = $this->getAdsCtr($mobile);
			$arr = $res['data'];
			$arr['org_ctr_id'] = 0;
			return LibFc::ReturnData(true, $arr);
		}
		$ctr_id = $res['data']['ctr_id'];
		$arr['org_ctr_id'] = $ctr_id;
		$now = time();
		//是否成交
		$res =	$this->Get('crm_customer_admin',['cca_ctr_id ctr_id', 'cca_level_id', 'cca_au_uid au_uid', 'cca_end_time end_time'],sprintf(" AND cca_ctr_id = %d and cca_end_time > %d and cca_level_id = 5",$ctr_id, $now),true);
		if(!empty($res['data'])){
			$arr = array_merge($arr, $res['data']);
		}else{
			//广告系统反找
			$OthB2cDb = new BaseDb(mvc::$cfg['DB']['B2COTH']);
			$res = $this->getAdsCtr($mobile);
			if($res['data']){
				$arr = array_merge($arr, $res['data']);
			}else{
				//找剩余状态保护的
				$res =	$this->Get('crm_customer_admin',['cca_ctr_id ctr_id', 'cca_level_id', 'cca_au_uid au_uid', 'cca_end_time end_time'], sprintf(" AND cca_ctr_id = %d and cca_end_time > %d",$ctr_id, $now),true);
				if(!empty($res['data'])){
					$arr = array_merge($arr, $res['data']);
				}
			}
		}
		return LibFc::ReturnData(true, $arr);
	}
	
	/**
	  * @method 广告系统 通过手机号码查找所属业务员
	  * @param  $mobile 手机号码
	  * @author soul
	  * @copyright 2025/11/22
	  * @return 
	  */
	private function getAdsCtr($mobile)
	{
		//广告系统反找
		$now = time();
		$OthB2cDb = new BaseDb(mvc::$cfg['DB']['B2COTH']);
		$res = $OthB2cDb->get('pj_place_ads_time JOIN pj_place_ads ON pla_id = pat_pla_id JOIN pj_user_ads ON ads_id = pla_ads_id', ['ads_u_id u_id', 'pat_etime end_time', 'pla_au_uid au_uid'], sprintf(" and pat_etime> %d and ads_url_data like '%%%s%%' limit 1", $now, $mobile), true);
		if($res['data']){
			$adsArr = $res['data'];
			//找所属客户
			$res = $this->Get('crm_customer',['ctr_id'],sprintf(" AND ctr_uid = %d",$adsArr['u_id']),true);
			if(!empty($res['data'])){
				$ctr_id = $res['data']['ctr_id'];
				$res =	$this->Get('crm_customer_admin',['cca_ctr_id ctr_id', 'cca_level_id', 'cca_au_uid au_uid', 'cca_end_time end_time'], sprintf(" AND cca_ctr_id = %d and cca_end_time > %d and cca_level_id = 5", $ctr_id, $now),true);
				if(!empty($res['data'])){
					$arr = $res['data'];
				}else{//避免CRM记录不存在
					$arr = [
						'ctr_id'=>$ctr_id,
						'cca_level_id'=>7,
						'au_uid'=>$adsArr['au_uid'],
						'end_time'=>$adsArr['end_time']
					];
				}
			}
		}
		return LibFc::ReturnData(true, $arr);
	}

	/**
	 * @method 获取广告信息数组列表
	 * @author zhengweihua 
	 * @copyright 2026-05-13
	 * @return Array 
	 array (
  'status' => true,
  'data' => 
  array (
    83 =>                 //商用车 =》有840、860，84、86=》乘用车
    array (
      'pa_id' => '83',    //广告ID
      'pa_name' => '开机广告',  //广告名称
      'pa_is_area' => '1',   //是否区域广告
      'pa_is_keyword' => '0',  // 是否关键字广告
      'pa_keyword_type' => '',  //关键字类型
      'pa_max' => '2',  // 广告位最大数量
      'use' =>         // 具体 省份/品牌
      array (
        19 => 
        array (
          'id' => '19',     //省份/品牌ID
          'name' => '广东省', // 省份/品牌名称
          'row' => 2,        //渲染表格的跨行数
          'has' => 2,        //当前存在广告
          'date' => 0,
          'max' => '2',      //最大数量
          'can' => 0,        //可使用数量
          'mod' => 'all',   //类型： all /pc：乘用车/cv:商用车
		  'price'=> 5000  //广告价格
          'client' =>      // 使用的客户
          array (
            0 => 
            array (
              'ads_id' => '2704',   //客户广告ID
              'pla_id' => '2704',  //广告位的广告关联ID
              'pla_pa_id' => '83', //广告位ID
              'pat_pc_id' => '19', //省份/品牌ID
			  'pla_au_uid'=>'1044384',业务员ID
              'pla_sales' => '赵丹', //业务员
			  'ads_u_id' =>'1044384', //客户UID
              'ads_title' => '温州市赛伦特汽车配件有限公司', //广告标题
              'pat_keyword' => '', 
              'pat_btime' => '1775664000',  //开始时间戳
              'pat_etime' => '1791475200',  //结束时间戳
              'ads_atime' => '2026-03-05',  //ads_atime
              'pla_remark' => '',          //备注
              'pla_status' => '1',         //状态 2:设计 1:启用/预售（通过s_date判断 预售);0:暂停
              'pal_shoufei' => '1',        //是否收费
              'pat_modcv' => '0',          //乘用车标识
              'pat_modpc' => '0',           //商用车标识
              'ads_sucai' => '',         
              'ads_require' => '',         //广告设计要求
              'ads_sucai_time' => '0', 
              'ads_template' => '',     //广告模板
              'ads_design' => '0',        // 通知设计时间
              's_date' => '2026-04-09',    // 开始时间
              'e_date' => '2026-10-09',    //结束时间
              'ads_add_time' => '1772699125',
              'pat_last_day' => 149,      //剩余天数
              'pat_total_day' => 183,    //总天数
            ),
            1 => 
            array (
              'ads_id' => '2643',
              'pla_id' => '2643',
              'pla_pa_id' => '83',
              'pat_pc_id' => '19',
              'pla_sales' => '彭自谦',
              'ads_title' => '广州信鸿誉汽车配件有限公司',
              'pat_keyword' => '',
              'pat_btime' => '1773331200',
              'pat_etime' => '1804867200',
              'ads_atime' => '2026-02-04',
              'pla_remark' => '',
              'pla_status' => '1',
              'pal_shoufei' => '1',
              'pat_modcv' => '0',
              'pat_modpc' => '0',
              'ads_sucai' => '',
              'ads_require' => '',
              'ads_sucai_time' => '0',
              'ads_template' => '',
              'ads_design' => '0',
              's_date' => '2026-03-13',
              'e_date' => '2027-03-13',
              'ads_add_time' => '1770168250',
              'pat_last_day' => 304,
              'pat_total_day' => 365,
            ),
          ),
        ),
      ),
      'size' => '1280*2276',  //尺寸
    ),
  ),
  'code' => 0,
);
	*/
	public function getNadsList()
	{
		$time = strtotime(date('Y-m-d 00:00:00'));
    
        // 省份
        $ads = new BaseDb(mvc::$cfg['DB']['B2COTH']);
		
        $res = $ads->get('yp_province_city', ['pc_id as id', 'pc_name as name'], 'and pc_pid = 0 order by pc_seq, pc_id');
        $city = array_column($res['data'], null, 'id');

        // 品牌
        $make = [];
        $com = new BaseDb(mvc::$cfg['DB']['B2C_CAR']);
        $res = $com->Get(
            'bc_brand join bc_model2 on brand_id = mod2_brand_id',
            ['brand_id as id', 'brand_name as name', 'mod2_pc', 'mod2_cv'],
            ' order by brand_name'
        );
        foreach ($res['data'] as $item)
        {
            if (!isset($make[$item['id']]))
            {
                $make[$item['id']] = [
                    'id' => $item['id'],
                    'name' => $item['name'],
                    'mod2_pc' => 0,
                    'mod2_cv' => 0,
                ];
            }

            if ($item['mod2_pc'] && !$make[$item['id']]['mod2_pc']) {
                $make[$item['id']]['mod2_pc'] = 1;
            }

            if ($item['mod2_cv'] && !$make[$item['id']]['mod2_cv']) {
                $make[$item['id']]['mod2_cv'] = 1;
            }
        }

        // 按省或者品牌合并规整
        $world = [['id'=>0, 'name'=>'独家']];

        // 广告名称
        $area = $ads->get('pj_place', ['pa_id', 'pa_name', 'pa_size'], 'order by pa_name');
        $area = array_column($area['data'], null, 'pa_id');

        $area[84]['pa_name'] = 'VIN解码-乘用车';
        $area[84*10] = array_merge($area[84], [
            'pa_id' => 84*10,
            'pa_name' => 'VIN解码-商用车',
        ]);

        $area[86]['pa_name'] = '车型查询-乘用车';
        $area[86*10] = array_merge($area[86], [
            'pa_id' => 86*10,
            'pa_name' => '车型查询-商用车',
        ]);
        ksort($area, SORT_STRING);

        // 已有客户数据
        $where = '';
        $column = [
            'ads_id',
            'pla_id',
            'pla_pa_id',
            'pat_pc_id',
            'pla_sales',
			'pla_au_uid',
            'ads_title',
            'pat_keyword',
            'pat_btime',
            'pat_etime',
            'ads_atime',
            'pla_remark',
            'pla_status',
            'pal_shoufei',
            'pat_modcv',
            'pat_modpc',
            'ads_sucai',
            'ads_require',
            'ads_sucai_time',
            'ads_template',
            'ads_design',
			'ads_u_id'
        ];
        
        $where = sprintf('%s  and pat_etime >= %d order by pat_etime', $where, $time);
        $table = 'pj_user_ads a JOIN pj_place_ads b ON ads_id = pla_ads_id join pj_place_ads_time on pla_id = pat_pla_id';
        $adsAr = $ads->get($table, $column, $where);

        // 业务员
        $where = sprintf(' and pat_etime >= %d and pla_sales != "" order by pla_sales', $time);
        $sale = $ads->get($table, ['distinct pla_sales'], $where);
        $sale = array_column($sale['data'], 'pla_sales');

        // 广告价格
        $price = [];
        $adsApp = new BaseDb(mvc::$cfg['DB']['B2C']);
        $adsRes = $adsApp->get('yp_ads.all_ad_price', ['aap_p_id, aap_pc_id, aap_keyword, aap_price, app_modtype']," and aap_site='pjd' order by aap_p_id, app_modtype");
        foreach ($adsRes['data'] as $item)
        {
            $label = $item['aap_pc_id'] ?: $item['aap_keyword'];

            if ($item['aap_price']) {
                $price[$item['aap_p_id']][$label][$item['app_modtype'] ?: 'all'] = (int) $item['aap_price'];
            }
        }

        // 广告区域
        $conform = [];
        $hasAr = ['row' => 1, 'has' => 0, 'date' => 0];
        $column = ['pa_id', 'pa_name', 'pa_is_area', 'pa_is_keyword', 'pa_keyword_type', 'pa_max'];
        $place = $ads->get('pj_place', $column, 'and pa_status = 1 order by pa_seq');
        foreach ($place['data'] as $item)
        {
            if ($item['pa_is_area'] && $item['pa_is_keyword']) {
                continue;
            }

            // 广告位
            $item['use'] = [];
            $item['client'] = [];
            $item['size'] = $area[$item['pa_id']]['pa_size'];
            if ($item['pa_is_area'])
            {
                foreach ($city as $pk => $pv)
                {
                    $item['use'][$pk] = array_merge($pv, $hasAr, [
                        'max' => $item['pa_max'], // 广告位最大个数
                        'can' => $item['pa_max'],
                        'mod' => 'all',
                    ]);
                }
            } else if ($item['pa_is_keyword'])
            {
                foreach ($make as $pk => $pv)
                {
                    if ($pv['mod2_pc'])
                    {
                        $item['use'][$pk] = array_merge($pv, $hasAr, [
                            'max' => $item['pa_max'], // 广告位最大个数
                            'can' => $item['pa_max'],
                            'mod' => 'pc',
                        ]);
                    }

                    if ($pv['mod2_cv'])
                    {
                        $item['use_oth'][$pk] = array_merge($pv, $hasAr, [
                            'max' => $item['pa_max'], // 广告位最大个数
                            'can' => $item['pa_max'],
                            'mod' => 'cv',
                        ]);
                    }
                }
            } else
            {
                $item['use'][] = array_merge($world[0], $hasAr, [
                    'max' => $item['pa_max'], // 广告位最大个数
                    'can' => $item['pa_max'],
                    'mod' => 'all',
                ]);
            }

            if (false !== in_array($item['pa_id'], [84, 86])) {
                $item['pa_name'] .= '-乘用车';
            }

            // 广告数据
            foreach ($adsAr['data'] as $data)
            {
				
                if ($data['pla_pa_id'] != $item['pa_id']) {
                    continue;
                }
			
                // 剩余天数
                $data['s_date'] = date('Y-m-d', $data['pat_btime']);
                $data['e_date'] = date('Y-m-d', $data['pat_etime']);
                $data['ads_add_time'] = $data['ads_atime'];
                $data['ads_atime'] = date('Y-m-d', $data['ads_atime']);
                $data['pat_last_day'] = (int) ceil(($data['pat_etime'] - $time) /3600 /24);
                $data['pat_total_day'] = (int) ceil(($data['pat_etime'] - $data['pat_btime']) /3600 /24);

                if ($item['pa_is_area'])
                {
                    $item['client'][$data['pat_pc_id']][] = $data;
                } else if ($item['pa_is_keyword'])
                {
                    if ($item['pa_keyword_type'] === 'brand')
                    {
                        if ($data['pat_modpc'] && isset($make[$data['pat_keyword']]) && $make[$data['pat_keyword']]['mod2_pc']) {
                            $item['client'][$data['pat_keyword']][] = $data;
                        }

                        if ($data['pat_modcv'] && isset($make[$data['pat_keyword']]) && $make[$data['pat_keyword']]['mod2_cv']) {
                            $item['other'][$data['pat_keyword']][] = $data;
                        }
                    }
                } else
                {
                    $item['client'][0][] = $data;
                }
            }

            $conform[$item['pa_id']] = $item;

            // 乘/商用车
            if (false !== in_array($item['pa_id'], [84, 86]))
            {
                $item['pa_name'] = str_replace('乘用车', '商用车', $item['pa_name']);
                $item['client'] = $item['other'] ?? [];
                $item['use'] = $item['use_oth'] ?? [];

                $conform[$item['pa_id'] * 10] = $item;
            }
        }

        // 计算一些东西
		$change = $conform;
		foreach ($change as $key => $val)
		{
			$order = [];
			foreach ($val['use'] as $kkk => $vvv)
			{
				$shoufei = [];
				if (isset($val['client'][$kkk])) {
					$shoufei = array_column($val['client'][$kkk], 'pal_shoufei');
				}

				// 表格行数
				$count = count($shoufei);
				$vvv['has'] = $count;
				$vvv['row'] = $count ?: 1;

				// 可售数量
				$count = array_count_values($shoufei);
				if (isset($count[1])) {
					$vvv['can'] = ($count[1] >= $vvv['max']) ? 0 : ($vvv['max'] - $count[1]);
				}

				$label = sprintf('%d.%d', $price[$key][$kkk][$vvv['mod']] ?? 0, $kkk);
				$vvv['price'] = $price[$key][$kkk][$vvv['mod']];
				$order[$label] = $vvv;
			}

			krsort($order, SORT_NUMERIC);
			$change[$key]['use'] = [];
			foreach ($order as $item_or) {
				$change[$key]['use'][$item_or['id']] = $item_or;
				$change[$key]['use'][$item_or['id']]['client'] = $val['client'][$item_or['id']] ?? [];
			}
			unset($change[$key]['client'],$change[$key]['use_oth'],$change[$key]['other']);
		}

		return LibFc::ReturnData(true, $change);
	}

}