diff --git a/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopController.java b/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopController.java index 5fc6092..6268608 100644 --- a/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopController.java +++ b/agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopController.java @@ -1,6 +1,8 @@ package com.agileboot.admin.controller.shop; import com.agileboot.admin.customize.aop.accessLog.AccessLog; +import com.agileboot.common.constant.Constants; +import com.agileboot.common.constant.WeixinConstants; import com.agileboot.common.core.base.BaseController; import com.agileboot.common.core.dto.ResponseDTO; import com.agileboot.common.core.page.PageDTO; @@ -26,16 +28,10 @@ import java.math.BigDecimal; import java.util.List; import javax.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/shop/shops") @@ -53,7 +49,10 @@ public class ShopController extends BaseController { @Operation(summary = "首页数据") @PreAuthorize("@permission.has('welcome:info')") @GetMapping("/Stats") - public ResponseDTO stats() { + public ResponseDTO stats(@RequestParam String corpid) { + if (StringUtils.isBlank(corpid)) { + corpid = WeixinConstants.corpid; + } // 创建统计数据DTO对象 StatsDTO statsDTO = new StatsDTO(); // 设置商店总数(调用商店服务统计) @@ -67,7 +66,7 @@ public class ShopController extends BaseController { // 设置订单总金额(调用订单服务计算) statsDTO.setOrderAmountSum(orderApplicationService.sumTotalAmount()); - List unReturnOrderGoods = orderApplicationService.selectUnReturnOrderGoods(); + List unReturnOrderGoods = orderApplicationService.selectUnReturnOrderGoods(corpid); // 设置未还商品数量(调用订单服务统计) statsDTO.setUnReturnedGoodsCount((long) unReturnOrderGoods.size()); // 设置未还订单数量(调用订单服务统计) diff --git a/agileboot-admin/src/main/java/com/agileboot/admin/customize/service/job/QywxMessageJob.java b/agileboot-admin/src/main/java/com/agileboot/admin/customize/service/job/QywxMessageJob.java new file mode 100644 index 0000000..12042cc --- /dev/null +++ b/agileboot-admin/src/main/java/com/agileboot/admin/customize/service/job/QywxMessageJob.java @@ -0,0 +1,176 @@ +package com.agileboot.admin.customize.service.job; + +import cn.hutool.core.date.DateUtil; +import com.agileboot.domain.ab98.user.db.Ab98UserService; +import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService; +import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity; +import com.agileboot.domain.qywx.api.QywxApiUtil; +import com.agileboot.domain.qywx.api.response.NewsArticle; +import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService; +import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity; +import com.agileboot.domain.qywx.department.DepartmentApplicationService; +import com.agileboot.domain.qywx.template.TemplateApplicationService; +import com.agileboot.domain.qywx.template.command.UpdateTemplateCommand; +import com.agileboot.domain.qywx.template.db.QyTemplateEntity; +import com.agileboot.domain.qywx.user.QyUserApplicationService; +import com.agileboot.domain.qywx.user.db.QyUserEntity; +import com.agileboot.domain.qywx.user.db.QyUserService; +import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService; +import com.agileboot.domain.ab98.user.db.Ab98UserEntity; +import com.agileboot.domain.shop.order.OrderApplicationService; +import com.agileboot.domain.shop.order.db.ShopOrderEntity; +import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity; +import com.agileboot.domain.shop.order.db.ShopOrderService; +import com.agileboot.domain.system.role.db.SysRoleService; +import com.agileboot.domain.system.user.model.UserModelFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Component +@Slf4j +public class QywxMessageJob { + private final TemplateApplicationService templateApplicationService; + private final AuthCorpInfoApplicationService authCorpInfoApplicationService; + private final AccessTokenApplicationService accessTokenApplicationService; + private final DepartmentApplicationService departmentApplicationService; + private final QyUserApplicationService qyUserApplicationService; + private final SysUserQyUserApplicationService sysUserQyUserApplicationService; + private final UserModelFactory userModelFactory; + private final SysRoleService sysRoleService; + private final OrderApplicationService orderApplicationService; + private final ShopOrderService orderService; + private final Ab98UserService ab98UserService; + private final QyUserService qyUserService; + +// private static final String appid = "QYTONG_YS_WXSHOP"; + /** + * 企业微信应用ID常量 + * 用于标识当前集成的第三方应用,对应企业微信服务商后台配置的应用凭证 + */ + private static final String appid2 = "QWTONG_YS_WXSHOP"; + + /** + * 每天向逾期未归还商品的用户发送提醒消息 + * 执行时间:每天凌晨2点 + */ + @Scheduled(cron = "0 0 10 * * *") + public void sendOverdueGoodsReminderTask() { + try { + // 1. 获取所有已授权企业信息 + List authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid2); + if (CollectionUtils.isEmpty(authCorpInfoList)) { + log.info("没有找到已授权的企业信息"); + return; + } + + // 2. 遍历企业处理 + for (QyAuthCorpInfoEntity authCorpInfo : authCorpInfoList) { + sendOverdueReminderForCorp(appid2, authCorpInfo); + } + } catch (Exception e) { + log.error("发送逾期商品提醒任务失败", e); + } + } + + /** + * 为单个企业发送逾期提醒 + */ + private void sendOverdueReminderForCorp(String appid, QyAuthCorpInfoEntity authCorpInfo) { + try { + // 3. 获取企业访问令牌 + QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid()); + if (accessToken == null || StringUtils.isBlank(accessToken.getAccessToken())) { + log.error("企业[{}]获取accessToken失败", authCorpInfo.getCorpid()); + return; + } + + // 4. 查询逾期未归还商品记录(需实现商品借阅相关Service) + List unReturnOrderGoods = orderApplicationService.selectUnReturnOrderGoods(authCorpInfo.getCorpid()); + if (CollectionUtils.isEmpty(unReturnOrderGoods)) { + log.info("企业[{}]没有未归还商品记录", authCorpInfo.getCorpid()); + return; + } + + // 5. 筛选createTime超过一周的记录 + Date oneWeekAgo = DateUtil.offsetDay(new Date(), -7); + List overdueRecords = unReturnOrderGoods.stream() + .filter(record -> record.getCreateTime().before(oneWeekAgo)) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(overdueRecords)) { + log.info("企业[{}]没有超过一周未归还的商品记录", authCorpInfo.getCorpid()); + return; + } + + // 6. 遍历逾期记录发送消息 + for (ShopOrderGoodsEntity record : overdueRecords) { + sendSingleReminder(accessToken.getAccessToken(), authCorpInfo, record); + } + } catch (Exception e) { + log.error("企业[{}]发送逾期提醒失败", authCorpInfo.getCorpid(), e); + } + } + + /** + * 发送单个逾期提醒消息 + */ + private void sendSingleReminder(String accessToken, QyAuthCorpInfoEntity authCorpInfo, ShopOrderGoodsEntity record) { + try { + ShopOrderEntity order = orderService.getById(record.getOrderId()); + if (order.getMode().equals(3) || order.getMode().equals(4)) { + log.info("订单[{}]为租赁订单,无需发送逾期提醒", order.getOrderId()); + return; + } + // 6. 获取用户信息 + List userList = qyUserApplicationService.getUserByUserId(order.getUserid()); + QyUserEntity user = null; + if (CollectionUtils.isEmpty(userList)) { + if (StringUtils.isBlank(order.getMobile())) { + log.error("用户[{}]不存在企业微信信息", order.getName()); + return; + } + Ab98UserEntity ab98User = ab98UserService.selectByTel(order.getMobile()); + user = qyUserService.getUserByAb98UserId(ab98User.getAb98UserId(), authCorpInfo.getCorpid()); + } else { + user = userList.get(0); + } + if (user == null || StringUtils.isBlank(user.getUserid())) { + log.error("用户[{}]不存在企业微信信息", order.getName()); + return; + } + + // 发送审核消息 + try { + // 获取用户ID + String toUser = user.getUserid(); + String toparty = ""; + String totag = ""; + List articles = new ArrayList<>(); + NewsArticle article = new NewsArticle(); + article.setTitle("耗材领用申请通知"); + article.setDescription("领用商品:" + record.getGoodsName()); + article.setDescription("你借用的 【" + record.getGoodsName() + "】 已逾期未归还,请及时归还"); + article.setPicurl(record.getCoverImg()); + article.setUrl("http://wxshop.ab98.cn/shop-api/api/shop/qy/wechatAuth/home"); + articles.add(article); + + QywxApiUtil.sendNewsMessage(accessToken, Integer.valueOf(authCorpInfo.getAgentid()), + toUser, toparty, totag, articles); + } catch (Exception e) { + log.error("发送退货审核通知失败", e); + } + } catch (Exception e) { + log.error("发送单个逾期提醒失败", e); + } + } +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserMapper.java index e59fa30..fda7dd6 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserMapper.java @@ -39,10 +39,13 @@ public interface Ab98UserMapper extends BaseMapper { List selectAllRegistered(); @Select("SELECT * FROM ab98_user WHERE userid = #{userid} LIMIT 1") - Ab98UserEntity selectByUserid(String userid); + Ab98UserEntity selectByUserid(@Param("userid")String userid); @Select("SELECT * FROM ab98_user WHERE openid = #{openid} LIMIT 1") - Ab98UserEntity selectByOpenid(String openid); + Ab98UserEntity selectByOpenid(@Param("openid")String openid); + + @Select("SELECT * FROM ab98_user WHERE tel = #{tel} LIMIT 1") + Ab98UserEntity selectByTel(@Param("tel")String tel); @Select("SELECT * FROM ab98_user WHERE openid = #{openid} AND userid = #{userid} LIMIT 1") Ab98UserEntity selectByOpenidAndUserid(@Param("openid")String openid, @Param("userid")String userid); diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserService.java b/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserService.java index 27664ed..7e46dec 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserService.java @@ -28,5 +28,7 @@ public interface Ab98UserService extends IService { Ab98UserEntity getByIdnum(String idnum); + Ab98UserEntity selectByTel(String tel); + Ab98UserEntity selectByOpenidAndUserid(String openid, String userid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserServiceImpl.java index 7d1f719..37f489e 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserServiceImpl.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/ab98/user/db/Ab98UserServiceImpl.java @@ -49,6 +49,11 @@ public class Ab98UserServiceImpl extends ServiceImpl selectUnReturnOrderGoods() { - return orderGoodsService.selectUnReturnOrderGoods(); + public List selectUnReturnOrderGoods(String corpid) { + return orderGoodsService.selectUnReturnOrderGoods(corpid); } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsMapper.java index 78b2fd3..fec96c8 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsMapper.java @@ -46,9 +46,9 @@ public interface ShopOrderGoodsMapper extends BaseMapper { "FROM shop_order_goods og " + "LEFT JOIN shop_goods g ON og.goods_id = g.goods_id " + "LEFT JOIN cabinet_cell cc ON og.cell_id = cc.cell_id " + - "WHERE og.status = 1 " + + "WHERE og.corpid = #{corpid} AND og.status = 1 " + "AND og.deleted = 0 " + "AND g.deleted = 0 " + "AND cc.deleted = 0 AND cc.goods_id = og.goods_id") - List selectUnReturnOrderGoods(); + List selectUnReturnOrderGoods(@Param("corpid") String corpid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsService.java index 07ae8fd..abcfdc5 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsService.java @@ -23,7 +23,7 @@ public interface ShopOrderGoodsService extends IService { List selectTodayLatestOrderGoods(); - List selectUnReturnOrderGoods(); + List selectUnReturnOrderGoods(String corpid); List selectOrderGoodsByApprovalId(Long approvalId); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsServiceImpl.java index a8a423b..1af07b6 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsServiceImpl.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderGoodsServiceImpl.java @@ -39,8 +39,8 @@ public class ShopOrderGoodsServiceImpl extends ServiceImpl selectUnReturnOrderGoods() { - return baseMapper.selectUnReturnOrderGoods(); + public List selectUnReturnOrderGoods(String corpid) { + return baseMapper.selectUnReturnOrderGoods(corpid); } @Override