13个文件已修改
3个文件已添加
601 ■■■■ 已修改文件
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoIr/IrIrrigatePlanMapper.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voPr/VoIntakeSimple.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/IrIrrigateGroupMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/IrIrrigatePlanMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/intake/IntakeCtrl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/intake/IntakeSv.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/intake/qo/QoIntake.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/irrigatePlan/IrrigatePlanCtrl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/irrigatePlan/IrrigatePlanSv.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardSv.java 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/dto/Client.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoIr/IrIrrigatePlanMapper.java
@@ -10,6 +10,7 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * @author ZhuBaoMin
@@ -74,11 +75,17 @@
    List<VoPlans> getNotCompletePlans();
    /**
     * 获取已完成的计划数量
     * @return
     */
    Long getCompletedPlansCount(Map<String, Object> params);
    /**
     * 获取已完成的计划列表,小程序计划列表页使用
     * 计划状态:1-草稿,2-未执行,3-执行中,4-已完成
     * @return
     */
    List<VoPlans> getCompletedPlans();
    List<VoPlans> getCompletedPlans(Map<String, Object> params);
    /**
     * 根据计划ID获取待终止计划的结束时间:未删除、未终止、已发布、当前时间小于计划结束时间
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java
@@ -2,10 +2,7 @@
import com.dy.pipIrrGlobal.pojoPr.PrIntake;
import com.dy.pipIrrGlobal.voPr.IntakeUpdateLngLat;
import com.dy.pipIrrGlobal.voPr.VoAllIntake;
import com.dy.pipIrrGlobal.voPr.VoIntake;
import com.dy.pipIrrGlobal.voPr.VoOnLineIntake;
import com.dy.pipIrrGlobal.voPr.*;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -197,4 +194,15 @@
     */
    int updateByPrimaryKeySelective1(IntakeUpdateLngLat record);
    /**
     * 获取未绑定到轮灌组的取水口列表
     * @return
     */
    List<VoIntakeSimple> getFreeIntakes(Map<?, ?> params);
    /**
     * 获取未绑定虚拟卡的取水口列表,给取水口绑虚拟卡使用
     * @return
     */
    List<VoIntakeSimple> getNotLinkVcIntakes();
}
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voPr/VoIntakeSimple.java
New file
@@ -0,0 +1,30 @@
package com.dy.pipIrrGlobal.voPr;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
/**
 * @author ZhuBaoMin
 * @date 2025-04-09 17:12
 * @LastEditTime 2025-04-09 17:12
 * @Description 取水口简单视图对象,轮灌组绑定取水口使用
 */
@Data
@JsonPropertyOrder({"intakeId", "intakeName"})
public class VoIntakeSimple {
    public static final long serialVersionUID = 202504091713001L;
    /**
     * 取水口ID
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long intakeId;
    /**
     * 取水口名称
     */
    private String intakeName;
}
pipIrr-platform/pipIrr-global/src/main/resources/mapper/IrIrrigateGroupMapper.xml
@@ -230,22 +230,7 @@
  <!--根据指定条件获取轮灌组记录数-->
  <select id="getSimpleGroupCount" resultType="java.lang.Long">
    SELECT COUNT(*) AS recordCount
<!--    FROM ir_irrigate_group grp-->
<!--        INNER JOIN ir_project_group pg ON pg.group_id = grp.id-->
<!--        INNER JOIN ir_project pro ON pg.project_id = pro.id-->
<!--    <where>-->
<!--      AND grp.deleted = 0-->
<!--      <if test="projectId != null and projectId != ''">-->
<!--        AND pro.id = #{projectId}-->
<!--      </if>-->
<!--      <if test="groupCode != null and groupCode != ''">-->
<!--        AND grp.group_code LIKE CONCAT('%', #{groupCode}, '%')-->
<!--      </if>-->
<!--    </where>-->
    FROM ir_irrigate_group grp
        INNER JOIN ir_project_group pg ON pg.group_id = grp.id
    <where>
      AND grp.deleted = 0
      <if test="projectId != null">
@@ -266,7 +251,6 @@
        grp.default_duration AS defaultDuration,
        0 as sort
    FROM ir_irrigate_group grp
        INNER JOIN ir_project_group pg ON pg.group_id = grp.id
    <where>
      AND grp.deleted = 0
pipIrr-platform/pipIrr-global/src/main/resources/mapper/IrIrrigatePlanMapper.xml
@@ -303,6 +303,15 @@
    ORDER BY plan.plan_state DESC
  </select>
  <!--获取已完成的计划数量-->
  <select id="getCompletedPlansCount" resultType="java.lang.Long">
    SELECT
        COUNT(*) AS recordCount
    FROM ir_irrigate_plan plan
    INNER JOIN ir_project pro ON pro.id = plan.project_id
    WHERE plan.deleted = 0 AND ((plan.plan_state = 2 AND NOW() &gt;= plan.plan_stop_time) OR (plan.executing_state = 3))
  </select>
  <!--获取已完成的计划列表,小程序计划列表页使用-->
  <select id="getCompletedPlans" resultType="com.dy.pipIrrGlobal.voIr.VoPlans">
    SELECT
@@ -318,6 +327,11 @@
        INNER JOIN ir_project pro ON pro.id = plan.project_id
    WHERE plan.deleted = 0 AND ((plan.plan_state = 2 AND NOW() &gt;= plan.plan_stop_time) OR (plan.executing_state = 3))
    ORDER BY plan.plan_state DESC
    <trim prefix="limit ">
      <if test="start != null and count != null">
        #{start,javaType=Integer,jdbcType=INTEGER}, #{count,javaType=Integer,jdbcType=INTEGER}
      </if>
    </trim>
  </select>
  <!--根据计划ID获取待终止计划的结束时间:未删除、未终止、已发布、当前时间小于计划结束时间-->
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml
@@ -737,4 +737,32 @@
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <!--获取未绑定到轮灌组的取水口列表-->
    <select id="getFreeIntakes" resultType="com.dy.pipIrrGlobal.voPr.VoIntakeSimple">
        SELECT
            id AS intakeId,
            name AS intakeName
        FROM pr_intake inta
        <where>
            AND inta.deleted = 0
            AND NOT EXISTS (SELECT 1 FROM ir_group_intake gi WHERE gi.intake_id = inta.id)
            <if test="intakeName != null and intakeName != ''">
                AND LOWER(inta.name) LIKE CONCAT('%', #{intakeName}, '%')
            </if>
        </where>
    </select>
    <!--获取未绑定虚拟卡的取水口列表,给取水口绑虚拟卡使用-->
    <select id="getNotLinkVcIntakes" resultType="com.dy.pipIrrGlobal.voPr.VoIntakeSimple">
        SELECT
            id AS intakeId,
            name AS intakeName
        FROM pr_intake inta
        WHERE NOT EXISTS (
                SELECT 1
                FROM pr_intake_vc iv
                WHERE iv.intake_id = inta.id
            ) AND inta.deleted = 0
    </select>
</mapper>
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/intake/IntakeCtrl.java
@@ -9,11 +9,9 @@
import com.dy.pipIrrGlobal.excel.CellWriteHandler;
import com.dy.pipIrrGlobal.excel.ExcelUtil;
import com.dy.pipIrrGlobal.pojoPr.PrIntake;
import com.dy.pipIrrGlobal.voPr.VoAllIntake;
import com.dy.pipIrrGlobal.voPr.VoIntake;
import com.dy.pipIrrGlobal.voPr.VoOnLineIntake;
import com.dy.pipIrrGlobal.voPr.*;
import com.dy.pipIrrGlobal.voSe.VoActiveCard;
import com.dy.pipIrrGlobal.voPr.IntakeUpdateLngLat;
import com.dy.pipIrrProject.intake.qo.QoIntake;
import com.dy.pipIrrProject.result.ProjectResultCode;
import com.taobao.api.ApiException;
import io.swagger.v3.oas.annotations.Operation;
@@ -347,4 +345,20 @@
            return BaseResponseUtils.buildException(e.getMessage());
        }
    }
    /**
     * 获取未绑定到轮灌组的取水口列表
     * @return
     */
    @GetMapping(path = "getFreeIntakes")
    @SsoAop()
    public BaseResponse<List<VoIntakeSimple>> getFreeIntakes(QoIntake qo) {
        try {
            List<VoIntakeSimple> res = intakeSv.getFreeIntakes(qo);
            return BaseResponseUtils.buildSuccess(res);
        } catch (Exception e) {
            log.error("查询取水口异常", e);
            return BaseResponseUtils.buildException(e.getMessage());
        }
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/intake/IntakeSv.java
@@ -12,10 +12,8 @@
import com.dy.pipIrrGlobal.daoPr.PrDivideMapper;
import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper;
import com.dy.pipIrrGlobal.pojoPr.PrIntake;
import com.dy.pipIrrGlobal.voPr.IntakeUpdateLngLat;
import com.dy.pipIrrGlobal.voPr.VoAllIntake;
import com.dy.pipIrrGlobal.voPr.VoIntake;
import com.dy.pipIrrGlobal.voPr.VoOnLineIntake;
import com.dy.pipIrrGlobal.voPr.*;
import com.dy.pipIrrProject.intake.qo.QoIntake;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.PojoUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -351,4 +349,13 @@
    public int updateIntakeLngLat(IntakeUpdateLngLat po) {
        return prIntakeMapper.updateByPrimaryKeySelective1(po);
    }
    /**
     * 获取未绑定到轮灌组的取水口列表
     * @return
     */
    public List<VoIntakeSimple> getFreeIntakes(QoIntake queryVo) {
        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo);
        return prIntakeMapper.getFreeIntakes(params);
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/intake/qo/QoIntake.java
New file
@@ -0,0 +1,17 @@
package com.dy.pipIrrProject.intake.qo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @author ZhuBaoMin
 * @date 2025-04-11 14:02
 * @LastEditTime 2025-04-11 14:02
 * @Description 取水口查询对象,获取未绑定轮灌组时使用
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class QoIntake {
    private String intakeName;
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java
@@ -415,6 +415,10 @@
            myParam.setOpenType(openType);
            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            // 如果命令执行失败,则再次执行命令
            if(!result.isSuccess()) {
                result = dealWithCommandResult(myParam);
            }
            Map map = new HashMap<>();
            map.put("success", result.isSuccess());
@@ -612,7 +616,13 @@
            myParam.setParam(param);
            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_wx);
            myParam.setOperator(operator);
            //BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            // 如果命令执行失败,则再次执行命令
            if(!result.isSuccess()) {
                result = dealWithCommandResult(myParam);
            }
            Map map = new HashMap<>();
            map.put("success", result.isSuccess());
@@ -783,7 +793,12 @@
            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_wx);
            myParam.setOperator(operator);
            //return dealWithCommandResult(myParam);
            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            // 如果命令执行失败,则再次执行命令
            if(!result.isSuccess()) {
                result = dealWithCommandResult(myParam);
            }
            Map map = new HashMap<>();
            map.put("success", result.isSuccess());
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java
@@ -424,7 +424,14 @@
            myParam.setParam(param);
            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_wx);
            myParam.setOperator(operator);
            return dealWithCommandResult(myParam);
            //return dealWithCommandResult(myParam);
            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            // 如果命令执行失败,则再次执行命令
            if(!result.isSuccess()) {
                result = dealWithCommandResult(myParam);
            }
            return result;
        } else {
            return BaseResponseUtils.buildErrorMsg("系统暂不支持该协议");
        }
@@ -527,7 +534,14 @@
            myParam.setParam(param);
            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_wx);
            myParam.setOperator(operator);
            return dealWithCommandResult(myParam);
            //return dealWithCommandResult(myParam);
            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            // 如果命令执行失败,则再次执行命令
            if(!result.isSuccess()) {
                result = dealWithCommandResult(myParam);
            }
            return result;
        } else {
            return BaseResponseUtils.buildErrorMsg("系统暂不支持该协议");
        }
@@ -774,7 +788,14 @@
            myParam.setParam(param);
            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_wx);
            myParam.setOperator(operator);
            return dealWithCommandResult(myParam);
            //return dealWithCommandResult(myParam);
            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
            // 如果命令执行失败,则再次执行命令
            if(!result.isSuccess()) {
                result = dealWithCommandResult(myParam);
            }
            return result;
        } else {
            return BaseResponseUtils.buildErrorMsg("系统暂不支持该协议");
        }
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/irrigatePlan/IrrigatePlanCtrl.java
@@ -2,6 +2,8 @@
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.common.webUtil.QueryConditionVo;
import com.dy.common.webUtil.QueryResultVo;
import com.dy.pipIrrGlobal.pojoIr.IrIrrigatePlan;
import com.dy.pipIrrGlobal.pojoIr.IrIrrigateSchedule;
import com.dy.pipIrrGlobal.pojoIr.IrPlanOperate;
@@ -388,10 +390,9 @@
     * @return
     */
    @GetMapping(path = "/getCompletedPlans")
    public BaseResponse<List<VoPlans>> getCompletedPlans() {
    public BaseResponse<QueryResultVo<List<VoPlans>>> getCompletedPlans(QueryConditionVo qo) {
        try {
            List<VoPlans> res = irrigatePlanSv.getCompletedPlans();
            return BaseResponseUtils.buildSuccess(res);
            return BaseResponseUtils.buildSuccess(irrigatePlanSv.getCompletedPlans(qo));
        } catch (Exception e) {
            log.error("获取项目记录异常", e);
            return BaseResponseUtils.buildException(e.getMessage());
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/irrigatePlan/IrrigatePlanSv.java
@@ -4,6 +4,8 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.common.webUtil.QueryConditionVo;
import com.dy.common.webUtil.QueryResultVo;
import com.dy.pipIrrGlobal.daoIr.*;
import com.dy.pipIrrGlobal.daoRm.RmCommandHistoryMapper;
import com.dy.pipIrrGlobal.pojoIr.IrIrrigatePlan;
@@ -12,9 +14,11 @@
import com.dy.pipIrrGlobal.pojoIr.IrPlanSchedule;
import com.dy.pipIrrGlobal.voIr.*;
import com.dy.pipIrrGlobal.voRm.VoIntakeVc;
import com.dy.pipIrrGlobal.voSe.VoClient;
import com.dy.pipIrrWechat.irrigatePlan.dto.PlanSimple;
import com.dy.pipIrrWechat.irrigatePlan.enums.OperateTypeENUM;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.PojoUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -186,8 +190,18 @@
     * 获取已完成的计划列表,小程序计划列表页使用
     * @return
     */
    public List<VoPlans> getCompletedPlans() {
        return irrigatePlanMapper.getCompletedPlans();
    public QueryResultVo<List<VoPlans>> getCompletedPlans(QueryConditionVo queryVo) {
        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo) ;
        Long itemTotal = (long)irrigatePlanMapper.getCompletedPlansCount(params);
        QueryResultVo<List<VoPlans>> rsVo = new QueryResultVo<>() ;
        rsVo.pageSize = queryVo.pageSize ;
        rsVo.pageCurr = queryVo.pageCurr ;
        rsVo.calculateAndSet(itemTotal, params);
        rsVo.obj = irrigatePlanMapper.getCompletedPlans(params);
        return rsVo ;
    }
    /**
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java
@@ -5,11 +5,13 @@
import com.dy.common.webUtil.QueryResultVo;
import com.dy.pipIrrGlobal.pojoSe.SeVcOperate;
import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
import com.dy.pipIrrGlobal.voIr.VoPlanDetails;
import com.dy.pipIrrGlobal.voSe.VoRechargeProfile;
import com.dy.pipIrrGlobal.voSe.VoVcRecharge;
import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
import com.dy.pipIrrWechat.result.WechatResultCode;
import com.dy.pipIrrWechat.util.PayHelper;
import com.dy.pipIrrWechat.virtualCard.dto.Client;
import com.dy.pipIrrWechat.virtualCard.dto.DtoCancel;
import com.dy.pipIrrWechat.virtualCard.dto.DtoRegist;
import com.dy.pipIrrWechat.virtualCard.enums.LastOperateENUM;
@@ -23,10 +25,7 @@
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
/**
 * @author ZhuBaoMin
@@ -57,61 +56,68 @@
        if(bindingResult != null && bindingResult.hasErrors()){
            return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        Long clientId = po.getClientId();
        // 获取5级行政区划串areaCode
        Long areaCodeL = virtualCardSv.getAreaCodeById(clientId);
        if(areaCodeL == null) {
            return BaseResponseUtils.buildErrorMsg(WechatResultCode.AREA_CODE_MISTAKE.getMessage());
        Map map_result = virtualCardSv.addVC(po.getClientId(), 0D);
        if(map_result.get("success").equals(false)) {
            return BaseResponseUtils.buildErrorMsg(map_result.get("msg").toString());
        }
        String areaCode = String.valueOf(areaCodeL);
        return BaseResponseUtils.buildSuccess() ;
        /**
         * 根据行政区划串(areaCode)在虚拟卡表中针对虚拟卡编号(vcNum)进行模糊查询
         * 如果5位顺序号已经达到最大值,提示用户联系系统管理员
         * 如果5位顺序号未达到最大值,则加1
         * cardNum为新的卡号
         */
        String vcNum = Optional.ofNullable(virtualCardSv.getVcCardNumOfMax(areaCode)).orElse("");
        if(vcNum != null && vcNum.trim().length() > 0) {
            Integer number = Integer.parseInt(vcNum.substring(12));
            number = number + 1;
            if(number > 65535) {
                return BaseResponseUtils.buildErrorMsg(WechatResultCode.CARD_NUMBER_OVERRUN.getMessage());
            }
            vcNum = vcNum.substring(0, 12) + String.format("%05d", number);
        } else {
            vcNum = areaCode + "00001";
        }
        // 生成虚拟卡记录
        SeVirtualCard seVirtualCard = new SeVirtualCard();
        seVirtualCard.setVcNum(Long.parseLong(vcNum));
        seVirtualCard.setClientId(clientId);
        seVirtualCard.setMoney(0d);
        seVirtualCard.setState((byte)1);
        seVirtualCard.setLastOperate(LastOperateENUM.OPEN_ACCOUNT.getCode());
        seVirtualCard.setLastOperateTime(new Date());
        seVirtualCard.setInUse((byte) 0);
        seVirtualCard.setCreateTime(new Date());
        Long vcId = virtualCardSv.insertVirtualCard(seVirtualCard);
        if(vcId == null) {
            return BaseResponseUtils.buildErrorMsg(WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
        }
        // 生成虚拟卡操作记录,注册虚拟卡操作人为农户
        SeVcOperate seVcOperate = new SeVcOperate();
        seVcOperate.setVcId(vcId);
        seVcOperate.setClientId(clientId);
        seVcOperate.setOperateType(LastOperateENUM.OPEN_ACCOUNT.getCode());
        seVcOperate.setOperator(clientId);
        seVcOperate.setOperateTime(new Date());
        Long vcOperateId = virtualCardSv.insertVcOperate(seVcOperate);
        if(vcOperateId == null) {
            return BaseResponseUtils.buildErrorMsg(WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
        //Long clientId = po.getClientId();
        //
        //// 获取5级行政区划串areaCode
        //Long areaCodeL = virtualCardSv.getAreaCodeById(clientId);
        //if(areaCodeL == null) {
        //    return BaseResponseUtils.buildErrorMsg(WechatResultCode.AREA_CODE_MISTAKE.getMessage());
        //}
        //String areaCode = String.valueOf(areaCodeL);
        //
        ///**
        // * 根据行政区划串(areaCode)在虚拟卡表中针对虚拟卡编号(vcNum)进行模糊查询
        // * 如果5位顺序号已经达到最大值,提示用户联系系统管理员
        // * 如果5位顺序号未达到最大值,则加1
        // * cardNum为新的卡号
        // */
        //String vcNum = Optional.ofNullable(virtualCardSv.getVcCardNumOfMax(areaCode)).orElse("");
        //if(vcNum != null && vcNum.trim().length() > 0) {
        //    Integer number = Integer.parseInt(vcNum.substring(12));
        //    number = number + 1;
        //    if(number > 65535) {
        //        return BaseResponseUtils.buildErrorMsg(WechatResultCode.CARD_NUMBER_OVERRUN.getMessage());
        //    }
        //    vcNum = vcNum.substring(0, 12) + String.format("%05d", number);
        //} else {
        //    vcNum = areaCode + "00001";
        //}
        //
        //// 生成虚拟卡记录
        //SeVirtualCard seVirtualCard = new SeVirtualCard();
        //seVirtualCard.setVcNum(Long.parseLong(vcNum));
        //seVirtualCard.setClientId(clientId);
        //seVirtualCard.setMoney(0d);
        //seVirtualCard.setState((byte)1);
        //seVirtualCard.setLastOperate(LastOperateENUM.OPEN_ACCOUNT.getCode());
        //seVirtualCard.setLastOperateTime(new Date());
        //seVirtualCard.setInUse((byte) 0);
        //seVirtualCard.setCreateTime(new Date());
        //Long vcId = virtualCardSv.insertVirtualCard(seVirtualCard);
        //if(vcId == null) {
        //    return BaseResponseUtils.buildErrorMsg(WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
        //}
        //
        //// 生成虚拟卡操作记录,注册虚拟卡操作人为农户
        //SeVcOperate seVcOperate = new SeVcOperate();
        //seVcOperate.setVcId(vcId);
        //seVcOperate.setClientId(clientId);
        //seVcOperate.setOperateType(LastOperateENUM.OPEN_ACCOUNT.getCode());
        //seVcOperate.setOperator(clientId);
        //seVcOperate.setOperateTime(new Date());
        //Long vcOperateId = virtualCardSv.insertVcOperate(seVcOperate);
        //if(vcOperateId == null) {
        //    return BaseResponseUtils.buildErrorMsg(WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
        //}
        //
        //return BaseResponseUtils.buildSuccess(true) ;
    }
    /**
@@ -344,4 +350,23 @@
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
    /**
     * 绑定虚拟卡到取水口
     * @return
     */
    @PostMapping(path = "linkVcToIntake")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> linkVcToIntake(@RequestBody @Valid Client client, BindingResult bindingResult) {
        if(bindingResult != null && bindingResult.hasErrors()){
            return BaseResponseUtils.buildErrorMsg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        Long clientId = client.getClientId();
        Map map_result = virtualCardSv.linkVcToIntake(clientId);
        if(map_result.get("success").equals(false)) {
            return BaseResponseUtils.buildErrorMsg(map_result.get("msg").toString());
        }
        return BaseResponseUtils.buildSuccess() ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardSv.java
@@ -3,13 +3,20 @@
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.common.webUtil.QueryResultVo;
import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper;
import com.dy.pipIrrGlobal.daoPr.PrIntakeVcMapper;
import com.dy.pipIrrGlobal.daoSe.*;
import com.dy.pipIrrGlobal.pojoIr.IrPlanOperate;
import com.dy.pipIrrGlobal.pojoPr.PrIntakeVc;
import com.dy.pipIrrGlobal.pojoSe.*;
import com.dy.pipIrrGlobal.voPr.VoIntakeSimple;
import com.dy.pipIrrGlobal.voSe.VoOrders;
import com.dy.pipIrrGlobal.voSe.VoRechargeProfile;
import com.dy.pipIrrGlobal.voSe.VoVcRecharge;
import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
import com.dy.pipIrrWechat.irrigatePlan.enums.OperateTypeENUM;
import com.dy.pipIrrWechat.result.WechatResultCode;
import com.dy.pipIrrWechat.virtualCard.dto.DtoRegist;
import com.dy.pipIrrWechat.virtualCard.dto.DtoVirtualCard;
import com.dy.pipIrrWechat.virtualCard.enums.LastOperateENUM;
import com.dy.pipIrrWechat.virtualCard.enums.OrderStateENUM;
@@ -21,9 +28,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
 * @author ZhuBaoMin
@@ -56,11 +61,18 @@
    @Autowired
    private SeRechargeProfileMapper seRechargeProfileMapper;
    @Autowired
    private PrIntakeMapper prIntakeMapper;
    @Autowired
    private PrIntakeVcMapper prIntakeVcMapper;
    @Value("${vc.alarmValue}")
    private Integer alarmValue;
    /**
     * 根据农户ID获取5级行政区划代码,注册虚拟卡使用
     *
     * @param clientId 农户ID
     * @return 5级行政区划代码
     */
@@ -70,6 +82,7 @@
    /**
     * 获取农户全部虚拟卡
     *
     * @return
     */
    public List<VoVirtualCard> getVCs(Long clientId) {
@@ -78,6 +91,7 @@
    /**
     * 根据虚拟卡ID获取虚拟卡对象
     *
     * @param vcId
     * @return
     */
@@ -87,6 +101,7 @@
    /**
     * 注册虚拟卡
     *
     * @param po
     * @return
     */
@@ -97,16 +112,18 @@
    /**
     * 根据农户ID及虚拟卡ID获取正常状态的虚拟卡对象
     *
     * @param clientId
     * @param vcId
     * @return
     */
    public SeVirtualCard getVcByClientIdAndVcId (Long clientId, Long vcId) {
    public SeVirtualCard getVcByClientIdAndVcId(Long clientId, Long vcId) {
        return seVirtualCardMapper.getVcByClientIdAndVcId(clientId, vcId);
    }
    /**
     * 根据虚拟卡ID注销虚拟卡
     *
     * @param clientId
     * @param vcId
     * @return
@@ -117,6 +134,7 @@
    /**
     * 根据行政区划串模糊查询虚拟卡编号,注册虚拟卡使用
     *
     * @param areaCode
     * @return
     */
@@ -136,6 +154,7 @@
    /**
     * 修改虚拟卡
     * 充值、消费、申请退款、审核退款时需要修改虚拟卡的:余额、最后操作、最后操作时间
     *
     * @param po
     * @return
     */
@@ -145,6 +164,7 @@
    /**
     * 根据虚拟卡编号获取虚拟卡对象
     *
     * @param virtualId
     * @return
     */
@@ -155,6 +175,7 @@
    /**
     * 添加虚拟卡充值记录
     * JSAPI下单后生成部分充值记录
     *
     * @param po
     * @return -1:虚拟卡不存在,0:添加充值记录失败
     */
@@ -168,7 +189,7 @@
        // 验证该虚拟卡账户是否存在并取出当前账户余额
        SeVirtualCard seVirtualCard = seVirtualCardMapper.selectByPrimaryKey(virtualId);
        if(seVirtualCard == null) {
        if (seVirtualCard == null) {
            return -1L;
        }
        Double money = seVirtualCard.getMoney();
@@ -184,7 +205,7 @@
        seVcRecharge.setOrderState(OrderStateENUM.NON_PAYMENT.getCode());
        seVcRechargeMapper.insert(seVcRecharge);
        Long rechargeId = seVcRecharge.getId();
        if(rechargeId == null) {
        if (rechargeId == null) {
            return 0L;
        }
        return rechargeId;
@@ -192,6 +213,7 @@
    /**
     * 根据订单号获取虚拟卡充值对象
     *
     * @param orderNumber
     * @return
     */
@@ -202,15 +224,16 @@
    /**
     * 修改虚拟卡充值记录
     * 微信支付通知后:
     *      1. 更新充值表:充值后余额、支付完成时间、订单状态
     *      2. 更新虚拟卡表:账户余额、最后操作、最后操作时间
     * 1. 更新充值表:充值后余额、支付完成时间、订单状态
     * 2. 更新虚拟卡表:账户余额、最后操作、最后操作时间
     *
     * @param orderNumber 订单编号
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> updateVCRecharge(String orderNumber, Date rechargeTime) {
        SeVcRecharge seVcRecharge = seVcRechargeMapper.getVCRechargeByorderNumber(orderNumber);
        if(seVcRecharge == null) {
        if (seVcRecharge == null) {
            return BaseResponseUtils.buildFail(WechatResultCode.RECHARGE_NOT_EXIST.getMessage());
        }
@@ -223,27 +246,28 @@
        seVcRecharge.setRechargeTime(rechargeTime);
        seVcRecharge.setOrderState(OrderStateENUM.PAID.getCode());
        Integer rec = seVcRechargeMapper.updateByPrimaryKeySelective(seVcRecharge);
        if(rec == null) {
        if (rec == null) {
            return BaseResponseUtils.buildFail(WechatResultCode.RECHARGE_FAIL.getMessage());
        }
        SeVirtualCard seVirtualCard = seVirtualCardMapper.selectByPrimaryKey(virtualId);
        if(seVirtualCard == null) {
        if (seVirtualCard == null) {
            return BaseResponseUtils.buildFail(WechatResultCode.VIRTUAL_CARD_NOT_EXIST.getMessage());
        }
        seVirtualCard.setMoney(afterRrecharge);
        seVirtualCard.setLastOperate(LastOperateENUM.RECHARGE.getCode());
        seVirtualCard.setLastOperateTime(new Date());
        Integer rec2 = seVirtualCardMapper.updateByPrimaryKeySelective(seVirtualCard);
        if(rec2 == null) {
        if (rec2 == null) {
            return BaseResponseUtils.buildFail(WechatResultCode.RECHARGE_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
        return BaseResponseUtils.buildSuccess(true);
    }
    /**
     * 修改虚拟卡充值记录(废弃)
     * 微信小程序支付通知后修改:余额、充值后余额、充值完成时间
     *
     * @param po
     * @return
     */
@@ -253,16 +277,18 @@
    /**
     * 根据虚拟卡号获取订单列表
     *
     * @param virtualId
     * @return
     */
    public List<VoOrders> selectOrders(Long virtualId) {
        List<VoOrders> rsVo = seVcRechargeMapper.getOrders(virtualId);
        return rsVo ;
        return rsVo;
    }
    /**
     * 根据退款ID获取退款对象
     *
     * @param refundId
     * @return
     */
@@ -272,6 +298,7 @@
    /**
     * 添加退款申请
     *
     * @param po
     * @return
     */
@@ -282,6 +309,7 @@
    /**
     * 修改退款记录
     *
     * @param po
     * @return
     */
@@ -291,6 +319,7 @@
    /**
     * 根据订单号获取其各笔退款金额
     *
     * @param orderNumber
     * @return
     */
@@ -301,6 +330,7 @@
    /**
     * 添加退款分项
     *
     * @param po
     * @return
     */
@@ -311,6 +341,7 @@
    /**
     * 编辑退款分项
     *
     * @param po
     * @return
     */
@@ -320,22 +351,24 @@
    /**
     * 根据订单号生成退款单号
     *
     * @param orderNumber
     * @return
     */
    public String generateRefundNumber(String orderNumber) {
        String refundNumber = seVcRefundItemMapper.getLastRefundNumber(orderNumber);
        if(refundNumber == null) {
        if (refundNumber == null) {
            refundNumber = orderNumber + "01";
            return refundNumber;
        }
        String a = String.format("%02d", (Integer.parseInt(refundNumber.substring(29,30).trim()) + 1));
        return  a;
        String a = String.format("%02d", (Integer.parseInt(refundNumber.substring(29, 30).trim()) + 1));
        return a;
    }
    /**
     * 根据订单号获取充值金额,调用退款申请接口使用
     *
     * @param orderNumber
     * @return
     */
@@ -346,6 +379,7 @@
    /**
     * 根据退款通知接口返回的退款单号反查退款ID,查询该退款ID下未退款记录数量
     *
     * @param refundNumber
     * @return
     */
@@ -355,6 +389,7 @@
    /**
     * 根据退款单号获取退款ID,退款通知后更新退款表所需
     *
     * @param refundNumber
     * @return
     */
@@ -364,10 +399,11 @@
    /**
     * 获取虚拟卡充值记录
     *
     * @param dtoVcRecharge
     * @return
     */
    public QueryResultVo<List<VoVcRecharge>> getVcRechargeRecords(QoVcRecharge dtoVcRecharge){
    public QueryResultVo<List<VoVcRecharge>> getVcRechargeRecords(QoVcRecharge dtoVcRecharge) {
        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(dtoVcRecharge);
        Long itemTotal = seVirtualCardMapper.getRechargeRecordCount(params);
@@ -383,6 +419,7 @@
    /**
     * 添加虚拟卡操作记录
     *
     * @param po
     * @return
     */
@@ -393,9 +430,144 @@
    /**
     * 获取虚拟卡常用充值金额配置
     *
     * @return
     */
    public List<VoRechargeProfile> gerRechargeProfiles() {
        return seRechargeProfileMapper.gerRechargeProfiles();
    }
    /**
     * 注册虚拟卡
     *
     * @param clientId
     * @return
     */
    public Map addVC(Long clientId, Double money) {
        // 获取5级行政区划串areaCode
        Long areaCodeL = getAreaCodeById(clientId);
        if (areaCodeL == null) {
            Map map = new HashMap<>();
            map.put("success", false);
            map.put("msg", WechatResultCode.AREA_CODE_MISTAKE.getMessage());
            map.put("content", null);
            return map;
        }
        String areaCode = String.valueOf(areaCodeL);
        /**
         * 根据行政区划串(areaCode)在虚拟卡表中针对虚拟卡编号(vcNum)进行模糊查询
         * 如果5位顺序号已经达到最大值,提示用户联系系统管理员
         * 如果5位顺序号未达到最大值,则加1
         * cardNum为新的卡号
         */
        String vcNum = Optional.ofNullable(getVcCardNumOfMax(areaCode)).orElse("");
        if (vcNum != null && vcNum.trim().length() > 0) {
            Integer number = Integer.parseInt(vcNum.substring(12));
            number = number + 1;
            if (number > 65535) {
                Map map = new HashMap<>();
                map.put("success", false);
                map.put("msg", WechatResultCode.CARD_NUMBER_OVERRUN.getMessage());
                map.put("content", null);
                return map;
            }
            vcNum = vcNum.substring(0, 12) + String.format("%05d", number);
        } else {
            vcNum = areaCode + "00001";
        }
        // 生成虚拟卡记录
        SeVirtualCard seVirtualCard = new SeVirtualCard();
        seVirtualCard.setVcNum(Long.parseLong(vcNum));
        seVirtualCard.setClientId(clientId);
        seVirtualCard.setMoney(money);
        seVirtualCard.setState((byte) 1);
        seVirtualCard.setLastOperate(LastOperateENUM.OPEN_ACCOUNT.getCode());
        seVirtualCard.setLastOperateTime(new Date());
        seVirtualCard.setInUse((byte) 0);
        seVirtualCard.setCreateTime(new Date());
        Long vcId = insertVirtualCard(seVirtualCard);
        if (vcId == null) {
            Map map = new HashMap<>();
            map.put("success", false);
            map.put("msg", WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
            map.put("content", null);
            return map;
        }
        // 生成虚拟卡操作记录,注册虚拟卡操作人为农户
        SeVcOperate seVcOperate = new SeVcOperate();
        seVcOperate.setVcId(vcId);
        seVcOperate.setClientId(clientId);
        seVcOperate.setOperateType(LastOperateENUM.OPEN_ACCOUNT.getCode());
        seVcOperate.setOperator(clientId);
        seVcOperate.setOperateTime(new Date());
        Long vcOperateId = insertVcOperate(seVcOperate);
        if (vcOperateId == null) {
            Map map = new HashMap<>();
            map.put("success", false);
            map.put("msg", WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
            map.put("content", null);
            return map;
        }
        Map map = new HashMap<>();
        map.put("success", true);
        map.put("msg", "虚拟卡注册成功");
        map.put("content", vcId);
        return map;
    }
    /**
     * 获取未绑定虚拟卡的取水口列表,给取水口绑虚拟卡使用
     *
     * @return
     */
    public Map linkVcToIntake(Long clientId) {
        // 验证是否存在取水口未绑虚拟卡
        List<VoIntakeSimple> list = prIntakeMapper.getNotLinkVcIntakes();
        if (list == null || list.size() == 0) {
            Map map = new HashMap<>();
            map.put("success", true);
            map.put("msg", "所有取水口都匹配了虚拟卡");
            map.put("content", null);
            return map;
        }
        // 遍历所有未绑虚拟卡的取水口
        for (VoIntakeSimple voIntakeSimple : list) {
            Long intakeId = voIntakeSimple.getIntakeId();
            // 创建虚拟卡
            Map map_result = addVC(clientId, 100000D);
            if (map_result.get("success").equals(false)) {
                Map map = new HashMap<>();
                map.put("success", false);
                map.put("msg", "灌虚拟卡注册失败");
                map.put("content", null);
                return map;
            }
            Long vcId = (Long) map_result.get("content");
            // 取水口绑虚拟卡
            PrIntakeVc intakeVc = new PrIntakeVc();
            intakeVc.setIntakeId(intakeId);
            intakeVc.setVcId(vcId);
            Integer result = prIntakeVcMapper.insert(intakeVc);
            if (result == null) {
                Map map = new HashMap<>();
                map.put("success", false);
                map.put("msg", "取水口绑虚拟卡失败");
                map.put("content", null);
                return map;
            }
        }
        Map map = new HashMap<>();
        map.put("success", true);
        map.put("msg", "取水口绑虚拟卡成功");
        map.put("content", null);
        return map;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/dto/Client.java
New file
@@ -0,0 +1,22 @@
package com.dy.pipIrrWechat.virtualCard.dto;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
 * @author ZhuBaoMin
 * @date 2025-04-10 16:09
 * @LastEditTime 2025-04-10 16:09
 * @Description 农户对象,给取水口绑虚拟卡时使用
 */
@Data
public class Client {
    public static final long serialVersionUID = 202504101610001L;
    /**
     * 农户ID
     */
    @NotNull(message = "农户ID不能为空")
    private Long clientId;
}