Team.php 133 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679
  1. <?php
  2. namespace app\api\controller;
  3. use app\empcrm\controller\Empcrm;
  4. use app\event\Msg;
  5. use app\model\Activity;
  6. use app\model\Company;
  7. use app\model\Customer;
  8. use app\model\CustomersSubscribe;
  9. use app\model\CustomerVisitLog;
  10. use app\model\Employee;
  11. use app\model\Org;
  12. use app\model\Setting;
  13. use app\model\WeworksingleCompanySetting;
  14. use app\model\WeworksingleCustomer;
  15. use think\App;
  16. use think\facade\Console;
  17. use think\facade\Log;
  18. use think\facade\Db;
  19. use toolkits\Aec;
  20. use app\model\PreformanceTasksOrg;
  21. use app\model\PreformanceTasks as PreformanceTasksModel;
  22. use app\model\AgentIntegral;
  23. use app\model\AgentUser;
  24. use app\model\AgentCustomerLog;
  25. use app\model\CreditsSetting;
  26. use app\model\CustomerInvalidLog;
  27. use app\model\CustomerPackage;
  28. use app\model\CustomerPortraitField;
  29. use app\model\CustomerPortraitFieldSelect;
  30. use app\model\User;
  31. use app\model\CustomerState;
  32. use app\model\CustomerVisiting;
  33. use wx\offiaccount\client\TmpMsg;
  34. use app\model\WechatActivityIntegral;
  35. /**
  36. * 团队数据
  37. */
  38. class Team extends Base
  39. {
  40. /**
  41. * 构造方法,判断是否是员工且是管理员
  42. */
  43. public function __construct(App $app)
  44. {
  45. parent::__construct($app);
  46. $token = $this->request->token;
  47. if (!$token['isEmployee'] || !isset($token['isManager']) || !$token['isManager'])
  48. abort('404', '未授权的用户');
  49. $this->team_orgs = orgSubIds($token['org_id']); //(new Org())->getChildOrg($token['org_id']);
  50. }
  51. public function getCondition(){
  52. //$type_arr = ['jiav', 'jiaofang', 'yjlf', 'liangfang', 'yjdd', 'daodian', 'jiaoding', 'qiandan', 'jianqun', 'zhibo', 'yydc', 'daochang', 'yygswjm', 'gswjm'];
  53. $param = $this->request->only(['start_date' => date('Y-m-d', 0), 'end_date' => date('Y-m-d'), 'source' => '', 'empid' => '', 'org_id' => '', 'type' => '']);
  54. $token = $this->request->token;
  55. if ($param['org_id']) {
  56. $param_sub_org = orgSubIds($param['org_id']);
  57. } else {
  58. $param_sub_org = $this->team_orgs;
  59. }
  60. $startTime = strtotime($param['start_date']) - 1;
  61. $endTime = strtotime($param['end_date']) + 86400;
  62. // 查询条件
  63. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  64. if ($token['org_type'] == 2) {
  65. $designer_employee = Employee::where([['org_id', 'in', $param_sub_org], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  66. // 是哪个员工
  67. if ($param['empid'] && in_array($param['empid'], $designer_employee)) {
  68. setCondition($param['empid'], 'designer_id', '=', $condition);
  69. } else {
  70. $condition[] = ['designer_id', 'in', $designer_employee];
  71. }
  72. } else {
  73. // 是哪个员工
  74. if ($param['empid']) {
  75. $condition[] = ['org_id', 'in', $param_sub_org];
  76. setCondition($param['empid'], 'employee_id', '=', $condition);
  77. } else {
  78. $condition[] = ['org_id', 'in', $param_sub_org];
  79. $condition[] = ['employee_id', '>', 0];
  80. }
  81. }
  82. $condition[] = ['died', '<>', 2];
  83. $condition[] = ['state', 'not in', Customer::changeState('无效', 'chaos')];
  84. $state_n = Customer::changeState('待确认', 'chaos');
  85. $state_w = Customer::changeState('无效', 'chaos');
  86. $query1 = array_merge($condition,[['state', 'not in', array_merge($state_n,$state_w)]]);
  87. $query2 = array_merge($condition,[['state', 'in',$state_n],['crm_res_id','NULL',NULL]]);
  88. $query3 = array_merge($condition,[['state', 'in',$state_n],['crm_res_id','NOTNULL',NULL],['valid_time','NOTNULL',NULL]]);
  89. $ids = Customer::whereOr([$query1, $query2,$query3])->column('id');
  90. unset($condition);
  91. $condition[] = ['Customer.id', 'in', $ids];
  92. // 有效
  93. $state1 = CustomerVisitLog::changeState('未到访', 'chaos');
  94. $state2 = CustomerVisitLog::changeState('已到访', 'chaos');
  95. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  96. $state4 = CustomerVisitLog::changeState('已到店', 'chaos');
  97. $state5 = CustomerVisitLog::changeState('交定', 'chaos');
  98. $state6 = CustomerVisitLog::changeState('签单', 'chaos');
  99. $state7 = CustomerVisitLog::changeState('已到场', 'chaos');
  100. // 查询条件
  101. switch ($param['type']) {
  102. case 'jiav':
  103. $condition[] = ['Customer.add_wechat_time', '>', date('Y-m-d H:i:s', $startTime)];
  104. $condition[] = ['Customer.add_wechat_time', '<', date('Y-m-d H:i:s', $endTime)];
  105. break;
  106. case 'jiaofang':
  107. $condition[] = ['Customer.house_delivery_time', '>', date('Y/m/d H:i:s', $startTime)];
  108. $condition[] = ['Customer.house_delivery_time', '<', date('Y/m/d H:i:s', $endTime)];
  109. break;
  110. case 'yjlf': // 预计量房
  111. $s_where[] = ['org_id', 'in', $param_sub_org];
  112. $s_where[] = ['state', '=', 0];
  113. $s_where[] = ['type', '=', 3];
  114. $s_where[] = ['addtime', '>', date('Y-m-d H:i:s', $startTime)];
  115. $s_where[] = ['addtime', '<', date('Y-m-d H:i:s', $endTime)];
  116. $customer_ids = CustomersSubscribe::where($s_where)->group('customer_id')->column('customer_id');
  117. $condition[] = ['Customer.id', 'in', $customer_ids];
  118. break;
  119. case 'liangfang':
  120. $condition[] = ['CustomerVisitLog.state', 'in', $state3];
  121. $condition[] = ['CustomerVisitLog.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  122. $condition[] = ['CustomerVisitLog.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  123. break;
  124. case 'yjdd': // 预计到店
  125. $s_where[] = ['org_id', 'in', $param_sub_org];
  126. $s_where[] = ['state', '=', 0];
  127. $s_where[] = ['type', '=', 1];
  128. $s_where[] = ['addtime', '>', date('Y-m-d H:i:s', $startTime)];
  129. $s_where[] = ['addtime', '<', date('Y-m-d H:i:s', $endTime)];
  130. $customer_ids = CustomersSubscribe::where($s_where)->group('customer_id')->column('customer_id');
  131. $condition[] = ['Customer.id', 'in', $customer_ids];
  132. break;
  133. case 'daodian':
  134. $condition[] = ['CustomerVisitLog.state', 'in', $state4];
  135. $condition[] = ['CustomerVisitLog.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  136. $condition[] = ['CustomerVisitLog.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  137. break;
  138. case 'jiaoding':
  139. $condition[] = ['CustomerVisitLog.state', 'in', $state5];
  140. $condition[] = ['CustomerVisitLog.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  141. $condition[] = ['CustomerVisitLog.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  142. break;
  143. case 'qiandan':
  144. $condition[] = ['CustomerVisitLog.state', 'in', $state6];
  145. $condition[] = ['CustomerVisitLog.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  146. $condition[] = ['CustomerVisitLog.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  147. break;
  148. case 'jianqun':
  149. $condition[] = ['Customer.group_building_date', '>', date('Y-m-d H:i:s', $startTime)];
  150. $condition[] = ['Customer.group_building_date', '<', date('Y-m-d H:i:s', $endTime)];
  151. break;
  152. case 'zhibo':
  153. $condition[] = ['Customer.live_broadcast_date', '>', date('Y-m-d H:i:s', $startTime)];
  154. $condition[] = ['Customer.live_broadcast_date', '<', date('Y-m-d H:i:s', $endTime)];
  155. break;
  156. case 'yydc':
  157. $s_where[] = ['org_id', 'in', $param_sub_org];
  158. $s_where[] = ['state', '=', 0];
  159. $s_where[] = ['type', '=', 2];
  160. $s_where[] = ['addtime', '>', date('Y-m-d H:i:s', $startTime)];
  161. $s_where[] = ['addtime', '<', date('Y-m-d H:i:s', $endTime)];
  162. $customer_ids = CustomersSubscribe::where($s_where)->group('customer_id')->column('customer_id');
  163. $condition[] = ['Customer.id', 'in', $customer_ids];
  164. break;
  165. case 'daochang':
  166. $condition[] = ['CustomerVisitLog.state', 'in', $state7];
  167. $condition[] = ['CustomerVisitLog.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  168. $condition[] = ['CustomerVisitLog.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  169. break;
  170. case 'yygswjm':
  171. $condition[] = ['Customer.subscribe_meet_outside', '>', date('Y-m-d H:i:s', $startTime)];
  172. $condition[] = ['Customer.subscribe_meet_outside', '<', date('Y-m-d H:i:s', $endTime)];
  173. break;
  174. case 'gswjm':
  175. $condition[] = ['Customer.meet_outside', '>', date('Y-m-d H:i:s', $startTime)];
  176. $condition[] = ['Customer.meet_outside', '<', date('Y-m-d H:i:s', $endTime)];
  177. break;
  178. default:
  179. //$condition[] = ['Customer.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  180. //$condition[] = ['Customer.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  181. break;
  182. }
  183. return $condition;
  184. }
  185. /**
  186. * 以客户跟进为主的查询条件
  187. *
  188. */
  189. public function logCondition(){
  190. $param = $this->request->only(['start_date' => date('Y-m-d', 0), 'end_date' => date('Y-m-d'), 'source' => '', 'empid' => '', 'org_id' => '', 'type' => '']);
  191. if ($param['org_id']) {
  192. $param_sub_org = orgSubIds($param['org_id']);
  193. } else {
  194. $param_sub_org = $this->team_orgs;
  195. }
  196. $startTime = strtotime($param['start_date']) - 1;
  197. $endTime = strtotime($param['end_date']) + 86400;
  198. $token = $this->request->token;
  199. // 查询条件
  200. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  201. if ($token['org_type'] == 2) {
  202. $designer_employee = Employee::where([['org_id', 'in', $param_sub_org], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  203. // 是哪个员工
  204. if ($param['empid'] && in_array($param['empid'], $designer_employee)) {
  205. setCondition($param['empid'], 'designer_id', '=', $condition);
  206. setCondition($param['empid'], 'Customer.designer_id', '=', $condition_log);
  207. setCondition($param['empid'], 'employee_id', '=', $s_where);
  208. } else {
  209. $condition[] = ['designer_id', 'in', $designer_employee];
  210. $condition_log[] = ['Customer.designer_id', 'in', $designer_employee];
  211. $s_where[] = ['employee_id', 'in', $designer_employee];
  212. }
  213. } else {
  214. // 是哪个员工
  215. if ($param['empid']) {
  216. $condition[] = ['org_id', 'in', $param_sub_org];
  217. setCondition($param['empid'], 'employee_id', '=', $condition);
  218. $condition_log[] = ['Customer.org_id', 'in', $param_sub_org];
  219. setCondition($param['empid'], 'Customer.employee_id', '=', $condition_log);
  220. $s_where[] = ['org_id', 'in', $param_sub_org];
  221. setCondition($param['empid'], 'employee_id', '=', $s_where);
  222. } else {
  223. $condition[] = ['org_id', 'in', $param_sub_org];
  224. $condition[] = ['employee_id', '>', 0];
  225. $condition_log[] = ['Customer.org_id', 'in', $param_sub_org];
  226. $condition_log[] = ['Customer.employee_id', '>', 0];
  227. $s_where[] = ['org_id', 'in', $param_sub_org];
  228. $s_where[] = ['employee_id', '>', 0];
  229. }
  230. }
  231. $condition[] = ['died', '<>', 2];
  232. $condition[] = ['state', 'not in', Customer::changeState('无效', 'chaos')];
  233. $condition_log[] = ['Customer.died', '<>', 2];
  234. $condition_log[] = ['Customer.state', 'not in', Customer::changeState('无效', 'chaos')];
  235. $state_n = Customer::changeState('待确认', 'chaos');
  236. $state_w = Customer::changeState('无效', 'chaos');
  237. $query_nw = [
  238. [['state', 'not in', array_merge($state_n,$state_w)]],
  239. [['state', 'in', $state_n], ['crm_res_id', 'NULL', NULL]]
  240. ];
  241. // 加v
  242. $condition_jiav[] = ['add_wechat_time', '>', date('Y-m-d H:i:s', $startTime)];
  243. $condition_jiav[] = ['add_wechat_time', '<', date('Y-m-d H:i:s', $endTime)];
  244. // 交房
  245. $condition_jiaofang[] = ['house_delivery_time', '>', date('Y/m/d H:i:s', $startTime)];
  246. $condition_jiaofang[] = ['house_delivery_time', '<', date('Y/m/d H:i:s', $endTime)];
  247. $ids = Customer::where($condition)->where(function($query) use ($query_nw){
  248. $query->whereOr($query_nw);
  249. })->where(function($query) use ($condition_jiav, $condition_jiaofang){
  250. $query->whereOr([$condition_jiav, $condition_jiaofang]);
  251. })
  252. ->column('id');
  253. //预计量房 预计到店
  254. $s_where[] = ['org_id', 'in', $param_sub_org];
  255. $s_where[] = ['state', '=', 0];
  256. $s_where[] = ['addtime', '>', date('Y-m-d H:i:s', $startTime)];
  257. $s_where[] = ['addtime', '<', date('Y-m-d H:i:s', $endTime)];
  258. $s_where[] = ['type', 'in', [1,3]];
  259. $yuji_ids_find = CustomersSubscribe::where($s_where)->group('customer_id')->column('customer_id');
  260. $customer_ids_1 = array_values(array_unique(array_merge($ids, $yuji_ids_find)));
  261. // 时间段内有跟踪
  262. $condition_log[] = ['CustomerVisitLog.addtime', '>', date('Y-m-d H:i:s', $startTime)];
  263. $condition_log[] = ['CustomerVisitLog.addtime', '<', date('Y-m-d H:i:s', $endTime)];
  264. $customer_ids_2_find = Db::view('Customer')
  265. ->view('Org', '', 'Org.id=Customer.org_id')
  266. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  267. ->where($condition_log)
  268. ->group('Customer.id')
  269. ->column('Customer.id');
  270. $customer_ids = array_values(array_unique(array_merge($customer_ids_1, $customer_ids_2_find)));
  271. return $customer_ids;
  272. }
  273. /**
  274. * 团队统计数据
  275. * @param string $start_date
  276. * @param string $end_date
  277. * @return string
  278. */
  279. public function statistics()
  280. {
  281. $type = input('type', '', 'trim');
  282. $search_type = input('search_type', 1, 'intval'); //数据查询方式 1,以客户为主导 2,以满足的搜索状态为主导,合并出所有客户
  283. $param = $this->request->only(['start_date' => date('Y-m-d', 0), 'end_date' => date('Y-m-d'), 'source' => '', 'empid' => '', 'org_id' => '', 'type' => '']);
  284. $startTime = strtotime($param['start_date']) - 1;
  285. $endTime = strtotime($param['end_date']) + 86400;
  286. $token = $this->request->token;
  287. if ($type){
  288. $condition = $this->getCondition();
  289. // 客户总数
  290. $customer_ids = Db::view('Customer')
  291. ->view('Org', '', 'Org.id=Customer.org_id')
  292. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  293. ->where($condition)
  294. ->group('Customer.id')
  295. ->column('Customer.id');
  296. $customer_num = count($customer_ids);
  297. if ($type == 'jiav'){
  298. $jiawei = $customer_num;
  299. } else {
  300. $jiav_condition = $condition;
  301. $jiav_condition[] = ['Customer.add_wechat_time', '<>', ''];
  302. $jiaweiIds = Db::view('Customer')
  303. ->view('Org', '', 'Org.id=Customer.org_id')
  304. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  305. ->where($jiav_condition)
  306. ->group('Customer.id')
  307. ->column('Customer.id');
  308. $jiawei = count($jiaweiIds);
  309. }
  310. $customer_data = Db::view('Customer')
  311. ->view('Org', '', 'Org.id=Customer.org_id')
  312. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  313. ->where($condition)
  314. ->group('Customer.id')
  315. ->column('Customer.return_visit,Customer.assigned_personnel');
  316. $signed_money = Db::view('Customer')
  317. ->view('Org', '', 'Org.id=Customer.org_id')
  318. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  319. ->where($condition)
  320. ->sum('signed_money');
  321. $customerData['signed_money'] = $signed_money ? round($signed_money / 10000, 2) : 0;
  322. $handle = 0;
  323. foreach ($customer_data as $k => $v){
  324. if ($v['return_visit'] == 1 || empty($v['assigned_personnel'])) {
  325. $handle ++;
  326. }
  327. }
  328. } else {
  329. if ($search_type == 1) {
  330. if ($param['org_id']) {
  331. $param_sub_org = orgSubIds($param['org_id']);
  332. } else {
  333. $param_sub_org = $this->team_orgs;
  334. }
  335. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  336. if ($token['org_type'] == 2) {
  337. $designer_employee = Employee::where([['org_id', 'in', $param_sub_org], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  338. if ($param['empid'] && in_array($param['empid'], $designer_employee)) {
  339. setCondition($param['empid'], 'designer_id', '=', $condition);
  340. } else {
  341. $condition[] = ['designer_id', 'in', $designer_employee];
  342. }
  343. } else {
  344. $condition[] = ['org_id', 'in', $param_sub_org];
  345. if ($param['empid']) {
  346. setCondition($param['empid'], 'employee_id', '=', $condition);
  347. } else {
  348. $condition[] = ['employee_id', '>', 0];
  349. }
  350. }
  351. $condition[] = ['died', '<>', 2];
  352. $condition[] = ['state', 'not in', Customer::changeState('无效', 'chaos')];
  353. $condition[] = ['addtime', '>', date('Y-m-d H:i:s', $startTime)];
  354. $condition[] = ['addtime', '<', date('Y-m-d H:i:s', $endTime)];
  355. $state_n = Customer::changeState('待确认', 'chaos');
  356. $state_w = Customer::changeState('无效', 'chaos');
  357. $query1 = array_merge($condition,[['state', 'not in', array_merge($state_n,$state_w)]]);
  358. $query2 = array_merge($condition,[['state', 'in',$state_n],['crm_res_id','NULL',NULL]]);
  359. $query3 = array_merge($condition,[['state', 'in',$state_n],['crm_res_id','NOTNULL',NULL],['valid_time','NOTNULL',NULL]]);
  360. $customer_ids = Customer::whereOr([$query1, $query2,$query3])->column('id');
  361. $customer_num = count($customer_ids);
  362. unset($condition);
  363. $condition[] = ['id', 'in', $customer_ids];
  364. // 加微数量
  365. $condition1 = $condition;
  366. $condition1[] = ['add_wechat_time', '<>', ''];
  367. $jiawei = Customer::where($condition1)->count();
  368. $customer_data = Customer::where($condition)->field('return_visit,assigned_personnel')->select()->toArray();
  369. $signed_money = Customer::where($condition)->sum('signed_money');
  370. $customerData['signed_money'] = $signed_money ? round($signed_money / 10000, 2) : 0;
  371. $handle = 0;
  372. foreach ($customer_data as $k => $v){
  373. if ($v['return_visit'] == 1 || empty($v['assigned_personnel'])) {
  374. $handle ++;
  375. }
  376. }
  377. } else {
  378. $customer_ids = $this->logCondition();
  379. $customer_num = count($customer_ids);
  380. // 加微数量
  381. $condition1[] = ['id', 'in', $customer_ids];
  382. $condition1[] = ['add_wechat_time', '<>', ''];
  383. $jiawei = Customer::where($condition1)->count();
  384. $customer_data = Customer::where($condition1)->field('return_visit,assigned_personnel')->select()->toArray();
  385. $signed_money = Customer::where($condition1)->sum('signed_money');
  386. $customerData['signed_money'] = $signed_money ? round($signed_money / 10000, 2) : 0;
  387. $handle = 0;
  388. foreach ($customer_data as $k => $v){
  389. if ($v['return_visit'] == 1 || empty($v['assigned_personnel'])) {
  390. $handle ++;
  391. }
  392. }
  393. }
  394. }
  395. //控制权限
  396. $type_arr = ['customer_num' => 1, 'visit_num' => 1, 'valid_count' => 1, 'deposit_num' => 1, 'signed_num' => 1, 'yylf_num' => 1, 'lf_num' => 1, 'yydd_num' => 1, 'ydd_num' => 1, 'yyhd_num' => 1, 'ydc_num' => 1];
  397. $setting = Setting::where([['name', '=', 'teamStatisticsJurisdiction'], ['root_id', '=', $token['root_org']]])->value('content');
  398. $setting = $setting ? explode(',', $setting) : [];
  399. foreach ($type_arr as $k => $v) {
  400. $type_arr[$k] = in_array($k, $setting) ? 1 : 0;
  401. }
  402. $sum = array_sum(array_values($type_arr));
  403. if ($sum < 5) $type_arr = ['customer_num' => 1, 'visit_num' => 1, 'valid_count' => 1, 'deposit_num' => 1, 'signed_num' => 1, 'yylf_num' => 1, 'lf_num' => 1, 'yydd_num' => 1, 'ydd_num' => 1, 'yyhd_num' => 1, 'ydc_num' => 1];
  404. $customerData['customer_num'] = $customer_num;
  405. $customerData['visit_num'] = $jiawei;
  406. //装修意向下拉
  407. $pid = CustomerPortraitField::where([['keyname', '=', 'intention'], ['root_id', '=', $token['root_org']]])->value('id');
  408. $select = CustomerPortraitFieldSelect::where([['pid', '=', $pid]])->column('name,id value');
  409. return json(['code' => 0, 'data' => $customerData, 'setting' => $type_arr, 'select'=> $select, 'handle'=> $handle]);
  410. }
  411. /**
  412. * 有效客户数量 (弃用 2023-02-10)
  413. */
  414. public function statistics_valid(){
  415. $type = input('type', '', 'trim');
  416. $param = $this->request->only(['start_date' => date('Y-m-d', 0), 'end_date' => date('Y-m-d'), 'source' => '', 'empid' => '', 'org_id' => '', 'type' => '']);
  417. $startTime = strtotime($param['start_date']) - 1;
  418. $endTime = strtotime($param['end_date']) + 86400;
  419. $token = $this->request->token;
  420. if ($type){
  421. $condition = $this->getCondition();
  422. // 客户总数
  423. $customerIdList = Db::view('Customer')
  424. ->view('Org', '', 'Org.id=Customer.org_id')
  425. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  426. ->where($condition)
  427. ->group('Customer.id')
  428. ->column('Customer.id');
  429. } else {
  430. if ($param['org_id']) {
  431. $param_sub_org = orgSubIds($param['org_id']);
  432. } else {
  433. $param_sub_org = $this->team_orgs;
  434. }
  435. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  436. if ($token['org_type'] == 2) {
  437. $designer_employee = Employee::where([['org_id', 'in', $param_sub_org], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  438. $condition[] = ['designer_id', 'in', $designer_employee];
  439. } else {
  440. $condition[] = ['org_id', 'in', $param_sub_org];
  441. $condition[] = ['employee_id', '>', 0];
  442. }
  443. $condition[] = ['state', 'not in', Customer::changeState('无效', 'chaos')];
  444. $condition[] = ['addtime', '>', date('Y-m-d H:i:s', $startTime)];
  445. $condition[] = ['addtime', '<', date('Y-m-d H:i:s', $endTime)];
  446. $customerIdList = Customer::where($condition)->column('id');
  447. }
  448. $state1 = CustomerVisitLog::changeState('未到访', 'chaos');
  449. $state2 = CustomerVisitLog::changeState('已到访', 'chaos');
  450. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  451. $state4 = CustomerVisitLog::changeState('已到店', 'chaos');
  452. $state5 = CustomerVisitLog::changeState('交定', 'chaos');
  453. $state6 = CustomerVisitLog::changeState('签单', 'chaos');
  454. $state7 = CustomerVisitLog::changeState('已到场', 'chaos');
  455. // 查询条件
  456. $stateList = array_merge($state1, $state2, $state3, $state4, $state5, $state6, $state7);
  457. if ($param['org_id']) {
  458. $condition_org_path = Org::where('id', '=', $param['org_id'])->value('path');
  459. } else {
  460. $condition_org_path = Org::where('id', '=', request()->token['org_id'])->value('path');
  461. }
  462. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  463. if ($token['org_type'] == 2) {
  464. $org_id = Org::where([['path', 'like', $condition_org_path . '%']])->column('id');
  465. $designer_employee = Employee::where([['org_id', 'in', $org_id], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  466. $condition1[] = ['Customer.designer_id', 'in', $designer_employee];
  467. } else {
  468. $condition1[] = ['Org.path', 'like', $condition_org_path . '%'];
  469. }
  470. $condition1[] = ['CustomerVisitLog.state', 'in', $stateList];
  471. $youxiaoIds = Db::view('CustomerVisitLog')
  472. ->view('Customer', '', 'Customer.id=CustomerVisitLog.customer_id')
  473. ->view('Org', '', 'Org.id=Customer.org_id')
  474. ->where($condition1)
  475. ->group('CustomerVisitLog.customer_id')
  476. ->column('CustomerVisitLog.customer_id');
  477. $youxiao = array_intersect($customerIdList, $youxiaoIds);
  478. return json(['code' => 0, 'data' => count($youxiao)]);
  479. }
  480. /**
  481. * 团队统计数据
  482. * @param string $start_date
  483. * @param string $end_date
  484. * @return string
  485. */
  486. public function statistics_more()
  487. {
  488. $type = input('type', '', 'trim');
  489. $search_type = input('search_type', 1, 'intval'); //数据查询方式 1,以客户为主导 2,以满足的搜索状态为主导,合并出所有客户
  490. $param = $this->request->only(['start_date' => date('Y-m-d', 0), 'end_date' => date('Y-m-d'), 'source' => '', 'empid' => '', 'org_id' => '', 'type' => '']);
  491. $startTime = strtotime($param['start_date']);
  492. $endTime = strtotime($param['end_date']) + 86400 - 1;
  493. $token = $this->request->token;
  494. if ($type){
  495. $condition = $this->getCondition();
  496. // 客户总数
  497. $customerIdList = Db::view('Customer')
  498. ->view('Org', '', 'Org.id=Customer.org_id')
  499. ->view('CustomerVisitLog', '', 'Customer.id=CustomerVisitLog.customer_id')
  500. ->where($condition)
  501. ->group('Customer.id')
  502. ->column('Customer.id');
  503. } else {
  504. if ($search_type == 1) {
  505. if ($param['org_id']) {
  506. $param_sub_org = orgSubIds($param['org_id']);
  507. } else {
  508. $param_sub_org = $this->team_orgs;
  509. }
  510. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  511. if ($token['org_type'] == 2) {
  512. $designer_employee = Employee::where([['org_id', 'in', $param_sub_org], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  513. if ($param['empid'] && in_array($param['empid'], $designer_employee)) {
  514. setCondition($param['empid'], 'designer_id', '=', $condition);
  515. } else {
  516. $condition[] = ['designer_id', 'in', $designer_employee];
  517. }
  518. } else {
  519. $condition[] = ['org_id', 'in', $param_sub_org];
  520. if ($param['empid']) {
  521. setCondition($param['empid'], 'employee_id', '=', $condition);
  522. } else {
  523. $condition[] = ['employee_id', '>', 0];
  524. }
  525. }
  526. $condition[] = ['state', 'not in', Customer::changeState('无效', 'chaos')];
  527. $condition[] = ['addtime', 'between', [date('Y-m-d H:i:s', $startTime), date('Y-m-d H:i:s', $endTime)]];
  528. $state_n = Customer::changeState('待确认', 'chaos');
  529. $state_w = Customer::changeState('无效', 'chaos');
  530. $query1 = array_merge($condition,[['state', 'not in', array_merge($state_n,$state_w)]]);
  531. $query2 = array_merge($condition,[['state', 'in',$state_n],['crm_res_id','NULL',NULL]]);
  532. $customerIdList = Customer::whereOr([$query1,$query2])->column('id');
  533. } else {
  534. $customerIdList = $this->logCondition();
  535. }
  536. }
  537. // 有效
  538. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  539. $state4 = CustomerVisitLog::changeState('已到店', 'chaos');
  540. $state5 = CustomerVisitLog::changeState('交定', 'chaos');
  541. $state6 = CustomerVisitLog::changeState('签单', 'chaos');
  542. $state7 = CustomerVisitLog::changeState('已到场', 'chaos');
  543. $state8 = CustomerVisitLog::changeState('预约量房', 'chaos');
  544. $state9 = CustomerVisitLog::changeState('预约到店', 'chaos');
  545. $state10 = CustomerVisitLog::changeState('预约活动', 'chaos');
  546. // 签单
  547. if ($param['org_id']) {
  548. $condition_org_path = Org::where('id', '=', $param['org_id'])->value('path');
  549. } else {
  550. $condition_org_path = Org::where('id', '=', $token['org_id'])->value('path');
  551. }
  552. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  553. if ($token['org_type'] == 2) {
  554. $org_id = Org::where([['path', 'like', $condition_org_path . '%']])->column('id');
  555. $designer_employee = Employee::where([['org_id', 'in', $org_id], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  556. $condition_all[] = ['Customer.employee_id|Customer.designer_id', 'in', $designer_employee];
  557. } else {
  558. $condition_all[] = ['Org.path', 'like', $condition_org_path . '%'];
  559. }
  560. // 签单 交定 预计量房 量房 预计到店 预约活动 已到店 已到场
  561. $condition_state = array_merge($state3, $state4, $state5, $state6, $state7, $state8, $state9, $state10);
  562. $condition_all[] = ['CustomerVisitLog.state', 'in', $condition_state];
  563. if (empty($type)){
  564. $condition_all[] = ['CustomerVisitLog.addtime', 'between', [date('Y-m-d H:i:s', $startTime), date('Y-m-d H:i:s', $endTime)]];
  565. }
  566. $visit_list = Db::view('CustomerVisitLog')
  567. ->view('Customer', '', 'Customer.id=CustomerVisitLog.customer_id')
  568. ->view('Org', '', 'Org.id=Customer.org_id')
  569. ->where($condition_all)
  570. ->column('CustomerVisitLog.customer_id,CustomerVisitLog.state,CustomerVisitLog.addtime');
  571. $qiandanIds = []; // 签单
  572. $jiaodingIds = []; // 交定
  573. $yylfIds = []; //预约量房
  574. $lfIds = []; // 量房
  575. $yyddIds = []; // 预约到店
  576. $yyhdIds = []; // 预约活动
  577. $yddIds = []; // 已到店
  578. $ydcIds = []; // 已到场
  579. $ydc_list = []; // 已到场记录
  580. $ydd_list = []; // 已到店记录
  581. foreach ($visit_list as $k => $v) {
  582. if (in_array($v['state'], $state6)) {
  583. $qiandanIds[] = $v['customer_id'];
  584. }
  585. if (in_array($v['state'], $state5)) {
  586. $jiaodingIds[] = $v['customer_id'];
  587. }
  588. if (in_array($v['state'], $state8)) {
  589. $yylfIds[] = $v['customer_id'];
  590. }
  591. if (in_array($v['state'], $state3)) {
  592. $lfIds[] = $v['customer_id'];
  593. }
  594. if (in_array($v['state'], $state9)) {
  595. $yyddIds[] = $v['customer_id'];
  596. }
  597. if (in_array($v['state'], $state10)) {
  598. $yyhdIds[] = $v['customer_id'];
  599. }
  600. if (in_array($v['state'], $state7)) {
  601. $ydcIds[] = $v['customer_id'];
  602. $ydc_list[] = $v;
  603. }
  604. if (in_array($v['state'], $state4)) {
  605. $yddIds[] = $v['customer_id'];
  606. $ydd_list[] = $v;
  607. }
  608. }
  609. $qiandan = array_intersect($customerIdList, $qiandanIds);
  610. $jiaoding = array_intersect($customerIdList, $jiaodingIds);
  611. $yylf_ing = CustomersSubscribe::where([['state', '=', 0], ['type', '=', 3], ['customer_id', 'in', $yylfIds]])->column('customer_id');
  612. $yylf = array_intersect($customerIdList, $yylf_ing);
  613. // 量房
  614. $lf = array_intersect($customerIdList, $lfIds);
  615. // 预计到店
  616. $yydd_ing = CustomersSubscribe::where([['state', '=', 0], ['type', '=', 1], ['customer_id', 'in', $yyddIds]])->column('customer_id');
  617. $yydd = array_intersect($customerIdList, $yydd_ing);
  618. // 预约活动
  619. $yyhd_ing = CustomersSubscribe::where([['state', '=', 0], ['type', '=', 2], ['customer_id', 'in', $yyhdIds]])->column('customer_id');
  620. $yyhd = array_intersect($customerIdList, $yyhd_ing);
  621. // 已到店
  622. // 客户5号加微信,10号到店,则10号手机端的到店数据要体现,15号再次到店,则15号手机端不计二次到店的数据,第二月5号再次到店,则5号的数据手机端计1次到店数据 小胖提
  623. if (empty($type)) {
  624. $ydd = [];
  625. $year_s = date('Y', $startTime);
  626. $year_e = date('Y', $endTime);
  627. $month_s = intval(date('m', $startTime));
  628. $month_e = intval(date('m', $endTime));
  629. if($year_s != $year_e || $month_s != $month_e){
  630. // 跨月
  631. if ($year_s == $year_e){ // 同一年
  632. for ($i = 0; $month_s <= $month_e; $i++){
  633. if ($i == 0){
  634. $startTimeFor = date('Y-m-d H:i:s', $startTime); //首次等于搜索的开始时间
  635. } else {
  636. $startTimeFor = $year_s . '-' . $month_s . '-01 00:00:00'; // 后面月份的开始时间
  637. }
  638. if ($month_s == $month_e) { // 等于搜索的结束月份
  639. $endTimeFor = date('Y-m-d H:i:s', $endTime);
  640. } else { //中间月份的结束时间
  641. $next_month = strtotime(($year_s . '-' . ($month_s + 1) . '-01 00:00:00'))-1;
  642. $endTimeFor = date('Y-m-d 23:59:59', $next_month);
  643. }
  644. $month_ids = [];
  645. $ids_for_sel = [];
  646. $strtotime_start = strtotime($startTimeFor);
  647. $strtotime_end = strtotime($endTimeFor);
  648. foreach ($ydd_list as $k => $v) {
  649. if (strtotime($v['addtime']) > $strtotime_start && strtotime($v['addtime']) < $strtotime_end) {
  650. if(!in_array($v['customer_id'], $month_ids)){
  651. $ids_for_sel[] = $v['customer_id'];
  652. }
  653. unset($ydd_list[$k]);
  654. }
  655. }
  656. $ids_for_one = array_intersect($customerIdList, $ids_for_sel);
  657. $ydd = array_merge($ydd, $ids_for_one);
  658. $month_s ++; // 月份增加
  659. }
  660. } else {
  661. for ($y = 0; $year_s <= $year_e; $y++){
  662. if ($year_s == $year_e) {
  663. $month_s_for = 1;
  664. $month_e_for = $month_e;
  665. for ($i = 0; $month_s_for <= $month_e_for; $i++){
  666. $startTimeFor = $year_s . '-' . $month_s_for . '-01 00:00:00';
  667. if ($month_s_for == $month_e_for) {
  668. $endTimeFor = date('Y-m-d H:i:s', $endTime);
  669. } else {
  670. $next_month = strtotime(($year_s . '-' . ($month_s_for + 1) . '-01 00:00:00'))-1;
  671. $endTimeFor = date('Y-m-d 23:59:59', $next_month);
  672. }
  673. $month_ids = [];
  674. $ids_for_sel = [];
  675. $strtotime_start = strtotime($startTimeFor);
  676. $strtotime_end = strtotime($endTimeFor);
  677. foreach ($ydd_list as $k => $v) {
  678. if (strtotime($v['addtime']) > $strtotime_start && strtotime($v['addtime']) < $strtotime_end) {
  679. if(!in_array($v['customer_id'], $month_ids)){
  680. $ids_for_sel[] = $v['customer_id'];
  681. }
  682. unset($ydd_list[$k]);
  683. }
  684. }
  685. $ids_for_one = array_intersect($customerIdList, $ids_for_sel);
  686. $ydd = array_merge($ydd, $ids_for_one);
  687. $month_s_for ++;
  688. }
  689. } else {
  690. if ($y == 0) {
  691. $month_s_for = $month_s;
  692. } else {
  693. $month_s_for = 1;
  694. }
  695. for ($i = 0; $month_s_for <= 12; $i++){
  696. if ($y == 0 && $i == 0) {
  697. $startTimeFor = date('Y-m-d H:i:s', $startTime);
  698. } else {
  699. $startTimeFor = $year_s . '-' . $month_s_for . '-01 00:00:00';
  700. }
  701. if ($month_s_for == 12) {
  702. $next_month = strtotime($year_s . '-12-31 23:59:59');
  703. } else {
  704. $next_month = strtotime(($year_s . '-' . ($month_s_for + 1) . '-01 00:00:00'))-1;
  705. }
  706. $endTimeFor = date('Y-m-d 23:59:59', $next_month);
  707. $month_ids = [];
  708. $ids_for_sel = [];
  709. $strtotime_start = strtotime($startTimeFor);
  710. $strtotime_end = strtotime($endTimeFor);
  711. foreach ($ydd_list as $k => $v) {
  712. if (strtotime($v['addtime']) > $strtotime_start && strtotime($v['addtime']) < $strtotime_end) {
  713. if(!in_array($v['customer_id'], $month_ids)){
  714. $ids_for_sel[] = $v['customer_id'];
  715. }
  716. unset($ydd_list[$k]);
  717. }
  718. }
  719. $ids_for_one = array_intersect($customerIdList, $ids_for_sel);
  720. $ydd = array_merge($ydd, $ids_for_one);
  721. $month_s_for ++;
  722. }
  723. }
  724. $year_s ++; // 下一年
  725. }
  726. }
  727. } else {
  728. $ydd = array_intersect($customerIdList, $yddIds);
  729. }
  730. } else {
  731. $ydd = array_intersect($customerIdList, $yddIds);
  732. }
  733. // 已到场
  734. if (empty($type)) {
  735. $ydc = [];
  736. $year_s = date('Y', $startTime);
  737. $year_e = date('Y', $endTime);
  738. $month_s = intval(date('m', $startTime));
  739. $month_e = intval(date('m', $endTime));
  740. if($year_s != $year_e || $month_s != $month_e){
  741. // 跨月
  742. if ($year_s == $year_e){ // 同一年
  743. for ($i = 0; $month_s <= $month_e; $i++){
  744. if ($i == 0){
  745. $startTimeFor = date('Y-m-d H:i:s', $startTime); //首次等于搜索的开始时间
  746. } else {
  747. $startTimeFor = $year_s . '-' . $month_s . '-01 00:00:00'; // 后面月份的开始时间
  748. }
  749. if ($month_s == $month_e) { // 等于搜索的结束月份
  750. $endTimeFor = date('Y-m-d H:i:s', $endTime);
  751. } else { //中间月份的结束时间
  752. $next_month = strtotime(($year_s . '-' . ($month_s + 1) . '-01 00:00:00'))-1;
  753. $endTimeFor = date('Y-m-d 23:59:59', $next_month);
  754. }
  755. $month_ids = [];
  756. $ids_for_sel = [];
  757. $strtotime_start = strtotime($startTimeFor);
  758. $strtotime_end = strtotime($endTimeFor);
  759. foreach ($ydc_list as $k => $v) {
  760. if (strtotime($v['addtime']) > $strtotime_start && strtotime($v['addtime']) < $strtotime_end) {
  761. if(!in_array($v['customer_id'], $month_ids)){
  762. $ids_for_sel[] = $v['customer_id'];
  763. }
  764. unset($ydc_list[$k]);
  765. }
  766. }
  767. $ids_for_one = array_intersect($customerIdList, $ids_for_sel);
  768. $ydc = array_merge($ydc, $ids_for_one);
  769. $month_s ++; // 月份增加
  770. }
  771. } else {
  772. for ($y = 0; $year_s <= $year_e; $y++){
  773. if ($year_s == $year_e) {
  774. $month_s_for = 1;
  775. $month_e_for = $month_e;
  776. for ($i = 0; $month_s_for <= $month_e_for; $i++){
  777. $startTimeFor = $year_s . '-' . $month_s_for . '-01 00:00:00';
  778. if ($month_s_for == $month_e_for) {
  779. $endTimeFor = date('Y-m-d H:i:s', $endTime);
  780. } else {
  781. $next_month = strtotime(($year_s . '-' . ($month_s_for + 1) . '-01 00:00:00'))-1;
  782. $endTimeFor = date('Y-m-d 23:59:59', $next_month);
  783. }
  784. $month_ids = [];
  785. $ids_for_sel = [];
  786. $strtotime_start = strtotime($startTimeFor);
  787. $strtotime_end = strtotime($endTimeFor);
  788. foreach ($ydc_list as $k => $v) {
  789. if (strtotime($v['addtime']) > $strtotime_start && strtotime($v['addtime']) < $strtotime_end) {
  790. if(!in_array($v['customer_id'], $month_ids)){
  791. $ids_for_sel[] = $v['customer_id'];
  792. }
  793. unset($ydc_list[$k]);
  794. }
  795. }
  796. $ids_for_one = array_intersect($customerIdList, $ids_for_sel);
  797. $ydc = array_merge($ydc, $ids_for_one);
  798. $month_s_for ++;
  799. }
  800. } else {
  801. if ($y == 0) {
  802. $month_s_for = $month_s;
  803. } else {
  804. $month_s_for = 1;
  805. }
  806. for ($i = 0; $month_s_for <= 12; $i++){
  807. if ($y == 0 && $i == 0) {
  808. $startTimeFor = date('Y-m-d H:i:s', $startTime);
  809. } else {
  810. $startTimeFor = $year_s . '-' . $month_s_for . '-01 00:00:00';
  811. }
  812. if ($month_s_for == 12) {
  813. $next_month = strtotime($year_s . '-12-31 23:59:59');
  814. } else {
  815. $next_month = strtotime(($year_s . '-' . ($month_s_for + 1) . '-01 00:00:00'))-1;
  816. }
  817. $endTimeFor = date('Y-m-d 23:59:59', $next_month);
  818. $month_ids = [];
  819. $ids_for_sel = [];
  820. $strtotime_start = strtotime($startTimeFor);
  821. $strtotime_end = strtotime($endTimeFor);
  822. foreach ($ydc_list as $k => $v) {
  823. if (strtotime($v['addtime']) > $strtotime_start && strtotime($v['addtime']) < $strtotime_end) {
  824. if(!in_array($v['customer_id'], $month_ids)){
  825. $ids_for_sel[] = $v['customer_id'];
  826. }
  827. unset($ydc_list[$k]);
  828. }
  829. }
  830. $ids_for_one = array_intersect($customerIdList, $ids_for_sel);
  831. $ydc = array_merge($ydc, $ids_for_one);
  832. $month_s_for++;
  833. }
  834. }
  835. $year_s++; // 下一年
  836. }
  837. }
  838. } else {
  839. $ydc = array_intersect($customerIdList, $ydcIds);
  840. }
  841. } else {
  842. $ydc = array_intersect($customerIdList, $ydcIds);
  843. }
  844. $customerData['signed_num'] = count($qiandan);
  845. $customerData['deposit_num'] = count($jiaoding);
  846. $customerData['yylf_num'] = count($yylf);
  847. $customerData['lf_num'] = count($lf);
  848. $customerData['yydd_num'] = count($yydd);
  849. $customerData['ydd_num'] = count($ydd);
  850. $customerData['yyhd_num'] = count($yyhd);
  851. $customerData['ydc_num'] = count($ydc);
  852. return json(['code' => 0, 'data' => $customerData]);
  853. }
  854. /**
  855. * 团队数据-客户列表
  856. */
  857. public function customers()
  858. {
  859. $param = $this->request->only([
  860. 'state' => '', 'source' => '', 'empid' => '', 'org_id' => '', 'keyword' => '', 'page' => 1, 'limit' => 15, 'return_visit' => '', 'start_date' => date('Y-m-d', 0), 'end_date' => date('Y-m-d'), 'order' => 'addtime', 'sort' => 'desc', 'type' => '', 'level' => '', 'intention' => '', 'is_assign' => ''
  861. ]);
  862. $condition = [];
  863. $search_type = input('search_type', 1, 'intval'); //数据查询方式 1,以客户为主导 2,以满足的搜索状态为主导,合并出所有客户
  864. $startCondition = ['addtime', '>', date('Y-m-d H:i:s', strtotime($param['start_date']))];
  865. $endCondition = ['addtime', '<', date('Y-m-d', strtotime($param['end_date'])) . ' 23:59:59'];
  866. if ($param['level']) $condition[] = ['level', '=', $param['level']]; //客户等级
  867. if ($param['org_id']) {
  868. $param_sub_org = orgSubIds($param['org_id']);
  869. } else {
  870. $param_sub_org = $this->team_orgs;
  871. }
  872. $token = $this->request->token;
  873. if ($search_type == 1) {
  874. $condition[] = ['state', 'not in', Customer::changeState('无效', 'chaos')];
  875. $condition[] = ['died', '<>', 2];
  876. // 设计师部门管理员,需要查询指派给下属设计师的客户信息
  877. if ($token['org_type'] == 2) {
  878. $designer_employee = Employee::where([['org_id', 'in', $param_sub_org], ['uid', '<>', 0], ['state', '=', '在职']])->column('id');
  879. if ($param['empid'] && in_array($param['empid'], $designer_employee)) {
  880. setCondition($param['empid'], 'designer_id', '=', $condition);
  881. } else {
  882. $condition[] = ['designer_id', 'in', $designer_employee];
  883. }
  884. } else {
  885. $condition[] = ['org_id', 'in', $param_sub_org];
  886. if ($param['empid']) {
  887. setCondition($param['empid'], 'employee_id', '=', $condition);
  888. } else {
  889. $condition[] = ['employee_id', '>', 0];
  890. }
  891. }
  892. if (empty($param['keyword'])) {
  893. $condition[] = $startCondition;
  894. $condition[] = $endCondition;
  895. }
  896. } else {
  897. $customerIdList = $this->logCondition();
  898. $condition[] = ['id', 'in', $customerIdList];
  899. }
  900. //意向程度
  901. if ($param['intention']) {
  902. $intention_customer = Customer::where($condition)->where([['ext', 'like', '%intention%']])->column('id,ext');
  903. $cid = [];
  904. foreach ($intention_customer as $value) {
  905. $json = json_decode($value['ext'], true);
  906. foreach ($json as $k2 => $v2) {
  907. if ($v2['keyname'] == 'intention' && !empty($v2['value']) && $v2['value'] == $param['intention']) {
  908. $cid[] = $value['id'];
  909. break;
  910. }
  911. }
  912. }
  913. if (empty($cid)) return json(['code' => 0, 'data' => []]);
  914. $condition[] = ['id', 'in', $cid];
  915. }
  916. $source = [
  917. 'ownadd' => [
  918. ['crm_res_id', '=', null],
  919. ['is_resource', '=', 0],
  920. ['remark', '=', '']
  921. ],
  922. 'crmres' => [
  923. ['crm_res_id', 'not null', ''],
  924. ['is_resource', '=', 0]
  925. ],
  926. 'public' => [
  927. ['remark', '=', '公海获取']
  928. ]
  929. ];
  930. if ($param['source'] && isset($source[$param['source']])) $condition = array_merge($condition, $source[$param['source']]);
  931. if (!empty($param['keyword'])) {
  932. if (preg_match('/^1[\d]{10}$/', $param['keyword'])) {
  933. $list = Customer::where($condition)->field('id,name,community_name,phone')->select();
  934. $keyCustomersId = [];
  935. foreach ($list as $v) {
  936. if (strpos($v->phone, trim($param['keyword'])) !== false) $keyCustomersId[] = $v['id'];
  937. }
  938. $condition[] = ['id', 'in', $keyCustomersId];
  939. } else {
  940. $name1 = array_merge($condition, [['name', 'like', '%' . $param['keyword'] . '%']]);
  941. $name2 = array_merge($condition, [['community_name', 'like', '%' . $param['keyword'] . '%']]);
  942. $keyCustomersId = Customer::whereOr([$name1, $name2])->column('id');
  943. $condition[] = ['id', 'in', $keyCustomersId];
  944. }
  945. }
  946. //待回访
  947. if ($param['return_visit'] == 1) {
  948. $condition[] = ['return_visit', '=', 1];
  949. }
  950. //待指派协作人
  951. if ($param['return_visit'] == 2) {
  952. $condition[] = ['designer_id', '=', null];
  953. }
  954. //客户的指派状态筛选
  955. if (!empty($param['is_assign']) && $param['is_assign'] == 1) $condition[] = ['assigned_personnel', 'NOTNULL', null];
  956. if (!empty($param['is_assign']) && $param['is_assign'] == 2) $condition[] = ['assigned_personnel', 'NULL', null];
  957. // 状态筛选
  958. if (!empty($param['state'])) {
  959. if ($param['state'] == '待确认') {
  960. //2022-10-30 小程序客户列表的待确认状态是根据客户表的当前状态来展示的,所以查询待确认状态时 查询客户当前
  961. $customer_model = Customer::with(['employee', 'designer'])->withAttr('addtime', function ($value) {
  962. return explode(' ', $value)[0];
  963. })->where($condition)->where(function ($query) {
  964. $state1 = Customer::changeState('待确认', 'chaos');
  965. $query1 = [['state', 'in', $state1], ['crm_res_id', 'NULL', NULL]];
  966. $query2 = [['state', 'in', $state1], ['crm_res_id', 'NOTNULL', NULL], ['valid_time', 'NOTNULL', NULL]];
  967. $query->whereOr([$query1, $query2]);
  968. });
  969. } elseif (CustomerVisitLog::changeState($param['state']) == '回访' || $param['state'] == '有效') {
  970. $customer_model = Customer::with(['employee', 'designer'])->withAttr('addtime', function ($value) {
  971. return explode(' ', $value)[0];
  972. })->where($condition)->where([['state', 'not in', array_merge(Customer::changeState('待确认', 'chaos'), Customer::changeState('无效', 'chaos'))]]);
  973. } else {
  974. $customersIdList = Customer::where($condition)->order('addtime desc')->column('id');
  975. $visit_where[] = ['customer_id', 'in', $customersIdList];
  976. $visit_where[] = ['state', 'in', CustomerVisitLog::changeState($param['state'], 'chaos')];
  977. $visit_where[] = $startCondition;
  978. $visit_where[] = $endCondition;
  979. $logCustomersIdList = CustomerVisitLog::where($visit_where)->group('customer_id')->column('customer_id');
  980. $customer_model = Customer::with(['employee', 'designer'])->withAttr('addtime', function ($value) {
  981. return explode(' ', $value)[0];
  982. })->where('id', 'in', $logCustomersIdList);
  983. // ->where(function($query){
  984. // $state1 = Customer::changeState('待确认', 'chaos');
  985. // $query1 = [['state', 'in', $state1], ['crm_res_id', 'NULL', NULL]];
  986. // $query2 = [['state', 'in', $state1], ['crm_res_id', 'NOTNULL', NULL], ['valid_time', 'NOTNULL', NULL]];
  987. // $query->whereOr([$query1, $query2]);
  988. // });
  989. }
  990. } else {
  991. $customer_model = Customer::with(['employee', 'designer'])->withAttr('addtime', function ($value) {
  992. return explode(' ', $value)[0];
  993. })->where($condition);
  994. // ->where(function ($query) {
  995. // $state1 = Customer::changeState('待确认', 'chaos');
  996. // $query1 = [['state', 'in', $state1], ['crm_res_id', 'NULL', NULL]];
  997. // $query2 = [['state', 'in', $state1], ['crm_res_id', 'NOTNULL', NULL], ['valid_time', 'NOTNULL', NULL]];
  998. // $query->whereOr([$query1, $query2]);
  999. // });
  1000. }
  1001. if ($param['order'] == 'visit') {
  1002. $customers = $customer_model->page($param['page'], $param['limit'])->order('last_contact_date ' . $param['sort'])->select();
  1003. $data = $customers->visible(['id', 'name', 'sex', 'level', 'addtime', 'community_name', 'employee.name', 'designer.name', 'state', 'return_visit', 'assign_type', 'assigned_personnel', 'square', 'last_contact_date', 'assigned_personnel', 'designer_id', 'employee_id'])->toArray();
  1004. } else {
  1005. $order = ($param['order'] ? $param['order'] : 'addtime') . ' ' . ($param['sort'] ? $param['sort'] : 'desc');
  1006. $customers = $customer_model->page($param['page'], $param['limit'])->order($order)->select();
  1007. $data = $customers->visible(['id', 'name', 'sex', 'level', 'addtime', 'community_name', 'employee.name', 'designer.name', 'state', 'return_visit', 'assign_type', 'assigned_personnel', 'square', 'last_contact_date', 'assigned_personnel', 'designer_id', 'employee_id'])->toArray();
  1008. }
  1009. foreach ($data as $k => $v) {
  1010. $data[$k]['return_visit'] = $token['org_type'] == 2 ? 0 : $v['return_visit']; //设计师身份不需要回访
  1011. }
  1012. // 状态统计获取
  1013. $pageIdList = array_column($data, 'id');
  1014. $customersStateList = CustomerVisitLog::where([['customer_id', 'in', $pageIdList]])->group('state,customer_id')->field('count(state) as num, state, customer_id')->select()->toArray();
  1015. $customersState = [];
  1016. foreach ($customersStateList as $s) {
  1017. if (!isset($customersState[$s['customer_id']]))
  1018. $customersState[$s['customer_id']] = ['count' => 0, 'shop' => 0, 'measure' => 0, 'activity' => 0, 'deposit' => 0, 'signed' => 0];
  1019. $customersState[$s['customer_id']]['count'] += $s['num'];
  1020. // 到店,量房,活动,定金,签单
  1021. if ($s['state'] == '已到店') $customersState[$s['customer_id']]['shop'] += $s['num'];
  1022. elseif ($s['state'] == '已量房') $customersState[$s['customer_id']]['measure'] += $s['num'];
  1023. elseif ($s['state'] == '已到场') $customersState[$s['customer_id']]['activity'] += $s['num'];
  1024. elseif ($s['state'] == '已交定') $customersState[$s['customer_id']]['deposit'] += $s['num'];
  1025. elseif ($s['state'] == '已签单') $customersState[$s['customer_id']]['signed'] += $s['num'];
  1026. }
  1027. //面积
  1028. //$cus = Customer::where([['id', 'in', $pageIdList]])->column('employee_id,square,id,assigned_personnel,designer_id,last_contact_date');
  1029. $square = array_column($data, 'square', 'id');
  1030. $last_contact_date = array_column($data, 'last_contact_date', 'id');
  1031. $assigned_personnel = array_column($data, 'assigned_personnel', 'id');
  1032. $designer = array_column($data, 'designer_id', 'id');
  1033. $emp = array_column($data, 'employee_id', 'id');
  1034. $eids = [];
  1035. foreach ($data as $key => $val) {
  1036. $data[$key]['stateNum'] = isset($customersState[$val['id']]) ? $customersState[$val['id']] : ['count' => 0, 'shop' => 0, 'measure' => 0, 'activity' => 0, 'deposit' => 0, 'signed' => 0];
  1037. $data[$key]['square'] = $square[$val['id']];
  1038. //上次沟通时间
  1039. $data[$key]['last_contact_date'] = $last_contact_date[$val['id']];
  1040. $designerid = $designer[$val['id']];
  1041. $data[$key]['designer_id'] = $designer[$val['id']];
  1042. $data[$key]['employee_id'] = $emp[$val['id']];
  1043. $eid = [];
  1044. if ($designer) $eid[] = $designerid;
  1045. if ($assigned_personnel[$val['id']]) $eid = array_merge($eid, explode(',', $assigned_personnel[$val['id']]));
  1046. $data[$key]['ems'] = array_unique(array_filter($eid));
  1047. $eids = array_merge($eid, $eids);
  1048. }
  1049. $ems = Employee::with(['org' => function ($query) {
  1050. $query->field('id,org_type')->bind(['org_type' => 'org_type']);
  1051. }])->where([['id', 'in', $eids]])->field('id,org_id,name')->select()->toArray();
  1052. $emss = [];
  1053. foreach ($ems as $vs) {
  1054. $emss[$vs['id']] = $vs;
  1055. }
  1056. $arr = array_column($ems, 'org_type', 'id');
  1057. // 最后跟进时间获取
  1058. $lastTime = CustomerVisitLog::where([['customer_id', 'in', $pageIdList]])->group('customer_id')->column('max(addtime)', 'customer_id');
  1059. // 交定时间获取
  1060. $dingTime = CustomerVisitLog::where([['customer_id', 'in', $pageIdList], ['state', 'in', CustomerVisitLog::changeState('已交定', 'chaos')]])->group('customer_id')->column("max(confirm_date)", "customer_id");
  1061. foreach ($data as $keys => $vals) {
  1062. $data[$keys]['designer'] = $vals['designer_id'] ? $emss[$vals['designer_id']]['name'] : '';
  1063. unset($sale);
  1064. $sale[] = $vals['employee']['name'] ?? '';
  1065. $row = [];
  1066. if ($vals['ems']) {
  1067. foreach ($vals['ems'] as $vas) {
  1068. $i = $emss[$vas];
  1069. if ($i['org_type'] == 1 && $i['id'] != $vals['employee_id']) {
  1070. $sale[] = $i['name'];
  1071. }
  1072. }
  1073. }
  1074. $data[$keys]['sale'] = $sale;
  1075. $data[$keys]['ems'] = $row;
  1076. $data[$keys]['last_visit_day'] = isset($lastTime[$vals['id']]) ? get_date_diff(time(), $lastTime[$vals['id']])->days : -1;
  1077. $data[$keys]['last_ding_day'] = isset($dingTime[$vals['id']]) ? get_date_diff(time(), $dingTime[$vals['id']])->days : 0;
  1078. }
  1079. // 返回结果
  1080. //2022-11-09 增加业务逻辑 在团队客户中高层和中高层领导不可以回访和跟进 ,只有基层领导可以
  1081. if (!$token['isManager']) {
  1082. $is_manager = 0;
  1083. } else {
  1084. //判断是否是基层领导 , 最底层部门的管理员
  1085. $child = Org::where('pid', $token['org_id'])->field('id')->findOrEmpty();
  1086. $is_manager = $child->isEmpty() ? 1 : 0;
  1087. }
  1088. return json(['code' => 0, 'data' => $data, 'is_manager' => $is_manager]);
  1089. }
  1090. /**
  1091. * 2022-10-27 逻辑修改,跟进保护优化 如果后台设置了重复客户跟进保护规则 跟进到保护状态后其他客户的此重复客户就不能在跟进了,但是可以置为无效
  1092. */
  1093. private function forbiddenState($id, $status)
  1094. {
  1095. if ($status == '无效') return false;
  1096. $token = $this->request->token;
  1097. //保护规则
  1098. $provite = Setting::where([['name', '=', 'forbiddenState'], ['root_id', '=', $token['root_org']]])->value('content');
  1099. if (!$provite) return false;
  1100. $info = Customer::where('id', $id)->column('phone,phone1,phone2');
  1101. //查询是否是重复客户
  1102. $orgs = Org::where([['path', 'like', $token['root_org'] . '-%']])->column('id');
  1103. $query[] = ['employee_id', '>', 0];
  1104. $query[] = ['org_id', 'in', $orgs];
  1105. $query[] = ['phone|phone1|phone2', 'in', array_filter($info[0])];
  1106. // $query[] = ['employee_id','<>',$token['employee_id']];
  1107. $check = Customer::where($query)->column('id,employee_id');
  1108. if (count($check) <= 1) return false;
  1109. $provite = explode(',', $provite);
  1110. $state = [];
  1111. foreach ($provite as $v) {
  1112. $state = array_merge($state, CustomerVisitLog::changeState($v, 'chaos'));
  1113. }
  1114. //查询该客户是否存在受保护的状态 只有第一个跟进的业务员可以继续跟进
  1115. $where[] = ['state', 'in', $state];
  1116. $where[] = ['customer_id', 'in', array_column($check, 'id')];
  1117. $where[] = ['employee_id|customer_employee_id', 'in', array_column($check, 'employee_id')];
  1118. $repeat = CustomerVisitLog::where($where)->order('id asc')->field('customer_id,state')->findOrEmpty();
  1119. if ($repeat->isEmpty() || (int)$repeat->customer_id == (int)$id) return false;
  1120. //该客户已被其他员工 确认到店/确认量房/确认到场/交定/签单 无法更近
  1121. $state = str_replace('已', '', $repeat->state);
  1122. $state = in_array(trim($state), ['交定', '签单']) ? trim($state) : '确认' . trim($state);
  1123. return '该客户已被其他员工“' . $state . '”无法跟进';
  1124. }
  1125. /**
  1126. * 2022-11-11 业务修改 签单之后可以编辑签单金额,跟进记录增加 业务员修改签单金额为3000元
  1127. */
  1128. private function updateMoney($param)
  1129. {
  1130. $token = $this->request->token;
  1131. $money = $param['money'] ?: 0;
  1132. $where[] = ['id', '=', $param['customer_id']];
  1133. Customer::where($where)->update(['signed_money' => $money]);
  1134. $token['name'] = Employee::where([['id', '=', $token['employee_id']]])->value('name');
  1135. $time = date('Y-m-d H:i:s');
  1136. //增加跟进记录
  1137. $save = [
  1138. 'customer_id' => $param['customer_id'],
  1139. 'type' => '',
  1140. 'next_contact_date' => date('Y-m-d'),
  1141. 'remark' => '业务员' . $token['name'] . '修改签单金额为' . $money . '元',
  1142. 'addtime' => $time,
  1143. 'employee_id' => $token['employee_id'],
  1144. 'user_id' => $token['uid'],
  1145. 'state' => 1,
  1146. 'org_id' => $token['org_id'],
  1147. 'customer_employee_id' => $token['employee_id'],
  1148. 'customer_org_id' => $token['org_id'],
  1149. 'money' => $money
  1150. ];
  1151. //2022-10-28 增加交定和签单凭证 凭证为图片
  1152. $deliverySignVoucher = request()->only(['sign_media_id' => '', 'sign_weixin_media' => '', 'sign_img' => '']);
  1153. $save = $save + $deliverySignVoucher;
  1154. CustomerVisitLog::insertGetId($save);
  1155. if ($deliverySignVoucher['sign_media_id']) Console::call('download', ['sign']);
  1156. return json(['code' => 0, 'msg' => '签单金额修改成功。', 'data' => '签单金额修改成功。']);
  1157. }
  1158. /**
  1159. * 添加客户追踪记录
  1160. * 签单、收定时记录金额,更新客户状态,记录回访时间
  1161. */
  1162. public function addVisitlog()
  1163. {
  1164. $token = $this->request->token;
  1165. if ($token['isManager'] != 1) return json(['code' => 1, 'msg' => '无权修改该信息']);
  1166. $param = request()->only(['customer_id', 'type', 'next_contact_date', 'remark', 'img' => '', 'state', 'money' => 0, 'aid' => 0, 'addtime' => date('Y-m-d H:i:s'), 'confirm_date' => '', 'weixin_media' => '', 'media_id' => '', 'starts' => 0, 'weixin_media1' => '', 'media_id1' => '', 'img1' => '', 'number_of_visitors' => 0, 'measure_room_img_type' => '', 'package' => '', 'deposit_mode' => 0]);
  1167. $param['confirm_date'] = $param['confirm_date'] ? $param['confirm_date'] . ' ' . date('H:i:s') : date('Y-m-d H:i:s');
  1168. $employeeTypeName = $token['org_type'] == 2 ? '设计师' : '销售';
  1169. $employeeType = $token['org_type'] == 2 ? 'designer_id' : 'employee_id';
  1170. //2022-10-04 逻辑修改,无效时无效原因必传remark
  1171. // if ($param['state'] == '无效' && empty($param['remark'])) return json(['code' => 1, 'msg' => '请填写无效原因']);
  1172. // 在跟进之前,增加了设计师必填判断,得先查一下设置
  1173. $state = Customer::changeState($param['state']);
  1174. $stateCheck = ['已到店' => 'daodian', '已到场' => 'daochang', '已量房' => 'liangfang', '已交定' => 'qiandan', '已签单' => 'zhuandan'];
  1175. if (in_array($state, ['已到店', '已到场', '已量房', '已交定', '已签单'])) {
  1176. $need_designer[] = ['root_id', '=', $token['root_org']];
  1177. $need_designer[] = ['name', '=', 'add_visit_log_need_designer'];
  1178. $need_designer_setting = Setting::where($need_designer)->findOrEmpty();
  1179. if (!$need_designer_setting->isEmpty()) {
  1180. $need_state = explode(',', $need_designer_setting['content']);
  1181. $input_state = $stateCheck[$state] ?? '';
  1182. if (!empty($input_state) && in_array($input_state, $need_state)) {
  1183. // 需要验证
  1184. $customer_find = Customer::find($param['customer_id']);
  1185. if (!empty($customer_find)) {
  1186. if (empty($customer_find['assigned_personnel'])) {
  1187. return json(['code'=> 1, 'msg'=> '请先指派设计师']);
  1188. }
  1189. $assigned_personnel = explode(',', $customer_find['assigned_personnel']);
  1190. $assigned_personnel_employee_org = Employee::where('id', 'in', $assigned_personnel)->column('org_id');
  1191. $assigned_personnel_org_type = Org::where('id', 'in', $assigned_personnel_employee_org)->column('org_type');
  1192. if (!in_array(2, $assigned_personnel_org_type)) {
  1193. return json(['code'=> 1, 'msg'=> '请先指派设计师']);
  1194. }
  1195. }
  1196. }
  1197. }
  1198. }
  1199. //2022-10-27 逻辑修改,跟进保护优化 如果后台设置了重复客户跟进保护规则 跟进到保护状态后其他业务员的此重复客户就不能在跟进了,但是可以置为无效
  1200. $forbiddenState = $this->forbiddenState($param['customer_id'], $param['state']);
  1201. if ($forbiddenState != false) return json(['code' => 1, 'msg' => $forbiddenState]);
  1202. //23-03-10 共有客户列表管理层查看下级部门所有员工指派的跟被指派的客户,同时还可以跟进修改查询客户的逻辑
  1203. $team_orgs = orgSubIds($token['org_id']);
  1204. $org_employee = Employee::where([['org_id', 'in', $team_orgs], ['state', '=', '在职'], ['uid', '>', 0]])->column('id');
  1205. $where = [
  1206. ['id', '=', $param['customer_id']],
  1207. ['state', '<>', '无效'],
  1208. ['employee_id', '=', $token['employee_id']]
  1209. ];
  1210. //指派的客户
  1211. $where_or = [['assigned_personnel', 'find in set', $token['employee_id']], ['id', '=', $param['customer_id']]];
  1212. $sub_employee = Employee::where([['org_id', 'in', $this->team_orgs], ['state', '=', '在职'], ['uid', '>', 0]])->column('id');
  1213. $where_or1 = [['designer_id', 'in', $sub_employee], ['id', '=', $param['customer_id']]];
  1214. $where_or2 = [['employee_id', 'in', $sub_employee], ['id', '=', $param['customer_id']]];
  1215. $had = Customer::whereOr([$where, $where_or, $where_or1, $where_or2])->find();
  1216. if (!$had) return json(['code' => 1, 'msg' => '添加失败,数据不存在']);
  1217. if ($had['died'] == 2) {
  1218. return json(['code' => 1, 'msg' => '客户死单,暂无法跟踪']);
  1219. }
  1220. //签单之后不能置为无效
  1221. if ($param['state'] == '无效') {
  1222. $is_orders = CustomerVisitLog::where([['state', 'in', CustomerVisitLog::changeState('已签单', 'chaos')], ['customer_id', '=', $had->id]])->count();
  1223. if ($is_orders) return json(['code' => 1, 'msg' => '该客户已签单,不能置为无效']);
  1224. }
  1225. //改为有效之后不能再改为待确认
  1226. if ($param['state'] == '待确认') {
  1227. if ($had->state != '待确认') return json(['code' => 1, 'msg' => '该客户已标记为有效,不能修改为待确认']);
  1228. }
  1229. // 撞单机制
  1230. if ($param['state'] == '未到访') { // 标记有效
  1231. // 同部门能否重复录入开关设置
  1232. $empcrm_repeat[] = ['root_id', '=', $token['root_org']];
  1233. $empcrm_repeat[] = ['name', '=', 'empcrm_customer_repeat'];
  1234. $repeat_setting = Setting::where($empcrm_repeat)->findOrEmpty();
  1235. //判断同部门
  1236. if (!$repeat_setting->isEmpty()) {
  1237. $repeat_org = explode(',', $repeat_setting['content']);
  1238. if (in_array($token['org_id'], $repeat_org)) {
  1239. // 需要验证
  1240. $not_sure = Customer::changeState('待确认', 'chaos');
  1241. $wuxiao = Customer::changeState('无效', 'chaos');
  1242. $phones_arr = array_filter([$had['phone'], $had['phone1'], $had['phone2']]);
  1243. $repeat_where[] = ['phone|phone1|phone2', 'in', $phones_arr];
  1244. $repeat_where[] = ['org_id', 'in', $repeat_org];
  1245. $repeat_where[] = ['state', 'not in', array_merge($not_sure, $wuxiao)];
  1246. $customerExist = Customer::where($repeat_where)->field('id,employee_id');
  1247. if (!empty($customerExist)) {
  1248. foreach ($customerExist as $ex) {
  1249. if ($ex['employee_id'] != $token['employee_id'] && $ex['id'] != $param['customer_id']) {
  1250. $have_emp = Employee::where('id', '=', $ex['employee_id'])->value('name');
  1251. return json(['code' => 2, 'msg' => '该客户与员工' . $have_emp . '撞单,无法标记有效']);
  1252. }
  1253. }
  1254. }
  1255. }
  1256. }
  1257. }
  1258. if (in_array($state, ['未到访', '已到店', '已到场', '已量房', '已交定', '已签单', '已卖卡']) && $had->state == '待确认') {
  1259. $valid_time = date('Y-m-d H:i:s');
  1260. if (!empty($param['confirm_date'])) {
  1261. $valid_time = $param['confirm_date'];
  1262. }
  1263. $had->valid_time = $valid_time;
  1264. }
  1265. // 如果是预约添加预约记录
  1266. $stateType = [
  1267. 1 => '到店',
  1268. 2 => '到场',
  1269. 3 => '量房'
  1270. ];
  1271. $yylf_state = CustomerVisitLog::changeState('预约量房', 'chaos');
  1272. $lf_state = CustomerVisitLog::changeState('已量房', 'chaos');
  1273. $yydc_state = CustomerVisitLog::changeState('预约活动', 'chaos');
  1274. $dc_state = CustomerVisitLog::changeState('已到场', 'chaos');
  1275. $yydd_state = CustomerVisitLog::changeState('预约到店', 'chaos');
  1276. $dd_state = CustomerVisitLog::changeState('已到店', 'chaos');
  1277. $check_state = array_merge($yylf_state, $lf_state, $yydc_state, $dc_state, $yydd_state, $dd_state);
  1278. if (in_array($param['state'], $check_state)) {
  1279. // 保护设置
  1280. $sub_setting = Setting::where([['root_id', '=', $token['root_org']], ['name', '=', 'subscribe_protected']])->findOrEmpty();
  1281. if (!$sub_setting->isEmpty()) { // 有设置
  1282. $setting_content = json_decode($sub_setting['content'], true);
  1283. $org_ids = orgSubIds($token['root_org']);
  1284. foreach ($setting_content as $k_s => $v_s) {
  1285. if (!empty($v_s['state']) && !empty($v_s['day']) && $v_s['state'] == 1) {
  1286. $continue = false;
  1287. $sub_state = 0;
  1288. $errmsg = '该客户在保护期内,无法提交';
  1289. $check_log = false;
  1290. $check_where = [];
  1291. switch ($k_s) {
  1292. case 'liangfang':
  1293. $sub_state = 3;
  1294. $visit_state = 1;
  1295. $check_log = true;
  1296. $check_where[] = ['org_id', 'in', $org_ids];
  1297. $check_where[] = ['addtime', '>', date('Y-m-d H:i:s', time() - 24 * 3600 * $v_s['day'])];
  1298. $check_where[] = ['employee_id', '<>', $token['employee_id']];
  1299. $check_where[] = ['state', 'in', $lf_state];
  1300. break;
  1301. case 'yliangfang': //预约量房
  1302. $sub_state = 3;
  1303. $visit_state = 0;
  1304. break;
  1305. case 'daodian':
  1306. $sub_state = 1;
  1307. $visit_state = 1;
  1308. $check_log = true;
  1309. $check_where[] = ['org_id', 'in', $org_ids];
  1310. $check_where[] = ['addtime', '>', date('Y-m-d H:i:s', time() - 24 * 3600 * $v_s['day'])];
  1311. $check_where[] = ['employee_id', '<>', $token['employee_id']];
  1312. $check_where[] = ['state', 'in', $dd_state];
  1313. break;
  1314. case 'ydaodian':
  1315. $sub_state = 1;
  1316. $visit_state = 0;
  1317. break;
  1318. case 'daochang':
  1319. $sub_state = 2;
  1320. $visit_state = 1;
  1321. $check_log = true;
  1322. $check_where[] = ['org_id', 'in', $org_ids];
  1323. $check_where[] = ['addtime', '>', date('Y-m-d H:i:s', time() - 24 * 3600 * $v_s['day'])];
  1324. $check_where[] = ['employee_id', '<>', $token['employee_id']];
  1325. $check_where[] = ['state', 'in', $dc_state];
  1326. break;
  1327. case 'ydaochang':
  1328. $sub_state = 2;
  1329. $visit_state = 0;
  1330. break;
  1331. default:
  1332. $continue = true;
  1333. break;
  1334. }
  1335. if ($continue) continue;
  1336. // “确认” 不受预约的限制
  1337. if (in_array($k_s, ['yliangfang', 'ydaodian', 'ydaochang']) && in_array($param['state'], array_merge($lf_state, $dd_state, $dc_state))) {
  1338. continue;
  1339. }
  1340. if (in_array($param['state'], array_merge($lf_state, $dd_state, $dc_state))) {
  1341. $errmsg = '该客户在保护期内,无法提交确认';
  1342. } elseif (in_array($param['state'], array_merge($yylf_state, $yydd_state, $yydc_state))) {
  1343. $errmsg = '该客户在保护期内,无法预约';
  1344. }
  1345. // 查询保护时间段内添加的预约量房记录
  1346. unset($v_where);
  1347. $v_where[] = ['org_id', 'in', $org_ids];
  1348. $v_where[] = ['addtime', '>', date('Y-m-d H:i:s', time() - 24 * 3600 * $v_s['day'])];
  1349. $v_where[] = ['employee_id', '<>', $token['employee_id']];
  1350. $v_where[] = ['type', '=', $sub_state];
  1351. $v_where[] = ['state', '=', $visit_state];
  1352. $sub_list = CustomersSubscribe::where($v_where)->select()->toArray();
  1353. if (!empty($sub_list)) {
  1354. $sub_list_ids = array_column($sub_list, 'customer_id');
  1355. $sub_employee_ids = array_column($sub_list, 'employee_id');
  1356. $sub_customers = Customer::where([['id', 'in', $sub_list_ids], ['employee_id', 'in', $sub_employee_ids]])->select()->toArray();
  1357. foreach ($sub_customers as $v) {
  1358. if (in_array($had->phone, [$v['phone'], $v['phone1'], $v['phone2']]) && $v['id'] != $had['id']) {
  1359. return json(['code' => 1, 'msg' => $errmsg]);
  1360. }
  1361. if (!empty($had->phone1) && in_array($had->phone1, [$v['phone'], $v['phone1'], $v['phone2']]) && $v['id'] != $had['id']) {
  1362. return json(['code' => 1, 'msg' => $errmsg]);
  1363. }
  1364. if (!empty($had->phone2) && in_array($had->phone2, [$v['phone'], $v['phone1'], $v['phone2']]) && $v['id'] != $had['id']) {
  1365. return json(['code' => 1, 'msg' => $errmsg]);
  1366. }
  1367. }
  1368. }
  1369. if ($check_log) {
  1370. $log_list = CustomerVisitLog::where($check_where)->select()->toArray();
  1371. $log_list_ids = array_column($log_list, 'customer_id');
  1372. $log_employee_ids = array_column($log_list, 'employee_id');
  1373. $log_customers = Customer::where([['id', 'in', $log_list_ids], ['employee_id', 'in', $log_employee_ids]])->select()->toArray();
  1374. foreach ($log_customers as $v) {
  1375. if (in_array($had->phone, [$v['phone'], $v['phone1'], $v['phone2']]) && $v['id'] != $had['id']) {
  1376. return json(['code' => 1, 'msg' => $errmsg]);
  1377. }
  1378. if (!empty($had->phone1) && in_array($had->phone1, [$v['phone'], $v['phone1'], $v['phone2']]) && $v['id'] != $had['id']) {
  1379. return json(['code' => 1, 'msg' => $errmsg]);
  1380. }
  1381. if (!empty($had->phone2) && in_array($had->phone2, [$v['phone'], $v['phone1'], $v['phone2']]) && $v['id'] != $had['id']) {
  1382. return json(['code' => 1, 'msg' => $errmsg]);
  1383. }
  1384. }
  1385. }
  1386. }
  1387. }
  1388. }
  1389. }
  1390. // 更改客户信息
  1391. $state = Customer::changeState($param['state']);
  1392. $orders = false;
  1393. //签单之后不能签单交定,可以跟进
  1394. if ($state == '已签单') {
  1395. $is = CustomerVisitLog::where([['state', 'in', CustomerVisitLog::changeState('已签单', 'chaos')], ['customer_id', '=', $had->id]])->count();
  1396. if ($is) {
  1397. //2022-11-11 业务修改 签单之后可以编辑签单金额,跟进记录增加 业务员修改签单金额为3000元
  1398. return $this->updateMoney($param);
  1399. // return json(['code' => 1, 'msg' => '该客户' . $state]);
  1400. }
  1401. $orders = true;
  1402. } elseif ($state == '已交定') {
  1403. $is = CustomerVisitLog::where([['state', 'in', CustomerVisitLog::changeState('已签单', 'chaos')], ['customer_id', '=', $had->id]])->count();
  1404. if ($is) {
  1405. return json(['code' => 1, 'msg' => '该客户已签单']);
  1406. }
  1407. $orders = true;
  1408. }
  1409. // 检测确认 到店/量房/交定/签单
  1410. $stateCheck = ['已到店' => 'visitShopConfirm', '已到场' => 'visitSiteConfirm', '已量房' => 'measureConfirm', '已交定' => 'depositConfirm', '已签单' => 'signConfirm'];
  1411. if ($token['org_type'] == 1 || ($token['org_type'] == 2 && $token['employee_id'] != $had['employee_id'])) {
  1412. foreach ($stateCheck as $ss => $set) {
  1413. if ($ss != $state)
  1414. continue;
  1415. $setContent = Setting::where(['name' => $set, 'root_id' => $this->request->token['root_org'], 'state' => 1])->value('content');
  1416. // 没有找到则不限制
  1417. if ($setContent == null)
  1418. continue;
  1419. $setContent = json_decode($setContent, true);
  1420. if (count($setContent) == 0)
  1421. continue;
  1422. if (in_array($had->designer_id, $org_employee) && in_array('designer', $setContent))
  1423. continue;
  1424. if (in_array($had->employee_id, $org_employee) && in_array('salesperson', $setContent))
  1425. continue;
  1426. // 共有客户 销售人员
  1427. $assigned_personnel = explode(',', $had['assigned_personnel']);
  1428. $designer_arr = !empty($had['designer_id']) ? [$had['designer_id']] : [];
  1429. $salesperson = array_diff($assigned_personnel, $designer_arr);
  1430. if (array_intersect($salesperson, $org_employee) && in_array('salesperson', $setContent))
  1431. continue;
  1432. return json(['code' => 1, 'msg' => '操作失败,无确认权限']);
  1433. }
  1434. }
  1435. Db::startTrans();
  1436. if (!empty($state)) {
  1437. $had->state = $state;
  1438. }
  1439. $had->revisit_time = !empty($param['next_contact_date']) ? $param['next_contact_date'] . ' 00:00:00' : null;
  1440. $had->last_contact_date = date('Y-m-d', time());
  1441. $had->updatetime = date('Y-m-d H:i:s', time());
  1442. if ($param['aid'] && $param['state'] == '预约活动') $had->aid = $param['aid'];
  1443. $had->fresh = 0;
  1444. // 交定产品
  1445. $dingMsg = '';
  1446. if ($had->state == '已交定') {
  1447. empty($param['money']) ?: $had->deposit_money = $param['money'];
  1448. if (!empty($param['package'])) {
  1449. $package = CustomerPackage::where([['root_id', '=', $this->request->token['root_org']], ['id', 'in', $param['package']]])->column('name', 'id');
  1450. if (!$package) return json(['code' => 1, 'msg' => '客户产品不存在']);
  1451. $had->package_id = implode(',', array_keys($package));
  1452. $dingMsg = '交定金额:' . $param['money'] . '元,选择产品:' . implode(',', $package);
  1453. }
  1454. }
  1455. if ($had->state == '已签单' && !empty($param['money'])) $had->signed_money = $param['money'];
  1456. $had->save();
  1457. // 更新客户保护期
  1458. if ($param['state'] !== '无效' && !empty($state)) {
  1459. $log_state = CustomerVisitLog::changeState($state, 'chaos');
  1460. $vis_where[] = ['employee_id', '=', $this->request->token['employee_id']];
  1461. $vis_where[] = ['state', 'in', $log_state];
  1462. $vis_where[] = ['customer_id', '=', $param['customer_id']];
  1463. if (!empty($had['employee_time'])) {
  1464. $vis_where[] = ['addtime', '>', $had['employee_time']];
  1465. }
  1466. $v_count = CustomerVisitLog::where($vis_where)->count();
  1467. //查看此状态的跟踪记录,如果有数据,说明此客户在此员工这里已经经历过此状态,不再更新保护期
  1468. if (!$v_count) {
  1469. Customer::changeProtectedTo($had->id, $this->request->token['root_org']);
  1470. }
  1471. }
  1472. // 添加确定消息内容
  1473. $confirmMsg = '';
  1474. if (!empty($param['confirm_date'])) {
  1475. $confirmMsg = ', 时间:' . $param['confirm_date'];
  1476. }
  1477. // 备注
  1478. $employeeName = Employee::where(['id' => $token['employee_id']])->value('name');
  1479. $remark = $param['remark'];
  1480. if (empty($remark)) {
  1481. if (empty($state))
  1482. $remark = '部门领导' . $employeeName . '对客户进行了回访';
  1483. else
  1484. $remark = '部门领导' . $employeeName . '更新客户状态为' . $state . $confirmMsg . ',' . $dingMsg;
  1485. }
  1486. // 添加追踪记录
  1487. $visitLog = [
  1488. 'customer_id' => $had->id,
  1489. 'type' => $param['type'],
  1490. 'next_contact_date' => !empty($param['next_contact_date']) ? $param['next_contact_date'] : null,
  1491. 'employee_id' => $token['employee_id'],
  1492. 'user_id' => $token['uid'],
  1493. 'remark' => $remark,
  1494. 'state' => $param['state'],
  1495. 'weixin_media' => $param['weixin_media'],
  1496. 'media_id' => $param['media_id'],
  1497. 'starts' => $param['starts'],
  1498. 'money' => $param['money'],
  1499. 'confirm_date' => $param['confirm_date'],
  1500. 'org_id' => $token['org_id'],
  1501. 'aid' => $param['aid'] ?: $had->aid,
  1502. 'weixin_media1' => $param['weixin_media1'],
  1503. 'media_id1' => $param['media_id1'],
  1504. 'customer_employee_id' => $had->employee_id,
  1505. 'customer_org_id' => Employee::where('id', $had->employee_id)->value('org_id'),
  1506. 'img' => $param['img'],
  1507. 'img1' => $param['img1'],
  1508. 'number_of_visitors' => $param['number_of_visitors'],
  1509. 'measure_room_img_type' => $param['measure_room_img_type'],
  1510. 'deposit_mode' => $param['deposit_mode']
  1511. ];
  1512. //2022-10-28 增加交定和签单凭证 凭证为图片 谈单时长talking_order_time
  1513. $deliverySignVoucher = request()->only(['delivery_media_id' => '', 'delivery_weixin_media' => '', 'sign_media_id' => '', 'sign_weixin_media' => '', 'delivery_img' => '', 'sign_img' => '', 'talking_order_time' => '']);
  1514. $visitLog = $visitLog + $deliverySignVoucher;
  1515. empty($param['img']) ?: $visitLog['img'] = $param['img'];
  1516. if (!empty($param['aid'])) {
  1517. // 检测活动是否存在
  1518. $existActivity = Activity::where([['id', '=', $param['aid']], ['root_id', '=', $token['root_org']]])->count();
  1519. if ($existActivity == 0) {
  1520. Db::rollback();
  1521. return json(['code' => 1, 'msg' => '活动不存在']);
  1522. }
  1523. $visitLog['aid'] = $param['aid'];
  1524. }
  1525. $visitLog = CustomerVisitLog::create($visitLog);
  1526. if ($orders) $this->preformance_tasks($state, $param['customer_id'], $param['money'], $visitLog->id, $token['employee_id']); //计算业绩
  1527. // 如果是预约添加预约记录
  1528. if (strpos($visitLog->state, '预约') !== false) {
  1529. //2022-11-09 增加指派客户逻辑 同一个客户可以指派多人, 但是该客户在同一天内只能有一个预约,预约之后其他人就不能预约了,,,不同日期可以继续预约
  1530. $state = str_replace('预约', '', $visitLog->state);
  1531. // 一天只能预约一个
  1532. $hadSubscribe = CustomersSubscribe::where([
  1533. ['customer_id', '=', $had['id']],
  1534. //['employee_id|designer_id', '=', $had['employee_id']],
  1535. ['subscribe_date', '=', $param['confirm_date']],
  1536. ['state', '=', 0]
  1537. ])->count();
  1538. // 查找是否已经预约
  1539. $typeSubscribe = CustomersSubscribe::where([
  1540. ['customer_id', '=', $had['id']],
  1541. //['employee_id|designer_id', '=', $had['employee_id']],
  1542. ['type', '=', array_search($state, $stateType)],
  1543. ['state', '=', 0]
  1544. ])->find();
  1545. if ($hadSubscribe) {
  1546. Db::rollback();
  1547. return json(['code' => 1, 'msg' => '该客户在当前日期已有预约']);
  1548. } elseif ($typeSubscribe) {
  1549. Db::rollback();
  1550. return json(['code' => 1, 'msg' => '该客户已有' . $state . '预约, 预约日期' . $typeSubscribe->subscribe_date]);
  1551. } else {
  1552. $subscribe = [
  1553. 'customer_id' => $had['id'],
  1554. 'subscribe_date' => $param['confirm_date'],
  1555. 'employee_id' => $had->employee_id,
  1556. 'designer_id' => $had->designer_id,
  1557. 'type' => $state,
  1558. 'aid' => $param['aid'] ?: $had->aid,
  1559. 'org_id' => $had->org_id
  1560. ];
  1561. CustomersSubscribe::create($subscribe);
  1562. }
  1563. }
  1564. //当设为无效时,记录当前操作人跟进的最后一次状态,此处在公海列表处展示
  1565. if ($param['state'] == '无效') {
  1566. $last_cvl = CustomerVisitLog::where('customer_id', $param['customer_id'])->with('employee')->order('addtime desc')->find();
  1567. //获取"无效"并进入公海之前的那次跟进记录的信息
  1568. if ($last_cvl) {
  1569. $before_pool = [
  1570. 'name' => $last_cvl->employee->name,
  1571. 'state' => $last_cvl->state,
  1572. 'addtime' => $last_cvl->addtime
  1573. ];
  1574. } else {
  1575. $before_pool = [
  1576. 'name' => Employee::find($had['employee_id'])->value('name'),
  1577. 'state' => '待确认',
  1578. 'addtime' => $had->addtime
  1579. ];
  1580. }
  1581. // 该客户预约中的状态置为无效
  1582. CustomersSubscribe::where([['customer_id', '=', $param['customer_id']], ['state', '=', 0]])->save(['state' => -1]);
  1583. //公海内是否存在该客户信息,存在则合并客户信息(phone、phone1、phone2)
  1584. $orgids = orgSubIds($token['root_org']);
  1585. $phone_arr = [];
  1586. !empty(trim($had['phone'])) ? $phone_arr[] = cypherphone(trim($had['phone'])) : '';
  1587. !empty(trim($had['phone1'])) ? $phone_arr[] = cypherphone(trim($had['phone1'])) : '';
  1588. !empty(trim($had['phone2'])) ? $phone_arr[] = cypherphone(trim($had['phone2'])) : '';
  1589. $phone_arr = array_filter($phone_arr);
  1590. $pool_condition = [
  1591. ['employee_id', '=', NULL],
  1592. ['is_resource', '=', 0],
  1593. ['org_id', 'in', $orgids],
  1594. ['phone|phone1|phone2', 'in', $phone_arr]
  1595. ];
  1596. $pool_crm = Customer::where($pool_condition)->column('id');
  1597. if (!empty($pool_crm)) {
  1598. //公海存在则删除
  1599. Customer::where([['id', 'in', $pool_crm]])->update(['delete_time' => time()]);
  1600. //关联回访记录修改
  1601. CustomerVisitLog::where([['customer_id', 'in', $pool_crm]])->update(['is_merge' => 1, 'customer_id' => $had['id']]);
  1602. CustomersSubscribe::where([['customer_id', 'in', $pool_crm]])->update(['is_merge' => 1, 'customer_id' => $had['id']]);
  1603. }
  1604. //增加无效记录
  1605. $vlglist = CustomerVisitLog::where([['customer_id', '=', $param['customer_id']], ['customer_employee_id', '=', $had['employee_id']],['state','not in',array_merge(CustomerVisitLog::changeState('待确认','chaos'), CustomerVisitLog::changeState('无效', 'chaos'))], ['save_portrait_field', 'NULL', null]])->count();
  1606. $invalidlog = [
  1607. 'customer_id'=> $param['customer_id'],
  1608. 'employee_id'=> $had->employee_id,
  1609. 'designer_id'=> $had->designer_id ? $had->designer_id : 0,
  1610. 'org_id' => $had->org_id,
  1611. 'root_id' => $token['root_org'],
  1612. 'cus_addtime' => $had->sign_time,
  1613. 'visitlog_id' => $visitLog->id,
  1614. 'assigned_personnel' => $had->assigned_personnel ? $had->assigned_personnel : '',
  1615. 'source_id' => $had->source_id ? $had->source_id : 0,
  1616. 'status' => !empty($vlglist) ? 1 : 2,
  1617. 'cus_employee_time'=> $had->employee_time,
  1618. 'is_resource'=> $had->is_resource,
  1619. 'valid_time' => $had->valid_time
  1620. ];
  1621. CustomerInvalidLog::create($invalidlog);
  1622. Customer::where('id', $param['customer_id'])->update(['state' => 7, 'employee_id' => NULL, 'org_id' => $had['org_id'], 'is_resource' => 0, 'before_pool' => json_encode($before_pool), 'designer_id' => NULL, 'ext->ext6' => '', 'employee_time' => NULL]);
  1623. }
  1624. // //如果签单,默认交定
  1625. /*if (strpos($param['state'], "签单") !== false) {
  1626. trace(strpos($param['state'], "签单"));
  1627. $lw[] = CustomerVisitLog::changeState(['state', '=', '交定']);
  1628. $lw[] = ['customer_id', '=', $param['customer_id']];
  1629. $check = CustomerVisitLog::where($lw)->find();
  1630. if (!$check) {
  1631. $l_visitlog = $visitLog->toArray();
  1632. unset($l_visitlog['id']);
  1633. $l_visitlog['state'] = '交定';
  1634. $l_visitlog['remark'] = !empty($param['remark']) ? $param['remark'] : $employeeName . '默认客户状态为交定';
  1635. $mr = CustomerVisitLog::create(array_merge($param, $l_visitlog));
  1636. $this->preformance_tasks('已交定', $param['customer_id'], $param['money'], $mr->id, $token['employee_id']); //计算业绩
  1637. }
  1638. }*/
  1639. if (in_array($param['state'], ['已到店', '已量房', '已到场'])) {
  1640. $state = str_replace('已', '', $param['state']);
  1641. $subscribe = CustomersSubscribe::where([['customer_id', '=', $had['id']], ['type', '=', array_search($state, $stateType)], ['state', '=', 0], ['employee_id', '=', $had['employee_id']]])->find();
  1642. if (!empty($subscribe)) {
  1643. $subscribe->state = 1;
  1644. $subscribe->save();
  1645. } elseif ($param['aid'] && in_array($param['state'], ['已到场'])) { //没有预约可以直接确认到场
  1646. $this->activityState($param, $had);
  1647. }
  1648. }
  1649. if (in_array($param['state'], ['未到店', '未量房', '未到场'])) {
  1650. $state = str_replace('未', '', $param['state']);
  1651. $subscribe = CustomersSubscribe::where([['customer_id', '=', $had['id']], ['type', '=', array_search($state, $stateType)], ['state', '=', 0], ['employee_id', '=', $token['employee_id']]])->find();
  1652. if (!empty($subscribe)) {
  1653. $subscribe->state = -1;
  1654. $subscribe->save();
  1655. }
  1656. //取消预约后,待回访状态也要取消
  1657. $had->return_visit = 0;
  1658. $had->save();
  1659. }
  1660. //增加经纪人送积分功能
  1661. if ($had->agents_id && in_array($param['state'], ['已到店', '已交定', '已签单'])) {
  1662. $this->agents_integral($had->agents_id, $param['state'], $had->id);
  1663. }
  1664. // 微爆活动
  1665. if (in_array($param['state'], ['已到店', '已量房', '已到场', '已交定', '已签单'])) {
  1666. $activity_data['customer_id'] = $param['customer_id'];
  1667. $activity_data['employee_id'] = $had->employee_id;
  1668. $activity_data['org_id'] = $had->org_id;
  1669. switch ($param['state']) {
  1670. case '已到店':
  1671. $activity_data['type'] = 2;
  1672. break;
  1673. case '已量房':
  1674. $activity_data['type'] = 3;
  1675. break;
  1676. case '已交定':
  1677. $activity_data['type'] = 4;
  1678. break;
  1679. case '已签单':
  1680. $activity_data['type'] = 5;
  1681. break;
  1682. case '已到场':
  1683. $activity_data['type'] = 7;
  1684. break;
  1685. default:
  1686. break;
  1687. }
  1688. WechatActivityIntegral::addIntegral($activity_data, $token['root_org']);
  1689. }
  1690. Db::commit();
  1691. Console::call('download', ['customer']);
  1692. Console::call('download', ['customer1']);
  1693. //2022-10-28 更新交定/签单凭证
  1694. if (in_array($param['state'], ['已交定', '已签单'])) {
  1695. $deliveryType = $param['state'] == '已交定' ? 'delivery' : 'sign';
  1696. Console::call('download', [$deliveryType]);
  1697. }
  1698. Console::call('medal', ['visit_log', (string)$this->request->token['employee_id'], (string)$this->request->token['root_org']]); //勋章
  1699. //经理回访后修改客户的待回访的状态
  1700. Customer::where('id', $had->id)->update(['return_visit' => 0]);
  1701. $had['name'] = !empty($had['name']) ? $had['name'] : '';
  1702. if (in_array($param['state'], $dd_state)) {
  1703. // 发送管理层模板消息
  1704. $msg = ['first'=>'行为通知', 'keyword1'=>'客户确认到店', 'keyword2'=>"客户".$had['name']."(".$had['phone'].")确认到店", 'keyword3'=>date('Y/m/d'), 'remark'=>'请悉知'];
  1705. TmpMsg::sendMsgToLeader($msg, $token['org_id']);
  1706. }
  1707. if ($state == '已签单') {
  1708. // 发送管理层模板消息
  1709. $msg = ['first'=>'行为通知', 'keyword1'=>'客户签单', 'keyword2'=>"客户".$had['name']."(".$had['phone'].")签单", 'keyword3'=>date('Y/m/d'), 'remark'=>'请悉知'];
  1710. TmpMsg::sendMsgToLeader($msg, $token['org_id']);
  1711. }
  1712. return json(['code' => 0, 'msg' => '跟进成功']);
  1713. }
  1714. /**
  1715. * 经纪人送积分功能
  1716. */
  1717. public function agents_integral($agentid, $state, $customer_id)
  1718. {
  1719. $token = $this->request->token;
  1720. $agent_data = AgentUser::where('id', $agentid)->field('agent_name,type')->find();
  1721. if ($state == '已到店') {
  1722. $code = 'daodian_integral';
  1723. $sta_type = 1;
  1724. }
  1725. if ($state == '已交定') {
  1726. $code = 'jiaoding_integral';
  1727. $sta_type = 2;
  1728. }
  1729. if ($state == '已签单') {
  1730. $code = 'qiandan_integral';
  1731. $sta_type = 3;
  1732. }
  1733. //添加与经纪人相关记录
  1734. $you = AgentCustomerLog::where([['agent_id', '=', $agentid], ['type', '=', $sta_type], ['customer_id', '=', $customer_id]])->count();
  1735. if (empty($you)) {
  1736. $add = array(
  1737. 'agent_id' => $agentid,
  1738. 'type' => $sta_type,
  1739. 'typename' => $state,
  1740. 'addtime' => time(),
  1741. 'customer_id' => $customer_id,
  1742. 'agent_type' => $agent_data['type'],
  1743. 'status' => 1
  1744. );
  1745. AgentCustomerLog::insert($add);
  1746. }
  1747. if ($agent_data['type'] == 2) return; //如果是网红经纪人直接返回
  1748. $jifen = CreditsSetting::where(['code' => $code, 'root_id' => $token['root_org']])->value('value');
  1749. /*if($agent_data['type']==2){
  1750. $jifen=0;
  1751. }*/
  1752. $ye = AgentIntegral::where(['customer_id' => $customer_id, 'agent_id' => $agentid])->column('state');
  1753. //var_dump(!in_array($state,$ye));
  1754. //exit;
  1755. if (!in_array($state, $ye) && $agent_data['type'] == 1) {
  1756. $add = array(
  1757. 'agent_id' => $agentid,
  1758. 'type' => 1,
  1759. 'integral' => $jifen ? $jifen : 1,
  1760. 'addtime' => time(),
  1761. 'state' => $state,
  1762. 'customer_id' => $customer_id
  1763. );
  1764. //var_dump($add);
  1765. //exit;
  1766. AgentIntegral::insert($add);
  1767. }
  1768. if ($state == '已交定' && !in_array('已到店', $ye)) {
  1769. $jifen = CreditsSetting::where(['code' => 'daodian_integral', 'root_id' => $token['root_org']])->value('value');
  1770. $add = array(
  1771. 'agent_id' => $agentid,
  1772. 'type' => 1,
  1773. 'integral' => $jifen ? $jifen : 1,
  1774. 'addtime' => time(),
  1775. 'state' => '已到店',
  1776. 'customer_id' => $customer_id
  1777. );
  1778. AgentIntegral::insert($add);
  1779. }
  1780. if ($state == '已签单' && !in_array('已到店', $ye)) {
  1781. $jifen = CreditsSetting::where(['code' => 'daodian_integral', 'root_id' => $token['root_org']])->value('value');
  1782. $add = array(
  1783. 'agent_id' => $agentid,
  1784. 'type' => 1,
  1785. 'integral' => $jifen ? $jifen : 1,
  1786. 'addtime' => time(),
  1787. 'state' => '已到店',
  1788. 'customer_id' => $customer_id
  1789. );
  1790. AgentIntegral::insert($add);
  1791. }
  1792. if ($state == '已签单' && !in_array('已交定', $ye)) {
  1793. $jifen = CreditsSetting::where(['code' => 'jiaoding_integral', 'root_id' => $token['root_org']])->value('value');
  1794. $add = array(
  1795. 'agent_id' => $agentid,
  1796. 'type' => 1,
  1797. 'integral' => $jifen ? $jifen : 1,
  1798. 'addtime' => time(),
  1799. 'state' => '已交定',
  1800. 'customer_id' => $customer_id
  1801. );
  1802. AgentIntegral::insert($add);
  1803. }
  1804. }
  1805. //计算业绩任务
  1806. public function preformance_tasks($state, $customer_id, $money = 0, $vislog_id, $employee_id)
  1807. {
  1808. $token = $this->request->token;
  1809. $info = Customer::where('id', $customer_id)->find();
  1810. //业绩算客户所属员工的
  1811. $token['employee_id'] = Customer::where('id', $customer_id)->value('employee_id');
  1812. //防止后台切换部门
  1813. $token['org_id'] = Employee::where('id', $token['employee_id'])->value('org_id');
  1814. if ($state == '已交定') {
  1815. $w2[] = ['customer_id', '=', $customer_id];
  1816. $w2[] = ['state', 'in', CustomerVisitLog::changeState('已交定', 'chaos')];
  1817. $w2[] = ['customer_employee_id', '=', $token['employee_id']];
  1818. $w2[] = ['customer_org_id', '=', $token['org_id']];
  1819. //切换部门重复交定仍然算业绩
  1820. $check = CustomerVisitLog::where($w2)->count(); //没有交定过计算业绩
  1821. if ($check == 1) {
  1822. $time = date('Y-m-d H:i:s');
  1823. //查询进行中的指派到所属部门的所有进度
  1824. // $w[] = ['org_id','=',$token['org_id']];
  1825. $w[] = ['root_id', '=', $token['root_org']];
  1826. $w[] = ['start_date', '<=', $time];
  1827. $w[] = ['end_date', '>=', $time];
  1828. $w[] = ['is_deposit', '=', 1];
  1829. $preformance_tasks = PreformanceTasksModel::where($w)->column('id');
  1830. $w1[] = ['root_id', '=', $token['root_org']];
  1831. $w1[] = ['org_id', '=', $token['org_id']];
  1832. $w1[] = ['performance_tasks_id', 'in', $preformance_tasks];
  1833. $w1[] = ['is_deposit', '=', 1];
  1834. //指派到自己部门
  1835. $pid = PreformanceTasksOrg::where($w1)->group('performance_tasks_id')->column('*');
  1836. $w4[] = ['id', 'in', array_column($pid, 'performance_tasks_id')];
  1837. $model = PreformanceTasksModel::where($w4)->column('*');
  1838. foreach ($model as $k => $v) {
  1839. $u = [];
  1840. $u['ok_deposit'] = $v['ok_deposit'] + 1;
  1841. $u['customer_visit_log_id'] = $v['customer_visit_log_id'] ? $v['customer_visit_log_id'] . ',' . $vislog_id : $vislog_id;
  1842. PreformanceTasksModel::where('id', $v['id'])->update($u);
  1843. unset($u);
  1844. }
  1845. PreformanceTasksOrg::where($w1)->inc('ok_deposit')->update();
  1846. }
  1847. } elseif ($state == '已签单') {
  1848. $w2[] = ['customer_id', '=', $customer_id];
  1849. $w2[] = ['state', 'in', CustomerVisitLog::changeState('已签单', 'chaos')];
  1850. $w2[] = ['customer_employee_id', '=', $token['employee_id']];
  1851. $check = CustomerVisitLog::where($w2)->count(); //没有交定过计算业绩
  1852. if ($check == 1) {
  1853. $time = date('Y-m-d H:i:s');
  1854. //查询进行中的指派到所属部门的所有进度
  1855. // $w[] = ['org_id','=',$token['org_id']];
  1856. $w[] = ['root_id', '=', $token['root_org']];
  1857. $w[] = ['start_date', '<=', $time];
  1858. $w[] = ['end_date', '>=', $time];
  1859. $w[] = ['is_money', '=', 1];
  1860. $preformance_tasks = PreformanceTasksModel::where($w)->column('id');
  1861. $w1[] = ['root_id', '=', $token['root_org']];
  1862. $w1[] = ['org_id', '=', $token['org_id']];
  1863. $w1[] = ['performance_tasks_id', 'in', $preformance_tasks];
  1864. $w1[] = ['is_money', '=', 1];
  1865. //指派到自己部门
  1866. $pid = PreformanceTasksOrg::where($w1)->group('performance_tasks_id')->column('*');
  1867. $w4[] = ['id', 'in', array_column($pid, 'performance_tasks_id')];
  1868. $model = PreformanceTasksModel::where($w4)->column('*');
  1869. foreach ($model as $k => $v) {
  1870. $u = [];
  1871. $u['ok_money'] = $v['ok_money'] + $money;
  1872. $u['customer_visit_log_id'] = $v['customer_visit_log_id'] ? $v['customer_visit_log_id'] . ',' . $vislog_id : $vislog_id;
  1873. PreformanceTasksModel::where('id', $v['id'])->update($u);
  1874. unset($u);
  1875. }
  1876. PreformanceTasksOrg::where($w1)->inc('ok_money', $money)->update();
  1877. }
  1878. }
  1879. return 1;
  1880. }
  1881. /**
  1882. * 没有预约活动,跟进时传了aid和state='预约活动'
  1883. * 没有预约可以直接确认到场
  1884. * 补全数据添加预约和的追踪记录
  1885. */
  1886. public function activityState($param, $had)
  1887. {
  1888. $employeeTypeName = $this->request->token['org_type'] == 2 ? '设计师' : '销售';
  1889. // 备注
  1890. $employeeName = Employee::where(['id' => $this->request->token['employee_id']])->value('name');
  1891. $remark = $param['remark'];
  1892. if (empty($remark)) {
  1893. $remark = $employeeTypeName . $employeeName . '对客户进行了回访';
  1894. }
  1895. //预约记录
  1896. $visitLog = [
  1897. 'customer_id' => $had->id,
  1898. 'type' => $param['type'],
  1899. 'next_contact_date' => !empty($param['next_contact_date']) ? $param['next_contact_date'] : date('Y-m-d'),
  1900. 'employee_id' => $this->request->token['employee_id'],
  1901. 'user_id' => $this->request->token['uid'],
  1902. 'remark' => $remark,
  1903. 'state' => 6,
  1904. 'weixin_media' => '',
  1905. 'media_id' => '',
  1906. 'starts' => $param['starts'],
  1907. 'money' => $param['money'],
  1908. 'confirm_date' => $param['confirm_date'],
  1909. 'org_id' => $this->request->token['org_id'],
  1910. 'aid' => $param['aid'],
  1911. 'weixin_media1' => '',
  1912. 'media_id1' => '',
  1913. 'customer_employee_id' => $had->employee_id,
  1914. 'customer_org_id' => Employee::where('id', $had->employee_id)->value('org_id')
  1915. ];
  1916. CustomerVisitLog::create($visitLog);
  1917. //
  1918. $subscribe = [
  1919. 'customer_id' => $had['id'],
  1920. 'subscribe_date' => $param['confirm_date'],
  1921. 'employee_id' => $had->employee_id,
  1922. 'designer_id' => $had->designer_id,
  1923. 'type' => 2,
  1924. 'aid' => $param['aid'],
  1925. 'org_id' => $visitLog['customer_org_id'],
  1926. 'state' => 1
  1927. ];
  1928. CustomersSubscribe::create($subscribe);
  1929. return 1;
  1930. }
  1931. /**
  1932. * 死单客户列表
  1933. */
  1934. public function dieCustomer()
  1935. {
  1936. $where[] = ['org_id', 'in', $this->team_orgs];
  1937. $status = input('status', 1, 'intval');
  1938. if ($status == 1) { //待审核
  1939. $where[] = ['died', '=', 1];
  1940. } else {
  1941. $where[] = ['died', '=', 2];
  1942. }
  1943. $name = input('name', '', 'trim');
  1944. if ($name) {
  1945. $where[] = ['name', 'like', '%' . $name . '%'];
  1946. }
  1947. $page = input('page', 1, 'intval');
  1948. $limit = input('limit', 10, 'intval');
  1949. $list = Customer::where($where)->order('addtime desc')->page($page, $limit)->select()->toArray();
  1950. return json(['code' => 0, 'data' => $list]);
  1951. }
  1952. /**
  1953. * 审核死单客户
  1954. */
  1955. public function checkDieCustomer()
  1956. {
  1957. $customer_id = input('customer_id', '', 'intval');
  1958. $check = input('check', '', 'intval');
  1959. $find = Customer::where('id', '=', $customer_id)->findOrEmpty();
  1960. if ($find->isEmpty()) {
  1961. return json(['code' => 1, 'msg' => '审核失败']);
  1962. }
  1963. $sub_employee = Employee::where('org_id', 'in', $this->team_orgs)->column('id');
  1964. if (!in_array($find['employee_id'], $sub_employee)) {
  1965. return json(['code' => 1, 'msg' => '审核失败']);
  1966. }
  1967. if ($check) {
  1968. $employee = Employee::where('id', $find['employee_id'])->findOrEmpty();
  1969. Db::startTrans();
  1970. $result = Customer::where('id', '=', $customer_id)->save(['died' => 2]);
  1971. if ($result === false) {
  1972. Db::rollback();
  1973. return json(['code' => 1, 'msg' => '审核失败']);
  1974. }
  1975. $param = [
  1976. 'customer_id' => $customer_id,
  1977. 'type' => 1,
  1978. 'remark' => '死单',
  1979. 'employee_id' => $find['employee_id'],
  1980. 'user_id' => $employee['uid'],
  1981. 'state' => ''
  1982. ];
  1983. CustomerVisitLog::create($param);
  1984. $msg = '您申请的客户死单已通过。';
  1985. } else {
  1986. $result = Customer::where('id', '=', $customer_id)->save(['died' => 0]);
  1987. if ($result === false) {
  1988. Db::rollback();
  1989. return json(['code' => 1, 'msg' => '审核失败']);
  1990. }
  1991. $msg = '您申请的客户死单未通过。';
  1992. }
  1993. event(new Msg($find['employee_id'], $msg, 'customer', $customer_id));
  1994. Db::commit();
  1995. return json(['code' => 0, 'msg' => '操作成功']);
  1996. }
  1997. /**
  1998. * 重新激活死单客户
  1999. */
  2000. public function activeDieCustomer()
  2001. {
  2002. $customer_id = input('customer_id', '', 'intval');
  2003. $find = Customer::where('id', '=', $customer_id)->findOrEmpty();
  2004. if ($find->isEmpty()) {
  2005. return json(['code' => 1, 'msg' => '激活失败']);
  2006. }
  2007. $sub_employee = Employee::where('org_id', 'in', $this->team_orgs)->column('id');
  2008. if (!in_array($find['employee_id'], $sub_employee)) {
  2009. return json(['code' => 1, 'msg' => '激活失败']);
  2010. }
  2011. Db::startTrans();
  2012. $result = Customer::where('id', '=', $customer_id)->save(['died' => 0]);
  2013. if ($result === false) {
  2014. Db::rollback();
  2015. return json(['code' => 1, 'msg' => '激活失败']);
  2016. }
  2017. $param = [
  2018. 'customer_id' => $customer_id,
  2019. 'type' => 1,
  2020. 'remark' => '客户激活',
  2021. 'employee_id' => $this->request->token['employee_id'],
  2022. 'user_id' => $this->request->token['uid'],
  2023. 'state' => ''
  2024. ];
  2025. CustomerVisitLog::create($param);
  2026. event(new Msg($find['employee_id'], '您的死单客户已重新激活。', 'customer', $customer_id));
  2027. Db::commit();
  2028. return json(['code' => 0, 'msg' => '操作成功']);
  2029. }
  2030. /**
  2031. * 量房率,到店率,交定率,转单率
  2032. * 全部,团队,业务员
  2033. */
  2034. public function teamRate()
  2035. {
  2036. $token = $this->request->token;
  2037. $param = $this->request->only(['org_id' => 0, 'eid' => 0]);
  2038. if (!$param['org_id'] && !$param['eid']) {
  2039. $orgids = orgSubIds($token['root_org']);
  2040. $where = [
  2041. ['org_id', 'in', $orgids],
  2042. ['uid', '>', 0],
  2043. ['state', '=', '在职']
  2044. ];
  2045. } elseif ($param['eid']) {
  2046. $where = [
  2047. ['id', '=', $param['eid']],
  2048. ['root_id', '=', $token['root_org']],
  2049. ['uid', '>', 0],
  2050. ['state', '=', '在职']
  2051. ];
  2052. } elseif ($param['org_id']) {
  2053. $orgids = orgSubIds($param['org_id']);
  2054. $where = [
  2055. ['org_id', 'in', $orgids],
  2056. ['uid', '>', 0],
  2057. ['state', '=', '在职']
  2058. ];
  2059. }
  2060. $eids = Employee::where($where)->column('id');
  2061. $cid = Customer::where([['employee_id', 'in', $eids]])->column('id');
  2062. $state = CustomerVisitLog::changeState('已到店', 'chaos');
  2063. $state1 = CustomerVisitLog::changeState('已交定', 'chaos');
  2064. $state2 = CustomerVisitLog::changeState('已量房', 'chaos');
  2065. $state3 = CustomerVisitLog::changeState('已签单', 'chaos');
  2066. $query = [
  2067. ['customer_id', 'in', $cid],
  2068. ['state', 'in', array_merge($state, $state1, $state2, $state3)]
  2069. ];
  2070. $vis = CustomerVisitLog::where($query)->column('customer_id,state');
  2071. $data['store_grawth'] = $data['room_grawth'] = $data['dep_grawth'] = $data['sign_grawth'] = [];
  2072. foreach ($vis as $v) {
  2073. if (in_array($v['state'], $state)) {
  2074. $data['store_grawth'][] = $v['customer_id'];
  2075. } elseif (in_array($v['state'], $state1)) {
  2076. $data['dep_grawth'][] = $v['customer_id'];
  2077. } elseif (in_array($v['state'], $state2)) {
  2078. $data['room_grawth'][] = $v['customer_id'];
  2079. } elseif (in_array($v['state'], $state3)) {
  2080. $data['sign_grawth'][] = $v['customer_id'];
  2081. }
  2082. }
  2083. if ($cid) {
  2084. $count = count($cid);
  2085. $data['store_grawth'] = round(count(array_unique($data['store_grawth'])) / $count * 100, 2) . '%';
  2086. $data['dep_grawth'] = round(count(array_unique($data['dep_grawth'])) / $count * 100, 2) . '%';
  2087. $data['room_grawth'] = round(count(array_unique($data['room_grawth'])) / $count * 100, 2) . '%';
  2088. $data['sign_grawth'] = round(count(array_unique($data['sign_grawth'])) / $count * 100, 2) . '%';
  2089. } else {
  2090. $data['store_grawth'] = $data['room_grawth'] = $data['dep_grawth'] = $data['sign_grawth'] = '0%';
  2091. }
  2092. return json(['code' => 0, 'data' => $data, 'msg' => '获取成功']);
  2093. }
  2094. /**
  2095. * 全部,团队,业务员
  2096. */
  2097. public function teamStatistics()
  2098. {
  2099. $token = $this->request->token;
  2100. $param = $this->request->only(['org_id' => 0, 'page' => 1, 'limit' => 10, 'order' => '', 'sc' => 'desc']);
  2101. $root_id = $param['org_id']==-1 ? $token['root_org'] : ($param['org_id'] ?: $token['org_id']);
  2102. $info = Org::where([['id', '=', $root_id], ['status', '=', 1], ['path', 'like', $token['root_org'] . '-%']])->findOrEmpty();
  2103. if ($info->isEmpty()) return json(['code' => 0, 'data' => [], 'count' => 0, 'msg' => '获取成功']);
  2104. // 获取部门列表(全部子部门)
  2105. $childList = Org::where([['path', 'like', $info->path . '%'], ['id', '<>', $root_id]])->column('id,path');
  2106. // 子部门获取
  2107. $closetChildList = Org::where([['pid', '=', $info->id]])->column('name', 'id');
  2108. $childIdList = array_column($childList, 'id');
  2109. /** 数据获取 */
  2110. // 员工数量
  2111. $OrgEmployeeNum = Employee::where([['org_id', 'in', $childIdList], ['state', '=', '在职'], ['uid', '>', 0]])->group('org_id')->column('count(id) count', 'org_id');
  2112. // 客户数量
  2113. $orgCustomerNum = Customer::where([['employee_id', '>', 0], ['org_id', 'in', $childIdList]])->group('org_id')->column('count(id)', 'org_id');
  2114. //2023-03-07 有效状态修改
  2115. $state1 = Customer::changeState('待确认', 'chaos');
  2116. $state2 = Customer::changeState('无效', 'chaos');
  2117. $queryv1 = [['state', 'not in', array_merge($state1,$state2)],['employee_id', '>', 0],['org_id', 'in', $childIdList]];
  2118. $queryv2 = [['state', 'in',$state1],['crm_res_id','null',null],['employee_id', '>', 0],['org_id', 'in', $childIdList]];
  2119. $youxiaoNum = Customer::whereOr([$queryv1,$queryv2])->group('org_id')->column('count(id)', 'org_id');
  2120. // 有效
  2121. $state1 = CustomerVisitLog::changeState('未到访', 'chaos');
  2122. $state2 = CustomerVisitLog::changeState('已到访', 'chaos');
  2123. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  2124. $state4 = CustomerVisitLog::changeState('已到店', 'chaos');
  2125. $state5 = CustomerVisitLog::changeState('交定', 'chaos');
  2126. $state6 = CustomerVisitLog::changeState('签单', 'chaos');
  2127. $state7 = CustomerVisitLog::changeState('已到场', 'chaos');
  2128. $stateList = array_merge($state1, $state2, $state3, $state4, $state5, $state6, $state7);
  2129. // $stateStr = implode('|', $stateList);
  2130. // $youxiaoNum = CustomerState::where([
  2131. // ['employee_id', '>', 0],
  2132. // ['org_id', 'in', $childIdList],
  2133. // ['state', 'REGEXP', '(^|,)(' . $stateStr . ')(,|$)']
  2134. // ])->group('org_id')->column('count(id)', 'org_id');
  2135. // 加微
  2136. $wechatNum = Customer::where([
  2137. ['employee_id', '>', 0],
  2138. ['org_id', 'in', $childIdList],
  2139. ['ext', 'REGEXP', " 'value\": ?\"[0-9|\/|\-]+\", \"keyname\": \"add_wechat_time\"'"]
  2140. ])->group('org_id')->column('count(id)', 'org_id');
  2141. // 业绩
  2142. $yejiNum = Customer::where([
  2143. ['employee_id', '>', 0],
  2144. ['org_id', 'in', $childIdList]
  2145. ])->group('org_id')->column('sum(signed_money) money', 'org_id');
  2146. // 量房客户
  2147. $stateStr = implode('|', $state3);
  2148. $liangfangNum = CustomerState::where([
  2149. ['employee_id', '>', 0],
  2150. ['org_id', 'in', $childIdList],
  2151. ['state', 'REGEXP', '(^|,)(' . $stateStr . ')(,|$)']
  2152. ])->group('org_id')->column('count(id)', 'org_id');
  2153. // 到店
  2154. $stateStr = implode('|', $state4);
  2155. $daodianNum = CustomerState::where([
  2156. ['employee_id', '>', 0],
  2157. ['org_id', 'in', $childIdList],
  2158. ['state', 'REGEXP', '(^|,)(' . $stateStr . ')(,|$)']
  2159. ])->group('org_id')->column('count(id)', 'org_id');
  2160. // 到场
  2161. $stateStr = implode('|', $state7);
  2162. $daochangNum = CustomerState::where([
  2163. ['employee_id', '>', 0],
  2164. ['org_id', 'in', $childIdList],
  2165. ['state', 'REGEXP', '(^|,)(' . $stateStr . ')(,|$)']
  2166. ])->group('org_id')->column('count(id)', 'org_id');
  2167. // 交定
  2168. $stateStr = implode('|', $state5);
  2169. $jiaodingNum = CustomerState::where([
  2170. ['employee_id', '>', 0],
  2171. ['org_id', 'in', $childIdList],
  2172. ['state', 'REGEXP', '(^|,)(' . $stateStr . ')(,|$)']
  2173. ])->group('org_id')->column('count(id)', 'org_id');
  2174. // 签单
  2175. $stateStr = implode('|', $state6);
  2176. $signNum = CustomerState::where([
  2177. ['employee_id', '>', 0],
  2178. ['org_id', 'in', $childIdList],
  2179. ['state', 'REGEXP', '(^|,)(' . $stateStr . ')(,|$)']
  2180. ])->group('org_id')->column('count(id)', 'org_id');
  2181. // 预约到店/量房/到场
  2182. $yuyue1 = CustomersSubscribe::where([
  2183. ['org_id', 'in', $childIdList],
  2184. ['state', '=', 0],
  2185. ['type', '=', 1]
  2186. ])->group('org_id')->column('count(id)', 'org_id');
  2187. $yuyue2 = CustomersSubscribe::where([
  2188. ['org_id', 'in', $childIdList],
  2189. ['state', '=', 0],
  2190. ['type', '=', 2]
  2191. ])->group('org_id')->column('count(id)', 'org_id');
  2192. $yuyue3 = CustomersSubscribe::where([
  2193. ['org_id', 'in', $childIdList],
  2194. ['state', '=', 0],
  2195. ['type', '=', 3]
  2196. ])->group('org_id')->column('count(id)', 'org_id');
  2197. // 数量整合到部门中
  2198. $rdata = [];
  2199. $pidList= array_keys($closetChildList);
  2200. foreach ($childList as $cOrg) {
  2201. $pathList = explode('-', trim($cOrg['path'], '-'));
  2202. $pid = $cOrg['id'];
  2203. foreach($pathList as $p){
  2204. if(in_array($p, $pidList)) {
  2205. $pid = $p;
  2206. break;
  2207. }
  2208. }
  2209. if (!isset($rdata[$pid]))
  2210. $rdata[$pid] = [
  2211. 'employee_count' => 0,
  2212. 'customer_count' => 0,
  2213. 'valid_count' => 0,
  2214. 'wechat_count' => 0,
  2215. 'yeji' => 0,
  2216. 'lf_count' => 0,
  2217. 'st_count' => 0,
  2218. 'sign_count' => 0,
  2219. 'dc_count' => 0,
  2220. 'dep_count' => 0,
  2221. 'yydd_count' => 0,
  2222. 'yylf_count' => 0,
  2223. 'yywc_count' => 0,
  2224. 'name' => $closetChildList[$pid]
  2225. ];
  2226. // 员工数量
  2227. $rdata[$pid]['employee_count'] += isset($OrgEmployeeNum[$cOrg['id']]) ? $OrgEmployeeNum[$cOrg['id']] : 0;
  2228. // 客户数量
  2229. $rdata[$pid]['customer_count'] += isset($orgCustomerNum[$cOrg['id']]) ? $orgCustomerNum[$cOrg['id']] : 0;
  2230. // 有效
  2231. $rdata[$pid]['valid_count'] += isset($youxiaoNum[$cOrg['id']]) ? $youxiaoNum[$cOrg['id']] : 0;
  2232. // 加微
  2233. $rdata[$pid]['wechat_count'] += isset($wechatNum[$cOrg['id']]) ? $wechatNum[$cOrg['id']] : 0;
  2234. // 业绩
  2235. $rdata[$pid]['yeji'] += isset($yejiNum[$cOrg['id']]) ? $yejiNum[$cOrg['id']] : 0;
  2236. // 量房客户
  2237. $rdata[$pid]['lf_count'] += isset($liangfangNum[$cOrg['id']]) ? $liangfangNum[$cOrg['id']] : 0;
  2238. // 到店
  2239. $rdata[$pid]['st_count'] += isset($daodianNum[$cOrg['id']]) ? $daodianNum[$cOrg['id']] : 0;
  2240. // 到场
  2241. $rdata[$pid]['dc_count'] += isset($daochangNum[$cOrg['id']]) ? $daochangNum[$cOrg['id']] : 0;
  2242. // 交定
  2243. $rdata[$pid]['dep_count'] += isset($jiaodingNum[$cOrg['id']]) ? $jiaodingNum[$cOrg['id']] : 0;
  2244. // 签单
  2245. $rdata[$pid]['sign_count'] += isset($signNum[$cOrg['id']]) ? $signNum[$cOrg['id']] : 0;
  2246. //预约到店
  2247. $rdata[$pid]['yydd_count'] += isset($yuyue1[$cOrg['id']]) ? $yuyue1[$cOrg['id']] : 0;
  2248. //预约量房
  2249. $rdata[$pid]['yylf_count'] += isset($yuyue2[$cOrg['id']]) ? $yuyue2[$cOrg['id']] : 0;
  2250. //预约到外场
  2251. $rdata[$pid]['yywc_count'] += isset($yuyue3[$cOrg['id']]) ? $yuyue3[$cOrg['id']] : 0;
  2252. }
  2253. $list = $rdata;
  2254. //排序 业绩 加微 已量房 已到店 已交定 已签单
  2255. $arr = ['业绩'=>'yeji','加微'=>'wechat_count','已量房'=>'lf_count','已到店'=>'st_count','已交定'=>'dep_count','已签单'=>'sign_count'];
  2256. if ($param['order'] && isset($arr[$param['order']])) {
  2257. $field = $arr[$param['order']];
  2258. $sc = $param['sc'] == 'desc' ? SORT_DESC : SORT_ASC;
  2259. array_multisort(array_column($list,$field), $sc, $list);
  2260. }
  2261. $count = count($list);
  2262. $list = array_slice($list, ($param['page'] - 1) * $param['limit'], $param['limit']);
  2263. $data = [];
  2264. foreach ($list as $key => $value) {
  2265. $value['yeji'] = $value['yeji'] ? round($value['yeji']/10000,2).'万元' : 0;
  2266. $data[] = $value;
  2267. }
  2268. return json(['code' => 0, 'data' => $data, 'count' => $count, 'msg' => '获取成功']);
  2269. }
  2270. /**
  2271. * 部门直属人员统计
  2272. */
  2273. public function OrgEmployeeStatistics()
  2274. {
  2275. $token = $this->request->token;
  2276. $param = $this->request->only(['org_id' => 0, 'page' => 1, 'limit' => 10, 'order' => '', 'sc' => 'desc']);
  2277. $root_id = ($param['org_id']==-1) ? $token['root_org'] : ($param['org_id'] ?: $token['org_id']);
  2278. $info = Org::where([['id', '=', $root_id], ['status', '=', 1]])->findOrEmpty();
  2279. if ($info->isEmpty()) return json(['code' => 0, 'data' => [], 'count' => 0, 'msg' => '获取成功']);
  2280. //部门直属人员
  2281. if (empty($param['order']) || empty($param['sc'])) {
  2282. $list = Employee::where('org_id', $root_id)->where([['state', '=', '在职'], ['uid', '>', 0]])->page($param['page'], $param['limit'])->column('id,name,uid');
  2283. $count = Employee::where('org_id', $root_id)->where([['state', '=', '在职'], ['uid', '>', 0]])->count();
  2284. } else {
  2285. $list = Employee::where('org_id', $root_id)->where([['state', '=', '在职'], ['uid', '>', 0]])->column('id,name,uid');
  2286. $sc = $param['sc'] == 'desc' ? SORT_DESC : SORT_ASC;
  2287. //排序
  2288. $ids = array_column($list, 'id');
  2289. if ($param['order'] == '业绩') {
  2290. //业绩排序
  2291. $order = Customer::where([['employee_id', 'in', $ids], ['died', '<>', 2], ['state', 'not in', Customer::changeState('无效', 'chaos')]])->group('employee_id')->column('sum(signed_money) money', 'employee_id');
  2292. } elseif ($param['order'] == '加微') {
  2293. //加微数量排序
  2294. $order = Customer::where([['employee_id', 'in', $ids], ['ext', 'like', '%add_wechat_time%'], ['died', '<>', 2], ['state', 'not in', Customer::changeState('无效', 'chaos')]])->column('employee_id,ext');
  2295. $orders = [];
  2296. foreach ($order as $v) {
  2297. $json = json_decode($v['ext'], true);
  2298. foreach ($json as $v2) {
  2299. if ($v2['keyname'] == 'add_wechat_time' && !empty($v2['value'])) {
  2300. @$orders[$v['employee_id']] += 1;
  2301. }
  2302. }
  2303. }
  2304. $order = $orders;
  2305. } elseif (in_array($param['order'], ['已量房', '已到店', '已交定', '已签单'])) {
  2306. $cid = Customer::where([['employee_id', 'in', $ids], ['died', '<>', 2], ['state', 'not in', Customer::changeState('无效', 'chaos')]])->column('id,employee_id');
  2307. $cids = array_column($cid, 'id');
  2308. $state = CustomerVisitLog::changeState($param['order'], 'chaos');
  2309. $vislog = CustomerVisitLog::where([['state', 'in', $state], ['customer_id', 'in', $cids]])->group('customer_id')->column('customer_id');
  2310. $order = [];
  2311. foreach ($cid as $k => $v) {
  2312. if (in_array($v['id'], $vislog)) @$order[$v['employee_id']] += 1;
  2313. }
  2314. } else {
  2315. return json(['code' => 0, 'data' => [], 'count' => 0, 'msg' => '获取成功']);
  2316. }
  2317. foreach ($list as $k => $v) {
  2318. $list[$k]['order'] = isset($order[$v['id']]) ? $order[$v['id']] : 0;
  2319. $list[$k]['order_type'] = $param['order'];
  2320. }
  2321. //排序
  2322. array_multisort(array_column($list, 'order'), $sc, $list);
  2323. $count = count($list);
  2324. $list = array_slice($list, ($param['page'] - 1) * $param['limit'], $param['limit']);
  2325. }
  2326. ////////
  2327. $eids = array_column($list, 'id');
  2328. //业绩
  2329. if ($param['order'] == '业绩') {
  2330. $yeji = $order;
  2331. } else {
  2332. $yeji = Customer::where([['employee_id', 'in', $eids], ['died', '<>', 2], ['state', 'not in', Customer::changeState('无效', 'chaos')]])->group('employee_id')->column('sum(signed_money) money', 'employee_id');
  2333. }
  2334. //加微客户
  2335. if ($param['order'] == '加微') {
  2336. $wechat = $order;
  2337. } else {
  2338. $order = Customer::where([['employee_id', 'in', $eids], ['ext', 'like', '%add_wechat_time%'], ['died', '<>', 2], ['state', 'not in', Customer::changeState('无效', 'chaos')]])->column('employee_id,ext');
  2339. $orders = [];
  2340. foreach ($order as $v) {
  2341. $json = json_decode($v['ext'], true);
  2342. foreach ($json as $v2) {
  2343. if ($v2['keyname'] == 'add_wechat_time' && !empty($v2['value'])) {
  2344. @$orders[$v['employee_id']] += 1;
  2345. }
  2346. }
  2347. }
  2348. $wechat = $orders;
  2349. }
  2350. //有效 量房 到店 签单
  2351. // $customer_ids = Customer::where([['employee_id', 'in', $eids], ['died', '<>', 2], ['state', 'not in', Customer::changeState('无效', 'chaos')]])->column('employee_id,id');
  2352. // $org_cus = [];
  2353. // foreach ($customer_ids as $k3 => $v3) {
  2354. // @$org_cus[$v3['employee_id']][] = $v3['id'];
  2355. // }
  2356. //2023-03-07 有效状态修改
  2357. $state1 = Customer::changeState('待确认', 'chaos');
  2358. $state2 = Customer::changeState('无效', 'chaos');
  2359. $queryv1 = [['state', 'not in', array_merge($state1,$state2)],['employee_id', 'in', $eids], ['died', '<>', 2]];
  2360. $queryv2 = [['state', 'in',$state1],['crm_res_id','null',null],['employee_id', 'in', $eids], ['died', '<>', 2]];
  2361. $customer_ids = Customer::whereOr([$queryv1,$queryv2])->column('employee_id,id');
  2362. $org_cus = [];
  2363. foreach ($customer_ids as $k3 => $v3) {
  2364. @$org_cus[$v3['employee_id']][] = $v3['id'];
  2365. }
  2366. $valid = array_column($customer_ids,'id');
  2367. $state1 = CustomerVisitLog::changeState('未到访', 'chaos');
  2368. $state2 = CustomerVisitLog::changeState('已到访', 'chaos');
  2369. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  2370. $state4 = CustomerVisitLog::changeState('已到店', 'chaos');
  2371. $state5 = CustomerVisitLog::changeState('交定', 'chaos');
  2372. $state6 = CustomerVisitLog::changeState('签单', 'chaos');
  2373. $state7 = CustomerVisitLog::changeState('已到场', 'chaos');
  2374. $vis_where[] = ['customer_id', 'in', array_column($customer_ids, 'id')];
  2375. $vis_where[] = ['state', 'in', array_merge($state1, $state2, $state3, $state4, $state5, $state6, $state7)];
  2376. // $vis_where[] = ['employee_id', 'in', $eids];
  2377. $vislog_list = CustomerVisitLog::where($vis_where)->column('customer_id,state');
  2378. // $valid = array_column($vislog_list, 'customer_id');
  2379. //签单 量房 到店
  2380. $sign = $lf = $st = $dep = $dc = [];
  2381. foreach ($vislog_list as $v4) {
  2382. if (in_array($v4['state'], $state6)) {
  2383. $sign[] = $v4['customer_id'];
  2384. } elseif (in_array($v4['state'], $state3)) {
  2385. $lf[] = $v4['customer_id'];
  2386. } elseif (in_array($v4['state'], $state4)) {
  2387. $st[] = $v4['customer_id'];
  2388. } elseif (in_array($v4['state'], $state5)) {
  2389. $dep[] = $v4['customer_id'];
  2390. } elseif (in_array($v4['state'], $state7)) {
  2391. $dc[] = $v4['customer_id'];
  2392. }
  2393. }
  2394. $cids = [];
  2395. foreach ($list as $k5 => $v5) {
  2396. //客户id
  2397. $list[$k5]['cid'] = $cid = isset($org_cus[$v5['id']]) ? $org_cus[$v5['id']] : [];
  2398. // /客户数量
  2399. $list[$k5]['customer_count'] = count($cid);
  2400. //有效
  2401. $list[$k5]['valid_count'] = $cid ? count(array_unique(array_intersect($cid, $valid))) : 0;
  2402. //加微
  2403. $list[$k5]['wechat_count'] = isset($wechat[$v5['id']]) ? $wechat[$v5['id']] : 0;
  2404. //业绩
  2405. $list[$k5]['yeji'] = isset($yeji[$v5['id']]) ? round($yeji[$v5['id']] / 10000, 2) . '万元' : '';
  2406. //量房客户
  2407. $list[$k5]['lf_count'] = $cid ? count(array_unique(array_intersect($cid, $lf))) : 0;
  2408. //到店
  2409. $list[$k5]['st_count'] = $cid ? count(array_unique(array_intersect($cid, $st))) : 0;
  2410. //签单
  2411. $list[$k5]['sign_count'] = $cid ? count(array_unique(array_intersect($cid, $sign))) : 0;
  2412. //交定
  2413. $list[$k5]['dep_count'] = $cid ? count(array_unique(array_intersect($cid, $dep))) : 0;
  2414. //外场到场
  2415. $list[$k5]['dc_count'] = $cid ? count(array_unique(array_intersect($cid, $dc))) : 0;
  2416. $cids = array_merge($cid, $cids);
  2417. }
  2418. //预约
  2419. $sub = CustomersSubscribe::where([['customer_id', 'in', $cids], ['state', '=', 0], ['type', 'in', [1, 2, 3]]])->column('customer_id,type');
  2420. $sub1 = $sub2 = $sub3 = [];
  2421. foreach ($sub as $key => $val) {
  2422. $val['type'] == 1 ? $sub1[] = $val['customer_id'] : ($val['type'] == 3 ? $sub3[] = $val['customer_id'] : $sub2[] = $val['customer_id']);
  2423. }
  2424. $uids = array_column($list, 'uid');
  2425. $headerimgs = User::where([['id', 'in', $uids]])->column('headimgurl', 'id');
  2426. foreach ($list as $ke => $va) {
  2427. //预约到店
  2428. $list[$ke]['yydd_count'] = $va['cid'] ? count(array_unique(array_intersect($va['cid'], $sub1))) : 0;
  2429. //预约量房
  2430. $list[$ke]['yylf_count'] = $va['cid'] ? count(array_unique(array_intersect($va['cid'], $sub3))) : 0;
  2431. //预约到外场
  2432. $list[$ke]['yywc_count'] = $va['cid'] ? count(array_unique(array_intersect($va['cid'], $sub2))) : 0;
  2433. unset($list[$ke]['cid']);
  2434. $list[$ke]['img'] = $headerimgs[$va['uid']];
  2435. }
  2436. return json(['code' => 0, 'data' => $list, 'count' => $count, 'msg' => '获取成功']);
  2437. }
  2438. }