HbController.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. namespace mall\controllers;
  3. use Yii;
  4. use common\components\util;
  5. use bizHd\hb\classes\HbClass;
  6. use bizHd\hb\classes\HbManageClass;
  7. use bizHd\hb\classes\HbScopeClass;
  8. use bizMall\hd\classes\HdClass;
  9. class HbController extends BaseController
  10. {
  11. /**
  12. * 我的红包列表
  13. * 返回分页列表,并附带各状态数量供顶部 Tab 展示:
  14. * all 全部、unUse 未使用、used 已使用、expired 已过期
  15. * 每条红包额外附带 hdId(xhHd.id),供「去使用」跳转对应店铺商品列表。
  16. */
  17. public function actionList()
  18. {
  19. $get = Yii::$app->request->get();
  20. $where = [];
  21. $where['t.userId'] = $this->userId;
  22. $status = $get['status'] ?? '';
  23. if ($status != '') {
  24. $where['t.status'] = $get['status'];
  25. }
  26. $respond = HbClass::getHbList(['t.*', 's.merchantName', 's.shopName'], $where);
  27. // 各状态数量不受当前 status 筛选影响,始终按当前用户统计(单次聚合查询)
  28. $statusCounts = HbClass::getStatusCounts(['userId' => $this->userId]);
  29. $respond['all'] = $statusCounts['all'];
  30. $respond['unUse'] = $statusCounts['unUse'];
  31. $respond['used'] = $statusCounts['used'];
  32. $respond['expired'] = $statusCounts['expired'];
  33. if (!empty($respond['list'])) {
  34. $hbIds = array_column($respond['list'], 'id');
  35. $scopeMap = HbScopeClass::getMapByHbIds($hbIds);
  36. // 按 shopId 批量查当前用户在该店的 xhHd.id,避免跨店跳转商品列表时缺少门店上下文
  37. $shopHdMap = $this->buildShopHdMap(array_column($respond['list'], 'shopId'));
  38. foreach ($respond['list'] as &$v) {
  39. $v['customName'] = $v['custom']['name'] ?? '';
  40. $v = HbScopeClass::attachScopeToHb($v, $scopeMap);
  41. $v['specialApplicableText'] = ((int)$v['specialApplicable'] === 1)
  42. ? '特价及活动商品适用'
  43. : '特价及活动商品不适用';
  44. $shopId = (int)($v['shopId'] ?? 0);
  45. $v['hdId'] = $shopHdMap[$shopId] ?? 0;
  46. if ($v['status'] == 0 && $v['endTime'] < time()) {
  47. //发现红包已过期,需要作废,多有处作废操作,搜索关键词 cancellation_hb
  48. $id = $v['id'];
  49. HbClass::updateById($id, ['status' => -1]);
  50. $v['status'] = -1;
  51. // 本页懒过期后同步修正 Tab 数量,避免未使用偏多、已过期偏少
  52. $respond['unUse']--;
  53. $respond['expired']++;
  54. }
  55. }
  56. unset($v);
  57. }
  58. util::success($respond);
  59. }
  60. /**
  61. * 按 shopId 批量解析当前用户的花店客户关系 id(xhHd.id)。
  62. * 「去使用」跳转商品列表必须带 hdId,否则商城接口无法正确绑定客户价与购物车店铺维度。
  63. *
  64. * @param array $shopIds 红包所属门店 id 列表
  65. * @return array shopId => hdId
  66. */
  67. private function buildShopHdMap($shopIds)
  68. {
  69. $shopIds = array_values(array_unique(array_filter(array_map('intval', $shopIds ?: []))));
  70. if (empty($shopIds) || $this->userId <= 0) {
  71. return [];
  72. }
  73. $hdList = HdClass::getAllByCondition(
  74. [
  75. 'userId' => $this->userId,
  76. 'shopId' => ['in', $shopIds],
  77. 'delStatus' => 0,
  78. ],
  79. null,
  80. 'id,shopId'
  81. );
  82. $map = [];
  83. foreach ($hdList ?: [] as $hd) {
  84. $sid = (int)($hd['shopId'] ?? 0);
  85. if ($sid > 0 && !isset($map[$sid])) {
  86. $map[$sid] = (int)$hd['id'];
  87. }
  88. }
  89. return $map;
  90. }
  91. /**
  92. * 某门店下所有可用红包(附带适用范围)
  93. */
  94. public function actionAvailableHb()
  95. {
  96. $where = [];
  97. $where['customId'] = $this->customId;
  98. $where['status'] = 0;
  99. $where['beginTime<='] = time();
  100. // 若传 shopId 则限定门店
  101. $shopId = (int)Yii::$app->request->get('shopId', 0);
  102. if ($shopId > 0) {
  103. $where['shopId'] = $shopId;
  104. }
  105. $list = HbClass::getAllByCondition($where, 'id DESC');
  106. if (!empty($list)) {
  107. $hbIds = array_column($list, 'id');
  108. $scopeMap = HbScopeClass::getMapByHbIds($hbIds);
  109. foreach ($list as $k => $v) {
  110. if ($v['status'] == 0 && $v['endTime'] < time()) {
  111. unset($list[$k]);
  112. $id = $v['id'];
  113. HbClass::updateById($id, ['status' => -1]);
  114. continue;
  115. }
  116. $list[$k] = HbScopeClass::attachScopeToHb($v, $scopeMap);
  117. }
  118. $list = array_values($list);
  119. }
  120. util::success($list);
  121. }
  122. /**
  123. * 检查是否有未提示的到账红包(首页弹框)
  124. * GET shopId 可选:个人首页不传则取任意一家有待提示红包的门店
  125. */
  126. public function actionCheckArrival()
  127. {
  128. $shopId = (int)Yii::$app->request->get('shopId', 0);
  129. $customId = (int)$this->customId;
  130. $userId = (int)$this->userId;
  131. if ($userId <= 0) {
  132. util::success(['has' => 0]);
  133. }
  134. // 通过 manage.notified=0 且 hb.status=0 查找
  135. $hbWhere = [
  136. 'userId' => $userId,
  137. 'status' => 0,
  138. 'beginTime<=' => time(),
  139. 'endTime>=' => time(),
  140. ];
  141. if ($shopId > 0) {
  142. $hbWhere['shopId'] = $shopId;
  143. }
  144. if ($customId > 0) {
  145. $hbWhere['customId'] = $customId;
  146. }
  147. $list = HbClass::getAllByCondition($hbWhere, 'id DESC', 'id,shopId,customId,name,amount,minConsume,beginTime,endTime,getType');
  148. if (empty($list)) {
  149. util::success(['has' => 0]);
  150. }
  151. $hbIds = array_column($list, 'id');
  152. // 取全部流水(含已提示),按 hbId 索引
  153. $manages = HbManageClass::getAllByCondition([
  154. 'hbId' => ['in', $hbIds],
  155. ], null, 'hbId,notified', 'hbId');
  156. $pending = [];
  157. foreach ($list as $hb) {
  158. $hid = (int)$hb['id'];
  159. $m = $manages[$hid] ?? null;
  160. if ($m === null) {
  161. // 历史无流水:补一条以便后续 mark,并视为未提示
  162. try {
  163. HbManageClass::add([
  164. 'hbId' => $hid,
  165. 'getType' => (int)$hb['getType'],
  166. 'getTargetId' => 0,
  167. 'createStaffId' => 0,
  168. 'createStaffName' => '系统',
  169. 'remark' => '',
  170. 'notified' => 0,
  171. ]);
  172. } catch (\Throwable $e) {
  173. }
  174. $pending[] = $hb;
  175. } elseif ((int)$m['notified'] === 0) {
  176. $pending[] = $hb;
  177. }
  178. }
  179. if (empty($pending)) {
  180. util::success(['has' => 0]);
  181. }
  182. $first = $pending[0];
  183. util::success([
  184. 'has' => 1,
  185. 'count' => count($pending),
  186. 'hb' => $first,
  187. 'hbIds' => array_column($pending, 'id'),
  188. ]);
  189. }
  190. /**
  191. * 标记红包已提示(弹框「立即查看」或「稍后再说」都调用)
  192. * POST hbIds[] 或 hbId
  193. */
  194. public function actionMarkNotified()
  195. {
  196. $post = Yii::$app->request->post();
  197. $hbIds = $post['hbIds'] ?? [];
  198. if (empty($hbIds) && !empty($post['hbId'])) {
  199. $hbIds = [$post['hbId']];
  200. }
  201. if (!is_array($hbIds)) {
  202. $hbIds = [$hbIds];
  203. }
  204. $hbIds = array_values(array_filter(array_map('intval', $hbIds)));
  205. if (empty($hbIds)) {
  206. util::complete();
  207. }
  208. // 校验归属
  209. $list = HbClass::getAllByCondition([
  210. 'id' => ['in', $hbIds],
  211. 'userId' => $this->userId,
  212. ], null, 'id');
  213. $okIds = array_column($list, 'id');
  214. if (!empty($okIds)) {
  215. // updateByCondition 仅支持等值条件,IN 需走 updateByIds
  216. $manages = HbManageClass::getAllByCondition(['hbId' => ['in', $okIds]], null, 'id');
  217. $manageIds = array_column($manages, 'id');
  218. if (!empty($manageIds)) {
  219. HbManageClass::updateByIds($manageIds, [
  220. 'notified' => 1,
  221. 'notifiedAt' => date('Y-m-d H:i:s'),
  222. ]);
  223. }
  224. }
  225. util::complete();
  226. }
  227. }