企微短剧业务系统

AccountDataTrendService.php 54KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. <?php
  2. namespace App\Service;
  3. use App\Log;
  4. use App\Models\AdqAccountTrendData;
  5. use App\Models\DjOrder;
  6. use App\Models\Es\AccountDataTrend;
  7. use App\Models\MpAccountTrendData;
  8. use App\Models\OfficialAccount;
  9. use App\Models\OfficialAccountRelation;
  10. use App\Models\OfficialWebUserActionSetId;
  11. use App\Models\TencentAdAuth;
  12. class AccountDataTrendService
  13. {
  14. /**
  15. * 获取账号数据趋势
  16. * */
  17. public static function getAdqAccountDataTrend($params, $sortField, $sortType, $page, $pageSize)
  18. {
  19. # 表头处理
  20. $commonHeader = config('accountDataHeader.basic');
  21. # 获取day1至day150表头
  22. $daysHeader = [];
  23. for($i = 0;$i < AdqAccountTrendData::ADQ_ACCOUNT_TREND_DAYS;$i++) {
  24. $title = [
  25. 'name' => 'DAY'.($i+1),
  26. 'column' => 'day'.($i+1),
  27. ];
  28. $daysHeader[] = $title;
  29. }
  30. $header = array_merge($commonHeader, $daysHeader);
  31. # 数据项处理
  32. if(isset($params['account_id']) && $params['account_id']) {
  33. list($list, $count) = AdqAccountTrendData::getAccountDataTrend($params, $sortField, $sortType, $page, $pageSize);
  34. } else {
  35. # 获取企业下的adq账号
  36. $accountList = OfficialWebUserActionSetId::select('account_id')->where('enable', 1)
  37. ->where('sys_group_id', $params['sys_group_id'])
  38. ->distinct()->pluck('account_id');
  39. if(empty($accountList)) return [[], 0, $header];
  40. list($list, $count) = AdqAccountTrendData::getAccountSummaryDataTrend(
  41. $params, $accountList, $sortField, $sortType, $page, $pageSize
  42. );
  43. }
  44. if(empty($list)) return [[], 0, $header];
  45. foreach ($list as $item) {
  46. # 消耗金额单位处理
  47. $item->paid = $item->paid / 100;
  48. # 企微关注成本
  49. $item->follow_cost = round($item->follow_cost / 100, 1);
  50. # 首日roi
  51. $item->first_roi = $item->first_roi * 100 . '%';
  52. # 总回本率
  53. $item->cost_cover_rate = $item->cost_cover_rate * 100 . '%';
  54. # 首日新增用户充值金额
  55. $item->pay_money = $item->pay_money / 100;
  56. # 用户累计充值金额
  57. $item->pay_money_total = $item->pay_money_total / 100;
  58. # 首日下单成本
  59. $item->first_charge_user_cost = round($item->first_charge_user_cost / 100, 2);
  60. # arpu
  61. $item->day_paid_user_arpu = round($item->day_paid_user_arpu / 100, 2);
  62. # 企微关注人数
  63. $item->scan_follow_count = intval($item->scan_follow_count);
  64. # 查询150天数据
  65. $dayInfo = [];
  66. if(isset($params['account_id']) && $params['account_id']) {
  67. $dayData = AdqAccountTrendData::where('enable', 1)
  68. ->where(function($query) use ($params) {
  69. if(isset($params['plat_order_type']) && is_numeric($params['plat_order_type']))
  70. $query->where('plat_order_type', $params['plat_order_type']);
  71. })
  72. ->where('account_id', $params['account_id'])
  73. ->where('expense_date', $item->expense_date)
  74. ->where('ref_date', '<=', date('Y-m-d', strtotime($item->expense_date.' +149 day')))
  75. ->selectRaw("sum(active_fans) as active_fans,sum(pay_money) as pay_money, sum(pay_money_total) as pay_money_total, ref_date")
  76. ->groupBy(['days_type'])
  77. ->get();
  78. if(!empty($dayData)){
  79. foreach($dayData as $val){
  80. $nd = (strtotime($val['ref_date']) - strtotime($item->expense_date)) / 86400;
  81. $new_roi = $item->paid ? round($val['pay_money'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  82. $total_roi = $item->paid ? round($val['pay_money_total'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  83. $income_times = $item->pay_money ? round($val['pay_money_total'] / 100 / $item->pay_money, 2) : 0;
  84. $dayInfo[$nd] = [
  85. 'days' => 'day' . ($nd+1),
  86. 'pay_money' => round($val['pay_money']/100, 2),
  87. 'new_roi' => $new_roi,
  88. 'total_roi' => $total_roi,
  89. 'income_times' => $income_times,
  90. 'charge_user' => $val['active_fans']
  91. ];
  92. }
  93. }
  94. } else {
  95. $dayData = AdqAccountTrendData::where('enable', 1)
  96. ->where(function($query) use ($params) {
  97. if(isset($params['plat_order_type']) && is_numeric($params['plat_order_type']))
  98. $query->where('plat_order_type', $params['plat_order_type']);
  99. })
  100. ->where('account_id', $item->account_id)
  101. ->where('expense_date', '>=', $item->expense_date)
  102. ->where('expense_date', '<=', $item->expense_date_end)
  103. ->where('ref_date', '<=', strtotime($item->expense_date_end.' +149 day'))
  104. ->selectRaw("sum(active_fans) as active_fans,sum(pay_money) as pay_money, sum(pay_money_total) as pay_money_total, ref_date, expense_date, plat_order_type")
  105. ->groupBy(['days_type'])
  106. ->get();
  107. $paidDataMid = [];
  108. $payMoneyTotal = 0;
  109. if(!empty($dayData)){
  110. foreach($dayData as $val){
  111. $nd = (strtotime($val['ref_date']) - strtotime($val['expense_date'])) / 86400;
  112. $payMoneyTotal += $val['pay_money'];
  113. if(isset($paidDataMid[$nd])) {
  114. $paidDataMid[$nd]['active_fans'] += $val['active_fans'];
  115. $paidDataMid[$nd]['pay_money'] += $val['pay_money'];
  116. // $paidDataMid[$nd]['pay_money_total'] += $val['pay_money_total'];
  117. $paidDataMid[$nd]['pay_money_total'] += $payMoneyTotal;
  118. } else {
  119. $paidDataMid[$nd]['active_fans'] = $val['active_fans'];
  120. $paidDataMid[$nd]['pay_money'] = $val['pay_money'];
  121. // $paidDataMid[$nd]['pay_money_total'] = $val['pay_money_total'];
  122. $paidDataMid[$nd]['pay_money_total'] = $payMoneyTotal;
  123. }
  124. }
  125. foreach ($paidDataMid as $i=>$v) {
  126. $new_roi = $item->paid ? round($v['pay_money'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  127. $total_roi = $item->paid ? round($v['pay_money_total'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  128. $income_times = $item->pay_money ? round($v['pay_money_total'] / 100 / $item->pay_money, 2) : 0;
  129. $dayInfo[$i] = [
  130. 'days' => 'day' . ($i+1),
  131. 'pay_money' => round($v['pay_money']/100, 2),
  132. 'new_roi' => $new_roi,
  133. 'total_roi' => $total_roi,
  134. 'income_times' => $income_times,
  135. 'charge_user' => $v['active_fans']
  136. ];
  137. }
  138. }
  139. }
  140. $item->day_info = $dayInfo;
  141. }
  142. return [$list, $count, $header];
  143. }
  144. /**
  145. * 获取MP账号数据趋势
  146. * */
  147. public static function getMpAccountDataTrend($params, $sortField, $sortType, $page, $pageSize)
  148. {
  149. # 表头处理
  150. $commonHeader = config('accountDataHeader.mp_basic');
  151. # 获取day1至day150表头
  152. $daysHeader = [];
  153. for($i = 0;$i < MpAccountTrendData::MP_ACCOUNT_TREND_DAYS;$i++) {
  154. $title = [
  155. 'name' => 'DAY'.($i+1),
  156. 'column' => 'day'.($i+1)
  157. ];
  158. $daysHeader[] = $title;
  159. }
  160. $header = array_merge($commonHeader, $daysHeader);
  161. # 数据项处理
  162. if(isset($params['app_id']) && $params['app_id']) {
  163. list($list, $count) = MpAccountTrendData::getAccountDataTrend($params, $sortField, $sortType, $page, $pageSize);
  164. } else {
  165. # 获取企业下的adq账号
  166. $accountList = OfficialAccountRelation::selectRaw('app_id')->where('enable', 1)
  167. ->where('sys_group_id', $params['sys_group_id'])
  168. ->distinct()->pluck('app_id');
  169. if(empty($accountList)) return [[], 0, $header];
  170. list($list, $count) = MpAccountTrendData::getAccountSummaryDataTrend(
  171. $params, $accountList, $sortField, $sortType, $page, $pageSize
  172. );
  173. }
  174. if(empty($list)) return [[], 0, $header];
  175. # 获取列表中的公众号appId信息
  176. $appIds = $list->pluck('app_id')->unique();
  177. $accountData = OfficialAccount::select('mp_app_id', 'mp_name')->whereIn('mp_app_id', $appIds)->get();
  178. foreach ($list as $item) {
  179. # 消耗金额单位处理
  180. $item->paid = $item->paid / 100;
  181. # 企微关注成本
  182. $item->follow_cost = round($item->follow_cost / 100, 1);
  183. # 首日roi
  184. $item->first_roi = $item->first_roi * 100 . '%';
  185. # 总回本率
  186. $item->cost_cover_rate = $item->cost_cover_rate * 100 . '%';
  187. # 首日新增用户充值金额
  188. $item->pay_money = $item->pay_money / 100;
  189. # 用户累计充值金额
  190. $item->pay_money_total = $item->pay_money_total / 100;
  191. # 首日下单成本
  192. $item->first_charge_user_cost = round($item->first_charge_user_cost / 100, 2);
  193. # arpu
  194. $item->day_paid_user_arpu = round($item->day_paid_user_arpu / 100, 2);
  195. # 企微关注人数
  196. $item->scan_follow_count = intval($item->scan_follow_count);
  197. # 公众号名称
  198. $accountInfo = $accountData->where('mp_app_id', $item->app_id)->first();
  199. $item->app_name = $accountInfo->mp_name ?? '-';
  200. # 查询150天数据
  201. $dayInfo = [];
  202. if(isset($params['app_id']) && $params['app_id']) {
  203. $dayData = MpAccountTrendData::where('enable', 1)
  204. ->where(function($query) use ($params) {
  205. if(isset($params['plat_order_type']) && is_numeric($params['plat_order_type']))
  206. $query->where('plat_order_type', $params['plat_order_type']);
  207. })
  208. ->where('app_id', $params['app_id'])
  209. ->where('expense_date', $item->expense_date)
  210. ->where('ref_date', '<=', date('Y-m-d', strtotime($item->expense_date.' +149 day')))
  211. ->selectRaw("sum(active_fans) as active_fans,sum(pay_money) as pay_money, sum(pay_money_total) as pay_money_total, ref_date")
  212. ->groupBy(['days_type'])
  213. ->get();
  214. if(!empty($dayData)){
  215. foreach($dayData as $val){
  216. $nd = (strtotime($val['ref_date']) - strtotime($item->expense_date)) / 86400;
  217. $new_roi = $item->paid ? round($val['pay_money'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  218. $total_roi = $item->paid ? round($val['pay_money_total'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  219. $income_times = $item->pay_money ? round($val['pay_money_total'] / 100 / $item->pay_money, 2) : 0;
  220. $dayInfo[$nd] = [
  221. 'days' => 'day' . ($nd+1),
  222. 'pay_money' => round($val['pay_money']/100, 2),
  223. 'new_roi' => $new_roi,
  224. 'total_roi' => $total_roi,
  225. 'income_times' => $income_times,
  226. 'charge_user' => $val['active_fans']
  227. ];
  228. }
  229. }
  230. } else {
  231. $dayData = MpAccountTrendData::where('enable', 1)
  232. ->where(function($query) use ($params) {
  233. if(isset($params['plat_order_type']) && is_numeric($params['plat_order_type']))
  234. $query->where('plat_order_type', $params['plat_order_type']);
  235. })
  236. ->where('app_id', $item->app_id)
  237. ->where('expense_date', '>=', $item->expense_date)
  238. ->where('expense_date', '<=', $item->expense_date_end)
  239. ->where('ref_date', '<=', date('Y-m-d', strtotime($item->expense_date_end.' +149 day')))
  240. ->selectRaw("sum(active_fans) as active_fans,sum(pay_money) as pay_money, sum(pay_money_total) as pay_money_total, ref_date, expense_date, plat_order_type")
  241. ->groupBy(['days_type'])
  242. ->get();
  243. $paidDataMid = [];
  244. $payMoneyTotal = 0;
  245. if(!empty($dayData)){
  246. foreach($dayData as $val){
  247. $nd = (strtotime($val['ref_date']) - strtotime($val['expense_date'])) / 86400;
  248. $payMoneyTotal += $val['pay_money'];
  249. if(isset($paidDataMid[$nd])) {
  250. $paidDataMid[$nd]['active_fans'] += $val['active_fans'];
  251. $paidDataMid[$nd]['pay_money'] += $val['pay_money'];
  252. $paidDataMid[$nd]['pay_money_total'] += $payMoneyTotal;
  253. } else {
  254. $paidDataMid[$nd]['active_fans'] = $val['active_fans'];
  255. $paidDataMid[$nd]['pay_money'] = $val['pay_money'];
  256. $paidDataMid[$nd]['pay_money_total'] = $payMoneyTotal;
  257. }
  258. }
  259. foreach ($paidDataMid as $i=>$v) {
  260. $new_roi = $item->paid ? round($v['pay_money'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  261. $total_roi = $item->paid ? round($v['pay_money_total'] / 100 / $item->paid, 4) * 100 . '%' : '0%';
  262. $income_times = $item->pay_money ? round($v['pay_money_total'] / 100 / $item->pay_money, 2) : 0;
  263. $dayInfo[$i] = [
  264. 'days' => 'day' . ($i+1),
  265. 'pay_money' => round($v['pay_money']/100, 2),
  266. 'new_roi' => $new_roi,
  267. 'total_roi' => $total_roi,
  268. 'income_times' => $income_times,
  269. 'charge_user' => $v['active_fans']
  270. ];
  271. }
  272. }
  273. }
  274. $item->day_info = $dayInfo;
  275. }
  276. return [$list, $count, $header];
  277. }
  278. /**
  279. * 获取ADQ账号总概数据
  280. * */
  281. public static function getAdqAccountDataSummary($params)
  282. {
  283. # 表头处理
  284. $header = config('accountDataHeader.summary');
  285. # 数据项处理
  286. if(isset($params['account_id']) && $params['account_id']) {
  287. $accountList = [$params['account_id']];
  288. } else {
  289. # 获取企业下的adq账号
  290. $accountList = OfficialWebUserActionSetId::select('account_id')->where('enable', 1)
  291. ->where('sys_group_id', $params['sys_group_id'])
  292. ->distinct()->pluck('account_id');
  293. if(empty($accountList)) return [[], $header];
  294. }
  295. $data = AdqAccountTrendData::getAccountDataCollect($params, $accountList);
  296. if(empty($data)) return [[], $header];
  297. # 获取累计回收金额
  298. $recycleData = AdqAccountTrendData::getCumulativeMoney($params, $accountList, true, [1, 3, 7, 15, 30]);
  299. # 3日消耗最早日期和最晚日期
  300. $threeDaysBegin = $recycleData->where('days_type', 3)->min('expense_date');
  301. $threeDaysEnd = $recycleData->where('days_type', 3)->max('expense_date');
  302. # 首日新增用户累计充值金额
  303. $threeDaysFirstPaid = $recycleData->where('expense_date', '>=', $threeDaysBegin)->where('expense_date', '<=', $threeDaysEnd)
  304. ->where('days_type', 1)
  305. ->sum('pay_money');
  306. # 3天累计回收金额
  307. $threeDaysMoney = $recycleData->where('days_type', 3)->sum('pay_money_total');
  308. $data->three_days_rate = $threeDaysFirstPaid ? round($threeDaysMoney / $threeDaysFirstPaid, 2) : "0";
  309. # 7日消耗最早日期和最晚日期
  310. $sevenDaysBegin = $recycleData->where('days_type', 7)->min('expense_date');
  311. $sevenDaysEnd = $recycleData->where('days_type', 7)->max('expense_date');
  312. # 首日新增用户累计充值金额
  313. $sevenDaysFirstPaid = $recycleData->where('expense_date', '>=', $sevenDaysBegin)->where('expense_date', '<=', $sevenDaysEnd)
  314. ->where('days_type', 1)
  315. ->sum('pay_money');
  316. # 7天累计回收金额
  317. $sevenDaysMoney = $recycleData->where('days_type', 7)->sum('pay_money_total');
  318. $data->seven_days_rate = $sevenDaysFirstPaid ? round($sevenDaysMoney / $sevenDaysFirstPaid, 2) : "0";
  319. # 15日消耗最早日期和最晚日期
  320. $fifteenDaysBegin = $recycleData->where('days_type', 15)->min('expense_date');
  321. $fifteenDaysEnd = $recycleData->where('days_type', 15)->max('expense_date');
  322. # 首日新增用户累计充值金额
  323. $fifteenDaysFirstPaid = $recycleData->where('expense_date', '>=', $fifteenDaysBegin)->where('expense_date', '<=', $fifteenDaysEnd)
  324. ->where('days_type', 1)
  325. ->sum('pay_money');
  326. # 15天累计回收金额
  327. $fifteenDaysMoney = $recycleData->where('days_type', 15)->sum('pay_money_total');
  328. $data->fifteen_days_rate = $fifteenDaysFirstPaid ? round($fifteenDaysMoney / $fifteenDaysFirstPaid, 2) : "0";
  329. # 30日消耗最早日期和最晚日期
  330. $thirtyDaysBegin = $recycleData->where('days_type', 30)->min('expense_date');
  331. $thirtyDaysEnd = $recycleData->where('days_type', 30)->max('expense_date');
  332. # 首日新增用户累计充值金额
  333. $thirtyDaysFirstPaid = $recycleData->where('expense_date', '>=', $thirtyDaysBegin)->where('expense_date', '<=', $thirtyDaysEnd)
  334. ->where('days_type', 1)
  335. ->sum('pay_money');
  336. # 30天累计回收金额
  337. $thirtyDaysMoney = $recycleData->where('days_type', 30)->sum('pay_money_total');
  338. $data->thirty_days_rate = $thirtyDaysFirstPaid ? round($thirtyDaysMoney / $thirtyDaysFirstPaid, 2) : "0";
  339. // # 3天累计回收金额
  340. // $threeDaysInfo = $recycleData->where('days_type', 3)->first();
  341. // $threeDaysMoney = $threeDaysInfo->pay_money_total ?? 0;
  342. // $data->three_days_rate = $data->pay_money ? round($threeDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  343. // # 获取7天累计回收金额
  344. // $sevenDaysInfo = $recycleData->where('days_type', 7)->first();
  345. // $sevenDaysMoney = $sevenDaysInfo->pay_money_total ?? 0;
  346. // $data->seven_days_rate = $data->pay_money ? round($sevenDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  347. // # 获取15天累计回收金额
  348. // $fifteenDaysInfo = $recycleData->where('days_type', 15)->first();
  349. // $fifteenDaysMoney = $fifteenDaysInfo->pay_money_total ?? 0;
  350. // $data->fifteen_days_rate = $data->pay_money ? round($fifteenDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  351. // # 获取30天累计回收金额
  352. // $thirtyDaysInfo = $recycleData->where('days_type', 30)->first();
  353. // $thirtyDaysMoney = $thirtyDaysInfo->pay_money_total ?? 0;
  354. // $data->thirty_days_rate = $data->pay_money ? round($thirtyDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  355. # 消耗金额单位处理
  356. $data->paid = $data->paid / 100;
  357. # 企微关注成本
  358. $data->follow_cost = round($data->follow_cost / 100, 1);
  359. # 首日roi
  360. $data->first_roi = $data->first_roi * 100 . '%';
  361. # 总回本率
  362. $data->cost_cover_rate = $data->cost_cover_rate * 100 . '%';
  363. # 首日新增用户充值金额
  364. $data->pay_money = $data->pay_money / 100;
  365. # 用户累计充值金额
  366. $data->pay_money_total = $data->pay_money_total / 100;
  367. # 首日下单成本
  368. $data->first_charge_user_cost = round($data->first_charge_user_cost / 100, 2);
  369. # arpu
  370. $data->day_paid_user_arpu = round($data->day_paid_user_arpu / 100, 2);
  371. # 企微关注人数
  372. $data->scan_follow_count = intval($data->scan_follow_count);
  373. return [$data, $header];
  374. }
  375. /**
  376. * 获取MP账号总概数据
  377. * */
  378. public static function getMpAccountDataSummary($params)
  379. {
  380. # 表头处理
  381. $header = config('accountDataHeader.summary');
  382. # 数据项处理
  383. if(isset($params['app_id']) && $params['app_id']) {
  384. $accountList = [$params['app_id']];
  385. } else {
  386. # 获取企业下的mp账号
  387. $accountList = OfficialAccountRelation::selectRaw('app_id')->where('enable', 1)
  388. ->where('sys_group_id', $params['sys_group_id'])
  389. ->distinct()->pluck('app_id');
  390. if(empty($accountList)) return [[], $header];
  391. }
  392. $data = MpAccountTrendData::getAccountDataCollect($params, $accountList);
  393. if(empty($data)) return [[], $header];
  394. # 获取累计回收金额
  395. $recycleData = MpAccountTrendData::getCumulativeMoney($params, $accountList, true, [1, 3, 7, 15, 30]);
  396. # 3日消耗最早日期和最晚日期
  397. $threeDaysBegin = $recycleData->where('days_type', 3)->min('expense_date');
  398. $threeDaysEnd = $recycleData->where('days_type', 3)->max('expense_date');
  399. # 首日新增用户累计充值金额
  400. $threeDaysFirstPaid = $recycleData->where('expense_date', '>=', $threeDaysBegin)->where('expense_date', '<=', $threeDaysEnd)
  401. ->where('days_type', 1)
  402. ->sum('pay_money');
  403. # 3天累计回收金额
  404. $threeDaysMoney = $recycleData->where('days_type', 3)->sum('pay_money_total');
  405. $data->three_days_rate = $threeDaysFirstPaid ? round($threeDaysMoney / $threeDaysFirstPaid, 2) : "0";
  406. # 7日消耗最早日期和最晚日期
  407. $sevenDaysBegin = $recycleData->where('days_type', 7)->min('expense_date');
  408. $sevenDaysEnd = $recycleData->where('days_type', 7)->max('expense_date');
  409. # 首日新增用户累计充值金额
  410. $sevenDaysFirstPaid = $recycleData->where('expense_date', '>=', $sevenDaysBegin)->where('expense_date', '<=', $sevenDaysEnd)
  411. ->where('days_type', 1)
  412. ->sum('pay_money');
  413. # 7天累计回收金额
  414. $sevenDaysMoney = $recycleData->where('days_type', 7)->sum('pay_money_total');
  415. $data->seven_days_rate = $sevenDaysFirstPaid ? round($sevenDaysMoney / $sevenDaysFirstPaid, 2) : "0";
  416. # 15日消耗最早日期和最晚日期
  417. $fifteenDaysBegin = $recycleData->where('days_type', 15)->min('expense_date');
  418. $fifteenDaysEnd = $recycleData->where('days_type', 15)->max('expense_date');
  419. # 首日新增用户累计充值金额
  420. $fifteenDaysFirstPaid = $recycleData->where('expense_date', '>=', $fifteenDaysBegin)->where('expense_date', '<=', $fifteenDaysEnd)
  421. ->where('days_type', 1)
  422. ->sum('pay_money');
  423. # 15天累计回收金额
  424. $fifteenDaysMoney = $recycleData->where('days_type', 15)->sum('pay_money_total');
  425. $data->fifteen_days_rate = $fifteenDaysFirstPaid ? round($fifteenDaysMoney / $fifteenDaysFirstPaid, 2) : "0";
  426. # 30日消耗最早日期和最晚日期
  427. $thirtyDaysBegin = $recycleData->where('days_type', 30)->min('expense_date');
  428. $thirtyDaysEnd = $recycleData->where('days_type', 30)->max('expense_date');
  429. # 首日新增用户累计充值金额
  430. $thirtyDaysFirstPaid = $recycleData->where('expense_date', '>=', $thirtyDaysBegin)->where('expense_date', '<=', $thirtyDaysEnd)
  431. ->where('days_type', 1)
  432. ->sum('pay_money');
  433. # 30天累计回收金额
  434. $thirtyDaysMoney = $recycleData->where('days_type', 30)->sum('pay_money_total');
  435. $data->thirty_days_rate = $thirtyDaysFirstPaid ? round($thirtyDaysMoney / $thirtyDaysFirstPaid, 2) : "0";
  436. // # 3天累计回收金额
  437. // $threeDaysInfo = $recycleData->where('days_type', 3)->first();
  438. // $threeDaysMoney = $threeDaysInfo->pay_money_total ?? 0;
  439. // $data->three_days_rate = $data->pay_money ? round($threeDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  440. // # 获取7天累计回收金额
  441. // $sevenDaysInfo = $recycleData->where('days_type', 7)->first();
  442. // $sevenDaysMoney = $sevenDaysInfo->pay_money_total ?? 0;
  443. // $data->seven_days_rate = $data->pay_money ? round($sevenDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  444. // # 获取15天累计回收金额
  445. // $fifteenDaysInfo = $recycleData->where('days_type', 15)->first();
  446. // $fifteenDaysMoney = $fifteenDaysInfo->pay_money_total ?? 0;
  447. // $data->fifteen_days_rate = $data->pay_money ? round($fifteenDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  448. // # 获取30天累计回收金额
  449. // $thirtyDaysInfo = $recycleData->where('days_type', 30)->first();
  450. // $thirtyDaysMoney = $thirtyDaysInfo->pay_money_total ?? 0;
  451. // $data->thirty_days_rate = $data->pay_money ? round($thirtyDaysMoney / $data->pay_money, 4) * 100 . "%" : "0%";
  452. # 消耗金额单位处理
  453. $data->paid = $data->paid / 100;
  454. # 企微关注成本
  455. $data->follow_cost = round($data->follow_cost / 100, 1);
  456. # 首日roi
  457. $data->first_roi = $data->first_roi * 100 . '%';
  458. # 总回本率
  459. $data->cost_cover_rate = $data->cost_cover_rate * 100 . '%';
  460. # 首日新增用户充值金额
  461. $data->pay_money = $data->pay_money / 100;
  462. # 用户累计充值金额
  463. $data->pay_money_total = $data->pay_money_total / 100;
  464. # 首日下单成本
  465. $data->first_charge_user_cost = round($data->first_charge_user_cost / 100, 2);
  466. # arpu
  467. $data->day_paid_user_arpu = round($data->day_paid_user_arpu / 100, 2);
  468. # 企微关注人数
  469. $data->scan_follow_count = intval($data->scan_follow_count);
  470. return [$data, $header];
  471. }
  472. /**
  473. * Adq账号数据汇总曲线
  474. * */
  475. public static function getAdqAccountDataCurve($params)
  476. {
  477. if(isset($params['account_id']) && $params['account_id']) {
  478. $accountList = [$params['account_id']];
  479. } else {
  480. # 获取企业下的adq账号
  481. $accountList = OfficialWebUserActionSetId::select('account_id')->where('enable', 1)
  482. ->where('sys_group_id', $params['sys_group_id'])
  483. ->distinct()->pluck('account_id');
  484. if(empty($accountList)) return [];
  485. }
  486. # Adq账号数据汇总曲线
  487. $data = AdqAccountTrendData::getAccountDataCurve($params, $accountList);
  488. # 获取累计回收金额
  489. $recycleData = AdqAccountTrendData::getCumulativeMoney($params, $accountList, true);
  490. if(empty($data)) return [];
  491. # 数据处理
  492. foreach($data as $item) {
  493. # 消耗金额
  494. $item->paid = $item->paid / 100;
  495. # 首日下单成本
  496. $item->first_charge_user_cost = round($item->first_charge_user_cost / 100, 2);
  497. # 当日付费用户arpu值
  498. $item->day_paid_user_arpu = round($item->day_paid_user_arpu / 100, 2);
  499. # 首日roi
  500. $item->first_roi = $item->first_roi * 100;
  501. # 3天累计回收金额
  502. $threeDaysInfo = $recycleData->where('days_type', 3)->where('expense_date', $item->expense_date)->first();
  503. $threeDaysMoney = $threeDaysInfo->pay_money_total ?? 0;
  504. $item->three_days_rate = $item->pay_money ? round($threeDaysMoney / $item->pay_money, 4) * 100 : 0;
  505. # 获取7天累计回收金额
  506. $sevenDaysInfo = $recycleData->where('days_type', 7)->where('expense_date', $item->expense_date)->first();
  507. $sevenDaysMoney = $sevenDaysInfo->pay_money_total ?? 0;
  508. $item->seven_days_rate = $item->pay_money ? round($sevenDaysMoney / $item->pay_money, 4) * 100 : 0;
  509. # 获取15天累计回收金额
  510. $fifteenDaysInfo = $recycleData->where('days_type', 15)->where('expense_date', $item->expense_date)->first();
  511. $fifteenDaysMoney = $fifteenDaysInfo->pay_money_total ?? 0;
  512. $item->fifteen_days_rate = $item->pay_money ? round($fifteenDaysMoney / $item->pay_money, 4) * 100 : 0;
  513. # 获取30天累计回收金额
  514. $thirtyDaysInfo = $recycleData->where('days_type', 30)->where('expense_date', $item->expense_date)->first();
  515. $thirtyDaysMoney = $thirtyDaysInfo->pay_money_total ?? 0;
  516. $item->thirty_days_rate = $item->pay_money ? round($thirtyDaysMoney / $item->pay_money, 4) * 100 : 0;
  517. # 首日新增用户充值金额
  518. $item->pay_money = $item->pay_money / 100;
  519. }
  520. return $data;
  521. }
  522. /**
  523. * mp账号数据汇总曲线
  524. * */
  525. public static function getMpAccountDataCurve($params)
  526. {
  527. if(isset($params['app_id']) && $params['app_id']) {
  528. $accountList = [$params['app_id']];
  529. } else {
  530. # 获取企业下的mp账号
  531. $accountList = OfficialAccountRelation::selectRaw('app_id')->where('enable', 1)
  532. ->where('sys_group_id', $params['sys_group_id'])
  533. ->distinct()->pluck('app_id');
  534. if(empty($accountList)) return [];
  535. }
  536. # mp账号数据汇总曲线
  537. $data = MpAccountTrendData::getAccountDataCurve($params, $accountList);
  538. # 获取累计回收金额
  539. $recycleData = MpAccountTrendData::getCumulativeMoney($params, $accountList, true);
  540. if(empty($data)) return [];
  541. # 数据处理
  542. foreach($data as $item) {
  543. # 消耗金额
  544. $item->paid = $item->paid / 100;
  545. # 首日下单成本
  546. $item->first_charge_user_cost = round($item->first_charge_user_cost / 100, 2);
  547. # 当日付费用户arpu值
  548. $item->day_paid_user_arpu = round($item->day_paid_user_arpu / 100, 2);
  549. # 首日roi
  550. $item->first_roi = $item->first_roi * 100;
  551. # 3天累计回收金额
  552. $threeDaysInfo = $recycleData->where('days_type', 3)->where('expense_date', $item->expense_date)->first();
  553. $threeDaysMoney = $threeDaysInfo->pay_money_total ?? 0;
  554. $item->three_days_rate = $item->pay_money ? round($threeDaysMoney / $item->pay_money, 4) * 100 : 0;
  555. # 获取7天累计回收金额
  556. $sevenDaysInfo = $recycleData->where('days_type', 7)->where('expense_date', $item->expense_date)->first();
  557. $sevenDaysMoney = $sevenDaysInfo->pay_money_total ?? 0;
  558. $item->seven_days_rate = $item->pay_money ? round($sevenDaysMoney / $item->pay_money, 4) * 100 : 0;
  559. # 获取15天累计回收金额
  560. $fifteenDaysInfo = $recycleData->where('days_type', 15)->where('expense_date', $item->expense_date)->first();
  561. $fifteenDaysMoney = $fifteenDaysInfo->pay_money_total ?? 0;
  562. $item->fifteen_days_rate = $item->pay_money ? round($fifteenDaysMoney / $item->pay_money, 4) * 100 : 0;
  563. # 获取30天累计回收金额
  564. $thirtyDaysInfo = $recycleData->where('days_type', 30)->where('expense_date', $item->expense_date)->first();
  565. $thirtyDaysMoney = $thirtyDaysInfo->pay_money_total ?? 0;
  566. $item->thirty_days_rate = $item->pay_money ? round($thirtyDaysMoney / $item->pay_money, 4) * 100 : 0;
  567. # 首日新增用户充值金额
  568. $item->pay_money = $item->pay_money / 100;
  569. }
  570. return $data;
  571. }
  572. /**
  573. * 获取账号数据趋势
  574. * */
  575. public static function getAccountDataTrend($params, $sortField, $sortType, $page, $pageSize)
  576. {
  577. $sortField = self::getSortField($sortField);
  578. # 表头处理
  579. $commonHeader = config('accountDataHeader.all');
  580. # 获取day1至day150表头
  581. $daysHeader = [];
  582. for($i = 0;$i < AccountDataTrend::ACCOUNT_TREND_DAYS;$i++) {
  583. $title = [
  584. 'name' => 'DAY'.($i+1),
  585. 'column' => 'day'.($i+1),
  586. ];
  587. $daysHeader[] = $title;
  588. }
  589. $header = array_merge($commonHeader, $daysHeader);
  590. # 获取当前登录账号可见的账号范围
  591. if($params['ad_type'] == 1) { // adq账号
  592. $authAccountList = PitcherService::adqAccountListForUser(
  593. $params['admin_id'], $params['sys_group_id'], $params['is_system_admin']
  594. );
  595. } elseif ($params['ad_type'] == 2) { // mp账号
  596. $authAccountList = OfficialAccount::getAccountMpAppIdList(
  597. $params['admin_id'], $params['sys_group_id'], $params['is_system_admin']
  598. );
  599. } else { // adq+mp
  600. $authAccountList = PitcherService::adAccountList('', $params['sys_group_id'], $params['admin_id'], $params['is_system_admin']);
  601. $authAccountList = array_column($authAccountList, 'account_id');
  602. }
  603. if(empty($authAccountList)) return [[], 0, $header];
  604. # 数据项处理
  605. if(isset($params['account_id']) && $params['account_id']) {
  606. $params['account_id'] = explode(',', $params['account_id']);
  607. foreach ($params['account_id'] as $index=>$accountId) {
  608. if(!in_array($accountId, $authAccountList)) unset($params['account_id'][$index]);
  609. }
  610. if(empty($params['account_id'])) return [[], 0, $header];
  611. list($list, $count) = AccountDataTrend::getAccountDataTrend($params, $sortField, $sortType, $page, $pageSize);
  612. } else {
  613. # 获取企业下的adq账号
  614. $adqAccountList = OfficialWebUserActionSetId::select('account_id')->where('enable', 1)
  615. ->where('sys_group_id', $params['sys_group_id'])
  616. ->whereIn('account_id', $authAccountList)
  617. ->distinct()->pluck('account_id')->toArray();
  618. # 获取企业下的mp账号
  619. $mpAccountList = OfficialAccountRelation::selectRaw('app_id')->where('enable', 1)
  620. ->where('sys_group_id', $params['sys_group_id'])
  621. ->whereIn('app_id', $authAccountList)
  622. ->distinct()->pluck('app_id')->toArray();
  623. $accountList = array_merge($adqAccountList, $mpAccountList);
  624. if(empty($accountList)) return [[], 0, $header];
  625. list($list, $count) = AccountDataTrend::getAccountSummaryDataTrend($params, $accountList, $sortField, $sortType, $page, $pageSize);
  626. }
  627. if(empty($list)) return [[], 0, $header];
  628. # 获取对应的mp账号信息
  629. $mpAccountData = TencentAdAuth::selectRaw('wechat_account_id, account_name')
  630. ->where('enable', 1)
  631. ->where('wechat_account_id', '>', '')
  632. ->get();
  633. foreach ($list as &$item) {
  634. # 账号名称处理
  635. if(is_array($item['account_id'])) {
  636. $accountCount = count($item['account_id']);
  637. if($accountCount == 1) {
  638. $item['account_id'] = $item['account_id'][0];
  639. $mpAccountInfo = $mpAccountData->where('wechat_account_id', $item['account_id'])->first();
  640. $item['account_name'] = $mpAccountInfo->account_name ?? $item['account_id'];
  641. } else {
  642. $accountNameStr = '';
  643. foreach ($item['account_id'] as $v) {
  644. $mpAccountInfo = $mpAccountData->where('wechat_account_id', $v)->first();
  645. $accountNameStr .= $mpAccountInfo->account_name ?? $v;
  646. $accountNameStr .= ',';
  647. }
  648. $item['account_name'] = trim($accountNameStr, ',');
  649. }
  650. } else {
  651. $mpAccountInfo = $mpAccountData->where('wechat_account_id', $item['account_id'])->first();
  652. $item['account_name'] = $mpAccountInfo->account_name ?? $item['account_id'];
  653. }
  654. # 消耗金额单位处理
  655. $item['paid'] = $item['paid'] / 100;
  656. # 企微关注成本
  657. $item['follow_cost'] = round($item['follow_cost'] / 100, 1);
  658. # 复粉率-不区分用户是否流失
  659. $item['repeat_user_rate'] = round($item['repeat_user_rate'], 4) * 100 . '%';
  660. # 复粉率-是否重复仅参考留存用户
  661. $item['repeat_user_no_loss_rate'] = round($item['repeat_user_no_loss_rate'], 4) * 100 . '%';
  662. # 首日roi
  663. $item['first_roi'] = round($item['first_roi'], 4) * 100 . '%';
  664. # 首日首充roi
  665. $item['first_pay_roi'] = round($item['first_pay_roi'], 4) * 100 . '%';
  666. # 总回本率
  667. $item['cost_cover_rate'] = round($item['cost_cover_rate'], 4) * 100 . '%';
  668. # 首日新增用户充值金额
  669. $item['pay_money'] = $item['pay_money'] / 100;
  670. # 用户累计充值金额
  671. $item['pay_money_total'] = $item['pay_money_total'] / 100;
  672. # 首日下单成本
  673. $item['first_charge_user_cost'] = round($item['first_charge_user_cost'] / 100, 2);
  674. # arpu
  675. $item['day_paid_user_arpu'] = round($item['day_paid_user_arpu'] / 100, 2);
  676. # 企微关注人数
  677. $item['scan_follow_count'] = intval($item['scan_follow_count']);
  678. # 企微加粉人数
  679. $item['followers_number'] = intval($item['followers_number']);
  680. # 复粉人数(不区分用户是否流失)
  681. $item['repeat_user'] = intval($item['repeat_user']);
  682. # 复粉人数(是否重复仅参考留存用户)
  683. $item['repeat_user_no_loss'] = intval($item['repeat_user_no_loss']);
  684. # 企微加粉成本
  685. $item['followers_cost'] = round($item['followers_cost'] / 100, 1);
  686. # 查询150天数据
  687. $dayInfo = [];
  688. if(isset($params['account_id']) && $params['account_id']) {
  689. # 查询该投放日期的后150天数据
  690. $dayData = AccountDataTrend::getDataAfterExpense($params, $item['expense_date']);
  691. if(!empty($dayData)){
  692. foreach($dayData as $val){
  693. $nd = (strtotime($val['ref_date']) - strtotime($item['expense_date'])) / 86400;
  694. $new_roi = $item['paid'] ? round($val['pay_money'] / 100 / $item['paid'], 4) * 100 . '%' : '0%';
  695. $total_roi = $item['paid'] ? round($val['pay_money_total'] / 100 / $item['paid'], 4) * 100 . '%' : '0%';
  696. $income_times = $item['pay_money'] ? round($val['pay_money_total'] / 100 / $item['pay_money'], 2) : 0;
  697. $dayInfo[$nd] = [
  698. 'days' => 'day' . ($nd+1),
  699. 'pay_money' => round($val['pay_money']/100, 2),
  700. 'new_roi' => $new_roi,
  701. 'total_roi' => $total_roi,
  702. 'income_times' => $income_times,
  703. 'charge_user' => $val['pay_user']
  704. ];
  705. }
  706. }
  707. } else {
  708. # 获取账号在指定时间范围内的投放效果数据趋势
  709. $dayData = AccountDataTrend::getDataAfterExpense(
  710. $params, $item['expense_date'], $item['expense_date_end'], $item['account_id']
  711. );
  712. $paidDataMid = [];
  713. $payMoneyTotal = 0;
  714. if(!empty($dayData)){
  715. foreach($dayData as $val){
  716. $nd = (strtotime($val['ref_date']) - strtotime($val['expense_date'])) / 86400;
  717. $payMoneyTotal += $val['pay_money'];
  718. if(isset($paidDataMid[$nd])) {
  719. $paidDataMid[$nd]['active_fans'] += $val['active_fans'];
  720. $paidDataMid[$nd]['pay_user'] += $val['pay_user'];
  721. $paidDataMid[$nd]['pay_money'] += $val['pay_money'];
  722. $paidDataMid[$nd]['pay_money_total'] += $payMoneyTotal;
  723. } else {
  724. $paidDataMid[$nd]['active_fans'] = $val['active_fans'];
  725. $paidDataMid[$nd]['pay_user'] = $val['pay_user'];
  726. $paidDataMid[$nd]['pay_money'] = $val['pay_money'];
  727. $paidDataMid[$nd]['pay_money_total'] = $payMoneyTotal;
  728. }
  729. }
  730. foreach ($paidDataMid as $i=>$v) {
  731. $new_roi = $item['paid'] ? round($v['pay_money'] / 100 / $item['paid'], 4) * 100 . '%' : '0%';
  732. $total_roi = $item['paid'] ? round($v['pay_money_total'] / 100 / $item['paid'], 4) * 100 . '%' : '0%';
  733. $income_times = $item['pay_money'] ? round($v['pay_money_total'] / 100 / $item['pay_money'], 2) : 0;
  734. $dayInfo[$i] = [
  735. 'days' => 'day' . ($i+1),
  736. 'pay_money' => round($v['pay_money']/100, 2),
  737. 'new_roi' => $new_roi,
  738. 'total_roi' => $total_roi,
  739. 'income_times' => $income_times,
  740. 'charge_user' => $v['pay_user']
  741. ];
  742. }
  743. }
  744. }
  745. $item['day_info'] = $dayInfo;
  746. }
  747. return [$list, $count, $header];
  748. }
  749. /**
  750. * 获取账号总概数据(ADQ+MP)
  751. * */
  752. public static function getAccountDataSummary($params)
  753. {
  754. # 表头处理
  755. $header = config('accountDataHeader.summary');
  756. # 获取当前登录账号可见的账号范围
  757. if($params['ad_type'] == 1) { // adq账号
  758. $authAccountList = PitcherService::adqAccountListForUser(
  759. $params['admin_id'], $params['sys_group_id'], $params['is_system_admin']
  760. );
  761. } elseif ($params['ad_type'] == 2) { // mp账号
  762. $authAccountList = OfficialAccount::getAccountMpAppIdList(
  763. $params['admin_id'], $params['sys_group_id'], $params['is_system_admin']
  764. );
  765. } else { // adq+mp
  766. $authAccountList = PitcherService::adAccountList('', $params['sys_group_id'], $params['admin_id'], $params['is_system_admin']);
  767. $authAccountList = array_column($authAccountList, 'account_id');
  768. }
  769. if(empty($authAccountList)) return [[], $header];
  770. # 数据项处理
  771. if(isset($params['account_id']) && $params['account_id']) {
  772. $accountList = explode(',', $params['account_id']);
  773. foreach ($accountList as $index=>$accountId) {
  774. if(!in_array($accountId, $authAccountList)) unset($accountList[$index]);
  775. }
  776. } else {
  777. # 获取企业下的adq账号
  778. $adqAccountList = OfficialWebUserActionSetId::select('account_id')->where('enable', 1)
  779. ->where('sys_group_id', $params['sys_group_id'])
  780. ->whereIn('account_id', $authAccountList)
  781. ->distinct()->pluck('account_id')->toArray();
  782. # 获取企业下的mp账号
  783. $mpAccountList = OfficialAccountRelation::selectRaw('app_id')->where('enable', 1)
  784. ->where('sys_group_id', $params['sys_group_id'])
  785. ->whereIn('app_id', $authAccountList)
  786. ->distinct()->pluck('app_id')->toArray();
  787. $accountList = array_merge($adqAccountList, $mpAccountList);
  788. }
  789. if(empty($accountList)) return [[], $header];
  790. $data = AccountDataTrend::getAccountDataCollect($params, $accountList);
  791. if(empty($data)) return [[], $header];
  792. # 获取累计回收金额
  793. // $recycleData = AdqAccountTrendData::getCumulativeMoney($params, $accountList, true, [1, 3, 7, 15, 30]);
  794. $recycleData = collect(AccountDataTrend::getCumulativeMoney($params, $accountList, [1, 3, 7, 15, 30]));
  795. # 3日消耗最早日期和最晚日期
  796. $threeDaysBegin = $recycleData->where('days_type', 3)->min('expense_date');
  797. $threeDaysEnd = $recycleData->where('days_type', 3)->max('expense_date');
  798. # 首日新增用户累计充值金额
  799. $threeDaysFirstPaid = $recycleData->where('expense_date', '>=', $threeDaysBegin)->where('expense_date', '<=', $threeDaysEnd)
  800. ->where('days_type', 1)
  801. ->sum('pay_money');
  802. # 3天累计回收金额
  803. $threeDaysMoney = $recycleData->where('days_type', 3)->sum('pay_money_total');
  804. $data['three_days_rate'] = $threeDaysFirstPaid ? round($threeDaysMoney / $threeDaysFirstPaid, 2) : "0";
  805. # 7日消耗最早日期和最晚日期
  806. $sevenDaysBegin = $recycleData->where('days_type', 7)->min('expense_date');
  807. $sevenDaysEnd = $recycleData->where('days_type', 7)->max('expense_date');
  808. # 首日新增用户累计充值金额
  809. $sevenDaysFirstPaid = $recycleData->where('expense_date', '>=', $sevenDaysBegin)->where('expense_date', '<=', $sevenDaysEnd)
  810. ->where('days_type', 1)
  811. ->sum('pay_money');
  812. # 7天累计回收金额
  813. $sevenDaysMoney = $recycleData->where('days_type', 7)->sum('pay_money_total');
  814. $data['seven_days_rate'] = $sevenDaysFirstPaid ? round($sevenDaysMoney / $sevenDaysFirstPaid, 2) : "0";
  815. # 15日消耗最早日期和最晚日期
  816. $fifteenDaysBegin = $recycleData->where('days_type', 15)->min('expense_date');
  817. $fifteenDaysEnd = $recycleData->where('days_type', 15)->max('expense_date');
  818. # 首日新增用户累计充值金额
  819. $fifteenDaysFirstPaid = $recycleData->where('expense_date', '>=', $fifteenDaysBegin)->where('expense_date', '<=', $fifteenDaysEnd)
  820. ->where('days_type', 1)
  821. ->sum('pay_money');
  822. # 15天累计回收金额
  823. $fifteenDaysMoney = $recycleData->where('days_type', 15)->sum('pay_money_total');
  824. $data['fifteen_days_rate'] = $fifteenDaysFirstPaid ? round($fifteenDaysMoney / $fifteenDaysFirstPaid, 2) : "0";
  825. # 30日消耗最早日期和最晚日期
  826. $thirtyDaysBegin = $recycleData->where('days_type', 30)->min('expense_date');
  827. $thirtyDaysEnd = $recycleData->where('days_type', 30)->max('expense_date');
  828. # 首日新增用户累计充值金额
  829. $thirtyDaysFirstPaid = $recycleData->where('expense_date', '>=', $thirtyDaysBegin)->where('expense_date', '<=', $thirtyDaysEnd)
  830. ->where('days_type', 1)
  831. ->sum('pay_money');
  832. # 30天累计回收金额
  833. $thirtyDaysMoney = $recycleData->where('days_type', 30)->sum('pay_money_total');
  834. $data['thirty_days_rate'] = $thirtyDaysFirstPaid ? round($thirtyDaysMoney / $thirtyDaysFirstPaid, 2) : "0";
  835. # 消耗金额单位处理
  836. $data['paid'] = $data['paid'] / 100;
  837. # 企微关注成本
  838. $data['follow_cost'] = round($data['follow_cost'] / 100, 1);
  839. # 首日roi
  840. $data['first_roi'] = round($data['first_roi'], 4) * 100 . '%';
  841. # 复粉率-不区分用户是否流失
  842. $data['repeat_user_rate'] = round($data['repeat_user_rate'], 4) * 100 . '%';
  843. # 复粉率-是否重复仅参考留存用户
  844. $data['repeat_user_no_loss_rate'] = round($data['repeat_user_no_loss_rate'], 4) * 100 . '%';
  845. # 总回本率
  846. $data['cost_cover_rate'] = round($data['cost_cover_rate'], 4) * 100 . '%';
  847. # 首日新增用户充值金额
  848. $data['pay_money'] = $data['pay_money'] / 100;
  849. # 用户累计充值金额
  850. $data['pay_money_total'] = $data['pay_money_total'] / 100;
  851. # 首日下单成本
  852. $data['first_charge_user_cost'] = round($data['first_charge_user_cost'] / 100, 2);
  853. # arpu
  854. $data['day_paid_user_arpu'] = round($data['day_paid_user_arpu'] / 100, 2);
  855. # 企微关注人数
  856. $data['scan_follow_count'] = intval($data['scan_follow_count']);
  857. # 企微加粉人数
  858. $data['followers_number'] = intval($data['followers_number']);
  859. # 企微加粉成本
  860. $data['followers_cost'] = round($data['followers_cost'] / 100, 1);
  861. # 复粉人数-不区分用户是否流失
  862. $data['repeat_user'] = intval($data['repeat_user']);
  863. # 复粉人数-是否重复仅参考留存用户
  864. $data['repeat_user_no_loss'] = intval($data['repeat_user_no_loss']);
  865. return [$data, $header];
  866. }
  867. /**
  868. * 账号数据汇总曲线(ADQ+MP)
  869. * */
  870. public static function getAccountDataCurve($params)
  871. {
  872. # 获取当前登录账号可见的账号范围
  873. if($params['ad_type'] == 1) { // adq账号
  874. $authAccountList = PitcherService::adqAccountListForUser(
  875. $params['admin_id'], $params['sys_group_id'], $params['is_system_admin']
  876. );
  877. } elseif ($params['ad_type'] == 2) { // mp账号
  878. $authAccountList = OfficialAccount::getAccountMpAppIdList(
  879. $params['admin_id'], $params['sys_group_id'], $params['is_system_admin']
  880. );
  881. } else { // adq+mp
  882. $authAccountList = PitcherService::adAccountList('', $params['sys_group_id'], $params['admin_id'], $params['is_system_admin']);
  883. $authAccountList = array_column($authAccountList, 'account_id');
  884. }
  885. if(empty($authAccountList)) return [];
  886. if(isset($params['account_id']) && $params['account_id']) {
  887. $accountList = explode(',', $params['account_id']);
  888. foreach ($accountList as $index=>$accountId) {
  889. if(!in_array($accountId, $authAccountList)) unset($accountList[$index]);
  890. }
  891. } else {
  892. # 获取企业下的adq账号
  893. $adqAccountList = OfficialWebUserActionSetId::select('account_id')->where('enable', 1)
  894. ->where('sys_group_id', $params['sys_group_id'])
  895. ->whereIn('account_id', $authAccountList)
  896. ->distinct()->pluck('account_id')->toArray();
  897. # 获取企业下的mp账号
  898. $mpAccountList = OfficialAccountRelation::selectRaw('app_id')->where('enable', 1)
  899. ->where('sys_group_id', $params['sys_group_id'])
  900. ->whereIn('app_id', $authAccountList)
  901. ->distinct()->pluck('app_id')->toArray();
  902. $accountList = array_merge($adqAccountList, $mpAccountList);
  903. }
  904. if(empty($accountList)) return [];
  905. # 账号数据汇总曲线
  906. $data = AccountDataTrend::getAccountDataCurve($params, $accountList);
  907. if(empty($data)) return [];
  908. # 获取累计回收金额
  909. $recycleData = collect(AccountDataTrend::getCumulativeMoney($params, $accountList));
  910. # 数据处理
  911. foreach($data as &$item) {
  912. # 消耗金额
  913. $item['paid'] = $item['paid'] / 100;
  914. # 首日下单成本
  915. $item['first_charge_user_cost'] = round($item['first_charge_user_cost'] / 100, 2);
  916. # 当日付费用户arpu值
  917. $item['day_paid_user_arpu'] = round($item['day_paid_user_arpu'] / 100, 2);
  918. # 首日roi
  919. $item['first_roi'] = round($item['first_roi'], 4) * 100;
  920. # 3天累计回收金额
  921. $threeDaysInfo = $recycleData->where('days_type', 3)->where('expense_date', $item['expense_date'])->first();
  922. $threeDaysMoney = $threeDaysInfo['pay_money_total'] ?? 0;
  923. $item['three_days_rate'] = $item['pay_money'] ? round($threeDaysMoney / $item['pay_money'], 4) * 100 : 0;
  924. # 获取7天累计回收金额
  925. $sevenDaysInfo = $recycleData->where('days_type', 7)->where('expense_date', $item['expense_date'])->first();
  926. $sevenDaysMoney = $sevenDaysInfo['pay_money_total'] ?? 0;
  927. $item['seven_days_rate'] = $item['pay_money'] ? round($sevenDaysMoney / $item['pay_money'], 4) * 100 : 0;
  928. # 获取15天累计回收金额
  929. $fifteenDaysInfo = $recycleData->where('days_type', 15)->where('expense_date', $item['expense_date'])->first();
  930. $fifteenDaysMoney = $fifteenDaysInfo['pay_money_total'] ?? 0;
  931. $item['fifteen_days_rate'] = $item['pay_money'] ? round($fifteenDaysMoney / $item['pay_money'], 4) * 100 : 0;
  932. # 获取30天累计回收金额
  933. $thirtyDaysInfo = $recycleData->where('days_type', 30)->where('expense_date', $item['expense_date'])->first();
  934. $thirtyDaysMoney = $thirtyDaysInfo['pay_money_total'] ?? 0;
  935. $item['thirty_days_rate'] = $item['pay_money'] ? round($thirtyDaysMoney / $item['pay_money'], 4) * 100 : 0;
  936. # 首日新增用户充值金额
  937. $item['pay_money'] = $item['pay_money'] / 100;
  938. unset($item['cost_cover_rate']);
  939. }
  940. return $data;
  941. }
  942. /**
  943. * 总表排序字段处理
  944. * */
  945. public static function getSortField($field)
  946. {
  947. $data = [
  948. 'expense_date' => '_key',
  949. 'paid' => 'day_paid_bucket > day_paid',
  950. 'scan_follow_count' => 'scan_follow_count_bucket > day_scan_follow_count',
  951. 'follow_cost' => 'follow_cost',
  952. 'first_roi' => 'first_roi',
  953. 'pay_money' => 'day_pay_money_bucket > day_pay_money',
  954. 'pay_money_total' => 'pay_money_total',
  955. 'pay_user' => 'day_pay_user_bucket > day_pay_user',
  956. 'pay_user_total' => 'pay_user_total',
  957. 'pay_count' => 'day_pay_count_bucket > day_pay_count',
  958. 'pay_count_total' => 'pay_count_total',
  959. 'first_charge_user_cost' => 'first_charge_user_cost',
  960. 'cost_cover_rate' => 'cost_cover_rate',
  961. 'day_paid_user_arpu' => 'day_paid_user_arpu'
  962. ];
  963. return isset($data[$field]) ? $data[$field] : 'day_paid_bucket > day_paid';
  964. }
  965. }