MemberCluster.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace app\model\member;
  11. use app\model\BaseModel;
  12. use addon\coupon\model\Coupon;
  13. use app\model\system\Cron;
  14. /**
  15. * 会员群体
  16. */
  17. class MemberCluster extends BaseModel
  18. {
  19. public $basic = [
  20. 'member_level' => '会员等级',
  21. 'member_label' => '会员标签',
  22. 'sex' => '性别',
  23. 'birthday' => '生日',
  24. 'reg_time' => '注册时间',
  25. 'point' => '当前积分',
  26. 'balance' => '当前余额',
  27. 'growth' => '当前成长值',
  28. 'sign_days_series' => '连续签到次数',
  29. 'mobile' => '会员手机',
  30. ];
  31. public $consume = [
  32. 'order_money' => '付款金额',
  33. 'order_complete_money' => '消费金额',
  34. 'order_num' => '付款次数',
  35. 'order_complete_num' => '消费次数',
  36. 'recharge_total' => '累计充值',
  37. 'recharge_time' => '充值次数',
  38. ];
  39. public $promotion = [
  40. 'coupon_num' => '优惠券数',
  41. ];
  42. /**
  43. * 查询规则
  44. */
  45. public $rule = [
  46. 'member_level' => ['field' => "member_level",'query_method' => "FIND_IN_SET", "table" => "member"],
  47. 'member_label' => ['field' => "member_label",'query_method' => "FIND_IN_SET", "table" => "member"],
  48. 'sex' => ['field' => "sex",'query_method' => "in", "table" => "member"],
  49. 'birthday' => ['field' => "birthday",'query_method' => "between time", "table" => "member"],
  50. 'reg_time' => ['field' => "reg_time",'query_method' => "between time", "table" => "member"],
  51. 'point' => ['field' => "point",'query_method' => "between", "table" => "member"],
  52. 'balance' => ['field' => "balance",'query_method' => "between", "table" => "member"],
  53. 'growth' => ['field' => "growth",'query_method' => "between", "table" => "member"],
  54. 'sign_days_series' => ['field' => "sign_days_series",'query_method' => "between", "table" => "member"],
  55. 'mobile' => ['field' => "mobile",'query_method' => "like", "table" => "member"],
  56. 'order_money' => ['field' => "order_money",'query_method' => "between", "table" => "member"],
  57. 'order_complete_money' => ['field' => "order_complete_money",'query_method' => "between", "table" => "member"],
  58. 'order_num' => ['field' => "order_num",'query_method' => "between", "table" => "member"],
  59. 'order_complete_num' => ['field' => "order_complete_num",'query_method' => "between", "table" => "member"],
  60. 'recharge_total' => ['field' => "recharge_total",'query_method' => "between", "table" => "member_recharge_order"],
  61. 'recharge_time' => ['field' => "recharge_time",'query_method' => "between", "table" => "member_recharge_order"],
  62. 'coupon_num' => ['field' => "coupon_num",'query_method' => "between", "table" => "promotion_coupon"]
  63. ];
  64. /**
  65. * 添加会员群体
  66. * @param $data
  67. * @return array
  68. */
  69. public function addMemberCluster($data)
  70. {
  71. //重新计算符合会员群体的会员
  72. $calculate_data = $this->calculate($data);
  73. $data['member_num'] = $calculate_data['data']['member_num'];
  74. $data['member_ids'] = $calculate_data['data']['member_ids'];
  75. $res = model('member_cluster')->add($data);
  76. return $this->success($res);
  77. }
  78. /**
  79. * 编辑会员群体
  80. * @param $data
  81. * @param $condition
  82. * @return array
  83. */
  84. public function editMemberCluster($data, $condition)
  85. {
  86. //重新计算符合会员群体的会员
  87. $calculate_data = $this->calculate($data);
  88. $data['member_num'] = $calculate_data['data']['member_num'];
  89. $data['member_ids'] = $calculate_data['data']['member_ids'];
  90. $res = model('member_cluster')->update($data, $condition);
  91. return $this->success($res);
  92. }
  93. /**
  94. * 删除会员群体
  95. * @param $condition
  96. * @return array
  97. */
  98. public function deleteMemberCluster($condition)
  99. {
  100. $res = model('member_cluster')->delete($condition);
  101. return $this->success($res);
  102. }
  103. /**
  104. * 会员群体信息
  105. * @param array $condition
  106. * @param string $field
  107. * @return array
  108. */
  109. public function getMemberClusterInfo($condition = [], $field = '*')
  110. {
  111. $info = model('member_cluster')->getInfo($condition, $field);
  112. return $this->success($info);
  113. }
  114. /**
  115. * 会员群体详情
  116. * @param array $condition
  117. * @param string $field
  118. * @return array
  119. */
  120. public function getMemberClusterDetail($condition = [], $field = '*')
  121. {
  122. $info = model('member_cluster')->getInfo($condition, $field);
  123. $info['rule_arr'] = json_decode($info['rule_json'],true);
  124. //获取标签
  125. $member_label_content = $info['rule_arr']['basic']['member_label']['content'];
  126. $info['rule_arr']['basic']['member_label']['content_name'] = '';
  127. if(!empty($member_label_content)){
  128. $member_label_list = model('member_label')->getColumn([ ["label_id", "in", $member_label_content] ],'label_name');
  129. $info['rule_arr']['basic']['member_label']['content_name'] = implode(",",$member_label_list);
  130. }
  131. //获取等级
  132. $member_level_content = $info['rule_arr']['basic']['member_level']['content'];
  133. $info['rule_arr']['basic']['member_level']['content_name'] = '';
  134. if(!empty($member_level_content)) {
  135. $member_level_list = model('member_level')->getColumn([ ["level_id", "in", $member_level_content] ],'level_name');
  136. $info['rule_arr']['basic']['member_level']['content_name'] = implode(",", $member_level_list);
  137. }
  138. //获取性别
  139. $member_sex_content = $info['rule_arr']['basic']['sex']['content'];
  140. $info['rule_arr']['basic']['sex']['content_arr'] = [];
  141. if(!empty($member_sex_content)) {
  142. $info['rule_arr']['basic']['sex']['content_arr'] = explode(",", $member_sex_content);
  143. }
  144. return $this->success($info);
  145. }
  146. /**
  147. * 会员群体列表
  148. * @param array $condition
  149. * @param string $field
  150. * @param string $order
  151. * @param null $limit
  152. * @return array
  153. */
  154. public function getMemberClusterList($condition = [], $field = '*', $order = 'cluster_id asc', $limit = null)
  155. {
  156. $list = model('member_cluster')->getList($condition, $field, $order, '', '', '', $limit);
  157. return $this->success($list);
  158. }
  159. /**
  160. * 会员群体分页列表
  161. * @param array $condition
  162. * @param int $page
  163. * @param int $page_size
  164. * @param string $order
  165. * @param string $field
  166. * @return array
  167. */
  168. public function getMemberClusterPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'cluster_id asc', $field = '*')
  169. {
  170. $list = model('member_cluster')->pageList($condition, $field, $order, $page, $page_size);
  171. return $this->success($list);
  172. }
  173. /**
  174. * 计算人数
  175. * @param $data
  176. * @return array
  177. */
  178. public function calculate($data)
  179. {
  180. //根据规则获得条件
  181. $condition = $this->handleRule($data['rule_json']);
  182. $condition[] = ["site_id",'=',$data['site_id']];
  183. //只查询正常用户
  184. $condition[] = ['is_delete', '=', 0];
  185. $member_arr = model('member')->getColumn($condition,'member_id');
  186. $member_ids = implode(',',$member_arr);
  187. $member_num = model('member')->getCount($condition);
  188. return $this->success(["member_num" => $member_num, "member_ids" => $member_ids]);
  189. }
  190. /**
  191. * 处理规则条件
  192. * @param $rule_json
  193. * @return array
  194. */
  195. public function handleRule($rule_json)
  196. {
  197. $rule_arr = json_decode($rule_json,true);
  198. $all_field = array_merge($this->basic,$this->consume,$this->promotion);
  199. $condition = [];
  200. foreach ($rule_arr as $key => $value){
  201. //获取键
  202. $keys = array_keys($value);
  203. foreach ($keys as $key) {
  204. if (array_key_exists($key, $all_field)) {
  205. $values = $value[$key];
  206. $query_method = $this->rule[$key]['query_method'];
  207. $start = isset($values['start']) ? $values['start'] : '';
  208. $end = isset($values['end']) ? $values['end'] : '';
  209. $content = isset($values['content']) ? $values['content'] : '';
  210. $include = $values['include'] == 2 ? "not " : "";
  211. $is_show = $values['is_show'];
  212. if($is_show == 1){
  213. switch ($query_method) {
  214. case "between":
  215. $condition[] = [$key, $include.'between', [$start,$end]];
  216. break;
  217. case "between time":
  218. if($values['include'] == 1){
  219. //注册时间
  220. if ($start != '' && $end != '') {
  221. $condition[] = [ $key, 'between', [ strtotime($start), strtotime($end) ] ];
  222. } else if ($start != '' && $end == '') {
  223. $condition[] = [ $key, '>=', strtotime($start) ];
  224. } else if ($start == '' && $end != '') {
  225. $condition[] = [ $key, '<=', strtotime($end) ];
  226. }
  227. }else if($values['include'] == 2){
  228. //注册时间
  229. if ($start != '' && $end != '') {
  230. $condition[] = [ $key, $include.'between', [ strtotime($start), strtotime($end) ] ];
  231. } else if ($start != '' && $end == '') {
  232. $condition[] = [ $key, '<', strtotime($start) ];
  233. } else if ($start == '' && $end != '') {
  234. $condition[] = [ $key, '>', strtotime($end) ];
  235. }
  236. }
  237. break;
  238. case "in":
  239. $condition[] = [$key, $include.'in', $content];
  240. break;
  241. case "like":
  242. $condition[] = [$key, $include.'like', "%" . $content . "%"];
  243. break;
  244. case "FIND_IN_SET":
  245. //使用like搜索 暂不使用find_in_set 不可用包含不包含
  246. // $content_arr = explode(",",$content);
  247. // $temp_sql = '';
  248. // foreach ($content_arr as $content_value){
  249. // if(empty($temp_sql)){
  250. // $temp_sql .= "FIND_IN_SET({$content_value}, member_label)";
  251. // }else{
  252. // $temp_sql .= " or FIND_IN_SET({$content_value}, member_label)";
  253. // }
  254. // }
  255. // $condition[] = [ "", 'exp', Db::raw($temp_sql) ];
  256. $content_arr = explode(",",$content);
  257. if($values['include'] == 1){
  258. $find_in_set = "or";
  259. $find_in_set_method = "like";
  260. }else if($values['include'] == 2){
  261. $find_in_set = "and";
  262. $find_in_set_method = "not like";
  263. }
  264. $temp_arr = [];
  265. foreach ($content_arr as $content_value){
  266. $content_condition = [ $content_value, '%' . $content_value . ',%', '%' . $content_value, '%,' . $content_value . ',%' ];
  267. $temp_arr = array_merge($content_condition,$temp_arr);
  268. }
  269. $condition[] = [ $key, $find_in_set_method, $temp_arr, $find_in_set ];
  270. break;
  271. case 4://其他表数据
  272. break;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. return $condition;
  279. }
  280. /**
  281. * 自动定时刷新数据
  282. * @return array
  283. */
  284. public function refreshMemberCluster()
  285. {
  286. $list = model('member_cluster')->getList([],'rule_json,site_id,cluster_id');
  287. //循环刷新事件
  288. foreach ($list as $value){
  289. $calculate_data = $this->calculate($value)['data'];
  290. model("member_cluster")->update(["member_num" => $calculate_data['member_num'], "member_ids" => $calculate_data['member_ids'], "update_time" => time()],["cluster_id" => $value['cluster_id']]);
  291. }
  292. return $this->success();
  293. }
  294. /**
  295. * 发放积分
  296. * @param $point
  297. * @param $cluster_id
  298. * @param $remark
  299. * @return array
  300. */
  301. public function sendPoint($point, $cluster_id, $remark)
  302. {
  303. $member_cluster_info = model("member_cluster")->getInfo(["cluster_id" => $cluster_id],"member_ids");
  304. $member_list = model("member")->getList([ ["member_id", "in", $member_cluster_info["member_ids"]] ],'site_id,member_id');
  305. $member_account_model = new MemberAccount();
  306. model('member_account')->startTrans();
  307. try {
  308. foreach ($member_list as $value){
  309. $member_account_model->addMemberAccount($value[ 'site_id' ], $value['member_id'], 'point', $point, 'adjust', '会员群体发放积分' . $point, $remark);
  310. }
  311. model('member_account')->commit();
  312. return $this->success();
  313. } catch (\Exception $e) {
  314. model('member_account')->rollback();
  315. return $this->error('', $e->getMessage());
  316. }
  317. }
  318. /**
  319. * 发放余额
  320. * @param $balance
  321. * @param $cluster_id
  322. * @param $remark
  323. * @return array
  324. */
  325. public function sendBalance($balance, $cluster_id, $remark)
  326. {
  327. $member_cluster_info = model("member_cluster")->getInfo(["cluster_id" => $cluster_id],"member_ids");
  328. $member_list = model("member")->getList([ ["member_id", "in", $member_cluster_info["member_ids"]] ],'site_id,member_id');
  329. $member_account_model = new MemberAccount();
  330. model('member_account')->startTrans();
  331. try {
  332. foreach ($member_list as $value){
  333. $member_account_model->addMemberAccount($value[ 'site_id' ], $value['member_id'], 'balance', $balance, 'adjust', '会员群体发放红包' . $balance, $remark);
  334. }
  335. model('member_account')->commit();
  336. return $this->success();
  337. } catch (\Exception $e) {
  338. model('member_account')->rollback();
  339. return $this->error('', $e->getMessage());
  340. }
  341. }
  342. /**
  343. * 发放优惠券
  344. * @param $coupon
  345. * @param $cluster_id
  346. * @return array
  347. */
  348. public function sendCoupon($coupon, $cluster_id)
  349. {
  350. $member_cluster_info = model("member_cluster")->getInfo(["cluster_id" => $cluster_id],"member_ids");
  351. $member_list = model("member")->getList([ ["member_id", "in", $member_cluster_info["member_ids"]] ],'site_id,member_id');
  352. model('promotion_coupon')->startTrans();
  353. try {
  354. $coupon_model = new Coupon();
  355. foreach ($member_list as $value){
  356. $coupon_model->giveCoupon($coupon, $value[ 'site_id' ], $value['member_id'], 4);
  357. }
  358. model('promotion_coupon')->commit();
  359. return $this->success();
  360. } catch (\Exception $e) {
  361. model('promotion_coupon')->rollback();
  362. return $this->error('', $e->getMessage());
  363. }
  364. }
  365. /**
  366. * 店铺初始化的时候添加定时任务
  367. */
  368. public function addMemberClusterCronRefresh()
  369. {
  370. //添加会员群体刷新时间
  371. $cron_model = new Cron();
  372. $execute_time = time() + 60;
  373. $res = $cron_model->addCron(2, 1, "会员群体定时刷新", "CronMemberClusterRefresh", $execute_time, 0);
  374. return $this->success($res);
  375. }
  376. }