SubNoticeJobs.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. <?php
  2. namespace App\Jobs\Manager\Process;
  3. use Illuminate\Bus\Queueable;
  4. use Illuminate\Contracts\Queue\ShouldBeUnique;
  5. use Illuminate\Contracts\Queue\ShouldQueue;
  6. use Illuminate\Foundation\Bus\Dispatchable;
  7. use Illuminate\Queue\InteractsWithQueue;
  8. use Illuminate\Queue\SerializesModels;
  9. use App\Facades\Servers\Logs\Log;
  10. use App\Models\Manager\Process\LowPriceGoodsMember as LowPriceGoodsMemberModel;
  11. use App\Models\Manager\Process\LowPriceGoods as LowPriceGoodsModel;
  12. use App\Models\Manager\Process\ViolationProductMember as ViolationProductMemberModel;
  13. use App\Models\Manager\Process\ViolationProduct as ViolationProductModel;
  14. use App\Models\Manager\Process\ViolationStore as ViolationStoreModel;
  15. use App\Models\Manager\Process\ViolationStoreMember as ViolationStoreMemberModel;
  16. use Illuminate\Support\Carbon;
  17. use App\Facades\Servers\Sms\VerifyCode as Sms;
  18. use App\Servers\Email\VerifyCode as EmailVerifyCode;
  19. use App\Models\Manager\Personnel\NoticeConfig as NoticeConfigModel;
  20. use App\Models\Manager\Process\SubNoticeLog as SubNoticeLogModel;
  21. use App\Models\Manager\Personnel\Employee as EmployeeModel;
  22. /**
  23. * 订阅通知
  24. * @author 唐远望
  25. * @version 1.0
  26. * @date 2026-03-30
  27. */
  28. class SubNoticeJobs implements ShouldQueue
  29. {
  30. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  31. protected $message_data;
  32. protected $user_data;
  33. /**
  34. * Create a new job instance.
  35. *
  36. * @return void
  37. */
  38. public function __construct(array $message_data)
  39. {
  40. $this->message_data = $message_data;
  41. }
  42. /**
  43. * Execute the job.
  44. *
  45. * @return void
  46. */
  47. public function handle()
  48. {
  49. try {
  50. $notice_config_data = $this->get_statistics_time_rule($this->message_data['company_id']);
  51. if ($notice_config_data['statistics_start_time'] == '' || $notice_config_data['statistics_end_time'] == '' || $notice_config_data['statistics_day'] == 0) {
  52. //记录日志
  53. // Log::info('job_info', '订阅未设置,不进行推送', ['data' => $this->message_data, 'notice_config_data' => $notice_config_data]);
  54. return true;
  55. }
  56. $statistics_start_time = $notice_config_data['statistics_start_time'];
  57. $statistics_end_time = $notice_config_data['statistics_end_time'];
  58. $push_time = $notice_config_data['push_time'];
  59. $EmailVerifyCode = new EmailVerifyCode();
  60. $EmployeeModel = new EmployeeModel();
  61. $sms_tpl_id = config('verifycode.aliyun_process_merge_notice.sms_tpl');
  62. $company_id = $this->message_data['company_id'];
  63. $action_one = $this->send_low_price_goods_notice($company_id, $statistics_start_time, $statistics_end_time);
  64. $action_two = $this->send_violation_product($company_id, $statistics_start_time, $statistics_end_time);
  65. $action_three = $this->send_violation_store($company_id, $statistics_start_time, $statistics_end_time);
  66. if (empty($this->user_data)) return true;
  67. $start_time = Carbon::today()->startOfDay()->getTimestamp(); // 今天开始时间 00:00:00
  68. $end_time = Carbon::today()->endOfDay()->getTimestamp(); // 今天结束时间 23:59:59
  69. $SubNoticeLogModel = new SubNoticeLogModel();
  70. if ($action_one && $action_two && $action_three) {
  71. foreach ($this->user_data as $key => $value) {
  72. $mobile = $value['mobile'];
  73. $email_to = $value['email'];
  74. $user_id = $key;
  75. //查询已已经开启通知设置的用户
  76. $employee_ids = $EmployeeModel->where('id', $user_id)->where('open_notice', 0)->get();
  77. if (empty($employee_ids)) continue;
  78. $number1 = isset($this->user_data[$key]['lowprice_product_logids']) ? count($this->user_data[$key]['lowprice_product_logids']) : 0;
  79. $number2 = isset($this->user_data[$key]['violation_product_logids']) ? count($this->user_data[$key]['violation_product_logids']) : 0;
  80. $number3 = isset($this->user_data[$key]['violation_store_logids']) ? count($this->user_data[$key]['violation_store_logids']) : 0;
  81. //统计总条数
  82. $totle_number = $number1 + $number2 + $number3;
  83. $sms_config_data = [];
  84. if (trim($mobile) != '') {
  85. $sms_config_data = ['parameter' => ['totle_number' => $totle_number, 'number1' => $number1, 'number2' => $number2, 'number3' => $number3], 'sms_tpl_id' => $sms_tpl_id];
  86. // $res_msg = Sms::sendContent($mobile, ['totle_number' => $totle_number, 'number1' => $number1, 'number2' => $number2, 'number3' => $number3], $sms_tpl_id);
  87. // Log::info('job_send_sms', '订阅短信通知推送队列记录', ['email' => $mobile, 'sms_tpl_id' => $sms_tpl_id, 'msg' => $res_msg]);
  88. }
  89. $header_date = '';
  90. $statistics_start_time_string = date('Y-m-d', strtotime($statistics_start_time));
  91. $statistics_end_time_string = date('Y-m-d', strtotime($statistics_end_time));
  92. if ($statistics_start_time_string == $statistics_end_time_string) {
  93. $header_date = $statistics_start_time;
  94. } else {
  95. $header_date = $statistics_start_time_string . '至' . $statistics_end_time_string;
  96. }
  97. $email_title = '';
  98. $email_content = '';
  99. if (trim($email_to) != '') {
  100. $email_title = '智价云违规数据通知提醒';
  101. $email_content = "智价云提醒:" . $header_date . "采集总数据共" . $totle_number . "条,其中低价挂网商品共" . $number1 . "条、禁止挂网商品共" . $number2 . "条、违规挂网店铺共" . $number3 . "条。";
  102. // $res_msg = $EmailVerifyCode->sendSmtpEmail($email_to, $email_title, $email_content);
  103. // Log::info('job_send_email', '订阅邮件通知推送队列记录', ['email' => $email_to, 'email_content' => $email_content, 'msg' => $res_msg]);
  104. }
  105. $internal_notice_content = $header_date . "采集总数据共" . $totle_number . "条,其中低价挂网商品共" . $number1 . "条、禁止挂网商品共" . $number2 . "条、违规挂网店铺共" . $number3 . "条。";
  106. $ext_data = [
  107. 'company_id' => $company_id,
  108. 'lowprice_product_number' => $number1,
  109. 'violation_product_number' => $number2,
  110. 'violation_store_number' => $number3,
  111. 'statistics_start_time' => $statistics_start_time,
  112. 'statistics_end_time' => $statistics_end_time,
  113. ];
  114. // 校验今日是否已推送记录,防止重复添加
  115. $exists = $SubNoticeLogModel->where([['insert_time','>=',$start_time], ['insert_time','<=',$end_time],['company_id','=',$company_id],['employee_id','=',$user_id]])->exists();
  116. if ($exists) {
  117. continue;
  118. }
  119. // 增加就订阅日志
  120. $insert_data = [
  121. 'company_id' => $company_id,
  122. 'employee_id' => $user_id,
  123. 'internal_notice_content' => $internal_notice_content,
  124. 'email' => $email_to,
  125. 'mobile' => $mobile,
  126. 'email_content' => trim($email_to) != '' ? json_encode(['title' => $email_title, 'content' => $email_content]) : '',
  127. 'mobile_content' => trim($mobile) != '' ? json_encode($sms_config_data) : '',
  128. 'push_time' => strtotime(date('Y-m-d', time()) . ' ' . $push_time . ':00'),
  129. 'ext_data' => json_encode($ext_data),
  130. 'insert_time' => time(),
  131. ];
  132. $SubNoticeLogModel->insert($insert_data);
  133. }
  134. }
  135. } catch (\Exception $e) {
  136. Log::info('job_error', '订阅通知推送队列失败', ['data' => $this->message_data, 'error' => $e->getMessage()]);
  137. }
  138. }
  139. /**
  140. * 获取统计时间规则
  141. * @author 唐远望
  142. * @version 1.0
  143. * @date 2026-04-11
  144. */
  145. private function get_statistics_time_rule($company_id)
  146. {
  147. // 获取当时时间是星期几
  148. $now_week = date('w');
  149. if ($now_week == 0) {
  150. $now_week = 7;
  151. }
  152. // $now_week = 1;//调试星期
  153. $NoticeConfigModel = new NoticeConfigModel();
  154. $data = $NoticeConfigModel->where(['company_id' => $company_id])->first();
  155. if (!$data) return ['now_week' => $now_week, 'statistics_day' => 0, 'statistics_start_time' => '', 'statistics_end_time' => '', 'push_time' => '', 'notice_week_config' => ''];
  156. //校验这个星期是否需要进行推送
  157. $notice_week_config = json_decode($data->notice_week_config, true);
  158. $is_open = 0;
  159. $now_week_day = 'week_' . $now_week;
  160. if ($notice_week_config[$now_week_day] == 0) {
  161. $is_open = 1;
  162. }
  163. if ($is_open == 0) {
  164. return ['now_week' => $now_week, 'statistics_day' => 0, 'statistics_start_time' => '', 'statistics_end_time' => '', 'push_time' => '', 'notice_week_config' => $notice_week_config];
  165. }
  166. //是否每天都推送
  167. $is_day_day_push = 0;
  168. for ($i = 7; $i >= 1; $i--) {
  169. $week_string = 'week_' . $i;
  170. if ($notice_week_config[$week_string] == 0) {
  171. $is_day_day_push = $is_day_day_push + 1;
  172. }
  173. }
  174. if ($is_day_day_push == 7) {
  175. $statistics_day = 1;
  176. } else {
  177. $statistics_day = 0;
  178. //判断当时时间是否是星期一
  179. if ($now_week == 1) {
  180. for ($i = 7; $i >= 1; $i--) {
  181. //校验前一天是否推送
  182. $week_string = 'week_7';
  183. if ($notice_week_config[$week_string] == 0) { // 如果前一天没有开启推送则统计,状态 0=开启 1=关闭
  184. $statistics_day = $statistics_day + 1;
  185. break;
  186. } else {
  187. $week_oth_string = 'week_' . $i;
  188. if ($notice_week_config[$week_oth_string] == '1') { // 如果前一天没有开启推送则统计,状态 0=开启 1=关闭
  189. $statistics_day = $statistics_day + 1;
  190. } else {
  191. $statistics_day = $statistics_day + 1;
  192. break;
  193. }
  194. }
  195. }
  196. } else {
  197. $statistics_day = 0;
  198. //如果当前$now_week星期,往前推,当遇到开启的日期时,停止往前推,最大为7天
  199. for ($i = $now_week; $i >= 1; $i--) {
  200. //校验前一天是否推送
  201. $yesterday_week = $now_week - 1;
  202. if ($yesterday_week < 1) {
  203. continue;
  204. }
  205. $week_string = 'week_' . $yesterday_week;
  206. //校验前一天是否开启了推送
  207. if ($i == $now_week && $notice_week_config[$week_string] == '0') {
  208. $statistics_day = $statistics_day + 1;
  209. break;
  210. } else {
  211. $i_index = $i - 1; //往前推一天
  212. if ($i_index < 1) {
  213. continue;
  214. }
  215. $week_oth_string = 'week_' . $i_index;
  216. if ($notice_week_config[$week_oth_string] == '1') {
  217. $statistics_day = $statistics_day + 1;
  218. } else {
  219. $statistics_day = $statistics_day + 1;
  220. break;
  221. }
  222. }
  223. }
  224. }
  225. }
  226. if ($statistics_day < 1) {
  227. return ['now_week' => $now_week, 'statistics_day' => $statistics_day, 'statistics_start_time' => '', 'statistics_end_time' => '', 'push_time' => '', 'notice_week_config' => $notice_week_config];
  228. }
  229. /** 新规则,统计时间为上一后期延长一天,且包扩今天的时间 */
  230. $statistics_day = $statistics_day -1;
  231. $statistics_start_time = Carbon::today()->subDays($statistics_day)->startOfDay()->toDateTimeString();
  232. //获取今日结束时间
  233. $statistics_end_time = Carbon::today()->endOfDay()->toDateTimeString();
  234. return ['now_week' => $now_week, 'statistics_day' => $statistics_day, 'statistics_start_time' => $statistics_start_time, 'statistics_end_time' => $statistics_end_time, 'push_time' => $data->push_time, 'notice_week_config' => $notice_week_config];
  235. }
  236. /**
  237. * 短信消息消息订阅推送(低价挂网)
  238. * @author 唐远望
  239. * @version 1.0
  240. * @date 2026-03-04
  241. */
  242. private function send_low_price_goods_notice($company_id, $statistics_start_time, $statistics_end_time)
  243. {
  244. $LowPriceGoodsMemberModel = new LowPriceGoodsMemberModel();
  245. $LowPriceGoodsModel = new LowPriceGoodsModel();
  246. //获取今日待处理的商品记录
  247. $todayStart = strtotime($statistics_start_time); // 统计开始时间
  248. $todayEnd = strtotime($statistics_end_time); // 统计结束时间
  249. $lowprice_ids = $LowPriceGoodsModel->where([['insert_time', '>=', $todayStart], ['insert_time', '<=', $todayEnd], ['company_id', '=', $company_id]])->pluck('id')->toArray();
  250. if (empty($lowprice_ids)) return true;
  251. //获取开启了通知服务的用户
  252. $usert_list = $LowPriceGoodsMemberModel
  253. ->whereIn('lowprice_product_logid', $lowprice_ids)
  254. ->join('personnel_employee', 'process_lowprice_product_member.employee_id', '=', 'personnel_employee.id')
  255. ->where('personnel_employee.open_notice', 0)
  256. ->where('personnel_employee.company_id', $company_id)
  257. ->select(['process_lowprice_product_member.*', 'personnel_employee.mobile', 'personnel_employee.email'])
  258. ->get()->toArray();
  259. if (empty($usert_list)) return true;
  260. //按用户统计待处理的商品数量
  261. foreach ($usert_list as $key => $value) {
  262. $user_id = $value['employee_id'];
  263. if (!isset($this->user_data[$user_id])) {
  264. $this->user_data[$user_id]['employee_id'] = $user_id;
  265. $this->user_data[$user_id]['mobile'] = $value['mobile'];
  266. $this->user_data[$user_id]['email'] = $value['email'];
  267. $this->user_data[$user_id]['lowprice_product_logids'][] = $value['lowprice_product_logid'];
  268. //去重
  269. $lowprice_product_logids_list = $this->user_data[$user_id]['lowprice_product_logids'];
  270. $this->user_data[$user_id]['lowprice_product_logids'] = array_unique($lowprice_product_logids_list);
  271. } else {
  272. $this->user_data[$user_id]['lowprice_product_logids'][] = $value['lowprice_product_logid'];
  273. $lowprice_product_logids_list = $this->user_data[$user_id]['lowprice_product_logids'];
  274. $this->user_data[$user_id]['lowprice_product_logids'] = array_unique($lowprice_product_logids_list);
  275. }
  276. }
  277. return true;
  278. }
  279. /**
  280. * 短信消息消息订阅推送(禁止挂网)
  281. * @author 唐远望
  282. * @version 1.0
  283. * @date 2026-03-04
  284. */
  285. private function send_violation_product($company_id, $statistics_start_time, $statistics_end_time)
  286. {
  287. $ViolationProductMemberModel = new ViolationProductMemberModel();
  288. $ViolationProductModel = new ViolationProductModel();
  289. //获取今日待处理的商品记录
  290. $todayStart = strtotime($statistics_start_time); // 统计开始时间
  291. $todayEnd = strtotime($statistics_end_time); // 统计结束时间
  292. $violation_price_ids = $ViolationProductModel->where([['insert_time', '>=', $todayStart], ['insert_time', '<=', $todayEnd], ['company_id', '=', $company_id]])->pluck('id')->toArray();
  293. if (empty($violation_price_ids)) return true;
  294. //获取开启了通知服务的用户
  295. $usert_list = $ViolationProductMemberModel
  296. ->whereIn('violation_product_logid', $violation_price_ids)
  297. ->join('personnel_employee', 'process_violation_product_member.employee_id', '=', 'personnel_employee.id')
  298. ->where('personnel_employee.open_notice', 0)
  299. ->where('personnel_employee.company_id', $company_id)
  300. ->select(['process_violation_product_member.*', 'personnel_employee.mobile', 'personnel_employee.email'])
  301. ->get()->toArray();
  302. if (empty($usert_list)) return true;
  303. //按用户统计待处理的商品数量
  304. foreach ($usert_list as $key => $value) {
  305. $user_id = $value['employee_id'];
  306. if (!isset($this->user_data[$user_id])) {
  307. $this->user_data[$user_id]['employee_id'] = $user_id;
  308. $this->user_data[$user_id]['mobile'] = $value['mobile'];
  309. $this->user_data[$user_id]['email'] = $value['email'];
  310. $this->user_data[$user_id]['violation_product_logids'][] = $value['violation_product_logid'];
  311. $iolation_product_logid_list = $this->user_data[$user_id]['violation_product_logids'];
  312. $this->user_data[$user_id]['violation_product_logids'] = array_unique($iolation_product_logid_list);
  313. } else {
  314. $this->user_data[$user_id]['violation_product_logids'][] = $value['violation_product_logid'];
  315. $iolation_product_logid_list = $this->user_data[$user_id]['violation_product_logids'];
  316. $this->user_data[$user_id]['violation_product_logids'] = array_unique($iolation_product_logid_list);
  317. }
  318. }
  319. return true;
  320. }
  321. /**
  322. * 短信消息消息订阅推送(禁止店铺)
  323. * @author 唐远望
  324. * @version 1.0
  325. * @date 2026-03-04
  326. */
  327. private function send_violation_store($company_id, $statistics_start_time, $statistics_end_time)
  328. {
  329. $ViolationStoreMemberModel = new ViolationStoreMemberModel();
  330. $ViolationStoreModel = new ViolationStoreModel();
  331. //获取今日待处理的店铺记录
  332. $todayStart = strtotime($statistics_start_time); // 统计开始时间
  333. $todayEnd = strtotime($statistics_end_time); // 统计结束时间
  334. $violation_price_ids = $ViolationStoreModel->where([['insert_time', '>=', $todayStart], ['insert_time', '<=', $todayEnd], ['company_id', '=', $company_id]])->pluck('id')->toArray();
  335. if (empty($violation_price_ids)) return true;
  336. //获取开启了通知服务的用户
  337. $usert_list = $ViolationStoreMemberModel
  338. ->whereIn('violation_store_logid', $violation_price_ids)
  339. ->join('personnel_employee', 'process_violation_store_member.employee_id', '=', 'personnel_employee.id')
  340. ->where('personnel_employee.open_notice', 0)
  341. ->where('personnel_employee.company_id', $company_id)
  342. ->select(['process_lowprice_product_member.*', 'personnel_employee.mobile', 'personnel_employee.email'])
  343. ->get()->toArray();
  344. if (empty($usert_list)) return true;
  345. //按用户统计待处理的商品数量
  346. foreach ($usert_list as $key => $value) {
  347. $user_id = $value['employee_id'];
  348. if (!isset($this->user_data[$user_id])) {
  349. $this->user_data[$user_id]['employee_id'] = $user_id;
  350. $this->user_data[$user_id]['mobile'] = $value['mobile'];
  351. $this->user_data[$user_id]['violation_store_logids'][] = $value['violation_store_logid'];
  352. //去重
  353. $violation_store_logids_list = $this->user_data[$user_id]['violation_store_logids'];
  354. $this->user_data[$user_id]['violation_store_logids'] = array_unique($violation_store_logids_list);
  355. } else {
  356. //去重
  357. $this->user_data[$user_id]['violation_store_logids'][] = $value['violation_store_logid'];
  358. $violation_store_logids_list = $this->user_data[$user_id]['violation_store_logids'];
  359. $this->user_data[$user_id]['violation_store_logids'] = array_unique($violation_store_logids_list);
  360. }
  361. }
  362. return true;
  363. }
  364. public function failed(\Throwable $exception)
  365. {
  366. Log::info('job_error', '订阅通知推送队列完全失败', ['data' => $this->message_data, 'error' => $exception->getMessage()]);
  367. }
  368. }