StatisticsLogic.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. <?php
  2. /**
  3. * StatisticsLogic.php UTF-8
  4. * 汇总数据
  5. *
  6. * @date : 2019/11/7 15:08
  7. *
  8. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  9. * @author : wuyonghong <wyh@huosdk.com>
  10. * @version : HUOUNION 8.5
  11. */
  12. namespace huo\logic\data;
  13. use huo\logic\agent\AgentLogic;
  14. use huo\logic\member\MemberLogic;
  15. use huo\model\common\CommonModel;
  16. use huo\model\game\GameModel;
  17. use huo\model\log\MemLoginLogModel;
  18. use huo\model\member\MemberModel;
  19. use huo\model\member\MemoauthModel;
  20. use huo\model\member\MgRoleModel;
  21. use huo\model\order\OrderModel;
  22. use huo\model\user\UserModel;
  23. use huolib\constant\CacheConst;
  24. use huolib\constant\CommonConst;
  25. use huolib\constant\OrderConst;
  26. use huolib\tool\StrUtils;
  27. use huolib\tool\Time;
  28. use think\Cache;
  29. class StatisticsLogic extends CommonModel {
  30. protected $cache_key_prefix = CacheConst::CACHE_STATISTICS_DATA_PREFIX;
  31. protected $expire_time = 1;
  32. /**
  33. * @param array $param
  34. *
  35. * @return array
  36. */
  37. protected function getWhere($param = []) {
  38. $_map = [];
  39. /* 时间搜索 */
  40. list($_start_time, $_end_time) = $this->getTime($param);
  41. $_map['create_time'] = ['between', [$_start_time, $_end_time]];
  42. if (!empty($param['agent_id'])) {
  43. if (is_array($param['agent_id'])) {
  44. if (in_array('in', $param['agent_id'])) {
  45. $_map['agent_id'] = $param['agent_id'];
  46. } else {
  47. $_map['agent_id'] = ['in', $param['agent_id']];
  48. }
  49. } else {
  50. $_map['agent_id'] = $param['agent_id'];
  51. }
  52. // 官方渠道筛选
  53. if ($param['agent_id'] == '-1') {
  54. $_map['agent_id'] = ['in', [0]];
  55. }
  56. }
  57. if (!empty($param['app_id'])) {
  58. if (is_array($param['app_id'])) {
  59. if (in_array('in', $param['app_id'])) {
  60. $_map['app_id'] = $param['app_id'];
  61. } else {
  62. $_map['app_id'] = ['in', $param['app_id']];
  63. }
  64. } else {
  65. $_map['app_id'] = $param['app_id'];
  66. }
  67. }
  68. return $_map;
  69. }
  70. public function getTime($param) {
  71. list($_start_time, $_end_time) = time::today();
  72. $_start_time = 0;
  73. if (!empty($param['start_time'])) {
  74. $_start_time = strtotime($param['start_time']);
  75. }
  76. if (!empty($param['end_time'])) {
  77. $_end_time = strtotime($param['end_time']) + CommonConst::CONST_DAY_SECONDS;
  78. }
  79. return [$_start_time, $_end_time];
  80. }
  81. public function getTodayData($where) {
  82. $where['start_time'] = $where['start_time'] = date('Y-m-d');
  83. $_data = $this->getStatisticsData($where);
  84. $_data['date'] = $where['start_time'];
  85. return $_data;
  86. }
  87. /**
  88. * 获取聚合今日数据
  89. *
  90. * @param $where
  91. *
  92. * @return array
  93. */
  94. public function getStatisticsData($where) {
  95. list($_start_time, $_end_time) = $this->getTime($where);
  96. $_map = $this->getWhere($where);
  97. $_data_by_login = $this->getDataByLoginData($_map, $_start_time, $_end_time);
  98. $_data_by_member = $this->getDataByMember($_map, $_start_time, $_end_time);
  99. $_data_by_order = $this->getDataByOrder($_map, $_start_time, $_end_time);
  100. $_data = array_merge($_data_by_login, $_data_by_member, $_data_by_order);
  101. if ($_data['user_cnt'] < $_data['reg_cnt']) {
  102. $_data['user_cnt'] = $_data['reg_cnt'];
  103. }
  104. if ($_data['ip_cnt'] < $_data['reg_ip_cnt']) {
  105. $_data['ip_cnt'] = $_data['reg_ip_cnt'];
  106. }
  107. if ($_data['device_cnt'] < $_data['reg_device_cnt']) {
  108. $_data['device_cnt'] = $_data['reg_device_cnt'];
  109. }
  110. /* 新增付费率 */
  111. if (isset($_data['reg_pay_cnt'])) {
  112. $_data['reg_pay_rate'] = StrUtils::getRate($_data['reg_pay_cnt'], $_data['reg_cnt']);
  113. /* 活跃付费率 */
  114. $_data['user_pay_rate'] = StrUtils::getRate($_data['pay_user_cnt'], $_data['user_cnt']);
  115. /* 新增ARPU */
  116. $_data['reg_arpu'] = StrUtils::getArpu($_data['reg_sum_money'], $_data['reg_cnt']);
  117. /* ARPU */
  118. $_data['arppu'] = StrUtils::getArpu($_data['sum_money'], $_data['pay_user_cnt']);
  119. /* ARPPU */
  120. $_data['arpu'] = StrUtils::getArpu($_data['sum_money'], $_data['user_cnt']);
  121. }
  122. if (!empty($where['app_id'])) {
  123. $_game_data = (new GameModel())->getInfoById($where['app_id']);
  124. $_data['game_name'] = get_val($_game_data, 'name', '');
  125. $_data['game_icon'] = get_val($_game_data, 'icon', '');
  126. $_data['classify'] = get_val($_game_data, 'classify', '');
  127. }
  128. if (!empty($where['agent_id'])) {
  129. $_agent_info = (new UserModel())->getInfoById($where['agent_id']);
  130. $_data['agent_name'] = get_val($_agent_info, 'user_login', '');
  131. $_data['agent_nickname'] = get_val($_agent_info, 'user_nicename', '');
  132. }
  133. $_data['cpa_cnt'] = 0; /* cpa有效用户 */
  134. $_role_map = [
  135. 'start_time' => $_start_time,
  136. 'end_time' => $_end_time,
  137. 'app_id' => get_val($where, 'app_id', 0),
  138. 'agent_id' => get_val($where, 'agent_id', 0)
  139. ];
  140. $_data['role_cnt'] = $this->getDayRole($_role_map); /* 创角数 */
  141. $_data['openid_cnt'] = $this->getOpenidCnt($_role_map); /* 第三方注册用户 */
  142. return $_data;
  143. }
  144. /**
  145. * 获取创角数
  146. *
  147. * @param $param
  148. *
  149. * @return int|string
  150. */
  151. public function getDayRole($param) {
  152. list($_start_time, $_end_time) = Time::today();
  153. $_start_time = get_val($param, 'start_time', $_start_time);
  154. $_end_time = get_val($param, 'end_time', $_end_time);
  155. $_role_model = new MgRoleModel();
  156. $_map = [
  157. 'mg_role_model.create_time' => ['between', [$_start_time, $_end_time]],
  158. ];
  159. $_app_id = get_val($param, 'app_id', 0);
  160. if (!empty($_app_id)) {
  161. $_map['mg_role_model.app_id'] = $_app_id;
  162. }
  163. $_agent_id = get_val($param, 'agent_id', 0);
  164. $_mem_ids = [];
  165. if (!empty($_agent_id)) {
  166. if (-1 == $_agent_id) {
  167. $_mem_ids = (new MemberLogic())->getIdsByAgentId(0);
  168. //$_map['mg.mem_id'] = ['in', $_mem_ids];
  169. } else {
  170. if (is_array($_agent_id)) {
  171. $_agent_mem_ids = (new MemberLogic())->getIdsByAgentId($_agent_id);
  172. } else {
  173. $_agent_ids = (new AgentLogic())->getAgentIds($_agent_id, true);
  174. $_agent_mem_ids = (new MemberLogic())->getIdsByAgentId(['in', $_agent_ids]);
  175. }
  176. $_mem_ids = $_agent_mem_ids;
  177. }
  178. if (empty($_mem_ids)) {
  179. return 0;
  180. }
  181. }
  182. if ($_start_time != strtotime(date('Y-m-d'))) {
  183. $_role_mem_ids = $_role_model->with('mg')->where($_map)->cache(CommonConst::CONST_MONTH_SECONDS)
  184. ->column('mem_id');
  185. } else {
  186. $_role_mem_ids = $_role_model->with('mg')->where($_map)->column('mem_id');
  187. }
  188. if (!empty($_mem_ids)) {
  189. $_role_mem_ids = array_intersect($_role_mem_ids, $_mem_ids);
  190. }
  191. return count($_role_mem_ids);
  192. }
  193. /**
  194. * 获取单条记录缓存key
  195. *
  196. * @param array $where 条件
  197. *
  198. * @return string
  199. */
  200. protected function getCacheKeyByLoginData($where) {
  201. return $this->cache_key_prefix.'ld_'.md5(json_encode($where));
  202. }
  203. /**
  204. * 获取单条记录缓存key
  205. *
  206. * @param array $where 条件
  207. *
  208. * @return string
  209. */
  210. protected function getCacheKeyByMember($where) {
  211. return $this->cache_key_prefix.'m_'.md5(json_encode($where));
  212. }
  213. /**
  214. * 获取单条记录缓存key
  215. *
  216. * @param array $where 条件
  217. *
  218. * @return string
  219. */
  220. protected function getCacheKeyByMemberRetain($where) {
  221. return $this->cache_key_prefix.'mr_'.md5(json_encode($where));
  222. }
  223. /**
  224. * 获取单条记录缓存key
  225. *
  226. * @param array $where 条件
  227. *
  228. * @return string
  229. */
  230. protected function getCacheKeyByOpenidCnt($where) {
  231. return $this->cache_key_prefix.'oc_'.md5(json_encode($where));
  232. }
  233. /**
  234. * 获取第三方注册数
  235. *
  236. * @param $param
  237. *
  238. * @return mixed
  239. */
  240. public function getOpenidCnt($param) {
  241. /* 缓存操作 */
  242. $_cache_key = $this->getCacheKeyByOpenidCnt($param);
  243. $_data = Cache::get($_cache_key);
  244. if (!empty($_data)) {
  245. return $_data;
  246. }
  247. list($_start_time, $_end_time) = Time::today();
  248. $_start_time = get_val($param, 'start_time', $_start_time);
  249. $_end_time = get_val($param, 'end_time', $_end_time);
  250. $_map = [
  251. 'ljmem.create_time' => ['between', [$_start_time, $_end_time]],
  252. ];
  253. $_app_id = get_val($param, 'app_id', 0);
  254. if (!empty($_app_id)) {
  255. $_map['app_id'] = $_app_id;
  256. }
  257. $_agent_id = get_val($param, 'agent_id', 0);
  258. if (!empty($_agent_id)) {
  259. if (-1 == $_agent_id) {
  260. $_map['agent_id'] = 0;
  261. } else {
  262. $_map['agent_id'] = $_agent_id;
  263. }
  264. }
  265. $_cnt = (new MemoauthModel())->with('ljmem')->where($_map)->count('DISTINCT mem_id');
  266. if (!empty($_cnt)) {
  267. Cache::set($_cache_key, $_cnt, $this->expire_time);
  268. }
  269. return $_cnt;
  270. }
  271. /**
  272. * 'user_cnt' 活跃玩家数量
  273. * 'ip_cnt' IP数量
  274. * 'device_cnt' 设备数量
  275. *
  276. * @param array $where
  277. *
  278. * @param string $start_time 开始时间
  279. * @param string $end_time 结束时间
  280. *
  281. * @return array
  282. */
  283. public function getDataByLoginData($where, $start_time, $end_time) {
  284. $_date = date('Y-m', $start_time);
  285. $_date_end = date('Y-m', $end_time);
  286. $_cache_where = $where;
  287. $_map = $where;
  288. /* 缓存操作 */
  289. $_cache_key = $this->getCacheKeyByLoginData($_cache_where);
  290. $_data = Cache::get($_cache_key);
  291. if (!empty($_data)) {
  292. return $_data;
  293. }
  294. $_field = [
  295. 'count(distinct(`mem_id`))' => 'user_cnt',
  296. 'count(distinct(`device_id`))' => 'device_cnt',
  297. 'count(distinct(`ip`))' => 'ip_cnt',
  298. ];
  299. $_model = new MemLoginLogModel();
  300. $_data = $_model->computeTable($_date)->field($_field)->where($_map)->find();
  301. if (is_object($_data)) {
  302. $_data = $_data->toArray();
  303. }
  304. if (empty($_data)) {
  305. $_data = [
  306. 'user_cnt' => 0,
  307. 'device_cnt' => 0,
  308. 'ip_cnt' => 0,
  309. ];
  310. }
  311. if ($_date_end != $_date) {
  312. $_data2 = $_model->computeTable($_date_end)->field($_field)->where($_map)->find();
  313. if (is_object($_data2)) {
  314. $_data2 = $_data2->toArray();
  315. }
  316. if (!empty($_data2)) {
  317. $_data['user_cnt'] += $_data2['user_cnt'];
  318. $_data['device_cnt'] += $_data2['device_cnt'];
  319. $_data['ip_cnt'] += $_data2['ip_cnt'];
  320. }
  321. }
  322. if (empty($_data)) {
  323. return [];
  324. }
  325. Cache::set($_cache_key, $_data, $this->expire_time);
  326. return $_data;
  327. }
  328. /**
  329. * 'history_user_cnt' 注册玩家数
  330. * 'reg_cnt' 注册玩家数
  331. * 'reg_device_cnt' 新增设备
  332. * 'reg_ip_cnt' 新增IP
  333. *
  334. * @param array $where 条件
  335. * @param string $start_time 开始时间
  336. * @param string $end_time 结束时间
  337. *
  338. * @return array
  339. */
  340. public function getDataByMember($where = [], $start_time = 0, $end_time = 0) {
  341. $_cache_where = $where;
  342. $_map = $where;
  343. /* 缓存操作 */
  344. $_cache_key = $this->getCacheKeyByMember($_cache_where);
  345. $_data = Cache::get($_cache_key);
  346. if (!empty($_data)) {
  347. return $_data;
  348. }
  349. $_model = (new MemberModel());
  350. $_field = [
  351. 'count(distinct(`id`))' => 'reg_cnt',
  352. 'count(distinct(`device_id`))' => 'reg_device_cnt',
  353. 'count(distinct(`reg_ip`))' => 'reg_ip_cnt',
  354. ];
  355. $_data = $_model->field($_field)->where($_map)->find();
  356. if (is_object($_data)) {
  357. $_data = $_data->toArray();
  358. }
  359. if (empty($_data)) {
  360. $_data = [
  361. 'reg_cnt' => 0,
  362. 'reg_device_cnt' => 0,
  363. 'reg_ip_cnt' => 0,
  364. ];
  365. }
  366. $_data['history_user_cnt'] = $_model->getRegisterCount(0, $end_time, $_map);
  367. Cache::set($_cache_key, $_data, $this->expire_time);
  368. return $_data;
  369. }
  370. /**
  371. * 通过订单获取今日数据
  372. * 'pay_user_cnt' 付费玩家数
  373. * 'order_cnt' 成功订单数
  374. * 'fail_order_cnt' 失败订单数
  375. * 'un_order_cnt' 待支付订单数
  376. * 'reg_order_cnt' 新增订单
  377. * 'reg_pay_cnt' 新增即付费人数
  378. * 'sum_money' 充值金额
  379. * 'sum_real_money' 充值流水
  380. * 'first_pay_cnt' 首次付费人数
  381. * 'first_pay_money' 首付金额
  382. * 'reg_sum_money' 新增即付总额
  383. * 'reg_real_sum_money' 自然流水金额
  384. *
  385. * @param array $where
  386. *
  387. * @param int $start_time 开始时间
  388. * @param int $end_time 结束时间
  389. *
  390. * @return array
  391. */
  392. public function getDataByOrder($where = [], $start_time = 0, $end_time = 0) {
  393. $_cache_where = $where;
  394. $_map = $where;
  395. /* 缓存操作 */
  396. $_cache_key = $this->getCacheKeyByMemberRetain($_cache_where);
  397. $_data = Cache::get($_cache_key);
  398. if (!empty($_data)) {
  399. return $_data;
  400. }
  401. $_model = (new OrderModel());
  402. $_map_order_cnt = $_map;
  403. $_map_pay_user_cnt = $_map;
  404. $_map_pay_user_cnt['status'] = OrderConst::PAY_STATUS_SUC;
  405. $_map_order_cnt['status'] = OrderConst::PAY_STATUS_SUC;
  406. $_map_fail_order_cnt['status'] = OrderConst::PAY_STATUS_FAIL;
  407. $_map_un_order_cnt['status'] = OrderConst::PAY_STATUS_NOT;
  408. $_data = [
  409. 'pay_user_cnt' => $_model->where($_map_pay_user_cnt)->count('distinct mem_id'),
  410. 'order_cnt' => $_model->where($_map_order_cnt)->count('id'),
  411. 'fail_order_cnt' => $_model->where($_map_fail_order_cnt)->count('id'),
  412. 'un_order_cnt' => $_model->where($_map_un_order_cnt)->count('id'),
  413. 'sum_money' => $_model->where($_map_order_cnt)->sum('amount'),
  414. 'sum_real_money' => $_model->where($_map_order_cnt)->sum('real_amount'),
  415. ];
  416. $_where_str = 'uo.`status` =2 and uo.create_time between '.$start_time.' AND '.$end_time
  417. .' and m.create_time between '.$start_time.' AND '.$end_time;
  418. if (!empty($_map['agent_id'])) {
  419. if (is_array($_map['agent_id'])) {
  420. $_where_str .= ' and uo.agent_id in ('.implode(',', $_map['agent_id'][1]).')';
  421. } else {
  422. $_where_str .= ' and uo.agent_id='.$_map['agent_id'];
  423. }
  424. }
  425. if (!empty($_map['app_id'])) {
  426. if (is_array($_map['app_id'])) {
  427. $_where_str .= ' and uo.app_id in ('.implode(',', $_map['app_id'][1]).')';
  428. } else {
  429. $_where_str .= ' and uo.app_id='.$_map['app_id'];
  430. }
  431. }
  432. $_sql
  433. = 'SELECT
  434. count(DISTINCT(uo.id)) AS reg_order_cnt,
  435. count(DISTINCT(uo.mem_id)) AS reg_pay_cnt,
  436. sum(uo.amount) AS reg_sum_money,
  437. sum(uo.real_amount) AS reg_real_sum_money
  438. FROM h_pay uo INNER JOIN h_member m ON m.id=uo.mem_id
  439. WHERE '.$_where_str;
  440. $_sql_data = db()->query($_sql);
  441. $_reg_data = $_sql_data[0];
  442. $_data = array_merge($_data, $_reg_data);
  443. if (empty($_data)) {
  444. $_data = [
  445. 'pay_user_cnt' => 0,
  446. 'order_cnt' => 0,
  447. 'fail_order_cnt' => 0,
  448. 'un_order_cnt' => 0,
  449. 'sum_money' => 0,
  450. 'sum_real_money' => 0,
  451. 'reg_order_cnt' => 0,
  452. 'reg_pay_cnt' => 0,
  453. 'reg_sum_money' => 0,
  454. 'reg_real_sum_money' => 0
  455. ];
  456. }
  457. if (empty($_data['reg_sum_money'])) {
  458. $_data['reg_sum_money'] = 0;
  459. }
  460. Cache::set($_cache_key, $_data, $this->expire_time);
  461. return $_data;
  462. }
  463. }