liulin
2025-07-08 7bfa5f63181b0cedd43899e9dacdfca26ebfd4ad
src/main/java/com/lunhan/water/service/PaymentRecordsService.java
@@ -1,38 +1,55 @@
/**
#                                                    __----~~~~~~~~~~~------___
#                                   .  .   ~~//====......          __--~ ~~
#                   -.            \_|//     |||\\  ~~~~~~::::... /~
#                ___-==_       _-~o~  \/    |||  \\            _/~~-
#        __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
#    _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
#  .~       .~       |   \\ -_    /  /-   /   ||      \   /
# /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
# |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
#          '         ~-|      /|    |-~\~~       __--~~
#                      |-~~-_/ |    |   ~\_   _-~            /\
#                           /  \     \__   \/~                \__
#                       _--~ _/ | .-~~____--~-/                  ~~==.
#                      ((->/~   '.|||' -_|    ~~-/ ,              . _||
#                                 -_     ~\      ~~---l__i__i__i--~~_/
#                                 _-~-__   ~)  \--______________--~~
#                               //.-~~~-~_--~- |-------~~~~~~~~
#                                      //.-~~~--\
#                  神兽保佑
#                  永无BUG!
*/
 #                                                    __----~~~~~~~~~~~------___
 #                                   .  .   ~~//====......          __--~ ~~
 #                   -.            \_|//     |||\\  ~~~~~~::::... /~
 #                ___-==_       _-~o~  \/    |||  \\            _/~~-
 #        __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 #    _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 #  .~       .~       |   \\ -_    /  /-   /   ||      \   /
 # /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 # |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 #          '         ~-|      /|    |-~\~~       __--~~
 #                      |-~~-_/ |    |   ~\_   _-~            /\
 #                           /  \     \__   \/~                \__
 #                       _--~ _/ | .-~~____--~-/                  ~~==.
 #                      ((->/~   '.|||' -_|    ~~-/ ,              . _||
 #                                 -_     ~\      ~~---l__i__i__i--~~_/
 #                                 _-~-__   ~)  \--______________--~~
 #                               //.-~~~-~_--~- |-------~~~~~~~~
 #                                      //.-~~~--\
 #                  神兽保佑
 #                  永无BUG!
 */
package com.lunhan.water.service;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.lunhan.water.common.*;
import com.lunhan.water.common.enums.*;
import com.lunhan.water.common.jwt.LoginUserDTO;
import com.lunhan.water.common.model.Tuple;
import com.lunhan.water.common.util.*;
import com.lunhan.water.entity.enums.EBillPayStatus;
import com.lunhan.water.entity.enums.ECapitalChange;
import com.lunhan.water.entity.request.paymentrecords.ReqBuyWater;
import com.lunhan.water.host.mqtt.CountVO;
import com.lunhan.water.host.mqtt.MQTTServer;
import com.lunhan.water.repository.impl.*;
import com.lunhan.water.repository.po.*;
import com.lunhan.water.repository.vo.WaterFacilityVO;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import com.lunhan.water.repository.impl.PaymentRecordsMapperImpl;
import com.lunhan.water.repository.po.PaymentRecordsPO;
import com.lunhan.water.entity.request.paymentrecords.ReqCreatePaymentRecords;
import com.lunhan.water.entity.request.paymentrecords.ReqModifyPaymentRecords;
import com.lunhan.water.entity.search.SearchPaymentRecords;
@@ -45,8 +62,24 @@
 */
@Service
public class PaymentRecordsService extends BaseService {
    private static final Logger DEBUG_LOGGER = LoggerUtil.get(ELogger.DEBUG);
    private static final Logger ERROR_LOGGER = LoggerUtil.get(ELogger.SYS_ERROR);
    @Autowired
    private PaymentRecordsMapperImpl mapper;
    @Autowired
    private UserLoginMapperImpl userLoginMapper;
    @Autowired
    private WaterFacilityMapperImpl waterFacilityMapper;
    @Autowired
    private MQTTServer mqttServer;
    @Autowired
    private UserCapitalChangeMapperImpl userCapitalChangeMapper;
    @Autowired
    private HeartbeatDataMapperImpl heartbeatDataMapper;
    @Autowired
    private FacilityAlarmRecordMapperImpl facilityAlarmRecordMapper;
    @Autowired
    private WaterFacilityRecordsMapperImpl waterFacilityRecordsMapper;
    public ExecutedResult<Long> create(ReqCreatePaymentRecords request) {
        // 转换po
@@ -92,7 +125,7 @@
        return ExecutedResult.success(result);
    }
//    public ExecutedResult<String> stop(Long id) {
    //    public ExecutedResult<String> stop(Long id) {
//        // 验证记录是否存在
//        ExecutedResult<PaymentRecordsPO> checkExists = this.check4Id(id);
//        if (checkExists.isFailed()) {
@@ -183,6 +216,182 @@
//        return ExecutedResult.success();
//    }
    /**
     * mqtt发送取水指令
     * @param request 消息内容
     */
    public ExecutedResult<String> userWaterInTaking(LoginUserDTO loginUser, ReqBuyWater request) {
        WaterFacilityPO facilityPO = waterFacilityMapper.getById(request.getFacilityId());
        if (Objects.isNull(facilityPO)) {
            return ExecutedResult.failed("未查询到取水设备!");
        }
        UserLoginPO userLoginPO = userLoginMapper.get4Openid(loginUser.getUserId());
        if (Objects.isNull(userLoginPO)) {
            return ExecutedResult.failed("用户数据不存在!");
        }
        if (userLoginPO.getBalance().compareTo(request.getAmount()) < 0) {
            return ExecutedResult.failed("余额水量不足!");
        }
        //发送mqtt取水指令
        String topic = "zundong/" + facilityPO.getFacilityCode() + "/send";
        JsonObject data = new JsonObject();
        data.addProperty(facilityPO.getFacilityCode() + "_count2", request.getAmount().multiply(BigDecimal.valueOf(100)));
        data.addProperty(facilityPO.getFacilityCode() + "_state2", 1);
        boolean send=false;
        if (Objects.nonNull(mqttServer)) {
            send = mqttServer.send(topic, data.toString());
        } else {
            try {
                System.out.println("mqttServer bean尚未初始化...");
                mqttServer = SpringUtil.getBean(MQTTServer.class);
                System.out.println("mqttServer 初始化bean成功!");
            } catch (Exception ignored) {
            }
            if (Objects.nonNull(mqttServer)) {
                send=mqttServer.send(topic, data.toString());
            }
        }
        if(!send){
            ExecutedResult.failed("通讯断开!");
        }
        //扣除余额
        //创建消费记录
        PaymentRecordsPO recordsPO=new PaymentRecordsPO();
        recordsPO.setUserId(userLoginPO.getId());
        recordsPO.setUserName(userLoginPO.getUserName());
        recordsPO.setFacilityCode(facilityPO.getFacilityCode());
        recordsPO.setPaymentAmount(request.getAmount());
        recordsPO.setWaterAmount(request.getAmount());
        recordsPO.setPayTime(LocalDateTimeUtil.nowDateTimeStr());
        recordsPO.setPayStatus(EBillPayStatus.PAID.getValue());
        recordsPO.setComment("取水");
        recordsPO.setCreateTime(LocalDateTimeUtil.nowTimeStamp());
        mapper.insert(recordsPO);
        //修改余额
        BigDecimal beforeMoney=userLoginPO.getBalance();
        BigDecimal subtract = beforeMoney.subtract(request.getAmount());
        userLoginPO.setBalance(subtract);
        userLoginMapper.updateById(userLoginPO);
        //生成余额变动记录
        UserCapitalChangePO changePO=new UserCapitalChangePO();
        changePO.setUserId(userLoginPO.getId());
        changePO.setBusiness(ECapitalChange.WATER_BILL_COUNTER_PAY.getValue());
        changePO.setBusinessName("取水");
        changePO.setBusinessCode("QS"+SnowFlakeUtil.getId());
        changePO.setChangeMoney(request.getAmount());
        changePO.setBeforeMoney(beforeMoney);
        changePO.setAfterMoney(subtract);
        changePO.setCreateTime(LocalDateTimeUtil.nowTimeStamp());
        userCapitalChangeMapper.insert(changePO);
        return ExecutedResult.success("请点击设备取水按钮取水");
    }
    /**
     * mqtt收到消息
     * @param topic 主题
     * @param msg 消息内容
     */
    public void mqttReceived(String topic, String msg) {
        if (StringUtil.isNullOrEmpty(topic)) {
            ERROR_LOGGER.error("主题不能为空");
            return;
        }
        if (StringUtil.isNullOrEmpty(msg)) {
            ERROR_LOGGER.error("消息不能为空");
            return;
        }
        String[] array = StringUtil.split(topic, "/");
        if (array.length != 3) {
            ERROR_LOGGER.error("主题未能解析, " + topic);
            return;
        }
        WaterFacilityPO facilityPO = waterFacilityMapper.getCode(array[1]);
        if (Objects.isNull(facilityPO)) {
            DEBUG_LOGGER.error("设备数据未找到!");
            return;
        }
//        数据上报格式:
//        主题格式:zundong/QS001/data
//        数据格式:{"Data":
//          [
//              {"name":"QS001_state","value":1}, //状态
//              {"name":"QS001_fault","value":0}, //是否故障
//              {"name":"QS001_count","value":10000} //总水量
//          ],"time":"2025-07-02 15:19:17"
//        }
//        心跳上报格式:
//        主题格式:zundong/QS001/state
//        数据格式:{"Data":
//              [
//               {"name":"QS001_heartbeat","value":1} //心跳
//              ],"time":"2025-07-02 15:19:17"
//          }
        //消息解析
        Gson gson = new Gson();
        JsonObject object = gson.fromJson(msg, JsonObject.class);
        String time = object.get("time").getAsString();
        //long time = LocalDateTimeUtil.getTimeStamp(asJsonObject).getTime();
        Type listType = new TypeToken<List<CountVO>>() {
        }.getType();
        JsonArray data = object.getAsJsonArray("Data");
        List<CountVO> listVo = gson.fromJson(data, listType);
        switch (array[2]) {
            case "data":
                uploadData(time,facilityPO,listVo);
                break;
//            case "state":
//                uploadState(time,facilityPO,listVo);
//                break;
        }
    }
    public void uploadData(String time,WaterFacilityPO facilityPO, List<CountVO> listVo) {
        CountVO stateVo = listVo.stream().filter(x -> x.getName().equals(facilityPO.getFacilityCode() + "_state1")).findFirst().orElse(null);
        CountVO heartbeat = listVo.stream().filter(x -> x.getName().equals(facilityPO.getFacilityCode() + "_heartbeat")).findFirst().orElse(null);
        CountVO countVO = listVo.stream().filter(x -> x.getName().equals(facilityPO.getFacilityCode() + "_count1")).findFirst().orElse(null);
        switch (stateVo.getValue()) {
            case "0"://取水完成
                BigDecimal divide = new BigDecimal(countVO.getValue()).setScale(2,RoundingMode.DOWN);
                BigDecimal subtract=divide.subtract(facilityPO.getWaterCount());
                if(subtract.compareTo(BigDecimal.ZERO)>0){
                    facilityPO.setWaterCount(divide);
                    int i = waterFacilityMapper.updateById(facilityPO);
                    if(i>0){
                        WaterFacilityRecordsPO recordsPO=new WaterFacilityRecordsPO();
                        recordsPO.setFacilityId(facilityPO.getId());
                        recordsPO.setFacilityName(facilityPO.getFacilityName());
                        recordsPO.setWaterValue(subtract);
                        recordsPO.setUseDate(time);
                        recordsPO.setCreateTime(LocalDateTimeUtil.nowTimeStamp());
                        recordsPO.setRemark("设备供水记录");
                        waterFacilityRecordsMapper.insert(recordsPO);
                    }
                }
                break;
            case "1"://运行
                break;
            case "2"://停止
                break;
            case "3"://故障
                break;
        }
        HeartbeatDataPO heartbeatDataPO = heartbeatDataMapper.getByKey(facilityPO.getFacilityCode());
        if(Objects.nonNull(heartbeatDataPO)){
            heartbeatDataPO.setDataValue(Integer.valueOf(heartbeat.getValue()));
            heartbeatDataPO.setSendValue(heartbeatDataPO.getSendValue()==0?1:0);
            heartbeatDataPO.setRemark(time);
            heartbeatDataMapper.updateById(heartbeatDataPO);
        }else {
            HeartbeatDataPO dataPO=new HeartbeatDataPO();
            dataPO.setDataKey(facilityPO.getFacilityCode());
            dataPO.setSendValue(0);
            dataPO.setDataValue(Integer.valueOf(heartbeat.getValue()));
            dataPO.setCreateTime(LocalDateTimeUtil.nowTimeStamp());
            dataPO.setRemark(LocalDateTimeUtil.nowDateTimeStr());
            heartbeatDataMapper.insert(dataPO);
        }
    }
    public ExecutedResult<List<PaymentRecordsVO>> getList(List<Long> listId) {
        List<PaymentRecordsVO> result = new ArrayList<>();
@@ -196,21 +405,50 @@
    public ExecutedResult<PagerResult<PaymentRecordsVO>> search(SearchPaymentRecords search) {
        // 处理创建时间范围-查询参数
        Tuple<String, String> createTimeRange = ParameterUtil.getTimeRange(search.getCreateTimeRange());
        if (StringUtil.isNotNullOrEmpty(createTimeRange.getItem1())) {
            search.setCreateTimeStart(LocalDateTimeUtil.getTimeStamp(createTimeRange.getItem1()).getTime());
        if (search.getDateType() != null && search.getDateType() > 0) {
            Long beginTime = 0L;
            Long endTime = 0L;
            switch (search.getDateType()) {
                case 1:
                    beginTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.todayStartTime()).getTime();
                    endTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.todayEndTime()).getTime();
                    break;
                case 2:
                    beginTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.weekStartTime()).getTime();
                    endTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.weekEndTime()).getTime();
                    break;
                case 3:
                    beginTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.monthStartTime()).getTime();
                    endTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.monthEndTime()).getTime();
                    break;
                case 4:
                    beginTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.yearStartTime()).getTime();
                    endTime = LocalDateTimeUtil.getTimeStamp(LocalDateTimeUtils.yearEndTime()).getTime();
                    break;
            }
            if (beginTime > 0) {
                search.setCreateTimeStart(beginTime);
            }
            if (endTime > 0) {
                search.setCreateTimeEnd(endTime);
            }
        }
        if (StringUtil.isNotNullOrEmpty(createTimeRange.getItem2())) {
            search.setCreateTimeEnd(LocalDateTimeUtil.getTimeStamp(createTimeRange.getItem2()).getTime());
        }
        PagerResult<PaymentRecordsPO> pageList = mapper.search(search);
        List<PaymentRecordsVO> listVo = new ArrayList<>();
        List<PaymentRecordsPO> list = pageList.getList();
        if (ListUtil.isNotNullOrEmpty(list)) {
            pageList.setLastId(list.get(list.size() - 1).getId());
            // 转换vo
            listVo = PaymentRecordsConvert.INSTANCE.toVo(list);
            listVo = CopierUtil.mapTo(list, PaymentRecordsVO.class);
            //获取列表所有用户id
            List<Long> idList = listVo.stream().map(PaymentRecordsVO::getUserId).distinct().collect(Collectors.toList());
            List<UserLoginPO> userList = userLoginMapper.getListById(idList);
            for (PaymentRecordsVO vo : listVo) {
                UserLoginPO userLoginPO = userList.stream().filter(x -> x.getId().equals(vo.getUserId())).findFirst().orElse(null);
                if (Objects.nonNull(userLoginPO)) {
                    vo.setBalance(userLoginPO.getBalance());
                }
            }
        }
        PagerResult<PaymentRecordsVO> result = new PagerResult<>(pageList.getLimit(), pageList.getPage(), pageList.getTotal(), listVo);
        result.setLastId(pageList.getLastId());
@@ -224,6 +462,7 @@
        }
        return ExecutedResult.success(exists);
    }
    protected ExecutedResult<List<PaymentRecordsPO>> check4Id(List<Long> listId) {
        // 从数据库查找null
        List<PaymentRecordsPO> list = mapper.getList(listId);
@@ -241,4 +480,5 @@
            }
        }
        return ExecutedResult.success(list);
    }}
    }
}