Bladeren bron

优化公告发送太慢问题 加入 并发处理

java110 4 jaren geleden
bovenliggende
commit
bd45741b7d
15 gewijzigde bestanden met toevoegingen van 1183 en 114 verwijderingen
  1. 106 0
      java110-bean/src/main/java/com/java110/dto/wechatSubscribe/WechatSubscribeDto.java
  2. 89 0
      java110-bean/src/main/java/com/java110/po/wechatSubscribe/WechatSubscribePo.java
  3. 140 0
      java110-db/src/main/resources/mapper/user/WechatSubscribeV1ServiceDaoImplMapper.xml
  4. 16 25
      java110-generator/src/main/java/com/java110/code/TableToJson.java
  5. 20 31
      java110-generator/src/main/resources/newBack/template_1.json
  6. 71 0
      java110-interface/src/main/java/com/java110/intf/user/IWechatSubscribeV1InnerServiceSMO.java
  7. 36 6
      service-api/src/main/java/com/java110/api/smo/wechatGateway/impl/WechatGatewaySMOImpl.java
  8. 90 52
      service-job/src/main/java/com/java110/job/task/wechat/WeChatPushMessageTemplate.java
  9. 71 0
      service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/DeleteWechatSubscribeCmd.java
  10. 84 0
      service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/ListWechatSubscribeCmd.java
  11. 77 0
      service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/SaveWechatSubscribeCmd.java
  12. 75 0
      service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/UpdateWechatSubscribeCmd.java
  13. 80 0
      service-user/src/main/java/com/java110/user/dao/IWechatSubscribeV1ServiceDao.java
  14. 120 0
      service-user/src/main/java/com/java110/user/dao/impl/WechatSubscribeV1ServiceDaoImpl.java
  15. 108 0
      service-user/src/main/java/com/java110/user/smo/impl/WechatSubscribeV1InnerServiceSMOImpl.java

+ 106 - 0
java110-bean/src/main/java/com/java110/dto/wechatSubscribe/WechatSubscribeDto.java

@@ -0,0 +1,106 @@
+package com.java110.dto.wechatSubscribe;
+
+import com.java110.dto.PageDto;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @ClassName FloorDto
+ * @Description 微信关注数据层封装
+ * @Author wuxw
+ * @Date 2019/4/24 8:52
+ * @Version 1.0
+ * add by wuxw 2019/4/24
+ **/
+public class WechatSubscribeDto extends PageDto implements Serializable {
+
+    public static final String OPEN_TYPE_WECHAT = "WECHAT";
+
+    private String subId;
+    private String openId;
+    private String appId;
+    private String nickname;
+    private String headimgurl;
+    private String userId;
+    private String openType;
+
+
+    private Date createTime;
+
+    private String statusCd = "0";
+
+
+    public String getSubId() {
+        return subId;
+    }
+
+    public void setSubId(String subId) {
+        this.subId = subId;
+    }
+
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    public String getHeadimgurl() {
+        return headimgurl;
+    }
+
+    public void setHeadimgurl(String headimgurl) {
+        this.headimgurl = headimgurl;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getOpenType() {
+        return openType;
+    }
+
+    public void setOpenType(String openType) {
+        this.openType = openType;
+    }
+
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getStatusCd() {
+        return statusCd;
+    }
+
+    public void setStatusCd(String statusCd) {
+        this.statusCd = statusCd;
+    }
+}

+ 89 - 0
java110-bean/src/main/java/com/java110/po/wechatSubscribe/WechatSubscribePo.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.po.wechatSubscribe;
+
+import java.io.Serializable;
+import java.util.Date;
+/**
+ * 类表述: Po 数据模型实体对象 基本保持与数据库模型一直 用于 增加修改删除 等时的数据载体
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+public class WechatSubscribePo implements Serializable {
+
+    private String subId;
+private String openId;
+private String appId;
+private String nickname;
+private String headimgurl;
+private String statusCd = "0";
+private String userId;
+private String openType;
+public String getSubId() {
+        return subId;
+    }
+public void setSubId(String subId) {
+        this.subId = subId;
+    }
+public String getOpenId() {
+        return openId;
+    }
+public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+public String getAppId() {
+        return appId;
+    }
+public void setAppId(String appId) {
+        this.appId = appId;
+    }
+public String getNickname() {
+        return nickname;
+    }
+public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+public String getHeadimgurl() {
+        return headimgurl;
+    }
+public void setHeadimgurl(String headimgurl) {
+        this.headimgurl = headimgurl;
+    }
+public String getStatusCd() {
+        return statusCd;
+    }
+public void setStatusCd(String statusCd) {
+        this.statusCd = statusCd;
+    }
+public String getUserId() {
+        return userId;
+    }
+public void setUserId(String userId) {
+        this.userId = userId;
+    }
+public String getOpenType() {
+        return openType;
+    }
+public void setOpenType(String openType) {
+        this.openType = openType;
+    }
+
+
+
+}

+ 140 - 0
java110-db/src/main/resources/mapper/user/WechatSubscribeV1ServiceDaoImplMapper.xml

@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="wechatSubscribeV1ServiceDaoImpl">
+
+
+    <!-- 保存微信关注信息 add by wuxw 2018-07-03 -->
+    <insert id="saveWechatSubscribeInfo" parameterType="Map">
+        insert into wechat_subscribe(
+        sub_id,open_id,app_id,nickname,headimgurl,user_id,open_type
+        ) values (
+        #{subId},#{openId},#{appId},#{nickname},#{headimgurl},#{userId},#{openType}
+        )
+    </insert>
+    <insert id="saveWechatSubscribeInfos" parameterType="Map">
+        insert into wechat_subscribe(
+        sub_id,open_id,app_id,nickname,headimgurl,user_id,open_type
+        ) values
+        <foreach collection="wechatSubscribes" item="item" separator=",">
+            (#{item.subId},#{item.openId},#{item.appId},#{item.nickname},#{item.headimgurl},#{item.userId},#{item.openType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFees" parameterType="Map">
+        insert into pay_fee (amount,status_cd,income_obj_id,fee_type_cd,start_time,end_time,community_id,b_id,fee_id,
+        user_id,payer_obj_id,fee_flag,state,config_id,payer_obj_type,batch_id)
+        VALUES
+        <foreach collection="payFeePos" item="item" separator=",">
+            (#{item.amount},'0',#{item.incomeObjId},#{item.feeTypeCd},#{item.startTime},#{item.endTime},#{item.communityId},
+            '-1',#{item.feeId},#{item.userId},#{item.payerObjId},#{item.feeFlag},#{item.state},#{item.configId},#{item.payerObjType},#{item.batchId})
+        </foreach>
+    </insert>
+
+
+    <!-- 查询微信关注信息 add by wuxw 2018-07-03 -->
+    <select id="getWechatSubscribeInfo" parameterType="Map" resultType="Map">
+        select t.sub_id,t.sub_id subId,t.open_id,t.open_id openId,t.app_id,t.app_id
+        appId,t.nickname,t.headimgurl,t.status_cd,t.status_cd statusCd,t.user_id,t.user_id
+        userId,t.open_type,t.open_type openType
+        from wechat_subscribe t
+        where 1 =1
+        <if test="subId !=null and subId != ''">
+            and t.sub_id= #{subId}
+        </if>
+        <if test="openId !=null and openId != ''">
+            and t.open_id= #{openId}
+        </if>
+        <if test="appId !=null and appId != ''">
+            and t.app_id= #{appId}
+        </if>
+        <if test="nickname !=null and nickname != ''">
+            and t.nickname= #{nickname}
+        </if>
+        <if test="headimgurl !=null and headimgurl != ''">
+            and t.headimgurl= #{headimgurl}
+        </if>
+        <if test="statusCd !=null and statusCd != ''">
+            and t.status_cd= #{statusCd}
+        </if>
+        <if test="userId !=null and userId != ''">
+            and t.user_id= #{userId}
+        </if>
+        <if test="openType !=null and openType != ''">
+            and t.open_type= #{openType}
+        </if>
+        order by t.create_time desc
+        <if test="page != -1 and page != null ">
+            limit #{page}, #{row}
+        </if>
+
+    </select>
+
+
+    <!-- 修改微信关注信息 add by wuxw 2018-07-03 -->
+    <update id="updateWechatSubscribeInfo" parameterType="Map">
+        update wechat_subscribe t set t.status_cd = #{statusCd}
+        <if test="newBId != null and newBId != ''">
+            ,t.b_id = #{newBId}
+        </if>
+        <if test="openId !=null and openId != ''">
+            , t.open_id= #{openId}
+        </if>
+
+        <if test="nickname !=null and nickname != ''">
+            , t.nickname= #{nickname}
+        </if>
+        <if test="headimgurl !=null and headimgurl != ''">
+            , t.headimgurl= #{headimgurl}
+        </if>
+        <if test="userId !=null and userId != ''">
+            , t.user_id= #{userId}
+        </if>
+        <if test="openType !=null and openType != ''">
+            , t.open_type= #{openType}
+        </if>
+        where 1=1
+        <if test="subId !=null and subId != ''">
+            and t.sub_id= #{subId}
+        </if>
+        <if test="appId !=null and appId != ''">
+            and t.app_id= #{appId}
+        </if>
+
+    </update>
+
+    <!-- 查询微信关注数量 add by wuxw 2018-07-03 -->
+    <select id="queryWechatSubscribesCount" parameterType="Map" resultType="Map">
+        select count(1) count
+        from wechat_subscribe t
+        where 1 =1
+        <if test="subId !=null and subId != ''">
+            and t.sub_id= #{subId}
+        </if>
+        <if test="openId !=null and openId != ''">
+            and t.open_id= #{openId}
+        </if>
+        <if test="appId !=null and appId != ''">
+            and t.app_id= #{appId}
+        </if>
+        <if test="nickname !=null and nickname != ''">
+            and t.nickname= #{nickname}
+        </if>
+        <if test="headimgurl !=null and headimgurl != ''">
+            and t.headimgurl= #{headimgurl}
+        </if>
+        <if test="statusCd !=null and statusCd != ''">
+            and t.status_cd= #{statusCd}
+        </if>
+        <if test="userId !=null and userId != ''">
+            and t.user_id= #{userId}
+        </if>
+        <if test="openType !=null and openType != ''">
+            and t.open_type= #{openType}
+        </if>
+
+
+    </select>
+
+</mapper>

+ 16 - 25
java110-generator/src/main/java/com/java110/code/TableToJson.java

@@ -18,34 +18,25 @@ import java.nio.charset.Charset;
 public class TableToJson {
 
     //show create table c_orders  用这个语句获取
-    public static final String createTableSql = "CREATE TABLE `return_pay_fee` (\n" +
-            "  `return_fee_id` varchar(30) NOT NULL COMMENT '退费id',\n" +
-            "  `community_id` varchar(30) NOT NULL COMMENT '小区id',\n" +
-            "  `b_id` varchar(30) NOT NULL COMMENT '业务id',\n" +
-            "  `config_id` varchar(30) NOT NULL COMMENT '费用项id',\n" +
-            "  `fee_id` varchar(30) NOT NULL COMMENT '费用id',\n" +
-            "  `fee_type_cd` varchar(30) NOT NULL COMMENT '费用类型',\n" +
-            "  `detail_id` varchar(30) NOT NULL COMMENT '缴费id',\n" +
-            "  `cycles` decimal(9,2) DEFAULT NULL COMMENT '周期',\n" +
-            "  `receivable_amount` decimal(10,2) DEFAULT NULL COMMENT '应收金额',\n" +
-            "  `received_amount` decimal(10,2) DEFAULT NULL COMMENT '实收金额',\n" +
-            "  `prime_rate` decimal(3,2) DEFAULT NULL COMMENT '打折率',\n" +
-            "  `remark` varchar(200) DEFAULT NULL COMMENT '备注',\n" +
-            "  `state` varchar(4) NOT NULL COMMENT '审核状态:1000待审核1001审核通过10002审核不通过',\n" +
-            "  `status_cd` varchar(2) NOT NULL COMMENT '数据状态,详细参考c_status表,S 保存,0, 在用 1失效',\n" +
-            "  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '申请退费时间',\n" +
-            "  `pay_time` datetime NOT NULL COMMENT '缴费时间',\n" +
-            "  `reason` varchar(200) NOT NULL COMMENT '退费原因',\n" +
-            "  PRIMARY KEY (`return_fee_id`)\n" +
+    public static final String createTableSql = "CREATE TABLE `wechat_subscribe` (\n" +
+            "  `sub_id` varchar(30) NOT NULL PRIMARY key  COMMENT '主键ID',\n" +
+            "  `open_id` varchar(128) NOT NULL COMMENT '微信ID',\n" +
+            "  `app_id` varchar(30) not null COMMENT '公众号ID',\n" +
+            "  `open_type` varchar(12) NOT NULL default 'WECHAT' COMMENT '开放类型 WECHAT 微信',\n" +
+            "  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +
+            "  `status_cd` varchar(2) NOT NULL DEFAULT '0' COMMENT '数据状态,详细参考c_status表,0, 在用 1失效',\n" +
+            "  `user_id` varchar(30) DEFAULT NULL COMMENT '用户ID',\n" +
+            "  `nickname` varchar(255) DEFAULT NULL COMMENT '昵称',\n" +
+            "  `headimgurl` varchar(255) DEFAULT NULL COMMENT '微信头像'\n" +
             ")";
 
     public static void main(String[] args) {
-        String desc = "退费表";
-        String id = "returnFeeId";
-        String name = "returnPayFee";
-        String shareName = "fee"; //生成到那个服务下
-        String shareColumn = "community_id";
-        String shareParam = "communityId";
+        String desc = "微信关注";
+        String id = "subId";
+        String name = "wechatSubscribe";
+        String shareName = "user"; //生成到那个服务下
+        String shareColumn = "app_id";
+        String shareParam = "appId";
         //业务名称 desc 业务编码名称生成后类名 name 主键 id  需要放到那个服务 shareName
         String newSql = createTableSql.substring(createTableSql.indexOf("(") + 1, createTableSql.lastIndexOf(")"));
         String tableName = createTableSql.substring(createTableSql.indexOf("TABLE") + 5, createTableSql.indexOf("("));

+ 20 - 31
java110-generator/src/main/resources/newBack/template_1.json

@@ -1,45 +1,34 @@
 {
   "param": {
-    "reason": "reason",
-    "primeRate": "prime_rate",
-    "feeTypeCd": "fee_type_cd",
-    "payTime": "pay_time",
-    "detailId": "detail_id",
-    "receivableAmount": "receivable_amount",
-    "cycles": "cycles",
-    "remark": "remark",
+    "subId": "sub_id",
+    "openId": "open_id",
+    "appId": "app_id",
+    "nickname": "nickname",
+    "headimgurl": "headimgurl",
     "statusCd": "status_cd",
-    "receivedAmount": "received_amount",
-    "feeId": "fee_id",
-    "returnFeeId": "return_fee_id",
-    "configId": "config_id",
-    "state": "state",
-    "communityId": "community_id"
+    "userId": "user_id",
+    "openType": "open_type"
   },
-  "name": "returnPayFee",
-  "shareColumn": "community_id",
-  "id": "returnFeeId",
-  "shareName": "fee",
+  "name": "wechatSubscribe",
+  "shareColumn": "app_id",
+  "id": "subId",
+  "shareName": "user",
   "autoMove": true,
   "required": [
     {
-      "msg": "小区id不能为空",
-      "code": "communityId"
+      "msg": "微信ID不能为空",
+      "code": "openId"
     },
     {
-      "msg": "费用项id不能为空",
-      "code": "configId"
+      "msg": "公众号ID不能为空",
+      "code": "appId"
     },
     {
-      "msg": "费用id不能为空",
-      "code": "feeId"
-    },
-    {
-      "msg": "费用类型不能为空",
-      "code": "feeTypeCd"
+      "msg": "开放类型不能为空",
+      "code": "openType"
     }
   ],
-  "desc": "退费表",
-  "shareParam": "communityId",
-  "tableName": "return_pay_fee"
+  "desc": "微信关注",
+  "shareParam": "appId",
+  "tableName": "wechat_subscribe"
 }

+ 71 - 0
java110-interface/src/main/java/com/java110/intf/user/IWechatSubscribeV1InnerServiceSMO.java

@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.intf.user;
+
+import com.java110.config.feign.FeignConfiguration;
+import com.java110.dto.wechatSubscribe.WechatSubscribeDto;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+
+/**
+ * 类表述: 服务之前调用的接口类,不对外提供接口能力 只用于接口建调用
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@FeignClient(name = "user-service", configuration = {FeignConfiguration.class})
+@RequestMapping("/wechatSubscribeV1Api")
+public interface IWechatSubscribeV1InnerServiceSMO {
+
+
+    @RequestMapping(value = "/saveWechatSubscribe", method = RequestMethod.POST)
+    public int saveWechatSubscribe(@RequestBody  WechatSubscribePo wechatSubscribePo);
+
+    @RequestMapping(value = "/saveWechatSubscribes", method = RequestMethod.POST)
+    public int saveWechatSubscribes(@RequestBody  List<WechatSubscribePo> wechatSubscribePos);
+
+    @RequestMapping(value = "/updateWechatSubscribe", method = RequestMethod.POST)
+    public int updateWechatSubscribe(@RequestBody  WechatSubscribePo wechatSubscribePo);
+
+    @RequestMapping(value = "/deleteWechatSubscribe", method = RequestMethod.POST)
+    public int deleteWechatSubscribe(@RequestBody  WechatSubscribePo wechatSubscribePo);
+
+    /**
+     * <p>查询小区楼信息</p>
+     *
+     *
+     * @param wechatSubscribeDto 数据对象分享
+     * @return WechatSubscribeDto 对象数据
+     */
+    @RequestMapping(value = "/queryWechatSubscribes", method = RequestMethod.POST)
+    List<WechatSubscribeDto> queryWechatSubscribes(@RequestBody WechatSubscribeDto wechatSubscribeDto);
+
+    /**
+     * 查询<p>小区楼</p>总记录数
+     *
+     * @param wechatSubscribeDto 数据对象分享
+     * @return 小区下的小区楼记录数
+     */
+    @RequestMapping(value = "/queryWechatSubscribesCount", method = RequestMethod.POST)
+    int queryWechatSubscribesCount(@RequestBody WechatSubscribeDto wechatSubscribeDto);
+}

+ 36 - 6
service-api/src/main/java/com/java110/api/smo/wechatGateway/impl/WechatGatewaySMOImpl.java

@@ -2,25 +2,27 @@ package com.java110.api.smo.wechatGateway.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.java110.api.properties.WechatAuthProperties;
 import com.java110.api.smo.DefaultAbstractComponentSMO;
-import com.java110.core.base.smo.front.AbstractFrontServiceSMO;
+import com.java110.api.smo.wechatGateway.IWechatGatewaySMO;
 import com.java110.core.context.IPageData;
+import com.java110.core.factory.GenerateCodeFactory;
 import com.java110.core.factory.WechatFactory;
+import com.java110.core.log.LoggerFactory;
 import com.java110.dto.owner.OwnerAppUserDto;
 import com.java110.dto.smallWeChat.SmallWeChatDto;
 import com.java110.dto.smallWechatAttr.SmallWechatAttrDto;
-import com.java110.api.properties.WechatAuthProperties;
-import com.java110.api.smo.wechatGateway.IWechatGatewaySMO;
+import com.java110.dto.wechatSubscribe.WechatSubscribeDto;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
 import com.java110.utils.cache.MappingCache;
 import com.java110.utils.constant.ServiceCodeConstant;
 import com.java110.utils.constant.ServiceCodeSmallWechatAttrConstant;
-import com.java110.utils.constant.ServiceConstant;
 import com.java110.utils.constant.WechatConstant;
 import com.java110.utils.util.Assert;
 import com.java110.utils.util.BeanConvertUtil;
 import com.java110.utils.util.StringUtil;
 import org.slf4j.Logger;
-import com.java110.core.log.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
@@ -28,7 +30,6 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
-
 import java.util.List;
 
 /**
@@ -48,6 +49,9 @@ public class WechatGatewaySMOImpl extends DefaultAbstractComponentSMO implements
     @Autowired
     private WechatAuthProperties wechatAuthProperties;
 
+    @Autowired
+    private IWechatSubscribeV1InnerServiceSMO wechatSubscribeV1InnerServiceSMOImpl;
+
     @Override
     public ResponseEntity<String> gateway(IPageData pd, String wId) throws Exception {
 
@@ -89,6 +93,8 @@ public class WechatGatewaySMOImpl extends DefaultAbstractComponentSMO implements
             responseStr = WechatFactory.formatText(toUserName, fromUserName, noBindOwnerResponseMessage);
             return new ResponseEntity<String>(responseStr, HttpStatus.OK);
         }
+        //保存到关注表
+        saveWechatSubscribe(WechatFactory.getAppId(wId), fromUserName);
 
         if (WechatConstant.MSG_TYPE_TEXT.equals(msgType)) {
             responseStr = textResponseHandler(fromUserName, toUserName, keyword);
@@ -100,6 +106,7 @@ public class WechatGatewaySMOImpl extends DefaultAbstractComponentSMO implements
         return new ResponseEntity<>(responseStr, HttpStatus.OK);
     }
 
+
     @Override
     public SmallWeChatDto getSmallWechat(IPageData pd, SmallWeChatDto smallWeChatDto) {
 
@@ -228,4 +235,27 @@ public class WechatGatewaySMOImpl extends DefaultAbstractComponentSMO implements
         return true;
     }
 
+
+    /**
+     * 校验是否在关注表里
+     *
+     * @param appId
+     * @param fromUserName
+     */
+    private void saveWechatSubscribe(String appId, String fromUserName) {
+        WechatSubscribeDto wechatSubscribeDto = new WechatSubscribeDto();
+        wechatSubscribeDto.setOpenId(fromUserName);
+        wechatSubscribeDto.setOpenId(appId);
+        List<WechatSubscribeDto> wechatSubscribeDtos = wechatSubscribeV1InnerServiceSMOImpl.queryWechatSubscribes(wechatSubscribeDto);
+        if (wechatSubscribeDtos != null && wechatSubscribeDtos.size() > 0) {
+            return;
+        }
+        WechatSubscribePo wechatSubscribePo = new WechatSubscribePo();
+        wechatSubscribePo.setAppId(appId);
+        wechatSubscribePo.setOpenId(fromUserName);
+        wechatSubscribePo.setSubId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_file_id));
+        wechatSubscribePo.setOpenType(WechatSubscribeDto.OPEN_TYPE_WECHAT);
+        wechatSubscribeV1InnerServiceSMOImpl.saveWechatSubscribe(wechatSubscribePo);
+    }
+
 }

+ 90 - 52
service-job/src/main/java/com/java110/job/task/wechat/WeChatPushMessageTemplate.java

@@ -7,8 +7,8 @@ import com.java110.core.annotation.Java110Synchronized;
 import com.java110.core.factory.GenerateCodeFactory;
 import com.java110.core.factory.Java110ThreadPoolFactory;
 import com.java110.core.factory.WechatFactory;
+import com.java110.core.log.LoggerFactory;
 import com.java110.core.smo.ISaveTransactionLogSMO;
-import com.java110.core.trace.Java110TraceFactory;
 import com.java110.dto.RoomDto;
 import com.java110.dto.app.AppDto;
 import com.java110.dto.community.CommunityDto;
@@ -19,6 +19,7 @@ import com.java110.dto.owner.OwnerRoomRelDto;
 import com.java110.dto.smallWeChat.SmallWeChatDto;
 import com.java110.dto.smallWechatAttr.SmallWechatAttrDto;
 import com.java110.dto.task.TaskDto;
+import com.java110.dto.wechatSubscribe.WechatSubscribeDto;
 import com.java110.entity.wechat.Content;
 import com.java110.entity.wechat.Data;
 import com.java110.entity.wechat.Miniprogram;
@@ -29,9 +30,11 @@ import com.java110.intf.store.ISmallWeChatInnerServiceSMO;
 import com.java110.intf.store.ISmallWechatAttrInnerServiceSMO;
 import com.java110.intf.user.IOwnerAppUserInnerServiceSMO;
 import com.java110.intf.user.IOwnerRoomRelInnerServiceSMO;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
 import com.java110.job.quartz.TaskSystemQuartz;
 import com.java110.po.logSystemError.LogSystemErrorPo;
 import com.java110.po.transactionLog.TransactionLogPo;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
 import com.java110.service.smo.ISaveSystemErrorSMO;
 import com.java110.utils.cache.MappingCache;
 import com.java110.utils.constant.WechatConstant;
@@ -39,13 +42,13 @@ import com.java110.utils.util.DateUtil;
 import com.java110.utils.util.ExceptionUtil;
 import com.java110.utils.util.StringUtil;
 import org.slf4j.Logger;
-import com.java110.core.log.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
@@ -61,6 +64,7 @@ public class WeChatPushMessageTemplate extends TaskSystemQuartz {
     private static Logger logger = LoggerFactory.getLogger(WeChatPushMessageTemplate.class);
 
     public static final int DEFAULT_THREAD_NUM = 20;
+    public static final int DEFAULT_SUBSCRIBE_PERSON = 100;
 
     @Autowired
     private INoticeInnerServiceSMO noticeInnerServiceSMOImpl;
@@ -82,13 +86,15 @@ public class WeChatPushMessageTemplate extends TaskSystemQuartz {
     @Autowired
     private ISaveTransactionLogSMO saveTransactionLogSMOImpl;
 
-
     @Autowired
     private RestTemplate outRestTemplate;
 
     @Autowired
     private ISaveSystemErrorSMO saveSystemErrorSMOImpl;
 
+    @Autowired
+    private IWechatSubscribeV1InnerServiceSMO wechatSubscribeV1InnerServiceSMOImpl;
+
     //模板信息推送地址
     private static String sendMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";
     private static String getUser = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN";
@@ -325,35 +331,67 @@ public class WeChatPushMessageTemplate extends TaskSystemQuartz {
     }
 
     private void sendAllOwner(NoticeDto noticeDto, String templateId, String accessToken, SmallWeChatDto weChatDto) {
-        doSendToOpenId(noticeDto, templateId, accessToken, "", weChatDto);
-    }
+        //判断关注表的用户量 是否大于100人
+        WechatSubscribeDto wechatSubscribeDto = new WechatSubscribeDto();
+        wechatSubscribeDto.setAppId(weChatDto.getAppId());
+        wechatSubscribeDto.setOpenType(WechatSubscribeDto.OPEN_TYPE_WECHAT);
+
+        int count = wechatSubscribeV1InnerServiceSMOImpl.queryWechatSubscribesCount(wechatSubscribeDto);
+
+        //可能公众号 已经 使用了好久 但是 程序可能刚开始用
+        if (count < DEFAULT_SUBSCRIBE_PERSON) {
+            //doSendToOpenId(noticeDto, templateId, accessToken, "", weChatDto);
+            WechatSubscribePo tmpWechatSubscribePo = new WechatSubscribePo();
+            tmpWechatSubscribePo.setAppId(weChatDto.getAppId());
+            wechatSubscribeV1InnerServiceSMOImpl.deleteWechatSubscribe(tmpWechatSubscribePo);
+            getAllOpenId(accessToken, "", weChatDto);
+        }
 
-    private void doSend(List<OwnerAppUserDto> ownerAppUserDtos, NoticeDto noticeDto, String templateId, String accessToken, SmallWeChatDto weChatDto) {
-        String wechatUrl = MappingCache.getValue("OWNER_WECHAT_URL") + "/#/pages/notice/detail/detail?noticeId=";
-        ResponseEntity<String> responseEntity = null;
-        String sendTemplate = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN,WechatConstant.SEND_TEMPLATE_URL);
-        if(StringUtil.isEmpty(sendTemplate)){
+        List<WechatSubscribeDto> wechatSubscribeDtos = wechatSubscribeV1InnerServiceSMOImpl.queryWechatSubscribes(wechatSubscribeDto);
+
+        if (wechatSubscribeDtos == null || wechatSubscribeDtos.size() < 1) {
+            return;
+        }
+
+        String wechatUrl = MappingCache.getValue("OWNER_WECHAT_URL");
+        Miniprogram miniprogram = null;
+        if (wechatUrl.startsWith("https://") || wechatUrl.startsWith("http://")) {
+
+        } else {
+            miniprogram = new Miniprogram();
+            miniprogram.setAppid(wechatUrl);
+        }
+
+        String sendTemplate = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.SEND_TEMPLATE_URL);
+        if (StringUtil.isEmpty(sendTemplate)) {
             sendTemplate = sendMsgUrl;
         }
-        for (OwnerAppUserDto appUserDto : ownerAppUserDtos) {
+        ResponseEntity<String> responseEntity = null;
+        for (WechatSubscribeDto wechatSubscribeDto1 : wechatSubscribeDtos) {
             Date startTime = DateUtil.getCurrentDate();
+            Data data = new Data();
             PropertyFeeTemplateMessage templateMessage = new PropertyFeeTemplateMessage();
             try {
-                Data data = new Data();
                 templateMessage.setTemplate_id(templateId);
-                templateMessage.setTouser(appUserDto.getOpenId());
+                templateMessage.setTouser(wechatSubscribeDto1.getOpenId());
                 data.setFirst(new Content(noticeDto.getTitle()));
                 data.setKeyword1(new Content(noticeDto.getTitle()));
                 data.setKeyword2(new Content(noticeDto.getStartTime()));
                 data.setKeyword3(new Content(StringUtil.delHtmlTag(noticeDto.getContext())));
                 data.setRemark(new Content("如有疑问请联系相关物业人员"));
                 templateMessage.setData(data);
-                templateMessage.setUrl(wechatUrl + noticeDto.getNoticeId() + "&wAppId=" + weChatDto.getAppId()+"&communityId="+noticeDto.getCommunityId());
-                logger.info("发送模板消息内容:{}", JSON.toJSONString(templateMessage));
-                //responseEntity = outRestTemplate.postForEntity(sendTemplate + accessToken, JSON.toJSONString(templateMessage), String.class);
-                PushWechatTemplateMessageThread pushWechatTemplateMessageThread = new PushWechatTemplateMessageThread(outRestTemplate,sendTemplate + accessToken, JSON.toJSONString(templateMessage));
+                if (!StringUtil.isEmpty(wechatUrl)) {
+                    if (miniprogram == null) {
+                        templateMessage.setUrl(wechatUrl + "/#/pages/notice/detail/detail?noticeId=" + noticeDto.getNoticeId() + "&wAppId=" + weChatDto.getAppId() + "&communityId=" + noticeDto.getCommunityId());
+                    } else {
+                        miniprogram.setPagepath("/pages/notice/detail/detail?noticeId=" + noticeDto.getNoticeId() + "&wAppId=" + weChatDto.getAppId() + "&communityId=" + noticeDto.getCommunityId());
+                        templateMessage.setMiniprogram(miniprogram);
+                    }
+                }
+                //并发处理
+                PushWechatTemplateMessageThread pushWechatTemplateMessageThread = new PushWechatTemplateMessageThread(outRestTemplate, sendTemplate + accessToken, JSON.toJSONString(templateMessage));
                 publicWeChatPushMessageTemplateJava110ThreadPoolFactory.submit(pushWechatTemplateMessageThread);
-                logger.info("微信模板返回内容:{}", responseEntity);
+                //responseEntity = outRestTemplate.postForEntity(sendTemplate + accessToken, JSON.toJSONString(templateMessage), String.class);
             } catch (Exception e) {
                 LogSystemErrorPo logSystemErrorPo = new LogSystemErrorPo();
                 logSystemErrorPo.setErrId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_errId));
@@ -362,14 +400,14 @@ public class WeChatPushMessageTemplate extends TaskSystemQuartz {
                 saveSystemErrorSMOImpl.saveLog(logSystemErrorPo);
                 logger.error("发送失败", e);
             } finally {
-                doSaveLog(startTime, DateUtil.getCurrentDate(), "/pages/notice/detail/detail", JSON.toJSONString(templateMessage), responseEntity, appUserDto.getOpenId());
+                doSaveLog(startTime, DateUtil.getCurrentDate(), "/pages/notice/detail/detail", JSON.toJSONString(templateMessage), responseEntity, wechatSubscribeDto1.getOpenId());
             }
         }
     }
 
-    private void doSendToOpenId(NoticeDto noticeDto, String templateId, String accessToken, String nextOpenid, SmallWeChatDto weChatDto) {
-        String url = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN,WechatConstant.GET_USER_URL);
-        if(StringUtil.isEmpty(url)){
+    private void getAllOpenId(String accessToken, String nextOpenid, SmallWeChatDto weChatDto) {
+        String url = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.GET_USER_URL);
+        if (StringUtil.isEmpty(url)) {
             url = getUser;
         }
         url = url.replace("ACCESS_TOKEN", accessToken);
@@ -395,47 +433,52 @@ public class WeChatPushMessageTemplate extends TaskSystemQuartz {
         JSONObject dataObj = paramOutObj.getJSONObject("data");
         JSONArray openids = dataObj.getJSONArray("openid");
         nextOpenid = paramOutObj.getString("next_openid");
-        String wechatUrl = MappingCache.getValue("OWNER_WECHAT_URL");
-        Miniprogram miniprogram = null;
-        if (wechatUrl.startsWith("https://") || wechatUrl.startsWith("http://")) {
+        List<WechatSubscribePo> wechatSubscribePos = new ArrayList<>();
+        for (int openIndex = 0; openIndex < openids.size(); openIndex++) {
+            String openId = openids.getString(openIndex);
+            WechatSubscribePo wechatSubscribePo = new WechatSubscribePo();
+            wechatSubscribePo.setAppId(weChatDto.getAppId());
+            wechatSubscribePo.setOpenId(openId);
+            wechatSubscribePo.setSubId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_file_id));
+            wechatSubscribePo.setOpenType(WechatSubscribeDto.OPEN_TYPE_WECHAT);
+            wechatSubscribePos.add(wechatSubscribePo);
+        }
 
-        } else {
-            miniprogram = new Miniprogram();
-            miniprogram.setAppid(wechatUrl);
+        if (wechatSubscribePos.size() > 0) {
+            wechatSubscribeV1InnerServiceSMOImpl.saveWechatSubscribes(wechatSubscribePos);
         }
 
-        String sendTemplate = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN,WechatConstant.SEND_TEMPLATE_URL);
-        if(StringUtil.isEmpty(sendTemplate)){
-            sendTemplate = sendMsgUrl;
+        //(关注者列表已返回完时,返回next_openid为空)
+        if (!StringUtil.isEmpty(nextOpenid)) {
+            getAllOpenId(accessToken, nextOpenid, weChatDto);
         }
+    }
+
+    private void doSend(List<OwnerAppUserDto> ownerAppUserDtos, NoticeDto noticeDto, String templateId, String accessToken, SmallWeChatDto weChatDto) {
+        String wechatUrl = MappingCache.getValue("OWNER_WECHAT_URL") + "/#/pages/notice/detail/detail?noticeId=";
         ResponseEntity<String> responseEntity = null;
-        for (int openIndex = 0; openIndex < openids.size(); openIndex++) {
+        String sendTemplate = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.SEND_TEMPLATE_URL);
+        if (StringUtil.isEmpty(sendTemplate)) {
+            sendTemplate = sendMsgUrl;
+        }
+        for (OwnerAppUserDto appUserDto : ownerAppUserDtos) {
             Date startTime = DateUtil.getCurrentDate();
-            Data data = new Data();
             PropertyFeeTemplateMessage templateMessage = new PropertyFeeTemplateMessage();
-            String openId = openids.getString(openIndex);
             try {
+                Data data = new Data();
                 templateMessage.setTemplate_id(templateId);
-                templateMessage.setTouser(openId);
+                templateMessage.setTouser(appUserDto.getOpenId());
                 data.setFirst(new Content(noticeDto.getTitle()));
                 data.setKeyword1(new Content(noticeDto.getTitle()));
                 data.setKeyword2(new Content(noticeDto.getStartTime()));
                 data.setKeyword3(new Content(StringUtil.delHtmlTag(noticeDto.getContext())));
                 data.setRemark(new Content("如有疑问请联系相关物业人员"));
                 templateMessage.setData(data);
-                if (!StringUtil.isEmpty(wechatUrl)) {
-                    if (miniprogram == null) {
-                        templateMessage.setUrl(wechatUrl + "/#/pages/notice/detail/detail?noticeId=" + noticeDto.getNoticeId() + "&wAppId=" + weChatDto.getAppId()+"&communityId="+noticeDto.getCommunityId());
-                    } else {
-                        miniprogram.setPagepath("/pages/notice/detail/detail?noticeId=" + noticeDto.getNoticeId() + "&wAppId=" + weChatDto.getAppId()+"&communityId="+noticeDto.getCommunityId());
-                        templateMessage.setMiniprogram(miniprogram);
-                    }
-                }
+                templateMessage.setUrl(wechatUrl + noticeDto.getNoticeId() + "&wAppId=" + weChatDto.getAppId() + "&communityId=" + noticeDto.getCommunityId());
                 logger.info("发送模板消息内容:{}", JSON.toJSONString(templateMessage));
-
-                PushWechatTemplateMessageThread pushWechatTemplateMessageThread = new PushWechatTemplateMessageThread(outRestTemplate,sendTemplate + accessToken, JSON.toJSONString(templateMessage));
-                publicWeChatPushMessageTemplateJava110ThreadPoolFactory.submit(pushWechatTemplateMessageThread);
                 //responseEntity = outRestTemplate.postForEntity(sendTemplate + accessToken, JSON.toJSONString(templateMessage), String.class);
+                PushWechatTemplateMessageThread pushWechatTemplateMessageThread = new PushWechatTemplateMessageThread(outRestTemplate, sendTemplate + accessToken, JSON.toJSONString(templateMessage));
+                publicWeChatPushMessageTemplateJava110ThreadPoolFactory.submit(pushWechatTemplateMessageThread);
                 logger.info("微信模板返回内容:{}", responseEntity);
             } catch (Exception e) {
                 LogSystemErrorPo logSystemErrorPo = new LogSystemErrorPo();
@@ -445,14 +488,9 @@ public class WeChatPushMessageTemplate extends TaskSystemQuartz {
                 saveSystemErrorSMOImpl.saveLog(logSystemErrorPo);
                 logger.error("发送失败", e);
             } finally {
-                doSaveLog(startTime, DateUtil.getCurrentDate(), "/pages/notice/detail/detail", JSON.toJSONString(templateMessage), responseEntity, openId);
+                doSaveLog(startTime, DateUtil.getCurrentDate(), "/pages/notice/detail/detail", JSON.toJSONString(templateMessage), responseEntity, appUserDto.getOpenId());
             }
         }
-
-        //(关注者列表已返回完时,返回next_openid为空)
-        if (!StringUtil.isEmpty(nextOpenid)) {
-            doSendToOpenId(noticeDto, templateId, accessToken, nextOpenid, weChatDto);
-        }
     }
 
     private void doSaveLog(Date startDate, Date endDate, String serviceCode, String reqJson, ResponseEntity<String> responseEntity, String userId) {

+ 71 - 0
service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/DeleteWechatSubscribeCmd.java

@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.cmd.wechatSubscribe;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.core.annotation.Java110Cmd;
+import com.java110.core.annotation.Java110Transactional;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.event.cmd.AbstractServiceCmdListener;
+import com.java110.core.event.cmd.CmdEvent;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
+import com.java110.utils.exception.CmdException;
+import com.java110.utils.util.Assert;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.vo.ResultVo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 类表述:删除
+ * 服务编码:wechatSubscribe.deleteWechatSubscribe
+ * 请求路劲:/app/wechatSubscribe.DeleteWechatSubscribe
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@Java110Cmd(serviceCode = "wechatSubscribe.deleteWechatSubscribe")
+public class DeleteWechatSubscribeCmd extends AbstractServiceCmdListener {
+    private static Logger logger = LoggerFactory.getLogger(DeleteWechatSubscribeCmd.class);
+
+    @Autowired
+    private IWechatSubscribeV1InnerServiceSMO wechatSubscribeV1InnerServiceSMOImpl;
+
+    @Override
+    public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) {
+        Assert.hasKeyAndValue(reqJson, "subId", "subId不能为空");
+        Assert.hasKeyAndValue(reqJson, "appId", "appId不能为空");
+
+    }
+
+    @Override
+    @Java110Transactional
+    public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException {
+
+        WechatSubscribePo wechatSubscribePo = BeanConvertUtil.covertBean(reqJson, WechatSubscribePo.class);
+        int flag = wechatSubscribeV1InnerServiceSMOImpl.deleteWechatSubscribe(wechatSubscribePo);
+
+        if (flag < 1) {
+            throw new CmdException("删除数据失败");
+        }
+
+        cmdDataFlowContext.setResponseEntity(ResultVo.success());
+    }
+}

+ 84 - 0
service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/ListWechatSubscribeCmd.java

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.cmd.wechatSubscribe;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.core.annotation.Java110Cmd;
+import com.java110.core.annotation.Java110Transactional;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.event.cmd.AbstractServiceCmdListener;
+import com.java110.core.event.cmd.CmdEvent;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
+import com.java110.utils.exception.CmdException;
+import com.java110.utils.util.Assert;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import com.java110.dto.wechatSubscribe.WechatSubscribeDto;
+import java.util.List;
+import java.util.ArrayList;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 类表述:查询
+ * 服务编码:wechatSubscribe.listWechatSubscribe
+ * 请求路劲:/app/wechatSubscribe.ListWechatSubscribe
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@Java110Cmd(serviceCode = "wechatSubscribe.listWechatSubscribe")
+public class ListWechatSubscribeCmd extends AbstractServiceCmdListener {
+
+  private static Logger logger = LoggerFactory.getLogger(ListWechatSubscribeCmd.class);
+    @Autowired
+    private IWechatSubscribeV1InnerServiceSMO wechatSubscribeV1InnerServiceSMOImpl;
+
+    @Override
+    public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) {
+        super.validatePageInfo(reqJson);
+    }
+
+    @Override
+    public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException {
+
+           WechatSubscribeDto wechatSubscribeDto = BeanConvertUtil.covertBean(reqJson, WechatSubscribeDto.class);
+
+           int count = wechatSubscribeV1InnerServiceSMOImpl.queryWechatSubscribesCount(wechatSubscribeDto);
+
+           List<WechatSubscribeDto> wechatSubscribeDtos = null;
+
+           if (count > 0) {
+               wechatSubscribeDtos = wechatSubscribeV1InnerServiceSMOImpl.queryWechatSubscribes(wechatSubscribeDto);
+           } else {
+               wechatSubscribeDtos = new ArrayList<>();
+           }
+
+           ResultVo resultVo = new ResultVo((int) Math.ceil((double) count / (double) reqJson.getInteger("row")), count, wechatSubscribeDtos);
+
+           ResponseEntity<String> responseEntity = new ResponseEntity<String>(resultVo.toString(), HttpStatus.OK);
+
+           cmdDataFlowContext.setResponseEntity(responseEntity);
+    }
+}

+ 77 - 0
service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/SaveWechatSubscribeCmd.java

@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.cmd.wechatSubscribe;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.core.annotation.Java110Cmd;
+import com.java110.core.annotation.Java110Transactional;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.event.cmd.AbstractServiceCmdListener;
+import com.java110.core.event.cmd.CmdEvent;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
+import com.java110.utils.exception.CmdException;
+import com.java110.utils.util.Assert;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 类表述:保存
+ * 服务编码:wechatSubscribe.saveWechatSubscribe
+ * 请求路劲:/app/wechatSubscribe.SaveWechatSubscribe
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@Java110Cmd(serviceCode = "wechatSubscribe.saveWechatSubscribe")
+public class SaveWechatSubscribeCmd extends AbstractServiceCmdListener {
+
+    private static Logger logger = LoggerFactory.getLogger(SaveWechatSubscribeCmd.class);
+
+    public static final String CODE_PREFIX_ID = "10";
+
+    @Autowired
+    private IWechatSubscribeV1InnerServiceSMO wechatSubscribeV1InnerServiceSMOImpl;
+
+    @Override
+    public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) {
+        Assert.hasKeyAndValue(reqJson, "openId", "请求报文中未包含openId");
+Assert.hasKeyAndValue(reqJson, "appId", "请求报文中未包含appId");
+Assert.hasKeyAndValue(reqJson, "openType", "请求报文中未包含openType");
+
+    }
+
+    @Override
+    @Java110Transactional
+    public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException {
+
+       WechatSubscribePo wechatSubscribePo = BeanConvertUtil.covertBean(reqJson, WechatSubscribePo.class);
+        wechatSubscribePo.setSubId(GenerateCodeFactory.getGeneratorId(CODE_PREFIX_ID));
+        int flag = wechatSubscribeV1InnerServiceSMOImpl.saveWechatSubscribe(wechatSubscribePo);
+
+        if (flag < 1) {
+            throw new CmdException("保存数据失败");
+        }
+
+        cmdDataFlowContext.setResponseEntity(ResultVo.success());
+    }
+}

+ 75 - 0
service-user/src/main/java/com/java110/user/cmd/wechatSubscribe/UpdateWechatSubscribeCmd.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.cmd.wechatSubscribe;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.core.annotation.Java110Cmd;
+import com.java110.core.annotation.Java110Transactional;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.event.cmd.AbstractServiceCmdListener;
+import com.java110.core.event.cmd.CmdEvent;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
+import com.java110.utils.exception.CmdException;
+import com.java110.utils.util.Assert;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 类表述:更新
+ * 服务编码:wechatSubscribe.updateWechatSubscribe
+ * 请求路劲:/app/wechatSubscribe.UpdateWechatSubscribe
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@Java110Cmd(serviceCode = "wechatSubscribe.updateWechatSubscribe")
+public class UpdateWechatSubscribeCmd extends AbstractServiceCmdListener {
+
+  private static Logger logger = LoggerFactory.getLogger(UpdateWechatSubscribeCmd.class);
+
+
+    @Autowired
+    private IWechatSubscribeV1InnerServiceSMO wechatSubscribeV1InnerServiceSMOImpl;
+
+    @Override
+    public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) {
+        Assert.hasKeyAndValue(reqJson, "subId", "subId不能为空");
+Assert.hasKeyAndValue(reqJson, "appId", "appId不能为空");
+
+    }
+
+    @Override
+    @Java110Transactional
+    public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException {
+
+       WechatSubscribePo wechatSubscribePo = BeanConvertUtil.covertBean(reqJson, WechatSubscribePo.class);
+        int flag = wechatSubscribeV1InnerServiceSMOImpl.updateWechatSubscribe(wechatSubscribePo);
+
+        if (flag < 1) {
+            throw new CmdException("更新数据失败");
+        }
+
+        cmdDataFlowContext.setResponseEntity(ResultVo.success());
+    }
+}

+ 80 - 0
service-user/src/main/java/com/java110/user/dao/IWechatSubscribeV1ServiceDao.java

@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.dao;
+
+
+import com.java110.utils.exception.DAOException;
+import com.java110.entity.merchant.BoMerchant;
+import com.java110.entity.merchant.BoMerchantAttr;
+import com.java110.entity.merchant.Merchant;
+import com.java110.entity.merchant.MerchantAttr;
+
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 类表述:
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+public interface IWechatSubscribeV1ServiceDao {
+
+
+    /**
+     * 保存 微信关注信息
+     * @param info
+     * @throws DAOException DAO异常
+     */
+    int saveWechatSubscribeInfo(Map info) throws DAOException;
+    int saveWechatSubscribeInfos(Map info) throws DAOException;
+
+
+
+
+
+
+    /**
+     * 查询微信关注信息(instance过程)
+     * 根据bId 查询微信关注信息
+     * @param info bId 信息
+     * @return 微信关注信息
+     * @throws DAOException DAO异常
+     */
+    List<Map> getWechatSubscribeInfo(Map info) throws DAOException;
+
+
+
+    /**
+     * 修改微信关注信息
+     * @param info 修改信息
+     * @throws DAOException DAO异常
+     */
+    int updateWechatSubscribeInfo(Map info) throws DAOException;
+
+
+    /**
+     * 查询微信关注总数
+     *
+     * @param info 微信关注信息
+     * @return 微信关注数量
+     */
+    int queryWechatSubscribesCount(Map info);
+
+}

+ 120 - 0
service-user/src/main/java/com/java110/user/dao/impl/WechatSubscribeV1ServiceDaoImpl.java

@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.dao.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.utils.constant.ResponseConstant;
+import com.java110.utils.exception.DAOException;
+import com.java110.utils.util.DateUtil;
+import com.java110.core.base.dao.BaseServiceDao;
+import com.java110.user.dao.IWechatSubscribeV1ServiceDao;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 类表述:
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@Service("wechatSubscribeV1ServiceDaoImpl")
+public class WechatSubscribeV1ServiceDaoImpl extends BaseServiceDao implements IWechatSubscribeV1ServiceDao {
+
+    private static Logger logger = LoggerFactory.getLogger(WechatSubscribeV1ServiceDaoImpl.class);
+
+
+
+
+
+    /**
+     * 保存微信关注信息 到 instance
+     * @param info   bId 信息
+     * @throws DAOException DAO异常
+     */
+    @Override
+    public int saveWechatSubscribeInfo(Map info) throws DAOException {
+        logger.debug("保存 saveWechatSubscribeInfo 入参 info : {}",info);
+
+        int saveFlag = sqlSessionTemplate.insert("wechatSubscribeV1ServiceDaoImpl.saveWechatSubscribeInfo",info);
+
+        return saveFlag;
+    }
+    @Override
+    public int saveWechatSubscribeInfos(Map info) throws DAOException {
+        logger.debug("保存 saveWechatSubscribeInfo 入参 info : {}",info);
+
+        int saveFlag = sqlSessionTemplate.insert("wechatSubscribeV1ServiceDaoImpl.saveWechatSubscribeInfos",info);
+
+        return saveFlag;
+    }
+
+
+    /**
+     * 查询微信关注信息(instance)
+     * @param info bId 信息
+     * @return List<Map>
+     * @throws DAOException DAO异常
+     */
+    @Override
+    public List<Map> getWechatSubscribeInfo(Map info) throws DAOException {
+        logger.debug("查询 getWechatSubscribeInfo 入参 info : {}",info);
+
+        List<Map> businessWechatSubscribeInfos = sqlSessionTemplate.selectList("wechatSubscribeV1ServiceDaoImpl.getWechatSubscribeInfo",info);
+
+        return businessWechatSubscribeInfos;
+    }
+
+
+    /**
+     * 修改微信关注信息
+     * @param info 修改信息
+     * @throws DAOException DAO异常
+     */
+    @Override
+    public int updateWechatSubscribeInfo(Map info) throws DAOException {
+        logger.debug("修改 updateWechatSubscribeInfo 入参 info : {}",info);
+
+        int saveFlag = sqlSessionTemplate.update("wechatSubscribeV1ServiceDaoImpl.updateWechatSubscribeInfo",info);
+
+        return saveFlag;
+    }
+
+     /**
+     * 查询微信关注数量
+     * @param info 微信关注信息
+     * @return 微信关注数量
+     */
+    @Override
+    public int queryWechatSubscribesCount(Map info) {
+        logger.debug("查询 queryWechatSubscribesCount 入参 info : {}",info);
+
+        List<Map> businessWechatSubscribeInfos = sqlSessionTemplate.selectList("wechatSubscribeV1ServiceDaoImpl.queryWechatSubscribesCount", info);
+        if (businessWechatSubscribeInfos.size() < 1) {
+            return 0;
+        }
+
+        return Integer.parseInt(businessWechatSubscribeInfos.get(0).get("count").toString());
+    }
+
+
+}

+ 108 - 0
service-user/src/main/java/com/java110/user/smo/impl/WechatSubscribeV1InnerServiceSMOImpl.java

@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.user.smo.impl;
+
+
+import com.java110.po.fee.PayFeePo;
+import com.java110.user.dao.IWechatSubscribeV1ServiceDao;
+import com.java110.intf.user.IWechatSubscribeV1InnerServiceSMO;
+import com.java110.dto.wechatSubscribe.WechatSubscribeDto;
+import com.java110.po.wechatSubscribe.WechatSubscribePo;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.core.base.smo.BaseServiceSMO;
+import com.java110.dto.user.UserDto;
+import com.java110.dto.PageDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 类表述: 服务之前调用的接口实现类,不对外提供接口能力 只用于接口建调用
+ * add by 吴学文 at 2022-02-22 16:17:23 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@RestController
+public class WechatSubscribeV1InnerServiceSMOImpl extends BaseServiceSMO implements IWechatSubscribeV1InnerServiceSMO {
+
+    @Autowired
+    private IWechatSubscribeV1ServiceDao wechatSubscribeV1ServiceDaoImpl;
+
+
+    @Override
+    public int saveWechatSubscribe(@RequestBody  WechatSubscribePo wechatSubscribePo) {
+        int saveFlag = wechatSubscribeV1ServiceDaoImpl.saveWechatSubscribeInfo(BeanConvertUtil.beanCovertMap(wechatSubscribePo));
+        return saveFlag;
+    }
+
+    @Override
+    public int saveWechatSubscribes(@RequestBody  List<WechatSubscribePo> wechatSubscribePos){
+
+        List<Map> wechatSubscribe = new ArrayList<>();
+        for (WechatSubscribePo payFeePo : wechatSubscribePos) {
+            wechatSubscribe.add(BeanConvertUtil.beanCovertMap(payFeePo));
+        }
+
+        Map info = new HashMap();
+        info.put("wechatSubscribes", wechatSubscribe);
+        int saveFlag = wechatSubscribeV1ServiceDaoImpl.saveWechatSubscribeInfos(info);
+        return saveFlag;
+    }
+
+     @Override
+    public int updateWechatSubscribe(@RequestBody  WechatSubscribePo wechatSubscribePo) {
+        int saveFlag = wechatSubscribeV1ServiceDaoImpl.updateWechatSubscribeInfo(BeanConvertUtil.beanCovertMap(wechatSubscribePo));
+        return saveFlag;
+    }
+
+     @Override
+    public int deleteWechatSubscribe(@RequestBody  WechatSubscribePo wechatSubscribePo) {
+       wechatSubscribePo.setStatusCd("1");
+       int saveFlag = wechatSubscribeV1ServiceDaoImpl.updateWechatSubscribeInfo(BeanConvertUtil.beanCovertMap(wechatSubscribePo));
+       return saveFlag;
+    }
+
+    @Override
+    public List<WechatSubscribeDto> queryWechatSubscribes(@RequestBody  WechatSubscribeDto wechatSubscribeDto) {
+
+        //校验是否传了 分页信息
+
+        int page = wechatSubscribeDto.getPage();
+
+        if (page != PageDto.DEFAULT_PAGE) {
+            wechatSubscribeDto.setPage((page - 1) * wechatSubscribeDto.getRow());
+        }
+
+        List<WechatSubscribeDto> wechatSubscribes = BeanConvertUtil.covertBeanList(wechatSubscribeV1ServiceDaoImpl.getWechatSubscribeInfo(BeanConvertUtil.beanCovertMap(wechatSubscribeDto)), WechatSubscribeDto.class);
+
+        return wechatSubscribes;
+    }
+
+
+    @Override
+    public int queryWechatSubscribesCount(@RequestBody WechatSubscribeDto wechatSubscribeDto) {
+        return wechatSubscribeV1ServiceDaoImpl.queryWechatSubscribesCount(BeanConvertUtil.beanCovertMap(wechatSubscribeDto));    }
+
+}