diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/dao/TbUserShopMsgMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/dao/TbUserShopMsgMapper.java new file mode 100644 index 0000000..2b5988c --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/dao/TbUserShopMsgMapper.java @@ -0,0 +1,28 @@ +package com.chaozhanggui.system.cashierservice.dao; + +import com.chaozhanggui.system.cashierservice.entity.TbUserShopMsg; +import org.apache.ibatis.annotations.Select; + +/** +* @author Administrator +* @description 针对表【tb_user_shop_msg】的数据库操作Mapper +* @createDate 2024-06-28 09:55:30 +* @Entity com.chaozhanggui.system.cashierservice.entity.TbUserShopMsg +*/ +public interface TbUserShopMsgMapper { + + int deleteByPrimaryKey(Long id); + + int insert(TbUserShopMsg record); + + int insertSelective(TbUserShopMsg record); + + TbUserShopMsg selectByPrimaryKey(Long id); + + int updateByPrimaryKeySelective(TbUserShopMsg record); + + int updateByPrimaryKey(TbUserShopMsg record); + + @Select("select * from tb_user_shop_msg where shop_id=#{shopId}") + TbUserShopMsg selectByShopId(String shopId); +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbUserShopMsg.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbUserShopMsg.java new file mode 100644 index 0000000..3012147 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbUserShopMsg.java @@ -0,0 +1,94 @@ +package com.chaozhanggui.system.cashierservice.entity; + +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * + * @TableName tb_user_shop_msg + */ +@Data +public class TbUserShopMsg implements Serializable { + /** + * + */ + private Integer shopId; + + /** + * + */ + private String openId; + + /** + * + */ + private String remark; + + /** + * 状态 1 正常 0 禁用 + */ + private String status; + + /** + * + */ + private Date createTime; + + /** + * + */ + private Date updateTime; + + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + TbUserShopMsg other = (TbUserShopMsg) that; + return (this.getShopId() == null ? other.getShopId() == null : this.getShopId().equals(other.getShopId())) + && (this.getOpenId() == null ? other.getOpenId() == null : this.getOpenId().equals(other.getOpenId())) + && (this.getRemark() == null ? other.getRemark() == null : this.getRemark().equals(other.getRemark())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) + && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getShopId() == null) ? 0 : getShopId().hashCode()); + result = prime * result + ((getOpenId() == null) ? 0 : getOpenId().hashCode()); + result = prime * result + ((getRemark() == null) ? 0 : getRemark().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); + result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", shopId=").append(shopId); + sb.append(", openId=").append(openId); + sb.append(", remark=").append(remark); + sb.append(", status=").append(status); + sb.append(", createTime=").append(createTime); + sb.append(", updateTime=").append(updateTime); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/CartService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/CartService.java index 90fbdcc..d9a3db6 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/CartService.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/CartService.java @@ -13,9 +13,11 @@ import com.chaozhanggui.system.cashierservice.redis.RedisUtil; import com.chaozhanggui.system.cashierservice.util.DateUtils; import com.chaozhanggui.system.cashierservice.util.JSONUtil; import com.chaozhanggui.system.cashierservice.util.N; +import com.chaozhanggui.system.cashierservice.wxUtil.WechatUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -24,6 +26,7 @@ import java.io.IOException; import java.math.BigDecimal; import java.time.Instant; import java.util.*; +import java.util.concurrent.CompletableFuture; /** * @author lyf @@ -54,9 +57,19 @@ public class CartService { private TbUserCouponsMapper userCouponsMapper; @Autowired private TbSystemCouponsMapper systemCouponsMapper; + private final TbUserShopMsgMapper tbUserShopMsgMapper; + private final WechatUtil wechatUtil; @Autowired private RabbitProducer producer; + @Qualifier("tbShopInfoMapper") + @Autowired + private TbShopInfoMapper tbShopInfoMapper; + + public CartService(TbUserShopMsgMapper tbUserShopMsgMapper, WechatUtil wechatUtil) { + this.tbUserShopMsgMapper = tbUserShopMsgMapper; + this.wechatUtil = wechatUtil; + } public void initCart(JSONObject jsonObject) { String tableId = jsonObject.getString("tableId"); @@ -237,13 +250,22 @@ public class CartService { } } + /** + * 修改库存并根据警告线发送消息 + * @param product 商品 + * @param productSku sku + * @param num 库存数 + */ private void updateProductStock(TbProduct product, TbProductSkuWithBLOBs productSku, Integer num) { String key = RedisCst.PRODUCT + product.getShopId() + ":product" + product.getId(); + double stock = num; if (product.getIsDistribute() == 1) { productMapper.updateStockById(product.getId().toString(), num); + stock = (double) (product.getStockNumber() - num); } else { key = RedisCst.PRODUCT + product.getShopId() + ":" + productSku.getId(); productSkuMapper.updateStockById(productSku.getId().toString(), num); + stock = productSku.getStockNumber() - num; } if (num > 0) { @@ -251,6 +273,42 @@ public class CartService { } else { redisUtil.getIncrNum(key, "2"); } + + CompletableFuture.runAsync(() -> checkWarnLineAndSendMsg(productSku, product)); + + } + + /** + * 校验商品库存警戒线并通知商户 + * @param productSku sku + */ + private void checkWarnLineAndSendMsg(TbProductSku productSku, TbProduct product) { + if (productSku.getWarnLine() == null) { + return; + } + + TbShopInfo shopInfo = tbShopInfoMapper.selectByPrimaryKey(Integer.valueOf(product.getShopId())); + if (shopInfo == null) { + log.info("商品库存预警发送失败,店铺不存在,店铺id:{}", product.getShopId()); + return; + } + + if (productSku.getStockNumber() == null) { + productSku.setStockNumber((double) 0); + } + + if (product.getStockNumber() == null) { + product.setStockNumber(0); + } + if ( + (product.getIsDistribute() == 1 && productSku.getStockNumber() <= productSku.getWarnLine()) + || (product.getIsDistribute() != 1) && product.getStockNumber() <= productSku.getWarnLine() + ) { + TbUserShopMsg tbUserShopMsg = tbUserShopMsgMapper.selectByShopId(productSku.getShopId()); + wechatUtil.sendStockWarnMsg(shopInfo.getShopName(), product.getName(), + product.getIsDistribute() == 1 ? productSku.getStockNumber().toString() : product.getStockNumber().toString(), + "耗材库存不足,请及时补充。", tbUserShopMsg.getOpenId()); + } } private TbCashierCart addCart(String productId, String skuId, Integer userId, Integer num, String tableId, String shopId) throws Exception { diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/wxUtil/WechatUtil.java b/src/main/java/com/chaozhanggui/system/cashierservice/wxUtil/WechatUtil.java index 7cfca73..8d42fcc 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/wxUtil/WechatUtil.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/wxUtil/WechatUtil.java @@ -1,17 +1,24 @@ package com.chaozhanggui.system.cashierservice.wxUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.chaozhanggui.system.cashierservice.util.HttpClientUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; - +@Slf4j +@Component public class WechatUtil { public static JSONObject getSessionKeyOrOpenId(String code, String appId, String secrete) { @@ -70,4 +77,87 @@ public class WechatUtil { return null; } + + @Value("${wx.msg.appId}") + private String appId; + + @Value("${wx.msg.secrete}") + private String secrete; + + @Value("${wx.msg.warnMsgTmpId}") + private String msgTmpId; + + static LinkedHashMap linkedHashMap=new LinkedHashMap<>(); + + static { + + linkedHashMap.put("40001","获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口"); + linkedHashMap.put("40003","不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID"); + linkedHashMap.put("40014","不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口"); + linkedHashMap.put("40037","不合法的 template_id"); + linkedHashMap.put("43101","用户未订阅消息"); + linkedHashMap.put("43107","订阅消息能力封禁"); + linkedHashMap.put("43108","并发下发消息给同一个粉丝"); + linkedHashMap.put("45168","命中敏感词"); + linkedHashMap.put("47003","参数错误"); + + } + + public JSONObject getAccessToken(){ + String requestUrl = "https://api.weixin.qq.com/cgi-bin/token"; + Map requestUrlParam = new HashMap<>(); + //小程序appId + requestUrlParam.put("appid", appId); + //小程序secret + requestUrlParam.put("secret", secrete); + //默认参数 + requestUrlParam.put("grant_type", "client_credential"); + JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doGet(requestUrl,requestUrlParam)); + return jsonObject; + } + + public JSONObject sendStockWarnMsg(String shopName, String productName, String stock, String note, String toUserOpenId) { + Map data = new HashMap() {{ + put("thing1", new HashMap(){{ + put("value", shopName); + }}); + put("thing6", new HashMap(){{ + put("value", productName); + }}); + put("number7", new HashMap(){{ + put("value", stock); + }}); + put("thing5", new HashMap(){{ + put("value", note); + }}); + }}; + log.info("开始发送库存预警消息, 接收用户openId: {}, 消息数据: {}", toUserOpenId, data); + return sendTempMsg(msgTmpId, toUserOpenId, data); + } + + + public JSONObject sendTempMsg(String tempId, String toUserOpenId, Map data) { + log.info("开始发送微信模板消息, 接收用户openId: {}, 消息数据: {}", toUserOpenId, data); + JSONObject object= getAccessToken(); + String accessToken=object.get("access_token")+""; + + JSONObject object1=new JSONObject(); + + object1.put("template_id", tempId); + object1.put("touser", toUserOpenId); + object1.put("data",data); + + object1.put("miniprogram_state","trial"); + object1.put("lang","zh_CN"); + + String response= HttpRequest.post("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=".concat(accessToken)).body(object1.toString()).execute().body(); + log.info("微信模板消息发送成功,相应内容:{}",response); + JSONObject resObj=JSONObject.parseObject(response); + if(ObjectUtil.isNotEmpty(resObj)&&ObjectUtil.isNotNull(resObj)&&"0".equals(resObj.get("errcode")+"")){ + return resObj; + } + + throw new RuntimeException(linkedHashMap.getOrDefault(resObj.get("errcode") + "", "未知错误")); + } + } diff --git a/src/main/resources/mapper/TbUserShopMsgMapper.xml b/src/main/resources/mapper/TbUserShopMsgMapper.xml new file mode 100644 index 0000000..46f9e4f --- /dev/null +++ b/src/main/resources/mapper/TbUserShopMsgMapper.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + shop_id,open_id,remark, + status,create_time,update_time + + + + + + delete from tb_user_shop_msg + where shop_id = #{shopId,jdbcType=INTEGER} + + + insert into tb_user_shop_msg + ( shop_id,open_id,remark + ,status,create_time,update_time + ) + values (#{shopId,jdbcType=INTEGER},#{openId,jdbcType=VARCHAR},#{remark,jdbcType=VARCHAR} + ,#{status,jdbcType=VARCHAR},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP} + ) + + + insert into tb_user_shop_msg + + shop_id, + open_id, + remark, + status, + create_time, + update_time, + + + #{shopId,jdbcType=INTEGER}, + #{openId,jdbcType=VARCHAR}, + #{remark,jdbcType=VARCHAR}, + #{status,jdbcType=VARCHAR}, + #{createTime,jdbcType=TIMESTAMP}, + #{updateTime,jdbcType=TIMESTAMP}, + + + + update tb_user_shop_msg + + + open_id = #{openId,jdbcType=VARCHAR}, + + + remark = #{remark,jdbcType=VARCHAR}, + + + status = #{status,jdbcType=VARCHAR}, + + + create_time = #{createTime,jdbcType=TIMESTAMP}, + + + update_time = #{updateTime,jdbcType=TIMESTAMP}, + + + where shop_id = #{shopId,jdbcType=INTEGER} + + + update tb_user_shop_msg + set + open_id = #{openId,jdbcType=VARCHAR}, + remark = #{remark,jdbcType=VARCHAR}, + status = #{status,jdbcType=VARCHAR}, + create_time = #{createTime,jdbcType=TIMESTAMP}, + update_time = #{updateTime,jdbcType=TIMESTAMP} + where shop_id = #{shopId,jdbcType=INTEGER} + +