123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141 |
- <?php
- /**
- * Created by PhpStorm.
- * User: shensong
- * Date: 2022/3/23
- * Time: 18:05
- */
- namespace App\Service;
- use App\Log;
- use App\Models\AndroidBindCorp;
- use App\Models\AndroidToolRequestLog;
- use App\Models\AuthorizeCorp;
- use App\Models\BatchTransferCustomer;
- use App\Models\BlackListRecord;
- use App\Models\ChatGroup;
- use App\Models\Customer;
- use App\Models\CustomerAssignmentRecord;
- use App\Models\CustomerAssignmentTotal;
- use App\Models\CustomerDetails;
- use App\Models\CustomerDynamic;
- use App\Models\CustomerShareRelation;
- use App\Models\CustomerTag;
- use App\Models\CustomerUnique;
- use App\Models\DjDepartment;
- use App\Models\DjOrder;
- use App\Models\DjUser;
- use App\Models\Es\ChatGroupMember;
- use App\Models\InviteChatGroupDetail;
- use App\Models\InviteChatGroupRule;
- use App\Models\OfficialAccount;
- use App\Models\RadarCustomerBehavior;
- use App\Models\RadarCustomerDetail;
- use App\Models\System\AdminManageCorp;
- use App\Models\System\Users;
- use App\Models\Tag;
- use App\Models\TagGroup;
- use App\Models\CustomerHourRecord;
- use App\Models\WaitInviteRequest;
- use App\Models\WarnRecordLog;
- use App\Models\WelcomeMsgRelation;
- use App\RedisModel;
- use App\Support\EmailQueue;
- use Illuminate\Support\Facades\Auth;
- class CustomerService
- {
- /**
- * 分配客户
- * @param $corpid string 企业id
- * @param $handoverUserId string 原跟进成员的userid
- * @param $takeoverUserId string 接替成员的userid
- * @param $externalUserIdList array 客户的external_userid列表,每次最多分配100个客户
- * @param $transferSuccessMsg string 转移成功后发给客户的消息,最多200个字符,不填则使用默认文案
- * @param $type int 1在职迁移 2离职迁移
- * @param $selectAll int 是否全选 0否 1是
- * @return mixed
- * 注意:
- * 1.external_userid必须是handover_userid的客户(即配置了客户联系功能的成员所添加的联系人)。
- * 2.为保障客户服务体验,90个自然日内,在职成员的每位客户仅可被转接2次。
- */
- public static function addCustomerAssignment($corpid, $handoverUserId, $takeoverUserId, $externalUserIdList,
- $transferSuccessMsg, $type, $selectAll)
- {
- if(2 == $type) {
- // 验证handover_userid 是否为离职员工
- $user = DjUser::query()
- ->where('user_id', $handoverUserId)
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->first();
- if(empty($user) || (isset($user->status) && $user->status != 5)) {
- return ['原跟进员工需为离职状态', 3003];
- }
- }
- $record = CustomerAssignmentTotal::query()
- ->create([
- 'corpid' => $corpid,
- 'handover_userid' => $handoverUserId,
- 'takeover_userid' => $takeoverUserId,
- 'transfer_success_msg' => $transferSuccessMsg,
- 'external_userid' => json_encode($externalUserIdList),
- 'type' => $type,
- 'select_all' => $selectAll,
- 'status' => 1,
- ]);
- return isset($record->id) ? ['申请成功', 0] : ['申请失败', 400];
- }
- /**
- * 返回客户来源列表
- * @return array
- */
- public static function addWayList()
- {
- $arr = [
- ['key' => 0 , 'val' => '未知来源'],
- ['key' => 1 , 'val' => '扫描二维码'],
- ['key' => 2 , 'val' => '搜索手机号'],
- ['key' => 3 , 'val' => '名片分享'],
- ['key' => 4 , 'val' => '群聊'],
- ['key' => 5 , 'val' => '手机通讯录'],
- ['key' => 6 , 'val' => '微信联系人'],
- ['key' => 8 , 'val' => '安装第三方应用时自动添加的客服人员'],
- ['key' => 9 , 'val' => '搜索邮箱'],
- ['key' => 10 , 'val' => '视频号添加'],
- ['key' => 11 , 'val' => '通过日程参与人添加'],
- ['key' => 12 , 'val' => '通过会议参与人添加'],
- ['key' => 13 , 'val' => '添加微信好友对应的企业微信'],
- ['key' => 14 , 'val' => '通过智慧硬件专属客服添加'],
- ['key' => 15 , 'val' => '通过上门服务客服添加'],
- ['key' => 16 , 'val' => '通过获客链接添加'],
- ['key' => 17 , 'val' => '通过定制开发添加'],
- ['key' => 18 , 'val' => '通过需求回复添加'],
- ['key' => 201 , 'val' => '内部成员共享'],
- ['key' => 202 , 'val' => '管理员/负责人分配'],
- ];
- return $arr;
- }
- // 客户管理列表
- public static function customerList($customerName, $userIdList, $addDateStart, $addDateEnd, $addWay, $gender
- , $payStatus, $payNumMin, $payNumMax, $tagType, $tagIdList, $lossStatus, $corpid, $page, $pageSize, $source
- , $lastPayTimeStart, $lastPayTimeEnd, $lossTimeStart, $lossTimeEnd, $isNewCustomerNoLoss, $canReceive, $retainedStatus)
- {
- $extra = ''; // 当用户筛选了客户关注起止时间时,返回列表中客户对应的客服列表
- if(2 == $source) {
- // 在职迁移列表
- $customerQuery = CustomerDetails::suffix($corpid)->where('loss_status', 1)->where('enable', 1);
- } else if(1 == $source) {
- // 客户列表 0已流失 1正常状态 2待分配
- $customerQuery = CustomerDetails::suffix($corpid)->where('enable', 1);
- // $customerQuery = CustomerDetails::suffix($corpid)->whereIn('loss_status', [0, 1, 2]);
- }
- $customerQuery = $customerQuery->where('corpid', $corpid);
- if(!empty($customerName)) {$customerQuery = $customerQuery->where('name', 'like', '%'.$customerName.'%');}
- if(!empty($userIdList)) {$customerQuery = $customerQuery->whereIn('user_id', $userIdList);}
- if(!empty($addDateStart)) {$customerQuery = $customerQuery->where('createtime', '>=', strtotime($addDateStart . ' 00:00:00'));}
- if(!empty($addDateEnd)) {$customerQuery = $customerQuery->where('createtime', '<=', strtotime($addDateEnd . ' 23:59:59'));}
- if(!empty($lastPayTimeStart)) {$customerQuery = $customerQuery->where('last_pay_time', '>=', $lastPayTimeStart . ' 00:00:00');}
- if(!empty($lastPayTimeEnd)) {$customerQuery = $customerQuery->where('last_pay_time', '<=', $lastPayTimeEnd . ' 23:59:59');}
- if(is_numeric($addWay)) {$customerQuery = $customerQuery->where('add_way', $addWay);}
- if(is_numeric($canReceive)) {$customerQuery = $customerQuery->where('can_receive', $canReceive);}
- if(is_numeric($retainedStatus)) {$customerQuery = $customerQuery->where('retained_status', $retainedStatus);}
- if(is_array($addWay) && !empty($addWay)) {$customerQuery = $customerQuery->whereIn('add_way', $addWay);}
- if(is_numeric($gender)) {$customerQuery = $customerQuery->where('gender', $gender);}
- if(is_numeric($isNewCustomerNoLoss)) {
- if(1 == $isNewCustomerNoLoss){$customerQuery = $customerQuery->whereIn('is_new_customer_no_loss', [1, 3]);}
- else{$customerQuery = $customerQuery->where('is_new_customer_no_loss', 0);}
- }
- // 付款状态,付款次数筛选
- if(is_numeric($payStatus)) {
- if(0 == $payStatus) {$customerQuery->where('is_paid', 0);
- }else {$customerQuery->where('is_paid', 1);}
- if(is_numeric($payNumMax)) {$customerQuery = $customerQuery->where('pay_num', '<=', $payNumMax);}
- if(is_numeric($payNumMin)) {$customerQuery = $customerQuery->where('pay_num', '>=', $payNumMin);}
- }
- if(1 == $tagType) {
- $tagRaw = '';
- foreach($tagIdList as $k=>$tagId) {
- $tagRaw .= $tagId;
- if($k < count($tagIdList) -1){
- $tagRaw = $tagRaw.' ';
- }
- }
- $customerQuery = $customerQuery->whereRaw('match(`tag_list`) against ("'.$tagRaw.'" in boolean mode)');
- }
- if(2 == $tagType) {
- $tagRaw = '';
- foreach($tagIdList as $k=>$tagId) {
- $tagRaw .= '+'.$tagId;
- if($k < count($tagIdList) -1){
- $tagRaw = $tagRaw.' ';
- }
- }
- $customerQuery = $customerQuery->whereRaw('match(`tag_list`) against ("'.$tagRaw.'" in boolean mode)');
- }
- if(3 == $tagType) {$customerQuery = $customerQuery->whereNull('tag_list');}
- if(!empty($lossTimeStart)) {$customerQuery->where('loss_time', '>=', $lossTimeStart);}
- if(!empty($lossTimeEnd)) {$customerQuery->where('loss_time', '<=', $lossTimeEnd);}
- if(is_numeric($lossStatus)) {$customerQuery = $customerQuery->where('loss_status', $lossStatus);}
- $customerRelationCount = clone $customerQuery;
- $followCount = $customerRelationCount->selectRaw('count(distinct(`con_user_cus`)) as count')->first();
- $followCount = $followCount->count;
- $customerQueryCount = clone $customerQuery;
- $count = $customerQueryCount->selectRaw('count(distinct(`external_userid`)) as count')->first();
- $count = $count->count;
- $customerLossQ = clone $customerQuery;
- $lossCountInfo = $customerLossQ->where('loss_status', 0)->selectRaw('count(distinct(`external_userid`)) as count')->first();
- $loss_count = $lossCountInfo->count ?? 0;
- if($addDateStart && $addDateEnd) {
- $userListQuery = clone $customerQuery;
- $userIdList = $userListQuery->selectRaw('distinct(user_id) as user_id')->pluck('user_id');
- if($userIdList->isNotEmpty()) {
- $userNameList = DjUser::select('name')->whereIn('user_id', $userIdList)->where('corpid', $corpid)->pluck('name');
- $extra = implode(',', $userNameList->toArray());
- }
- }
- if($pageSize == 20000) $pageSize = 100000; // 临时修改,增加业务导出量
- $offset = ($page - 1) * $pageSize;
- $data = $customerQuery->selectRaw("customer_id, name, gender, loss_time, external_userid, user_id, remark,
- createtime, add_way, corpid, pay_num, loss_status as relation_enable, blacklist_status, con_user_cus, tag_list,
- loss_time, is_new_customer_no_loss, retained_status")
- ->groupBy('con_user_cus')
- ->orderBy('createtime', 'desc')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- // 提取客户id列表
- $customerIdList = array_column($data, 'customer_id');
- // 获取客户基础信息
- $customerDataList = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->whereIn('id', $customerIdList)
- ->get()
- ->keyBy('id')
- ->toArray();
- $insideUserIdList = array_unique(array_column($data, 'user_id'));
- // 查询客服基本信息
- $insideUserDataList = DjUser::query()
- ->select(['user_id', 'name', 'open_user_id', 'avatar', 'avatar', 'department'])
- ->whereIn('user_id', $insideUserIdList)
- // ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('user_id')
- ->toArray();
- $tagList = Tag::query()
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->get()
- ->keyBy('tag_md5')
- ->toArray();
- // 查询部门列表
- $departmentList = DjDepartment::query()
- ->selectRaw('department_id, name as department_name')
- ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('department_id')
- ->toArray();
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- // 循环将数据补充
- foreach($data as $key => $value) {
- $customerInfo = isset($customerDataList[$value['customer_id']]) ? $customerDataList[$value['customer_id']] : [];
- $customerTag = [];
- $customerTagList = empty($value['tag_list']) ? [] : explode(',', $value['tag_list']);
- foreach($customerTagList as $tagId) {
- $tagName = isset($tagList[$tagId]['tag_name']) ? $tagList[$tagId]['tag_name'] : '';
- if(!empty($tagName)) {
- $customerTag[] = $tagName;
- }
- }
- $data[$key]['type'] = isset($customerInfo['type']) ? $customerInfo['type'] : 0;
- $data[$key]['avatar'] = isset($customerInfo['avatar']) ? $customerInfo['avatar'] : 0;
- $customerServiceData = [];
- $departmentData = null;
- $userId = $value['user_id'];
- if(isset($insideUserDataList[$userId])) {
- $customerServiceData = $insideUserDataList[$userId];
- $departmentIdData = explode(',', $insideUserDataList[$userId]['department']);
- foreach ($departmentIdData as $item) {
- $departmentData = isset($departmentList[$item]['department_name']) ?
- $departmentList[$item]['department_name'] : '';
- }
- }
- $data[$key]['user_list'] = $customerServiceData;
- $data[$key]['department_list'] = [$departmentData];
- $data[$key]['tag_list'] = $customerTag;
- $data[$key]['createtime'] = date('Y-m-d H:i', $value['createtime']);
- $data[$key]['add_way'] = isset($addWayData[$value['add_way']]['val']) ? $addWayData[$value['add_way']]['val'] : '';
- }
- $excludeCount = $followCount - $count;
- return [['list' => $data, 'count' => $count, 'exclude_count' => $excludeCount, 'cust_loss_uc' => $loss_count], $followCount, $extra];
- }
- // 客户订单列表
- public static function customerOrderList($corpid, $customerId, $page, $pageSize)
- {
- $offset = ($page - 1) * $pageSize;
- // 获取客户的外部联系人id
- $externalUserId = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('id', $customerId)
- ->first();
- $externalUserId = isset($externalUserId->external_userid) ? $externalUserId->external_userid : null;
- if(empty($externalUserId)) {
- return [[], 0];
- }
- $query = DjOrder::query()
- ->select(['order_id', 'pay_money', 'created_ts', 'pay_status', 'playlet_name', 'order_type', 'bind_app_id'
- , 'adq_account_id', 'origin_pay_money', 'pay_type'])
- ->where('system_corpid', $corpid)
- ->where('pay_status', 1)
- ->where('external_userid', $externalUserId);
- $count = $query->count();
- $data = $query->orderBy('created_ts', 'desc')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- # 提取公众号APPID
- $appIdList = array_column($data, 'bind_app_id');
- $appList = OfficialAccount::query()->select(['mp_name', 'mp_app_id'])->whereIn('mp_app_id', $appIdList)->get();
- // 循环将数据格式化
- foreach($data as $key => $value) {
- $data[$key]['pay_money'] = round($value['pay_money']/10000, 2);
- $data[$key]['origin_pay_money'] = round($value['origin_pay_money']/10000, 2);
- $data[$key]['created_ts'] = date('Y-m-d H:i', round($value['created_ts']/1000, 0));
- # 投放账号
- if(1 == $value['order_type']) {
- # 公众号
- $wxAccountInfo = $appList->where('mp_app_id', $value['bind_app_id'])->first();
- $data[$key]['launch_account'] = isset($wxAccountInfo->mp_name) ? $wxAccountInfo->mp_name : '-';
- } else {
- $data[$key]['launch_account'] = $value['adq_account_id'];
- }
- $payType = $value['pay_type'] == 1 ? '小程序虚拟支付' : '其他类型支付';
- $data[$key]['pay_type'] = $payType;
- }
- return [$data, $count];
- }
- // 客户概览(废弃)
- public static function customerDetail($corpid, $customerId, $userId)
- {
- // 查询客户基础信息
- $customerInfo = Customer::suffix($corpid)
- ->select(['external_userid', 'name', 'avatar', 'type', 'gender', 'e_weibo', 'e_company', 'e_source',
- 'e_qq', 'e_position', 'e_phone', 'e_email', 'e_desc', 'e_birthday', 'e_age', 'e_address'])
- ->selectRaw('id as customer_id')
- ->where('id', $customerId)
- ->where('corpid', $corpid)
- // ->where('enable', 1)
- ->first();
- if(empty($customerInfo)) {
- $requestData = [
- 'corpid' => $corpid,
- 'customer_id' => $customerId,
- 'user_id' => $userId,
- ];
- Log::logInfo('customerDetail 数据为空 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['数据为空', 3002];
- }
- $customerInfo = json_decode(json_encode($customerInfo), 1);
- $customerInfo['e_birthday'] = !empty($customerInfo['e_birthday']) ? date('Y-m-d', strtotime($customerInfo['e_birthday'])) : null;
- // 查询客户跟进信息
- $followList = CustomerDetails::suffix($corpid)
- ->select(['user_id', 'add_way', 'createtime', 'remark', 'tag_list'])
- ->where('corpid', $corpid)
- ->where('external_userid', $customerInfo['external_userid'])
- ->where('user_id', $userId)
- ->orderBy('loss_status', 'desc')
- ->first();
- $tagIdList = empty($followList->tag_list) ? [] : explode(',', $followList->tag_list);
- if(!empty($tagIdList)) {
- $tagList = Tag::query()
- ->whereIn('tag_md5', $tagIdList)
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->get()
- ->toArray();
- $customerInfo['tag_list'] = array_column($tagList, 'tag_name');
- } else {
- $customerInfo['tag_list'] = [];
- }
- // 提取跟进信息中的客服id
- $userDataList = DjUser::query()
- ->select(['user_id', 'name', 'avatar'])
- // ->where('enable', 1)
- ->where('user_id', $userId)
- ->where('corpid', $corpid)
- ->first();
- $userDataList = !empty($userDataList) ? $userDataList->toArray() : [];
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- $followList = empty($followList) ? [] : json_decode(json_encode($followList), 1);
- $followList['user_name'] = isset($userDataList['name']) ? $userDataList['name'] : '';
- $followList['avatar'] = isset($userDataList['avatar']) ? $userDataList['avatar'] : '';
- $followList['createtime'] = isset($followList['createtime']) ? date('Y-m-d H:i', $followList['createtime']) : null;
- $followList['add_way'] = (isset($followList['add_way']) && isset($addWayData[$followList['add_way']]['val'])) ?
- $addWayData[$followList['add_way']]['val'] : '';
- $customerInfo['follow_list'] = $followList;
- return [$customerInfo, 0];
- }
- // 客户概览
- public static function customerDetails($corpid, $customerId)
- {
- // 查询客户基础信息
- $customerInfo = Customer::suffix($corpid)
- ->select(['external_userid', 'name', 'avatar', 'type', 'gender', 'e_weibo', 'e_company', 'e_source',
- 'e_qq', 'e_position', 'e_phone', 'e_email', 'e_desc', 'e_birthday', 'e_age', 'e_address'])
- ->selectRaw('id as customer_id')
- ->where('id', $customerId)
- ->where('corpid', $corpid)
- // ->where('enable', 1)
- ->first();
- if(empty($customerInfo)) {
- $requestData = [
- 'corpid' => $corpid,
- 'customer_id' => $customerId,
- ];
- Log::logInfo('customerDetails 数据为空 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['数据为空', 3002];
- }
- $customerInfo = json_decode(json_encode($customerInfo), 1);
- $customerInfo['e_birthday'] = !empty($customerInfo['e_birthday']) ? date('Y-m-d', strtotime($customerInfo['e_birthday'])) : null;
- // 查询客户跟进信息
- $followList = CustomerDetails::suffix($corpid)
- ->select(['user_id', 'add_way', 'createtime', 'remark', 'tag_list'])
- ->where('corpid', $corpid)
- ->where('external_userid', $customerInfo['external_userid'])
- ->where('loss_status', 1)
- ->orderBy('loss_status', 'desc')
- ->get();
- $userTagIdList = $allTagIdList = $userList = [];
- if($followList->isNotEmpty()) {
- foreach($followList as $followInfo) {
- $tagIdList = empty($followInfo->tag_list) ? [] : explode(',', $followInfo->tag_list);
- $userTagIdList[$followInfo['user_id']] = $tagIdList;
- $allTagIdList = array_merge($allTagIdList, $tagIdList);
- $userList[] = $followInfo['user_id'];
- }
- $allTagIdList = array_unique($allTagIdList);
- }
- $userTagList = [];
- if(!empty($allTagIdList)) {
- $tagList = Tag::query()
- ->whereIn('tag_md5', $allTagIdList)
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->get();
- foreach($userTagIdList as $userId => $userTag) {
- $userTagList[$userId] = $tagList->whereIn('tag_md5', $userTag)->pluck('tag_name');
- }
- }
- // 提取跟进信息中的客服id
- $userDataList = DjUser::query()
- ->select(['user_id', 'name', 'avatar'])
- // ->where('enable', 1)
- ->whereIn('user_id', $userList)
- ->where('corpid', $corpid)
- ->get()
- ->toArray();
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- foreach($userDataList as $userData) {
- $item['user_name'] = isset($userData['name']) ? $userData['name'] : '';
- $item['avatar'] = isset($userData['avatar']) ? $userData['avatar'] : '';
- $followData = $followList->where('user_id', $userData['user_id'])->first();
- $item['createtime'] = date('Y-m-d H:i', $followData->createtime);
- $item['add_way'] = isset($addWayData[$followData->add_way]['val']) ?
- $addWayData[$followData->add_way]['val'] : '';
- $item['remark'] = isset($followData->remark) ? $followData->remark : '';
- $item['user_id'] = $userData['user_id'];
- $item['tag_list'] = isset($userTagList[$userData['user_id']]) ? $userTagList[$userData['user_id']] : [];
- $customerInfo['follow_list'][] = $item;
- }
- return [$customerInfo, 0];
- }
- // 客户详情信息编辑
- public static function customerInfoUpdate($corpid, $customerId, $params)
- {
- $res = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('id', $customerId)
- ->update($params);
- $requestData = [
- 'corpid' => $corpid,
- 'customer_id' => $customerId,
- 'params' => $params,
- ];
- if($res > 0) {
- // Log::logInfo('customerInfoUpdate 编辑成功, request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['编辑成功', 0];
- } else {
- Log::logInfo('customerInfoUpdate 编辑失败, request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['编辑失败', 400];
- }
- }
- public static function moveCustomerToBlackList($corpid, $customerId, $userId, $reason)
- {
- // 获取客户的外部联系人id
- $customerInfo = Customer::getCustomerInfoById($corpid, $customerId);
- $customerInfo = json_decode(json_encode($customerInfo), 1);
- $externalUserId = $customerInfo['external_userid'];
- $operUserID = Auth::id();
- // 开启事务
- \DB::begintransaction();
- $recordRes = BlackListRecord::query()
- ->updateOrCreate([
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'customer_id' => $customerId
- ], [
- 'external_userid' => $externalUserId,
- 'oper_user_id' => $operUserID,
- 'enable' => 1,
- 'reason' => $reason,
- ]);
- $relationRes = CustomerDetails::suffix($corpid)
- ->where('user_id', $userId)
- ->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->update(['blacklist_status' => 1]);
- CustomerDynamic::customerDynamicSave($corpid, $externalUserId, $userId, 6);
- # 给客户添加黑名单用户标签
- RedisModel::lPush(CustomerTagService::CUSTOMER_TAG_MARK_RDS, json_encode([
- 'corpid' => $corpid, 'user_id' => $userId, 'external_userid' => $externalUserId,
- 'type' => 2, 'tag_group_name' => '猎羽', 'tag_name_list' => ['黑名单客户']
- ], 256));
- $requestData = [
- 'corpid' => $corpid,
- 'customer_id' => $customerId,
- 'user_id' => $userId,
- 'reason' => $reason
- ];
- if($relationRes > 0 && (isset($recordRes->id) && $relationRes > 0)) {
- \DB::commit();
- // Log::logInfo('moveCustomerToBlackList 操作成功 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['操作成功', 0];
- } else {
- \DB::rollBack();
- Log::logInfo('moveCustomerToBlackList 操作失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['操作失败', 400];
- }
- }
- public static function removeCustomerFromBlackList($corpid, $customerId, $userId)
- {
- // 获取客户的外部联系人id
- $customerInfo = Customer::getCustomerInfoById($corpid, $customerId);
- $customerInfo = json_decode(json_encode($customerInfo), 1);
- $externalUserId = $customerInfo['external_userid'];
- $operUserID = Auth::id();
- // 开启事务
- \DB::begintransaction();
- $recordRes = BlackListRecord::query()
- ->updateOrCreate([
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'customer_id' => $customerId
- ], [
- 'external_userid' => $externalUserId,
- 'oper_user_id' => $operUserID,
- 'enable' => 0
- ]);
- $relationRes = CustomerDetails::suffix($corpid)
- ->where('user_id', $userId)
- ->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->update(['blacklist_status' => 0]);
- CustomerDynamic::customerDynamicSave($corpid, $externalUserId, $userId, 7);
- # 将客户黑名单标签取消(先查询黑名单标签ID,并且查看用户当前是否含有该标签)
- $tagGroupId = TagGroup::getGroupIdByGroupName($corpid, '猎羽');
- if(!empty($tagGroupId)) {
- $tagInfoList = Tag::getTagInfoByTagGroup($corpid, $tagGroupId);
- $tagInfo = $tagInfoList->where('tag_name', '黑名单客户')->first();
- $tagId = $tagInfo->tag_id ?? null;
- if (!empty($tagId)) {
- RedisModel::lPush(CustomerTagService::CUSTOMER_TAG_MARK_RDS, json_encode([
- 'corpid' => $corpid, 'user_id' => $userId, 'external_userid' => $externalUserId,
- 'type' => 1, 'tag_group_id' => $tagGroupId, 'remove_tag_id_list' => [$tagId]
- ], 256));
- }
- }
- $requestData = [
- 'corpid' => $corpid,
- 'customer_id' => $customerId,
- 'user_id' => $userId
- ];
- if($relationRes > 0 && (isset($recordRes->id) && $relationRes > 0)) {
- \DB::commit();
- // Log::logInfo('removeCustomerFromBlackList 操作成功 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['操作成功', 0];
- } else {
- \DB::rollBack();
- Log::logInfo('removeCustomerFromBlackList 操作失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['操作失败', 400];
- }
- }
- // 黑名单列表
- public static function blackList($corpid, $addWay, $customerName, $adminId, $page, $pageSize)
- {
- $customerQuery = CustomerDetails::suffix($corpid)
- ->where('blacklist_status', 1)
- ->whereIn('loss_status', [0, 1, 2]);
- if(!empty($customerName)) {
- $customerQuery = $customerQuery->where('name', 'like', '%'.$customerName.'%');}
- if(is_numeric($addWay)) {
- $customerQuery = $customerQuery->where('add_way', $addWay);}
- $customerQuery = $customerQuery->where('corpid', $corpid);
- $customerQueryCount = clone $customerQuery;
- $count = $customerQueryCount->selectRaw('count(distinct(`external_userid`)) as count')->first();
- $count = $count->count;
- $offset = ($page - 1) * $pageSize;
- $data = $customerQuery->selectRaw('customer_id, name, enable as relation_enable, loss_time, external_userid,
- user_id, remark, createtime, add_way, blacklist_status, con_user_cus')
- ->groupBy('con_user_cus')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- // 提取客户id列表
- $customerIdList = array_column($data, 'customer_id');
- // 获取客户基础信息
- $customerDataList = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->whereIn('id', $customerIdList)
- ->get()
- ->keyBy('id')
- ->toArray();
- // 提取客服id列表
- $insideUserIdList = array_unique(array_column($data, 'user_id'));
- // 查询客户对应的操作记录
- $blackListRecord = BlackListRecord::query()
- ->whereIn('customer_id', $customerIdList)
- ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->toArray();
- $blackListData = [];
- foreach($blackListRecord as $item) {
- $key = $item['customer_id'].'-'.$item['user_id'];
- $blackListData[$key] = $item;
- }
- // 查询客服基本信息
- $insideUserDataList = DjUser::query()
- ->select(['user_id', 'name', 'open_user_id', 'avatar', 'avatar', 'department'])
- ->whereIn('user_id', $insideUserIdList)
- // ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('user_id')
- ->toArray();
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- // 循环将数据补充
- foreach($data as $key => $value) {
- $k = $value['customer_id'].'-'.$value['user_id'];
- $blackList = isset($blackListData[$k]) ? $blackListData[$k] : [];
- $customerInfo = isset($customerDataList[$value['customer_id']]) ? $customerDataList[$value['customer_id']] : [];
- $customerServiceData = [];
- $userId = $value['user_id'];
- if(isset($insideUserDataList[$userId])) {
- $customerServiceData = $insideUserDataList[$userId];
- }
- $data[$key]['type'] = isset($customerInfo['type']) ? $customerInfo['type'] : 0;
- $data[$key]['avatar'] = isset($customerInfo['avatar']) ? $customerInfo['avatar'] : '';
- $data[$key]['reason'] = isset($blackList['reason']) ? $blackList['reason'] : '';
- $data[$key]['operate_time'] = isset($blackList['create_time']) ? $blackList['create_time'] : '';
- $data[$key]['user_list'] = $customerServiceData;
- $data[$key]['createtime'] = date('Y-m-d H:i', $value['createtime']);
- $data[$key]['add_way'] = isset($addWayData[$value['add_way']]['val']) ? $addWayData[$value['add_way']]['val'] :
- '';
- }
- return [$data, $count];
- }
- // 黑名单列表(新)
- public static function blackListNew($corpid, $addWay, $customerName, $adminId, $page, $pageSize)
- {
- $customerList = $customerIdList = null;
- if(!empty($addWay) || !empty($customerName)) {
- // 从客户关系表中查询符合条件的外部联系人id列表
- $customerList = CustomerDetails::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('blacklist_status', 1)
- ->whereIn('loss_status', [0, 1, 2])
- ->where(function($query) use ($addWay, $customerName) {
- if($addWay) $query->where('add_way', $addWay);
- if($customerName) $query->where('customer_name', 'like', '%'.$customerName.'%');
- })->get();
- $customerIdList = $customerList->pluck('customer_id')->toArray();
- }
- // 查询客户对应的操作记录
- $blackListRecordQuery = BlackListRecord::query()
- ->where('enable', 1)
- ->where('corpid', $corpid);
- if(!is_null($customerIdList)) {
- $blackListRecordQuery->whereIn('customer_id', $customerIdList);
- }
- if($adminId) {
- $blackListRecordQuery->where('oper_user_id', $adminId);
- }
- $blackListRecordCountQuery = clone $blackListRecordQuery;
- $countRres = $blackListRecordCountQuery->selectRaw('count(distinct(customer_id)) as count')->first();
- $count = !empty($countRres->count) ? $countRres->count : 0;
- $offset = ($page - 1) * $pageSize;
- $blackListRecordList = $blackListRecordQuery
- ->select(['user_id', 'customer_id', 'external_userid', 'oper_user_id', 'reason', 'create_time'])
- ->offset($offset)
- ->limit($pageSize)
- ->orderBy('id', 'desc')
- ->get();
- $insideUserIdList = array_unique(array_column($blackListRecordList->toArray(), 'user_id'));
- $customerIds = array_unique(array_column($blackListRecordList->toArray(), 'customer_id'));
- $operUserIds = array_unique(array_column($blackListRecordList->toArray(), 'oper_user_id'));
- // 查询客服基本信息
- $insideUserDataList = DjUser::query()
- ->select(['user_id', 'name', 'open_user_id', 'avatar', 'avatar', 'department'])
- ->whereIn('user_id', $insideUserIdList)
- // ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get();
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- // 获取客户基础信息
- $customerDataList = Customer::suffix($corpid)
- // ->where('corpid', $corpid)
- ->whereIn('id', $customerIds)
- ->get();
- // 获取操作用户信息
- $users = Users::query()
- ->whereIn('id', $operUserIds)
- ->get();
- if(empty($customerList)) {
- $customerList = CustomerDetails::suffix($corpid)
- ->where('blacklist_status', 1)
- ->whereIn('loss_status', [0, 1, 2])
- ->where('corpid', $corpid)
- ->whereIn('customer_id', $customerIds)
- ->get();
- }
- foreach($blackListRecordList as &$blackList) {
- # 客户详细信息 添加渠道,客户状态,添加时间
- $customerDetails = !empty($customerList) ? $customerList->where('user_id', $blackList->user_id)
- ->where('external_userid', $blackList->external_userid)->first() : null;
- # 客户信息 头像,昵称,来源
- $customer = $customerDataList->where('id', $blackList->customer_id)->first();
- # 客服信息 昵称
- $user = $insideUserDataList->where('user_id', $blackList->user_id)->first();
- # 操作人信息
- $operUser = $users->where('id', $blackList->oper_user_id)->first();
- $blackList->type = !empty($customer) ? $customer->type : 0;
- $blackList->avatar = !empty($customer) ? $customer->avatar : '';
- $blackList->name = !empty($customer) ? $customer->name : '';
- $blackList->operate_time = $blackList->create_time;
- $blackList->user_list = $user;
- $blackList->createtime = !empty($customerDetails) ? date('Y-m-d H:i', $customerDetails->createtime) : '';
- $blackList->add_way = !empty($addWayData[$customerDetails->add_way]) ? $addWayData[$customerDetails->add_way]['val'] : '';
- $blackList->oper_user = !empty($operUser) ? $operUser->name : '';
- $blackList->blacklist_status = 1;
- $blackList->remark = !empty($customerDetails) ? $customerDetails->remark : '';
- $blackList->relation_enable = !empty($customerDetails) ? $customerDetails->enable : 1;
- }
- return [$blackListRecordList, $count];
- }
- /**
- * 待分配客户列表
- * @param $customerName string 客户名称
- * @param $userIdList string 客服user_id列表
- * @param $addDateStart string 起始添加时间
- * @param $addDateEnd string 截止添加时间
- * @param $addWay int 添加渠道
- * @param $payStatus int 付款状态
- * @param $payNumMin int 最小付款次数
- * @param $payNumMax int 最大付款次数
- * @param $tagType int 标签筛选类型 0不筛选 1满足其一 2同时满足 3没有标签
- * @param $tagIdList array 标签id列表
- * @param $corpid string 企业id
- * @param $page
- * @param $pageSize
- * @return array
- */
- public static function unassignedCustomerList(
- $customerName, $userIdList, $addDateStart, $addDateEnd, $addWay, $payStatus, $payNumMin, $payNumMax, $tagType,
- $tagIdList, $corpid, $page, $pageSize
- )
- {
- $customerQuery = CustomerDetails::suffix($corpid)
- ->where('loss_status', 2)
- ->where('corpid', $corpid);
- if(!empty($customerName)) {
- $customerQuery = $customerQuery->where('name', 'like', '%'.$customerName.'%');}
- if(!empty($userIdList)) {
- $customerQuery = $customerQuery->whereIn('user_id', $userIdList);}
- if(!empty($addDateStart)) {
- $customerQuery = $customerQuery->where('createtime', '>=', strtotime($addDateStart . ' 00:00:00'));}
- if(!empty($addDateEnd)) {
- $customerQuery = $customerQuery->where('createtime', '<=', strtotime($addDateEnd . ' 23:59:59'));}
- if(is_numeric($addWay)) {
- $customerQuery = $customerQuery->where('add_way', $addWay);}
- // 付款状态,付款次数筛选
- if(is_numeric($payStatus)) {
- if(0 == $payStatus) {
- $payNumMax=0;
- $payNumMin=0;
- } else {
- if(empty($payNumMin)) {
- $payNumMin = 1;
- }
- }
- if(is_numeric($payNumMax)) {
- $customerQuery = $customerQuery->where('pay_num', '<=', $payNumMax);
- }
- if(is_numeric($payNumMin)) {
- $customerQuery = $customerQuery->where('pay_num', '>=', $payNumMin);
- }
- }
- if(1 == $tagType) {
- $tagRaw = '';
- foreach($tagIdList as $k=>$tagId) {
- $tagRaw .= $tagId;
- if($k < count($tagIdList) -1){
- $tagRaw = $tagRaw.' ';
- }
- }
- $customerQuery = $customerQuery->whereRaw('match(`tag_list`) against ("'.$tagRaw.'" in boolean mode)');
- }
- if(2 == $tagType) {
- $tagRaw = '';
- foreach($tagIdList as $k=>$tagId) {
- $tagRaw .= '+'.$tagId;
- if($k < count($tagIdList) -1){
- $tagRaw = $tagRaw.' ';
- }
- }
- $customerQuery = $customerQuery->whereRaw('match(`tag_list`) against ("'.$tagRaw.'" in boolean mode)');
- }
- if(3 == $tagType) {
- $customerQuery = $customerQuery->whereNull('tag_list');
- }
- $customerQueryCount = clone $customerQuery;
- $count = $customerQueryCount->selectRaw('count(distinct(`external_userid`)) as count')->first();
- $count = $count->count;
- $offset = ($page - 1) * $pageSize;
- $data = $customerQuery->selectRaw('customer_id, name, gender, enable as relation_enable, external_userid,
- user_id, remark, createtime, add_way, corpid, pay_num, loss_time, blacklist_status, con_user_cus, tag_list')
- ->groupBy('con_user_cus')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- // 提取客户id列表
- $customerIdList = array_column($data, 'customer_id');
- // 获取客户基础信息
- $customerDataList = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->whereIn('id', $customerIdList)
- ->get()
- ->keyBy('id')
- ->toArray();
- $insideUserIdList = array_unique(array_column($data, 'user_id'));
- $tagList = Tag::query()
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->get()
- ->keyBy('tag_md5')
- ->toArray();
- // 查询客服基本信息
- $insideUserDataList = DjUser::query()
- ->select(['user_id', 'name', 'open_user_id', 'avatar', 'avatar', 'department'])
- ->whereIn('user_id', $insideUserIdList)
- // ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('user_id')
- ->toArray();
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- // 查询部门列表
- $departmentList = DjDepartment::query()
- ->selectRaw('department_id, name as department_name')
- ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('department_id')
- ->toArray();
- // 循环将数据补充
- foreach($data as $key => $value) {
- $customerInfo = isset($customerDataList[$value['customer_id']]) ? $customerDataList[$value['customer_id']] : [];
- $customerServiceData = [];
- $departmentData = null;
- $userId = $value['user_id'];
- $customerTag = [];
- $customerTagList = empty($value['tag_list']) ? [] : explode(',', $value['tag_list']);
- foreach($customerTagList as $tagId) {
- $tagName = isset($tagList[$tagId]['tag_name']) ? $tagList[$tagId]['tag_name'] : '';
- if(!empty($tagName)) {
- $customerTag[] = $tagName;
- }
- }
- $data[$key]['type'] = isset($customerInfo['type']) ? $customerInfo['type'] : 0;
- $data[$key]['avatar'] = isset($customerInfo['avatar']) ? $customerInfo['avatar'] : 0;
- if(isset($insideUserDataList[$userId])) {
- $customerServiceData = $insideUserDataList[$userId];
- $departmentIdData = explode(',', $insideUserDataList[$userId]['department']);
- foreach($departmentIdData as $item) {
- $departmentData = isset($departmentList[$item]['department_name']) ? $departmentList[$item]['department_name'] : '';
- }
- }
- $data[$key]['user_list'] = $customerServiceData;
- $data[$key]['department_list'] = [$departmentData];
- $data[$key]['tag_list'] = $customerTag;
- $data[$key]['createtime'] = date('Y-m-d H:i', $value['createtime']);
- $data[$key]['add_way'] = isset($addWayData[$value['add_way']]['val']) ? $addWayData[$value['add_way']]['val'] : '';
- }
- return [$data, $count];
- }
- /**
- * 流失客户列表
- * @param $userIdList array 客服user_id
- * @param $addDateStart string 起始添加时间
- * @param $addDateEnd string 截止添加时间
- * @param $lossDateStart string 起始流失时间
- * @param $lossDateEnd string 截止流失时间
- * @param $addDurationMin int 最小添加天数
- * @param $addDurationMax int 最大添加天数
- * @param $corpid string 企业id
- * @param $page
- * @param $pageSize
- * @return array
- */
- public static function lossCustomerList(
- $userIdList, $addDateStart, $addDateEnd, $lossDateStart, $lossDateEnd, $addDurationMin, $addDurationMax,
- $corpid, $page, $pageSize
- )
- {
- $customerQuery = CustomerDetails::suffix($corpid)
- ->where('loss_status', 0)
- ->where('corpid', $corpid);
- // 统一处理添加天数和添加时间
- if(empty($addDateStart) && empty($addDateEnd) && !empty($addDurationMin) && !empty($addDurationMax)) {
- // 没有添加时间筛选,只有添加时长筛选
- $addDateStart = date('Y-m-d', strtotime('-'.$addDurationMax.' days'));
- $addDateEnd = date('Y-m-d', strtotime('-'.$addDurationMin.' days'));
- } else if(!empty($addDateStart) && !empty($addDateEnd) && !empty($addDurationMin) && !empty($addDurationMax)) {
- // 既有添加时间筛选,又有添加时长筛选
- $addDurationStatDate = date('Y-m-d', strtotime('-'.$addDurationMax.' days'));
- $addDurationEndDate = date('Y-m-d', strtotime('-'.$addDurationMin.' days'));
- if($addDurationStatDate > $addDateStart) $addDateStart = $addDurationStatDate;
- if($addDurationEndDate < $addDateEnd) $addDateEnd = $addDurationEndDate;
- if($addDateStart > $addDateEnd) return [[], 0];
- }
- if(!empty($customerName)) {
- $customerQuery = $customerQuery->where('name', 'like', '%'.$customerName.'%');}
- if(!empty($userIdList)) {
- $customerQuery = $customerQuery->whereIn('user_id', $userIdList);}
- if(!empty($addDateStart)) {
- $customerQuery = $customerQuery->where('createtime', '>=', strtotime($addDateStart . ' 00:00:00'));}
- if(!empty($addDateEnd)) {
- $customerQuery = $customerQuery->where('createtime', '<=', strtotime($addDateEnd . ' 23:59:59'));}
- if(!empty($lossDateStart)) {
- $customerQuery = $customerQuery->where('loss_time', '>=', $lossDateStart.' 00:00:00');}
- if(!empty($lossDateEnd)) {
- $customerQuery = $customerQuery->where('loss_time', '<=', $lossDateEnd.' 23:59:59');}
- $customerQueryCount = clone $customerQuery;
- $count = $customerQueryCount->selectRaw('count(distinct(`external_userid`)) as count')->first();
- $count = $count->count;
- $offset = ($page - 1) * $pageSize;
- $data = $customerQuery->selectRaw('customer_id, name, gender, loss_time, external_userid, user_id, remark,
- createtime, add_way, corpid, blacklist_status, loss_status as relation_enable, con_user_cus, tag_list')
- ->groupBy('con_user_cus')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- // 提取客户id列表
- $customerIdList = array_column($data, 'customer_id');
- // 获取客户基础信息
- $customerDataList = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->whereIn('id', $customerIdList)
- ->get()
- ->keyBy('id')
- ->toArray();
- $insideUserIdList = array_unique(array_column($data, 'user_id'));
- $tagList = Tag::query()
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->get()
- ->keyBy('tag_md5')
- ->toArray();
- // 查询客服基本信息
- $insideUserDataList = DjUser::query()
- ->select(['user_id', 'name', 'open_user_id', 'avatar', 'avatar', 'department'])
- ->whereIn('user_id', $insideUserIdList)
- // ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('user_id')
- ->toArray();
- // 获取添加渠道数据
- $addWayData = self::addWayList();
- $addWayData = array_column($addWayData, null, 'key');
- // 查询部门列表
- $departmentList = DjDepartment::query()
- ->selectRaw('department_id, name as department_name')
- ->where('enable', 1)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('department_id')
- ->toArray();
- // 循环将数据补充
- foreach($data as $key => $value) {
- $customerInfo = isset($customerDataList[$value['customer_id']]) ? $customerDataList[$value['customer_id']] : [];
- $customerTag = [];
- $customerTagList = empty($value['tag_list']) ? [] : explode(',', $value['tag_list']);
- foreach($customerTagList as $tagId) {
- $tagName = isset($tagList[$tagId]['tag_name']) ? $tagList[$tagId]['tag_name'] : '';
- if(!empty($tagName)) {
- $customerTag[] = $tagName;
- }
- }
- $data[$key]['type'] = isset($customerInfo['type']) ? $customerInfo['type'] : 0;
- $data[$key]['avatar'] = isset($customerInfo['avatar']) ? $customerInfo['avatar'] : 0;
- $customerServiceData = [];
- $departmentData = null;
- $userId = $value['user_id'];
- if(isset($insideUserDataList[$userId])) {
- $customerServiceData = $insideUserDataList[$userId];
- $departmentIdData = explode(',', $insideUserDataList[$userId]['department']);
- foreach($departmentIdData as $departmentId) {
- $departmentData = isset($departmentList[$departmentId]['department_name']) ?
- $departmentList[$departmentId]['department_name'] : '';
- }
- }
- $data[$key]['user_list'] = $customerServiceData;
- $data[$key]['department_list'] = [$departmentData];
- $data[$key]['tag_list'] = $customerTag;
- $data[$key]['createtime'] = date('Y-m-d H:i', $value['createtime']);
- $data[$key]['add_way'] = isset($addWayData[$value['add_way']]['val']) ? $addWayData[$value['add_way']]['val'] :
- '';
- // 计算添加时长
- $data[$key]['add_duration_days'] = floor((time() - $value['createtime']) / 86400);
- }
- return [$data, $count];
- }
- /**
- * 客户分配记录
- * @param $corpid string 企业id
- * @param $handoverUserId string 转接员工userId
- * @param $takeoverUserId string 接替员工userid
- * @param $assignmentDateStart string 起始接替时间
- * @param $assignmentDateEnd string 截止接替时间
- * @param $assignmentStatus int 接替状态
- * @param $type int 接替类型 1在职 2离职
- * @param $page
- * @param $pageSize
- * @return array
- */
- public static function customerAssignmentRecordList(
- $corpid, $handoverUserId, $operatorId, $takeoverUserId, $assignmentDateStart, $assignmentDateEnd, $assignmentStatus,
- $type, $page, $pageSize
- )
- {
- $customerAssignmentQuery = CustomerAssignmentTotal::query()->where('corpid', $corpid)
- ->where('enable', 1);
- if(!empty($assignmentDateStart)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('create_time', '>=',
- $assignmentDateStart.' 00:00:00');
- }
- if(!empty($assignmentDateEnd)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('create_time', '<=',
- $assignmentDateEnd.' 23:59:59');
- }
- if(!empty($type)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('type', $type);
- }
- if(!empty($handoverUserId)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('handover_userid', $handoverUserId);
- }
- if(!empty($takeoverUserId)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('takeover_userid', $takeoverUserId);
- }
- if(!empty($assignmentStatus)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('status', $assignmentStatus);
- }
- if(!empty($operatorId)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('operator_id', $operatorId);
- }
- $customerAssignmentCountQuery = clone $customerAssignmentQuery;
- $count = $customerAssignmentCountQuery->count();
- $offset = ($page - 1) * $pageSize;
- $data = $customerAssignmentQuery->selectRaw('create_time, takeover_userid, status, type, corpid'
- . ',handover_userid, id as record_id, customer_number, operator_id')->orderBy('id', 'desc')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- $takeOverUserIdList = array_unique(array_column($data, 'takeover_userid'));
- $handOverUserIdList = array_unique(array_column($data, 'handover_userid'));
- $userIdList = array_unique(array_merge($takeOverUserIdList, $handOverUserIdList));
- $userInfoList = DjUser::query()->where('corpid', $corpid)
- ->whereIn('user_id', $userIdList)->get()->keyBy('user_id')->toArray();
- $operatorIdList = array_unique(array_column($data, 'operator_id'));
- $operatorInfoList = Users::query()->whereIn('id', $operatorIdList)
- ->get()->keyBy('id')->toArray();
- $errcodeConf = config('qyWechat.errcode');
- foreach($data as $key => $value) {
- // 接替客服昵称
- $data[$key]['takeover_username'] = isset($userInfoList[$value['takeover_userid']]['name']) ?
- $userInfoList[$value['takeover_userid']]['name'] : '';
- // 迁出客服昵称
- $data[$key]['handover_username'] = isset($userInfoList[$value['handover_userid']]['name']) ?
- $userInfoList[$value['handover_userid']]['name'] : '';
- // 迁移失败原因展示
- $data[$key]['err_msg'] = [];
- $errCodeList = CustomerAssignmentRecord::suffix($value['corpid'])->where('record_id', $value['record_id'])
- ->where('errcode', '!=', 0)->select('errcode')->get();
- if($errCodeList->isNotEmpty()) {
- $errCodeList = $errCodeList->toArray();
- foreach ($errCodeList as $errCode) {
- $errCode = $errCode['errcode'];
- $errMsg = $errcodeConf[$errCode] ?? null;
- $errMsg = $value['status'] == '-1' ? $errMsg : ('部分迁移失败由于'.$errMsg);
- if($errMsg && !in_array($errMsg, $data[$key]['err_msg'])) {
- $data[$key]['err_msg'][] = $errMsg;
- }
- }
- }
- // 创建人
- $data[$key]['operator_name'] = isset($operatorInfoList[$value['operator_id']]['name']) ?
- $operatorInfoList[$value['operator_id']]['name'] : '';
- }
- return [$data, $count];
- }
- /**
- * 客户分配记录
- * @param $corpid string 企业id
- * @param $customerName string 客户名称
- * @param $recordId int 分配记录id
- * @param $assignmentDateStart string 起始接替时间
- * @param $assignmentDateEnd string 截止接替时间
- * @param $assignmentStatus int 接替状态
- * @param $page
- * @param $pageSize
- * @return array
- */
- public static function customerAssignmentList(
- $corpid, $customerName, $recordId, $assignmentDateStart, $assignmentDateEnd, $assignmentStatus, $page, $pageSize
- )
- {
- $customerAssignmentQuery = CustomerAssignmentRecord::suffix($corpid)
- ->where('corpid', $corpid)->where('enable', 1)->where('record_id', $recordId);
- if(!empty($customerName)){
- $customerAssignmentQuery = $customerAssignmentQuery->where('customer_name', 'like', '%'.$customerName.'%');
- }
- if(!empty($assignmentDateStart)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('takeover_time', '>=',
- $assignmentDateStart.' 00:00:00');
- }
- if(!empty($assignmentDateEnd)) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('takeover_time', '<=',
- $assignmentDateEnd.' 23:59:59');
- }
- if(!empty($assignmentStatus)) {
- if(2 == $assignmentStatus) {
- $customerAssignmentQuery = $customerAssignmentQuery->whereIn('status', [0, 2]);
- } else if(-1 == $assignmentStatus) {
- $customerAssignmentQuery = $customerAssignmentQuery->where('errcode', '>', 0);
- }else {
- $customerAssignmentQuery = $customerAssignmentQuery->where('status', $assignmentStatus);
- }
- }
- $customerAssignmentCountQuery = clone $customerAssignmentQuery;
- $count = $customerAssignmentCountQuery->count();
- $offset = ($page - 1) * $pageSize;
- $data = $customerAssignmentQuery->select(['customer_name', 'takeover_userid', 'status', 'takeover_time',
- 'customer_id', 'corpid', 'errcode', 'handover_userid'])->orderBy('id', 'desc')
- ->offset($offset)
- ->limit($pageSize)
- ->get()
- ->toArray();
- $takeOverUserIdList = array_unique(array_column($data, 'takeover_userid'));
- $handOverUserIdList = array_unique(array_column($data, 'handover_userid'));
- $userIdList = array_unique(array_merge($takeOverUserIdList, $handOverUserIdList));
- $userInfoList = DjUser::query()
- ->where('corpid', $corpid)
- ->whereIn('user_id', $userIdList)
- ->get()
- ->keyBy('user_id')
- ->toArray();
- $errcodeConf = config('qyWechat.errcode');
- foreach($data as $key => $value) {
- if( 0 == $value['status']) {
- $data[$key]['status'] = 2;
- }
- $data[$key]['takeover_username'] = isset($userInfoList[$value['takeover_userid']]['name']) ?
- $userInfoList[$value['takeover_userid']]['name'] : '';
- $data[$key]['handover_username'] = isset($userInfoList[$value['handover_userid']]['name']) ?
- $userInfoList[$value['handover_userid']]['name'] : '';
- $data[$key]['err_msg'] = null;
- if(!empty($value['errcode'])) {
- $data[$key]['err_msg'] = $errcodeConf[$value['errcode']] ?? null;
- }
- }
- return [$data, $count];
- }
- /**
- * 客户动态列表
- * @param $corpid string 企业id
- * @param $customerId integer 客户id
- * @return array
- */
- public static function customerDynamicList($corpid, $customerId)
- {
- // 根据客户id查询客户信息
- $customerInfo = Customer::suffix($corpid)
- ->where('id', $customerId)
- ->first();
- if(empty($customerInfo)) {
- return [];
- }
- $externalUserid = $customerInfo->external_userid;
- $data = CustomerDynamic::suffix($corpid)
- ->select(['type', 'handover_userid', 'takeover_userid', 'create_time', 'radar_name', 'request_id'])
- ->where('corpid', $corpid)
- ->where('external_userid', $externalUserid)
- ->orderBy('create_time', 'desc')
- ->get()
- ->toArray();
- // 提取客服信息
- $handOverUserIdList = array_column($data, 'handover_userid');
- $takeOverUserIdList = array_column($data, 'takeover_userid');
- $userIdList = array_unique(array_merge($handOverUserIdList, $takeOverUserIdList));
- $userDataList = DjUser::query()
- ->select(['user_id', 'name'])
- ->whereIn('user_id', $userIdList)
- ->where('corpid', $corpid)
- ->get()
- ->keyBy('user_id')
- ->toArray();
- // 提取雷达request_id
- $requestIdList = array_column($data, 'request_id');
- $radarCustomerBehaviorList = RadarCustomerBehavior::query()
- ->whereIn('request_id', $requestIdList)
- ->get();
- $weekName = array('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六');
- $result = [];
- foreach($data as $key => $item) {
- $date = date('Y-m-d', strtotime($item['create_time']));
- $item['customer_id'] = $customerInfo->id;
- $item['customer_name'] = $customerInfo->name;
- $value = $item;
- if(!isset($result[$date])) {
- $week = $weekName[date('w', strtotime($item['create_time']))];
- $result[$date]['date'] = $date;
- $result[$date]['week'] = $week;
- }
- $value['time'] = date('H:i:s', strtotime($item['create_time']));
- if(!empty($item['handover_userid'])) {
- $item['handover_username'] = isset($userDataList[$item['handover_userid']]['name']) ?
- $userDataList[$item['handover_userid']]['name'] : '';
- } else {
- $item['handover_username'] = '';
- }
- if(!empty($item['takeover_userid'])) {
- $item['takeover_username'] = isset($userDataList[$item['takeover_userid']]['name']) ?
- $userDataList[$item['takeover_userid']]['name'] : '';
- } else {
- $item['takeover_username'] = '';
- }
- switch($item['type']) {
- case 1:
- $value['type_desc'] = '添加好友';
- $value['content'] = $item['customer_name'].'添加了'.$item['handover_username'].'为好友';
- break;
- case 2:
- $value['type_desc'] = '被员工删除';
- $value['content'] = $item['handover_username'].'将'.$item['customer_name'].'删除了';
- break;
- case 3:
- $value['type_desc'] = '删除跟进客户';
- $value['content'] = $item['customer_name'].'将'.$item['handover_username'].'删除了';
- break;
- case 4:
- $value['type_desc'] = '客户转移';
- $value['content'] = $item['customer_name'].'从'.$item['handover_username'].'迁移到了'.
- $item['takeover_username'];
- break;
- case 5:
- $value['type_desc'] = '客户下单';
- $value['content'] = '客户'.$item['customer_name'].'下单了';
- break;
- case 6:
- $value['type_desc'] = '加入黑名单';
- $value['content'] = '将'.$item['customer_name'].'加入黑名单';
- break;
- case 7:
- $value['type_desc'] = '移出黑名单';
- $value['content'] = '将'.$item['customer_name'].'从黑名单中移除';
- break;
- case 8:
- $value['type_desc'] = '聊天';
- $value['content'] = $item['customer_name'].'与'.$item['handover_username'].'聊天了';
- break;
- case 9:
- $value['type_desc'] = '查看智能雷达';
- $radarCustomerBehaviorInfo = $radarCustomerBehaviorList->where('request_id', $item['request_id'])->first();
- $second = !empty($radarCustomerBehaviorInfo->view_time) ? $radarCustomerBehaviorInfo->view_time : 0;
- $value['content'] = $item['customer_name'].'点击了【'.$item['radar_name'].'】雷达,浏览时长'.$second.'秒';
- break;
- default:
- $value['type_desc'] = '';
- $value['content'] = '';
- break;
- }
- $result[$date]['sub'][] = $value;
- }
- return array_values($result);
- }
- /**
- * 客户详情-编辑标签时标签展示
- * @param $corpid string 企业id
- * @param $customerId int 客户id
- * @param $userId string 客服user_id
- * @return array
- */
- public static function customerDetailTagList($corpid, $customerId, $userId)
- {
- $followList = CustomerDetails::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('customer_id', $customerId)
- ->where('user_id', $userId)
- ->where('loss_status', 1)
- ->first();
- $tagIdList = empty($followList->tag_list) ? [] : explode(',', $followList->tag_list);
- // 获取企业下所有标签数据
- $tagGroupList = TagGroup::query()
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->orderBy('order', 'asc')
- ->get()
- ->toArray();
- $data = [];
- foreach($tagGroupList as $tagGroup) {
- $item = [];
- $item['group_id'] = $tagGroup['group_id'];
- $item['group_name'] = $tagGroup['group_name'];
- $tagList = Tag::query()
- ->select(['tag_name', 'tag_md5', 'order'])
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->where('group_id', $item['group_id'])
- ->get()
- ->toArray();
- foreach($tagList as $k=>$v) {
- $tagList[$k]['tag_id'] = $v['tag_md5'];
- if(in_array($v['tag_md5'], $tagIdList)){
- $tagList[$k]['selected'] = 1;
- } else {
- $tagList[$k]['selected'] = 0;
- }
- }
- $item['tag_list'] = $tagList;
- $item['tag_num'] = count($tagList);
- if($item['tag_num'] > 0) {
- $data[] = $item;
- }
- }
- return $data;
- }
- // 更新客户标签
- public static function customerDetailTagUpdate($corpid, $externalUserId, $userId, $selectedTagIdList)
- {
- // 判断客户跟进关系状态是否支持打标签
- $customerRelation = CustomerDetails::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->where('user_id', $userId)
- ->where('enable', 1)
- ->where('loss_status', 1)
- ->first();
- if(empty($customerRelation)) {
- // 已流失或者是待分配状态 因为没有客服跟进关系,所以不能调用企业微信打标签功能
- return ['客户状态不可用,不可编辑标签', 2008];
- }
- $tagIdList = Tag::query()
- ->where('corpid', $corpid)
- ->where('enable', 1)
- ->get()
- ->keyBy('tag_md5')
- ->toArray();
- $customerTagIdList = empty($customerRelation->tag_list) ? [] : explode(',', $customerRelation->tag_list);
- $removeTagIdList = array_values(array_diff($customerTagIdList, $selectedTagIdList));
- $addTagIdList = array_values(array_diff($selectedTagIdList, $customerTagIdList));
- $newRemoveTagIdList = [];
- $newAddTagIdList = [];
- foreach ($removeTagIdList as $tagId) {
- if(!isset($tagIdList[$tagId]['tag_id'])) continue;
- $newRemoveTagIdList[] = $tagIdList[$tagId]['tag_id'];
- }
- foreach($addTagIdList as $tagId) {
- if(!isset($tagIdList[$tagId]['tag_id'])) continue;
- $newAddTagIdList[] = $tagIdList[$tagId]['tag_id'];
- }
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '更新客户标签');
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag?access_token='.$accessToken;
- $params['userid'] = $userId;
- $params['external_userid'] = $externalUserId;
- $params['add_tag'] = $newAddTagIdList;
- $params['remove_tag'] = $newRemoveTagIdList;
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result= json_decode($result, 1);
- // Log::logInfo('编辑客户标签结果', [$result], 'mark_tag');
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- // 处理系统数据
- // $res = self::updateCustomerTag($corpid, $externalUserId, $userId, $addTagIdList, $removeTagIdList);
- $res = TagService::updateLocalCustomerTagSecond($corpid, $userId, $externalUserId, $newAddTagIdList,
- $newRemoveTagIdList);
- if($res) {
- return ['编辑成功', 0];
- } else {
- return ['编辑失败', 400];
- }
- } else {
- if('84061' == $result['errcode']) {
- RedisModel::lPush(CustomerDetails::CUSTOMER_LOSS_INFO_RDS, json_encode([
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'external_userid' => $externalUserId
- ], 256));
- return ['编辑失败,客户关系不存在', 2011];
- }
- if('40068' == $result['errcode']) {
- // 编辑标签ID不存在,报警
- EmailQueue::rPush('编辑客户标签时,客户标签不存在', json_encode([
- 'corpid' => $corpid,'user_id' => $userId, 'external_userid' => $externalUserId,
- 'add_tag' => $newAddTagIdList, 'remove_tag' => $newRemoveTagIdList
- ], 256), ['song.shen@kuxuan-inc.com'], '猎羽');
- }
- Log::logError('单独编辑客户标签失败', [
- 'params' => ['user_id' => $userId, 'corpid' => $corpid, 'external_userid' => $externalUserId
- , 'add_tag' => $newAddTagIdList, 'remove_tag' => $newRemoveTagIdList],
- 'result' => $result
- ], 'mark_tag');
- // 记录
- return ['编辑失败', 400];
- }
- }
- public static function updateCustomerTag($corpid, $externalUserId, $userId, $addTagIdList, $removeTagIdList)
- {
- \DB::begintransaction();
- if(!empty($removeTagIdList)) {
- $res1 = CustomerTag::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->where('user_id', $userId)
- ->whereIn('tag_id', $removeTagIdList)
- ->update(['enable' => 0]);
- } else {
- $res1 = true;
- }
- if(!empty($addTagIdList)) {
- // 查询标签对应的标签名以及标签组名
- $tagList = Tag::query()
- ->where('corpid', $corpid)
- ->whereIn('tag_id', $addTagIdList)
- ->get()
- ->keyBy('tag_id')
- ->toArray();
- $groupIdList = array_unique(array_column($tagList, 'group_id'));
- $tagGroupList = TagGroup::query()
- ->where('corpid', $corpid)
- ->whereIn('group_id', $groupIdList)
- ->get()
- ->keyBy('group_id')
- ->toArray();
- // 获取员工id
- $customeInfo = Customer::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->first()
- ->toArray();
- $createData = [];
- foreach($tagList as $tag) {
- $item['corpid'] = $corpid;
- $item['user_id'] = $userId;
- $item['customer_id'] = $customeInfo['id'];
- $item['external_userid'] = $externalUserId;
- $item['tag_id'] = $tag['tag_id'];
- $item['tag_name'] = $tag['tag_name'];
- $item['type'] = 1;
- $item['group_name'] = isset($tagGroupList[$tag['group_id']]['group_name']) ?
- $tagGroupList[$tag['group_id']]['group_name'] : '';
- $createData[] = $item;
- }
- $res2 = CustomerTag::suffix($corpid)
- ->insert($createData);
- } else {
- $res2 = true;
- }
- if($res1 > 0 && $res2 > 0) {
- \DB::commit();
- return true;
- } else {
- \DB::rollback();
- return false;
- }
- }
- // 客户迁移
- public static function addCustomerAssignmentNew(
- $corpid, $takeoverUserId, $externalUserList, $transferSuccessMsg, $type, $portraitInheritance, $selectAll,
- $filterCustomerList, $params
- )
- {
- $requestData = [
- 'corpid' => $corpid,
- 'takeover_userid' => $takeoverUserId,
- 'external_user_list' => $externalUserList,
- 'transfer_success_msg' => $transferSuccessMsg,
- 'type' => $type,
- 'portrait_inheritance' => $portraitInheritance,
- 'select_all' => $selectAll,
- 'filter_customer_list' => $filterCustomerList,
- 'params' => $params,
- ];
- // 检测接替员工是否为在职状态
- $takeoverUserInfo = DjUser::query()->where('user_id', $takeoverUserId)->where('corpid', $corpid)
- ->where('status', 1)->first();
- if(empty($takeoverUserInfo)){
- return ['接替员工状态不合法', 2012];
- }
- if(1 == $selectAll) {
- $res = BatchTransferCustomer::query()
- ->insert([
- 'corpid' => $corpid,
- 'params' => json_encode($params, JSON_UNESCAPED_UNICODE),
- 'takeover_userid' => $takeoverUserId,
- 'filter_customer_list' => json_encode($filterCustomerList, JSON_UNESCAPED_UNICODE),
- 'transfer_success_msg' => $transferSuccessMsg,
- 'portrait_inheritance' => $portraitInheritance,
- 'type' => $type,
- 'operator_id' => \Auth::id(),
- ]);
- if(isset($res)) {
- return ['申请成功', 0];
- } else {
- Log::logInfo('addCustomerAssignmentNew 申请失败, params:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['申请失败', 400];
- }
- } else {
- $handoverUserList = [];
- foreach($externalUserList as $data) {
- $handoverUserList[$data['handover_userid']][] = $data['external_userid'];
- }
- \DB::begintransaction();
- foreach($handoverUserList as $handoverUserId => $externalUserIdList) {
- $enableExternalUserIdList = [];
- if(1 == $type) {
- // 检测接替员工是否为在职状态
- $handoverUserInfo = DjUser::query()->where('user_id', $handoverUserId)->where('corpid', $corpid)
- ->where('status', 1)->first();
- if(empty($handoverUserInfo)){
- return ['迁出员工状态不合法', 2013];
- }
- $enableExternalUserIdList = CustomerDetails::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('user_id', $handoverUserId)
- ->whereIn('external_userid', $externalUserIdList)
- // ->where('loss_status', 1)
- ->get();
- $enableExternalUserIdList = $enableExternalUserIdList->isNotEmpty() ?
- $enableExternalUserIdList->toArray() : [];
- $enableExternalUserIdList = array_column($enableExternalUserIdList, 'external_userid');
- } else if(2 == $type) {
- // 检测接替员工是否为在职状态
- $handoverUserInfo = DjUser::query()->where('user_id', $handoverUserId)->where('corpid', $corpid)
- ->where('status', 5)->first();
- if(empty($handoverUserInfo)){
- return ['迁出员工状态不合法', 2013];
- }
- $enableExternalUserIdList = CustomerDetails::suffix($corpid)
- ->where('corpid', $corpid)
- ->where('user_id', $handoverUserId)
- ->whereIn('external_userid', $externalUserIdList)
- // ->where('loss_status', 2)
- ->get();
- $enableExternalUserIdList = $enableExternalUserIdList->isNotEmpty() ?
- $enableExternalUserIdList->toArray() : [];
- $enableExternalUserIdList = array_column($enableExternalUserIdList, 'external_userid');
- }
- if(count($enableExternalUserIdList) > 0) {
- $res = CustomerAssignmentTotal::query()
- ->insert([
- 'corpid' => $corpid,
- 'handover_userid' => $handoverUserId,
- 'takeover_userid' => $takeoverUserId,
- 'transfer_success_msg' => $transferSuccessMsg,
- 'external_userid' => json_encode($enableExternalUserIdList),
- 'type' => $type,
- 'status' => 1,
- 'portrait_inheritance' => $portraitInheritance,
- 'operator_id' => \Auth::id(),
- 'customer_number' => count($enableExternalUserIdList)
- ]);
- if(!$res) {
- \DB::rollBack();
- Log::logInfo('addCustomerAssignmentNew 申请失败, params:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return ['申请失败', 400];
- }
- }
- }
- \DB::commit();
- return ['申请成功', 0];
- }
- }
- /**
- * 获取外部联系人信息
- * */
- public static function updateExternalInfo($corpid, $userId, $externalUserid, $state, $changeType)
- {
- $flag = true;
- $nextCursor = null;
- try {
- while($flag) {
- # 获取外部联系人详情
- $externalUserData = ExternalContactService::getExternalContactDetail($corpid, $externalUserid, $nextCursor);
- if(empty($externalUserData)) {
- if($externalUserData === false) {
- Log::logError('外部联系人详情获取失败', [
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'external_userid' => $externalUserid,
- 'state' => $state,
- 'change_type' => $changeType,
- 'nextCursor' => $nextCursor
- ], 'UpdateExternalContact');
- }
- $flag = false;
- continue;
- }
- # 更新外部联系人信息至数据库
- $customerId = 0;
- ExternalContactService::updateExternalContacts($externalUserData, $corpid, $userId, $state, $changeType, $customerId);
- if($customerId) {
- // $followInfo = [
- // 'createtime' => time(),
- // 'userid' => $userId,
- // ];
- // TagService::autoMarkCustomerAddDateTag($corpid, $customerId, $followInfo);
- if('add_external_contact' == $changeType) {
- # 设置自动标签
- $tagNameList = [date('Y年m月')];
- $redisArr = [
- 'corpid' => $corpid, 'user_id' => $userId, 'external_userid' => $externalUserid,
- 'tag_group_name' => '自动标签', 'tag_name_list' => $tagNameList, 'type' => 2
- ];
- RedisModel::lPush(CustomerTagService::CUSTOMER_TAG_MARK_RDS, json_encode($redisArr, 1));
- }
- }
- # 翻页查询外部联系人所有的关联员工
- if(isset($externalUserData['next_cursor']) && !empty($externalUserData['next_cursor'])) {
- $nextCursor = $externalUserData['next_cursor'];
- } else {
- $flag = false;
- }
- }
- } catch (\Exception $e) {
- Log::logError('获取外部联系人详情', [
- 'line' => $e->getLine(),
- 'msg' => $e->getMessage(),
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'external_userid' => $externalUserid,
- 'state' => $state,
- 'change_type' => $changeType,
- 'nextCursor' => $nextCursor
- ], 'UpdateExternalContact-Exception');
- $flag = false;
- return false;
- }
- return true;
- }
- /**
- * 获取外部联系人信息
- * */
- public static function getCustomerInfo($corpid, $externalUserid, $userid)
- {
- return CustomerDetails::suffix($corpid)
- ->select(['name', 'remark'])
- ->where('user_id', $userid)
- ->where('external_userid', $externalUserid)
- ->where('loss_status', 1)
- ->first();
- }
- /**
- * 获取待邀请入群的新用户
- * */
- public static function waitInvite($deviceId, $beginTime, $endTime, $retry, $requestCorpId, $customerNumber)
- {
- # 校验开始时间和结束时间,最大时间差不超过十分钟
- $endTimestamps = strtotime($endTime);
- $beginTimestamps = strtotime($beginTime);
- if($endTimestamps - $beginTimestamps > 600) {
- $beginTimestamps = strtotime('-10 minute', $endTimestamps);
- }
- # 持续邀请客户入群任务单次最大请求次数配置
- $maxRequestNum = 5;
- # 查询设备对应的企微及客服信息
- $userList = AndroidBindCorp::select('corpid', 'user_id')->where('device_id', $deviceId)
- ->where('enable', 1)->where(function($query) use ($requestCorpId) {
- if($requestCorpId) $query->where('corpid', $requestCorpId);
- })->get();
- if(empty($userList)) {
- Log::logError('此设备号未绑定任何企微信息', [
- 'device_id' => $deviceId
- ], 'WaitInvite');
- return [];
- }
- # 查询支持无障碍模式的企微列表
- $corpIds = $userList->pluck('corpid');
- $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpIds)->where('enable', 1)->get();
- $data = [];
- # 查询企微和客服是否配置了邀请入群功能
- foreach ($userList as $userInfo) {
- $corpid = $userInfo->corpid ?? null;
- $userId = $userInfo->user_id ?? null;
- if(!$corpid || !$userId) {
- Log::logError('检索待邀请入群的客服时存在异常数据', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'WaitInvite');
- continue;
- }
- # 使用更新时间最近的配置
- $inviteConfig = InviteChatGroupRule::where('corpid', $corpid)
- ->whereRaw("FIND_IN_SET('".$userId."', `users`)")
- ->where('status', 1)->where('enable', 1)
- ->orderBy('updated_at', 'desc')
- ->first();
- if(empty($inviteConfig)) {
- $inviteConfig = InviteChatGroupRule::where('corpid', $corpid)
- ->where('is_for_all', 1)
- ->where('enable', 1)->where('status', 1)
- ->orderBy('updated_at', 'desc')
- ->first();
- }
- if(empty($inviteConfig)) {
- Log::logError('客服暂未配置邀请入群规则', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'WaitInvite');
- continue;
- }
- $datetimeNow = date('Y-m-d H:i:s');
- if(1 == $inviteConfig->continuously_attract_groups) {// 客户续拉任务
- if(1 == $inviteConfig->invite_type) {
- Log::logError('含有重试标识,邀请类型不能是立即邀请', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray()
- ], 'WaitInvite');
- continue;
- }
- # 重试
- if(strtotime($inviteConfig->next_invite_time) > time()) {
- # 查询当前请求次数
- $requestNum = WaitInviteRequest::getNumber($inviteConfig->id, $corpid, $deviceId);
- $requestNum = intval($requestNum);
- if($requestNum >= $maxRequestNum) {
- Log::logError('客户续拉任务重试次数超过限制', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'request_num' => $requestNum+1,
- 'max_request_num' => $maxRequestNum,
- 'retry' => $retry
- ], 'WaitInvite');
- continue;
- } else {
- WaitInviteRequest::saveData($inviteConfig->id, $corpid, $deviceId, $requestNum+1);
- Log::logInfo('客户续拉任务', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'request_num' => $requestNum+1,
- 'retry' => $retry
- ], 'WaitInvite');
- }
- } else { # 首次
- $customerNumber = null;
- WaitInviteRequest::saveData($inviteConfig->id, $corpid, $deviceId, 1);
- Log::logInfo('客户续拉任务首次请求',[
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'request_num' => 1,
- 'retry' => $retry
- ], 'WaitInvite');
- $nextInviteTime = CircleMassMsgService::getNextSendTime(1, $inviteConfig->invite_time, 0, $datetimeNow);
- $result = InviteChatGroupRule::where('id', $inviteConfig->id)->update(['next_invite_time' => $nextInviteTime]);
- if(!$result) {
- Log::logError('更新下次邀请时间失败', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'next_invite_time' => $nextInviteTime
- ], 'WaitInvite');
- }
- }
- } else {
- $customerNumber = null;
- if($inviteConfig->invite_type == 2 && strtotime($inviteConfig->next_invite_time) > time()) {
- Log::logError('对应客服尚未到定时邀请入群时间', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray()
- ], 'WaitInvite');
- continue;
- }
- # 满足邀请入群时间
- # 更新下次邀请入群时间
- if($inviteConfig->invite_type == 2) { // 定时邀请
- $nextInviteTime = CircleMassMsgService::getNextSendTime(1, $inviteConfig->invite_time, 0, $datetimeNow);
- $result = InviteChatGroupRule::where('id', $inviteConfig->id)->update(['next_invite_time' => $nextInviteTime]);
- if(!$result) {
- Log::logError('更新下次邀请时间失败', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'next_invite_time' => $nextInviteTime
- ], 'WaitInvite');
- }
- }
- }
- # 规则ID
- $ruleId = $inviteConfig->id;
- $joinType = $inviteConfig->join_type;
- $filterType = $inviteConfig->filter_type;
- $addTimeLater = $inviteConfig->add_time_later;
- $announcement = $inviteConfig->announcement;
- # 单次创建群聊任务建群数量上限
- $upperLimit = $inviteConfig->upper_limit;
- # 建群类型 1当前客户直接建群 2其他客服建群
- $ownerType = in_array($inviteConfig->owner_type, [1, 2]) ? $inviteConfig->owner_type : 1;
- # 是否为持续拉取客户入群任务
- $continuouslyAttractGroups = $inviteConfig->continuously_attract_groups;
- $cursor = intval($inviteConfig->cursor);
- # 获取邀请入群配置
- $configList = InviteChatGroupDetail::select('corpid', 'chat_id', 'sort', 'user_limit')
- ->where('enable', 1)->where('status', 1)->where('rule_id', $ruleId)
- ->orderBy('sort')->get();
- if(empty($configList)) {
- Log::logError('该企业成员无可用的群配置', [
- 'device_id' => $deviceId, 'join_type' => $joinType,
- 'corpid' => $corpid, 'add_time_later' => $addTimeLater,
- 'filter_type' => $filterType, 'add_time_st' => $inviteConfig->add_time_st, 'add_time_et' => $inviteConfig->add_time_et,
- 'userId' => $userId, 'rule_id' => $ruleId,
- ], 'WaitInvite');
- continue;
- }
- # 获取群信息
- $chatIdList = $configList->pluck('chat_id');
- $chatGroupData = ChatGroup::select('chat_id', 'name', 'owner')->where('corpid', $corpid)
- ->whereIn('chat_id', $chatIdList)->get();
- # 拉取客户人数
- $userLimit = 40;
- foreach ($configList as $config) {
- $groupInfo = $chatGroupData->where('chat_id', $config->chat_id)->first();
- $config->groupName = $groupInfo->name;
- $config->owner = $groupInfo->owner;
- $config->announcement = $announcement;
- $userLimit = min($userLimit, $config->user_limit);
- }
- $limit = $upperLimit * ($userLimit-1);
- if(is_numeric($customerNumber)) {
- $limit = $customerNumber;
- }
- $customerList = self::getInviteCustomerList($inviteConfig, $filterType, $deviceId, $joinType, $datetimeNow
- , $corpid, $addTimeLater, $userId, $ruleId, $continuouslyAttractGroups, $cursor, $limit);
- if(empty($customerList) || $customerList->isEmpty()) {
- Log::logError('该企业成员无新添加的客户', [
- 'device_id' => $deviceId, 'corpid' => $corpid,
- 'userId' => $userId, 'begin_time' => $beginTimestamps,
- 'end_time' => $endTimestamps, 'invite_config' => $inviteConfig,
- 'filter_type' => $filterType, 'join_type' => $joinType, 'datetimenow' => $datetimeNow,
- 'add_time_later' => $addTimeLater, 'rule_id' => $ruleId, 'continuouslyAttractGroups'=>$continuouslyAttractGroups,
- 'cursor' =>$cursor, 'limit' => $limit
- ], 'WaitInvite');
- continue;
- }
- $corpInfo = $corpList->where('corpid', $corpid)->first();
- $corpName = $corpInfo->corp_name ?? null;
- if(is_null($corpName)) {
- Log::logError('企微名称获取为空', [
- 'device_id' => $deviceId,
- 'corpid' => $corpid,
- 'userId' => $userId,
- ], 'WaitInvite');
- continue;
- }
- # 持续拉取客户入群任务更新游标
- if(1 == $continuouslyAttractGroups) {
- $newCursor = $customerList->max('id');
- InviteChatGroupRule::updateCursor($ruleId, $newCursor);
- }
- $data[] = [
- 'companyName' => $corpName,
- 'corpid' => $corpid,
- 'joinType' => $joinType,
- 'owner_type' => $ownerType,
- 'groupBeans' => $configList,
- 'peopleList' => $customerList,
- 'upper_limit' => $upperLimit,
- 'retry' => $retry
- ];
- }
- return $data;
- }
- public static function getInviteCustomerList(
- $inviteConfig, $filterType, $deviceId, $joinType, $datetimeNow, $corpid, $addTimeLater, $userId, $ruleId,
- $continuouslyAttractGroups, $cursor, $limit
- )
- {
- $search = [];
- if($inviteConfig->customer_filter == 1) {
- # 客户添加时间范围
- if($filterType == 1) {
- # 根据筛选条件重新定义$beginTimestamps和$endTimestamps
- $endTimestamps = strtotime($datetimeNow);
- $beginTimestamps = strtotime('- ' . $inviteConfig->add_time_later . ' hours', $endTimestamps);
- } elseif ($filterType == 2) {
- $endTimestamps = strtotime($inviteConfig->add_time_et);
- $beginTimestamps = strtotime($inviteConfig->add_time_st);
- }
- # 性别
- $gender = (!is_null($inviteConfig->gender) && $inviteConfig->gender != '') ? explode(',', $inviteConfig->gender) : [];
- if(!empty($gender)) $search['gender'] = $gender;
- # 标签
- $tagScreenType = $inviteConfig->tag_screen_type ?? null;
- $tagList = $inviteConfig->tag_list ?? null;
- if($tagScreenType == 1 && empty($tagList)) {
- Log::logError('筛选条件异常 - 选择标签为空', [
- 'device_id' => $deviceId, 'join_type' => $joinType, 'gender' => $inviteConfig->gender,
- 'corpid' => $corpid, 'add_time_later' => $addTimeLater, 'tag_list' => $inviteConfig->tag_list,
- 'filter_type' => $filterType, 'add_time_st' => $inviteConfig->add_time_st,
- 'add_time_et' => $inviteConfig->add_time_et, 'tag_screen_type' => $inviteConfig->tag_screen_type,
- 'userId' => $userId, 'rule_id' => $ruleId,
- ], 'WaitInvite');
- return [];
- }
- if($tagScreenType) {
- $search['tag_screen_type'] = $tagScreenType;
- $search['tag_list'] = explode(',', $tagList);
- }
- // 付费情况
- $payStatus = $inviteConfig->pay_status;
- $payNumMin = $inviteConfig->pay_num_min;
- $payNumMax = $inviteConfig->pay_num_max;
- if (is_numeric($payStatus)) {
- $search['pay_status'] = $payStatus;
- }
- if (is_numeric($payNumMin) && $payNumMin > 0) {
- $search['pay_num_min'] = $payNumMin;
- }
- if (is_numeric($payNumMax) && $payNumMax > 0) {
- $search['pay_num_max'] = $payNumMax;
- }
- }
- # 获取新加入的客户信息
- $customerListQuery = CustomerDetails::suffix($corpid)->where('corpid', $corpid)
- ->select('external_userid', 'name', 'remark', 'id')
- ->where('user_id', $userId)
- ->where('loss_status', 1)
- ->where('blacklist_status', 0);
- if(!empty($beginTimestamps)) {
- $customerListQuery->where('createtime', '>', $beginTimestamps);
- }
- if(!empty($endTimestamps)) {
- $customerListQuery->where('createtime', '<=', $endTimestamps);
- }
- # 按性别搜索
- if(isset($search['gender'])) {
- $customerListQuery->whereIn('gender', $search['gender']);
- }
- # 按标签搜索
- if(isset($search['tag_screen_type'])) {
- $tagList = $search['tag_list'] ?? [];
- $tagRaw = '';
- switch($search['tag_screen_type']) {
- case 1: // 所选标签满足其一
- foreach($tagList as $tagId) {
- $tagRaw .= $tagId. ' ';
- }
- if(isset($search['exclude_tag_list']) && !empty($search['exclude_tag_list'])) {
- # 增加屏蔽标签
- $tagRaw = CustomerDetails::excludeTagSqlDeal($search['exclude_tag_list'], $tagRaw);
- }
- if(!empty($tagRaw))
- $customerListQuery->whereRaw('match(`tag_list`) against ("'.$tagRaw.'" in boolean mode)');
- break;
- case 2: // 所选标签同时满足
- foreach($tagList as $tagId) {
- $tagRaw .= '+' .$tagId. ' ';
- }
- if(isset($search['exclude_tag_list']) && !empty($search['exclude_tag_list'])) {
- # 增加屏蔽标签
- $tagRaw = CustomerDetails::excludeTagSqlDeal($search['exclude_tag_list'], $tagRaw);
- }
- if(!empty($tagRaw))
- $customerListQuery->whereRaw('match(`tag_list`) against ("'.$tagRaw.'" in boolean mode)');
- break;
- case 3:
- $customerListQuery->whereNull('tag_list');
- break;
- }
- }
- # 按付费状态
- if(isset($search['pay_status'])) {
- if($search['pay_status']) {
- $customerListQuery->where('is_paid', 1);
- } else {
- $customerListQuery->where('is_paid', 0);
- }
- }
- # 最小付费次数
- if(isset($search['pay_num_min'])) {
- $customerListQuery->where('pay_num', '>=', $search['pay_num_min']);
- }
- # 最大付费次数
- if(isset($search['pay_num_max'])) {
- $customerListQuery->where('pay_num', '<=', $search['pay_num_max']);
- }
- if(1 == $continuouslyAttractGroups) {
- $customerList = $customerListQuery->where('id', '>', $cursor)->limit($limit)->orderby('createtime')->get();
- } else {
- $customerList = $customerListQuery->orderby('createtime')->get();
- }
- return $customerList;
- }
- /**
- * 获取待邀请入群的新用户
- * */
- public static function waitShare($deviceId, $beginTime, $endTime)
- {
- $endTimestamps = strtotime($endTime);
- $beginTimestamps = strtotime($beginTime);
- # 查询设备对应的企微及客服信息
- $userList = AndroidBindCorp::select('corpid', 'user_id')->where('device_id', $deviceId)
- ->where('enable', 1)->get();
- if(empty($userList)) {
- Log::logError('此设备号未绑定任何企微信息', [
- 'device_id' => $deviceId
- ], 'waitShare');
- return [];
- }
- # 查询支持无障碍模式的企微列表
- $corpIds = $userList->pluck('corpid');
- $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpIds)->where('enable', 1)->get();
- $data = [];
- # 查询企微和客服待共享的客户列表
- foreach ($userList as $userInfo) {
- $corpid = $userInfo->corpid ?? null;
- $userId = $userInfo->user_id ?? null;
- if(!$corpid || !$userId) {
- Log::logError('检索待共享好友的客服时存在异常数据', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'waitShare');
- continue;
- }
- # 检索共享好友配置
- $takeoverUserIdList = CustomerShareRelation::where('status', 1)->where('enable', 1)->where('corpid', $corpid)
- ->where('user_id', $userId)->value('takeover_users');
- if(empty($takeoverUserIdList)) {
- Log::logError('未检索到共享好友配置', [
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'device_id' => $deviceId
- ], 'waitShare');
- continue;
- }
- $takeoverUserIds = explode(',', $takeoverUserIdList);
- $takeoverUserList = DjUser::where('corpid', $corpid)->whereIn('user_id', $takeoverUserIds)->where('enable', 1)
- ->where('status', 1)->pluck('name');
- # 获取新加入的客户信息
- $customerList = CustomerDetails::suffix($corpid)->where('corpid', $corpid)
- ->select('name')
- ->where('user_id', $userId)->where('createtime', '>', $beginTimestamps)
- ->where('createtime', '<=', $endTimestamps)
- ->where('loss_status', 1)
- ->get()->pluck('name');
- if($customerList->isEmpty()) {
- Log::logError('该企业成员无新添加的客户', [
- 'device_id' => $deviceId, 'corpid' => $corpid,
- 'userId' => $userId, 'begin_time' => $beginTimestamps,
- 'end_time' => $endTimestamps, ''
- ], 'waitShare');
- continue;
- }
- $corpInfo = $corpList->where('corpid', $corpid)->first();
- $corpName = $corpInfo->corp_name ?? null;
- if(is_null($corpName)) {
- Log::logError('企微名称获取为空', [
- 'device_id' => $deviceId,
- 'corpid' => $corpid,
- 'userId' => $userId,
- ], 'waitShare');
- continue;
- }
- $data[] = [
- 'companyName' => $corpName,
- 'colleagueNames' => $takeoverUserList,
- 'clientNames' => $customerList
- ];
- }
- return $data;
- }
- public static function waitSupplementaryInvite($deviceId, $beginTime, $endTime)
- {
- # 校验开始时间和结束时间,最大时间差不超过十分钟
- $endTimestamps = strtotime($endTime);
- $beginTimestamps = strtotime($beginTime);
- if($endTimestamps - $beginTimestamps > 600) {
- $beginTimestamps = strtotime('-10 minute', $endTimestamps);
- }
- # 查询设备对应的企微及客服信息
- $userList = AndroidBindCorp::select('corpid', 'user_id')->where('device_id', $deviceId)
- ->where('enable', 1)->get();
- if(empty($userList)) {
- Log::logError('此设备号未绑定任何企微信息', [
- 'device_id' => $deviceId
- ], 'waitSupplementaryInvite');
- return [];
- }
- # 查询支持无障碍模式的企微列表
- $corpIds = $userList->pluck('corpid');
- $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpIds)->where('enable', 1)->get();
- $data = [];
- # 查询企微和客服是否配置了邀请入群功能
- foreach ($userList as $userInfo) {
- $corpid = $userInfo->corpid ?? null;
- $userId = $userInfo->user_id ?? null;
- if(!$corpid || !$userId) {
- Log::logError('检索待邀请入群的客服时存在异常数据', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'waitSupplementaryInvite');
- continue;
- }
- # 使用更新时间最近的配置
- $inviteConfig = InviteChatGroupRule::where('corpid', $corpid)
- ->whereRaw("FIND_IN_SET('".$userId."', `users`)")
- ->where('status', 1)->where('enable', 1)->where('supplementary_invite', 1)
- ->orderBy('updated_at', 'desc')
- ->first();
- if(empty($inviteConfig)) {
- $inviteConfig = InviteChatGroupRule::where('corpid', $corpid)
- ->where('is_for_all', 1)->where('supplementary_invite', 1)
- ->where('enable', 1)->where('status', 1)
- ->orderBy('updated_at', 'desc')
- ->first();
- }
- if(empty($inviteConfig)) {
- Log::logError('客服暂未配置邀请入群规则', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'waitSupplementaryInvite');
- continue;
- }
- $datetimeNow = date('Y-m-d H:i:s');
- if($inviteConfig->invite_type == 2 && strtotime($inviteConfig->next_supplementary_invite_time) > time()) {
- Log::logError('对应客服尚未到定时补充邀请入群时间', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray()
- ], 'waitSupplementaryInvite');
- continue;
- }
- $lastSupplementaryInviteTime = $inviteConfig->last_supplementary_invite_time;
- # 满足邀请入群时间
- # 更新下次邀请入群时间
- if($inviteConfig->invite_type == 2) { // 定时邀请
- $nextSupplementaryInviteTime = CircleMassMsgService::getNextSupplementaryInviteTime(1
- , $inviteConfig->invite_time, $inviteConfig->supplementary_invite_cycle, $datetimeNow);
- $result = InviteChatGroupRule::where('id', $inviteConfig->id)->update([
- 'next_supplementary_invite_time' => $nextSupplementaryInviteTime,
- 'last_supplementary_invite_time' => $datetimeNow
- ]);
- if(!$result) {
- Log::logError('更新下次邀请时间失败', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'last_supplementary_invite_time' => $lastSupplementaryInviteTime,
- 'next_supplementary_invite_time' => $nextSupplementaryInviteTime,
- 'now_supplementary_invite_time' => $datetimeNow
- ], 'waitSupplementaryInvite');
- }
- }
- # 规则ID
- $ruleId = $inviteConfig->id;
- # 建群类型 1当前客户直接建群 2其他客服建群
- $ownerType = in_array($inviteConfig->owner_type, [1, 2]) ? $inviteConfig->owner_type : 1;
- # 获取邀请入群配置
- $configList = InviteChatGroupDetail::select('corpid', 'chat_id', 'sort', 'user_limit')
- ->where('enable', 1)->where('status', 1)->where('rule_id', $ruleId)
- ->orderBy('sort')->get();
- if(empty($configList)) {
- Log::logError('该企业成员无可用的群配置', [
- 'device_id' => $deviceId, 'add_time_et' => $datetimeNow,
- 'corpid' => $corpid, 'add_time_st' => $lastSupplementaryInviteTime,
- 'userId' => $userId, 'rule_id' => $ruleId,
- ], 'waitSupplementaryInvite');
- continue;
- }
- # 获取群信息
- $chatIdList = $configList->pluck('chat_id');
- $chatGroupData = ChatGroup::select('chat_id', 'name', 'owner')->where('corpid', $corpid)
- ->whereIn('chat_id', $chatIdList)->get();
- $userList = DjUser::getUserBySearch([
- 'corp_list' => [$corpid]
- ]);
- # 拉取客户人数
- foreach ($configList as $config) {
- $groupInfo = $chatGroupData->where('chat_id', $config->chat_id)->first();
- $config->groupName = $groupInfo->name ?? '';
- $config->owner = $groupInfo->owner ?? '';
- $ownerInfo = $userList->where('user_id', $config->owner)->first();
- $config->owner_name = $ownerInfo->name ?? '';
- # 找到所有群主为当前客服的模板群聊
- $chatGroupModel = ChatGroup::getSearchModel([
- 'status' => 1, 'corpid' => $corpid, 'owner' => $config->owner, 'name' => $config->groupName
- ]);
- $userChatList = $chatGroupModel->select(['chat_id'])->get();
- if($userChatList->isEmpty()) {
- Log::logError('该群模板无法找到当前客服所属的群聊', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config
- ], 'waitSupplementaryInvite');
- $config->people_list = [];
- continue;
- }
- $userChatIdList = array_column($userChatList->toArray(), 'chat_id');
- Log::logInfo('根据群模板获取到的群聊结果', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId, 'owner' => $config->owner,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'user_chat_id_list' => $userChatIdList
- ], 'waitSupplementaryInvite');
- if(2 == $ownerType) {# 群主与进粉客服不是同一人,再次筛选包含进粉客服的群聊ID
- $newChatList = ChatGroupMember::getGroupMember([
- 'corpid' => $corpid, 'chat_id_list' => $userChatIdList, 'user_id' => $userId, 'status' => 1
- ]);
- if(empty($newChatList)) {
- Log::logError('查找进粉客服在群聊中的群聊信息', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId, 'owner' => $config->owner,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'user_chat_id_list' => $userChatIdList, 'new_chat_list'=> $newChatList
- ], 'waitSupplementaryInvite');
- $config->people_list = [];
- continue;
- }
- $newUserChatIdList = array_unique(array_column($newChatList, 'chat_id'));
- Log::logInfo('查找进粉客服在群聊中的群聊信息结果', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId, 'owner' => $config->owner,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'user_chat_id_list' => $userChatIdList, 'new_user_chat_id_list' => $newUserChatIdList
- ], 'waitSupplementaryInvite');
- $userChatIdList = $newUserChatIdList;
- }
- # 找到这些群聊在间隔时间范围内退群的客户外部联系人ID
- $externalUserList = ChatGroupMember::getGroupMember([
- 'corpid' => $corpid, 'chat_id_list' => $userChatIdList, 'status' => 2,
- 'quit_time_st' => $lastSupplementaryInviteTime, 'quit_time_ed' => $datetimeNow
- ]);
- if(empty($externalUserList)) {
- Log::logError('退群客户为空', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'chat_id_list' => $userChatIdList, 'quit_time_st' => $lastSupplementaryInviteTime,
- 'quit_time_ed' => $datetimeNow
- ], 'waitSupplementaryInvite');
- $config->people_list = [];
- continue;
- }
- # 通过外部联系人ID查询客户信息
- $externalUserIdList = array_unique(array_column($externalUserList, 'user_id'));
- Log::logInfo('客户ID列表', $externalUserIdList, 'waitSupplementaryInvite');
- $customerList = CustomerDetails::suffix($corpid)->select(['external_userid', 'name', 'remark', 'id'])
- ->where('corpid', $corpid)->whereIn('external_userid', $externalUserIdList)
- ->where('loss_status', 1)->where('blacklist_status', 0)->groupBy('external_userid')->orderBy('id', 'desc')->get();
- if($customerList->isEmpty()) {
- Log::logError('查询客户列表结果为空', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, "external_userid_list" => $externalUserIdList
- ], 'waitSupplementaryInvite');
- continue;
- }
- $config->people_list = $customerList;
- }
- $corpInfo = $corpList->where('corpid', $corpid)->first();
- $corpName = $corpInfo->corp_name ?? null;
- if(is_null($corpName)) {
- Log::logError('企微名称获取为空', [
- 'device_id' => $deviceId,
- 'corpid' => $corpid,
- 'userId' => $userId,
- ], 'waitSupplementaryInvite');
- continue;
- }
- $data[] = [
- 'companyName' => $corpName,
- 'corpid' => $corpid,
- 'owner_type' => $ownerType,
- 'groupBeans' => $configList,
- ];
- }
- return $data;
- }
- public static function waitInviteTargetGroup($deviceId, $beginTime, $endTime)
- {
- # 查询设备对应的企微及客服信息
- $userList = AndroidBindCorp::select('corpid', 'user_id')->where('device_id', $deviceId)
- ->where('enable', 1)->get();
- if(empty($userList)) {
- Log::logError('此设备号未绑定任何企微信息', [
- 'device_id' => $deviceId
- ], 'waitInviteTargetGroup');
- return [];
- }
- # 查询支持无障碍模式的企微列表
- $corpIds = $userList->pluck('corpid');
- $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpIds)->where('enable', 1)->get();
- $data = [];
- # 查询企微和客服是否配置了邀请入群功能
- foreach ($userList as $userInfo) {
- $corpid = $userInfo->corpid ?? null;
- $userId = $userInfo->user_id ?? null;
- if(!$corpid || !$userId) {
- Log::logError('检索待邀请入群的客服时存在异常数据', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'waitInviteTargetGroup');
- continue;
- }
- # 使用更新时间最近的配置
- $inviteConfig = InviteChatGroupRule::where('corpid', $corpid)
- ->whereRaw("FIND_IN_SET('".$userId."', `users`)")
- ->where('status', 1)->where('enable', 1)->where('supplementary_invite', 1)
- ->orderBy('updated_at', 'desc')
- ->first();
- if(empty($inviteConfig)) {
- $inviteConfig = InviteChatGroupRule::where('corpid', $corpid)
- ->where('is_for_all', 1)->where('supplementary_invite', 1)
- ->where('enable', 1)->where('status', 1)
- ->orderBy('updated_at', 'desc')
- ->first();
- }
- if(empty($inviteConfig)) {
- Log::logError('客服暂未配置邀请入群规则', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'waitInviteTargetGroup');
- continue;
- }
- $datetimeNow = date('Y-m-d H:i:s');
- if($inviteConfig->invite_type == 2 && strtotime($inviteConfig->next_supplementary_invite_time) > time()) {
- Log::logError('对应客服尚未到定时补充邀请入群时间', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray()
- ], 'waitInviteTargetGroup');
- continue;
- }
- $lastSupplementaryInviteTime = $inviteConfig->last_supplementary_invite_time;
- # 满足邀请入群时间,更新下次邀请入群时间
- if($inviteConfig->invite_type == 2) { // 定时邀请
- $nextSupplementaryInviteTime = CircleMassMsgService::getNextSupplementaryInviteTime(1
- , $inviteConfig->invite_time, $inviteConfig->supplementary_invite_cycle, $datetimeNow);
- $result = InviteChatGroupRule::where('id', $inviteConfig->id)->update([
- 'next_supplementary_invite_time' => $nextSupplementaryInviteTime,
- 'last_supplementary_invite_time' => $datetimeNow
- ]);
- if(!$result) {
- Log::logError('更新下次邀请时间失败', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config_info' => $inviteConfig->toArray(),
- 'last_supplementary_invite_time' => $lastSupplementaryInviteTime,
- 'next_supplementary_invite_time' => $nextSupplementaryInviteTime,
- 'now_supplementary_invite_time' => $datetimeNow
- ], 'waitInviteTargetGroup');
- }
- }
- # 规则ID
- $ruleId = $inviteConfig->id;
- # 建群类型 1当前客户直接建群 2其他客服建群
- $ownerType = in_array($inviteConfig->owner_type, [1, 2]) ? $inviteConfig->owner_type : 1;
- # 获取邀请入群配置
- $configList = InviteChatGroupDetail::select('corpid', 'chat_id', 'sort', 'user_limit')
- ->where('enable', 1)->where('status', 1)->where('rule_id', $ruleId)
- ->orderBy('sort')->get();
- if(empty($configList)) {
- Log::logError('该企业成员无可用的群配置', [
- 'device_id' => $deviceId, 'add_time_et' => $datetimeNow,
- 'corpid' => $corpid, 'add_time_st' => $lastSupplementaryInviteTime,
- 'userId' => $userId, 'rule_id' => $ruleId,
- ], 'waitInviteTargetGroup');
- continue;
- }
- # 获取群信息
- $chatIdList = $configList->pluck('chat_id');
- $chatGroupData = ChatGroup::select('chat_id', 'name', 'owner')->where('corpid', $corpid)
- ->whereIn('chat_id', $chatIdList)->get();
- $userList = DjUser::getUserBySearch([
- 'corp_list' => [$corpid]
- ]);
- # 拉取客户人数
- foreach ($configList as $config) {
- $groupInfo = $chatGroupData->where('chat_id', $config->chat_id)->first();
- $config->groupName = $groupInfo->name ?? '';
- $config->owner = $groupInfo->owner ?? '';
- $ownerInfo = $userList->where('user_id', $config->owner)->first();
- $config->owner_name = $ownerInfo->name ?? '';
- # 找到所有群主为当前客服的模板群聊
- $chatGroupModel = ChatGroup::getSearchModel([
- 'status' => 1, 'corpid' => $corpid, 'owner' => $config->owner, 'name' => $config->groupName
- ]);
- $userChatList = $chatGroupModel->select(['chat_id'])->get();
- if($userChatList->isEmpty()) {
- Log::logError('该群模板无法找到当前客服所属的群聊', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config
- ], 'waitInviteTargetGroup');
- $config->people_list = [];
- continue;
- }
- $userChatIdList = array_column($userChatList->toArray(), 'chat_id');
- Log::logInfo('根据群模板获取到的群聊结果', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId, 'owner' => $config->owner,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'user_chat_id_list' => $userChatIdList
- ], 'waitInviteTargetGroup');
- if(2 == $ownerType) { // 群主与进粉客服不是同一人,再次筛选包含进粉客服的群聊ID
- $newChatList = ChatGroupMember::getGroupMember([
- 'corpid' => $corpid, 'chat_id_list' => $userChatIdList, 'user_id' => $userId, 'status' => 1
- ]);
- if(empty($newChatList)) {
- Log::logError('查找进粉客服在群聊中的群聊信息', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId, 'owner' => $config->owner,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'user_chat_id_list' => $userChatIdList, 'new_chat_list'=> $newChatList
- ], 'waitInviteTargetGroup');
- $config->people_list = [];
- continue;
- }
- $newUserChatIdList = array_unique(array_column($newChatList, 'chat_id'));
- Log::logInfo('查找进粉客服在群聊中的群聊信息结果', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId, 'owner' => $config->owner,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'user_chat_id_list' => $userChatIdList, 'new_user_chat_id_list' => $newUserChatIdList
- ], 'waitInviteTargetGroup');
- $userChatIdList = $newUserChatIdList;
- }
- $inviteList = [];
- foreach ($userChatIdList as $userChatId) {
- # 查找对应群在指定时间的流失客户
- $externalUserList = ChatGroupMember::getGroupMember([
- 'corpid' => $corpid, 'chat_id' => $userChatId, 'status' => 2,
- 'quit_time_st' => $lastSupplementaryInviteTime, 'quit_time_ed' => $datetimeNow
- ]);
- if(empty($externalUserList)) {
- Log::logError('退群客户为空', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, 'chat_id' => $userChatId, 'quit_time_st' => $lastSupplementaryInviteTime,
- 'quit_time_ed' => $datetimeNow
- ], 'waitInviteTargetGroup');
- continue;
- }
- # 通过外部联系人ID查询客户信息
- $externalUserIdList = array_unique(array_column($externalUserList, 'user_id'));
- Log::logInfo('客户ID列表', $externalUserIdList, 'waitInviteTargetGroup');
- $customerList = CustomerDetails::suffix($corpid)->select(['external_userid', 'name', 'remark', 'id'])
- ->where('corpid', $corpid)->whereIn('external_userid', $externalUserIdList)
- ->where('loss_status', 1)->where('blacklist_status', 0)->groupBy('external_userid')
- ->orderBy('id', 'desc')
- ->get();
- if($customerList->isEmpty()) {
- Log::logError('查询客户列表结果为空', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'user_id' => $userId,
- 'name' => $config->groupName, 'rule_id' => $ruleId, 'invite_config' => $inviteConfig,
- 'config' => $config, "external_userid_list" => $externalUserIdList
- ], 'waitInviteTargetGroup');
- continue;
- }
- $inviteList[] = [
- 'chat_id' => $userChatId,
- 'group_name' => $config->groupName,
- 'owner' => $config->owner,
- 'owner_name' => $config->owner_name,
- 'customer_list' => $customerList
- ];
- }
- $config->invite_list = $inviteList;
- }
- $corpInfo = $corpList->where('corpid', $corpid)->first();
- $corpName = $corpInfo->corp_name ?? null;
- if(is_null($corpName)) {
- Log::logError('企微名称获取为空', [
- 'device_id' => $deviceId,
- 'corpid' => $corpid,
- 'userId' => $userId,
- ], 'waitInviteTargetGroup');
- continue;
- }
- $data[] = [
- 'companyName' => $corpName,
- 'corpid' => $corpid,
- 'owner_type' => $ownerType,
- 'groupBeans' => $configList,
- ];
- }
- return $data;
- }
- public static function inviteNewUser($deviceId, $beginTime, $endTime)
- {
- # 校验开始时间和结束时间,最大时间差不超过十分钟
- $endTimestamps = strtotime($endTime);
- $beginTimestamps = strtotime($beginTime);
- if($endTimestamps - $beginTimestamps > 600) {
- $beginTimestamps = strtotime('-10 minute', $endTimestamps);
- }
- # 查询设备对应的企微及客服信息
- $userList = AndroidBindCorp::select('corpid', 'user_id')->where('device_id', $deviceId)
- ->where('enable', 1)->get();
- if(empty($userList)) {
- Log::logError('此设备号未绑定任何企微信息', [
- 'device_id' => $deviceId
- ], 'inviteNewUser');
- return [];
- }
- # 查询支持无障碍模式的企微列表
- $corpIds = $userList->pluck('corpid');
- $corpList = AuthorizeCorp::select('corpid', 'corp_name')->whereIn('corpid', $corpIds)->where('enable', 1)->get();
- $data = [];
- # 查询企微和客服是否配置了新用户邀请入群功能
- foreach ($userList as $userInfo) {
- $corpid = $userInfo->corpid ?? null;
- $userId = $userInfo->user_id ?? null;
- if(!$corpid || !$userId) {
- Log::logError('检索待邀请入群的客服时存在异常数据', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId
- ], 'inviteNewUser');
- continue;
- }
- $ruleInfo = WelcomeMsgRelation::select('id', 'is_invite_user', 'group_name_prefix')->where('corpid', $corpid)
- ->whereRaw("FIND_IN_SET('".$userId."', users)")->where('enable', 1)->where('is_for_all', 0)
- ->where('is_del', 0)->orderBy('updated_at', 'desc')
- ->first();
- if(empty($ruleInfo)) { // 未查询到该员工的专属配置,则查询企业全体员工通用配置
- $ruleInfo = WelcomeMsgRelation::select('id', 'is_invite_user', 'group_name_prefix')->where('corpid', $corpid)
- ->where('enable', 1)->where('is_del', 0)
- ->where('is_for_all', 1)->orderBy('updated_at', 'desc')
- ->first();
- }
- if(empty($ruleInfo) || !$ruleInfo->is_invite_user || !$ruleInfo->group_name_prefix) {
- Log::logError('客服未配置邀请新用户入群', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config' => $ruleInfo
- ], 'inviteNewUser');
- continue;
- }
- $search = array('is_invited' => 0, 'add_time_start' => $beginTimestamps, 'add_time_end' => $endTimestamps);
- $field = 'id, name';
- list($customerList, $count) = CustomerDetails::getUserInfo($corpid, $search, $field, 1, 200, []);
- if(!$count) {
- Log::logError('该企业成员无新添加的客户', [
- 'device_id' => $deviceId, 'corpid' => $corpid, 'datetime_now' => date("Y-m-d H:i:s"),
- 'userId' => $userId, 'begin_time' => $beginTimestamps,
- 'end_time' => $endTimestamps, 'invite_config' => $ruleInfo,
- ], 'inviteNewUser');
- continue;
- }
- if($count == 200) {
- Log::logError('待邀请入群用户数超出200', [
- 'user_info' => $userInfo->toArray(),
- 'device_id' => $deviceId,
- 'config' => $ruleInfo
- ], 'inviteNewUser');
- }
- # 更新该批次用户的is_invited信息
- CustomerDetails::suffix($corpid)->whereIn('id', $customerList->pluck('id'))->update(['is_invited' => 1]);
- $corpInfo = $corpList->where('corpid', $corpid)->first();
- $corpName = $corpInfo->corp_name ?? null;
- if(is_null($corpName)) {
- Log::logError('企微名称获取为空', [
- 'device_id' => $deviceId,
- 'corpid' => $corpid,
- 'userId' => $userId,
- ], 'inviteNewUser');
- continue;
- }
- $data[] = [
- 'companyName' => $corpName,
- 'corpid' => $corpid,
- 'groupNamePrefix' => $ruleInfo->group_name_prefix,
- 'peopleList' => $customerList->pluck('name'),
- ];
- }
- return $data;
- }
- /**
- * 获取客户首次关注时间
- * */
- public static function getCustomerFirstAddTime($name, $avatar, $createTime)
- {
- if(!$name && !$avatar) { // 客户头像和昵称都为空,异常情况
- $datetimeNow = time();
- return [$datetimeNow, $datetimeNow];
- }
- # 生成uni_customer_label
- $uniCustomerLabel = md5($name . $avatar);
- # 优先从dj_customer_unique中获取最早关注时间
- $firstAddTimeData = CustomerUnique::getFirstAddTime($uniCustomerLabel);
- $firstAddTime = $firstAddTimeData->first_add_time ?? null;
- $firstAddTimeNoLoss = $firstAddTimeData->first_add_time_no_loss ?? null;
- if($firstAddTime && $firstAddTimeNoLoss) return [strtotime($firstAddTime), strtotime($firstAddTimeNoLoss)];
- # 遍历50个客户详情表,找到最早关注时间
- $firstAddTime = $firstAddTimeNoLoss = $createTime;
- for ($i=0; $i<50; $i++) {
- $minCreateTime = CustomerDetails::suffix($i)->where('uni_customer_label', $uniCustomerLabel)
- ->min('createtime');
- $minCreateTimeNoLoss = CustomerDetails::suffix($i)->where('uni_customer_label', $uniCustomerLabel)
- ->where('enable', 1)->where('loss_status', 1)
- ->min('createtime');
- if($minCreateTime && $minCreateTime < $firstAddTime)
- $firstAddTime = $minCreateTime;
- if($minCreateTimeNoLoss && $minCreateTimeNoLoss < $firstAddTimeNoLoss)
- $firstAddTimeNoLoss = $minCreateTimeNoLoss;
- }
- # 记录并返回首次关注时间
- CustomerUnique::updateOrCreate(['uni_customer_label' => $uniCustomerLabel], [
- 'name' => $name, 'avatar' => $avatar, 'first_add_time' => date('Y-m-d H:i:s', $firstAddTime),
- 'first_add_time_no_loss' => date('Y-m-d H:i:s', $firstAddTimeNoLoss), 'enable' => 1
- ]);
- return [$firstAddTime, $firstAddTimeNoLoss];
- }
- /**
- * 更新客户首次关注时间
- * */
- public static function updateCustomerFirstAddTime($name, $avatar, $createtime)
- {
- if(!$name && !$avatar) { // 客户头像和昵称都为空,异常情况
- EmailQueue::rPush(
- '更新客户首次关注时间时,用户头像和昵称异常',
- json_encode(['name' => $name, 'avatar' => $avatar]),
- ['xiaohua.hou@kuxuan-inc.com'], '猎羽'
- );
- return false;
- }
- # 生成uni_customer_label
- $uniCustomerLabel = md5($name . $avatar);
- # 优先从dj_customer_unique中获取最早关注时间
- $firstAddTimeData = CustomerUnique::getFirstAddTime($uniCustomerLabel);
- $firstAddTimeNoLoss = $firstAddTimeData->first_add_time_no_loss ?? null;
- if($createtime == strtotime($firstAddTimeNoLoss)) { // 当前流失用户为留存用户中关注最早的
- # 重新检索该用户在用户池中还留存的最早关注时间
- $firstAddTimeNoLoss = null;
- for ($i=0; $i<50; $i++) {
- $minCreateTimeNoLoss = CustomerDetails::suffix($i)->where('uni_customer_label', $uniCustomerLabel)
- ->where('enable', 1)->where('loss_status', 1)
- ->min('createtime');
- if($minCreateTimeNoLoss && (is_null($firstAddTimeNoLoss) || $minCreateTimeNoLoss <= $firstAddTimeNoLoss))
- $firstAddTimeNoLoss = $minCreateTimeNoLoss;
- }
- if(is_null($firstAddTimeNoLoss)) {
- CustomerUnique::where('uni_customer_label', $uniCustomerLabel)->update(['enable' => 0]);
- } else {
- CustomerUnique::where('uni_customer_label', $uniCustomerLabel)->update([
- 'first_add_time_no_loss' => date('Y-m-d H:i:s', $firstAddTimeNoLoss
- )]);
- }
- }
- return true;
- }
- /**
- * 校验客户是否在单主体内全部流失
- * */
- public static function checkCustomerLossStatusInCorp($corpid, $externalUserId)
- {
- # 判断客户是否有单主体内全部流失标识
- $isExist = CustomerDetails::suffix($corpid)->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->where('loss_status', 1)->where('can_receive', 1)
- ->where('enable', 1)->exists();
- if($isExist) {
- $rst = CustomerDetails::suffix($corpid)->where('corpid', $corpid)
- ->where('external_userid', $externalUserId)
- ->where('retained_status', 0)
- ->update(['retained_status'=>1]);
- } else {
- $rst = CustomerDetails::suffix($corpid)->where('corpid', $corpid)
- ->where('retained_status', 1)
- ->where('external_userid', $externalUserId)
- ->update(['retained_status'=>0]);
- }
- Log::logInfo('本次起始ID为:', [
- 'corpid' => $corpid, 'external_userid' => $externalUserId,
- 'rst' => $rst, 'is_exist' => $isExist
- ], 'CheckCustomerLossStatusInCorp');
- }
- }
|