SaveOwnerRepairCmd.java 15.1 KB
package com.java110.community.cmd.ownerRepair;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.java110.core.annotation.Java110Cmd;
import com.java110.core.annotation.Java110Transactional;
import com.java110.core.context.CmdContextUtils;
import com.java110.core.context.ICmdDataFlowContext;
import com.java110.core.event.cmd.Cmd;
import com.java110.core.event.cmd.CmdEvent;
import com.java110.core.factory.GenerateCodeFactory;
import com.java110.doc.annotation.*;
import com.java110.dto.fee.FeeConfigDto;
import com.java110.dto.fee.FeeDto;
import com.java110.dto.file.FileDto;
import com.java110.dto.file.FileRelDto;
import com.java110.dto.repair.RepairDto;
import com.java110.dto.repair.RepairSettingDto;
import com.java110.dto.repair.RepairUserDto;
import com.java110.dto.user.UserDto;
import com.java110.intf.common.IFileInnerServiceSMO;
import com.java110.intf.common.IFileRelInnerServiceSMO;
import com.java110.intf.community.IRepairPoolV1InnerServiceSMO;
import com.java110.intf.community.IRepairSettingV1InnerServiceSMO;
import com.java110.intf.community.IRepairUserV1InnerServiceSMO;
import com.java110.intf.fee.IFeeConfigInnerServiceSMO;
import com.java110.intf.fee.IFeeInnerServiceSMO;
import com.java110.intf.user.INotepadV1InnerServiceSMO;
import com.java110.intf.user.IUserV1InnerServiceSMO;
import com.java110.po.file.FileRelPo;
import com.java110.po.notepad.NotepadPo;
import com.java110.po.owner.RepairPoolPo;
import com.java110.po.owner.RepairUserPo;
import com.java110.utils.cache.MappingCache;
import com.java110.utils.constant.FeeTypeConstant;
import com.java110.utils.constant.MappingConstant;
import com.java110.utils.exception.CmdException;
import com.java110.utils.util.*;
import com.java110.vo.ResultVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * 业主提交报修命令类
 * 处理业主报修相关业务逻辑,包括报修信息验证、报修单创建、费用检查、图片保存等功能
 * 请求地址为/app/ownerRepair.saveOwnerRepair
 * @author 张峰
 * @version 1.0
 * @since 2023
 */

@Java110CmdDoc(title = "业主报修",
        description = "主要用于业主报修",
        httpMethod = "post",
        url = "http://{ip}:{port}/app/ownerRepair.saveOwnerRepair",
        resource = "communityDoc",
        author = "张峰",
        serviceCode = "ownerRepair.saveOwnerRepair",
        seq = 23
)
//入参要求
@Java110ParamsDoc(params = {
        @Java110ParamDoc(name = "communityId", length = 30, remark = "项目编码"),
        @Java110ParamDoc(name = "appointmentTime", length = 30, remark = "预约时间"),
        @Java110ParamDoc(name = "context", length = 30, remark = "报修内容"),
        @Java110ParamDoc(name = "photos", length = 30, remark = "报修图片"),
        @Java110ParamDoc(name = "repairName", length = 30, remark = "报修人姓名"),
        @Java110ParamDoc(name = "repairObjName", length = 30, remark = "报修人住址"),
        @Java110ParamDoc(name = "repairObjName", length = 30, remark = "报修人所在项目"),
        @Java110ParamDoc(name = "roomId", length = 30, remark = "房屋id"),
        @Java110ParamDoc(name = "tel", length = 30, remark = "报修联系电话"),
        @Java110ParamDoc(name = "userName", length = 30, remark = "业主或成员姓名"),
        @Java110ParamDoc(name = "repairChannel", length = 30, remark = "报修渠道"),
        @Java110ParamDoc(name = "repairType", length = 30, remark = "派单类型"),
        @Java110ParamDoc(name = "repairObjType", length = 30, remark = "房屋??"),
})

@Java110ResponseDoc(
        params = {
                @Java110ParamDoc(name = "code", type = "int", length = 11, defaultValue = "0", remark = "返回编号,0 成功 其他失败"),
                @Java110ParamDoc(name = "msg", type = "String", length = 250, defaultValue = "成功", remark = "报修成功")
        }
)

@Java110ExampleDoc(
        reqBody = "{\"repairName\":\"测试\",\"repairType\":\"102022081592760001\",\"appointmentTime\":\"2022-11-26 15:18:00\",\"tel\":\"15239726115\",\"roomId\":\"752022090312040033\",\"photos\":[],\"context\":\"反反复复烦烦烦\",\"userId\":\"302022102708350644\",\"userName\":\"测试\",\"communityId\":\"2022032267510001\",\"bindDate\":\"2022-11-26\",\"bindTime\":\"15:18\",\"repairObjType\":\"004\",\"repairChannel\":\"Z\",\"repairObjId\":\"752022090312040033\",\"repairObjName\":\"1号楼1单元202室\"}",
        resBody = "{\"code\":0,\"msg\":\"成功\",\"page\":0,\"records\":0,\"rows\":0,\"total\":0}"
)

@Java110Cmd(serviceCode = "ownerRepair.saveOwnerRepair")
public class SaveOwnerRepairCmd extends Cmd {

    @Autowired
    private IFeeConfigInnerServiceSMO feeConfigInnerServiceSMOImpl;

    @Autowired
    private IFeeInnerServiceSMO feeInnerServiceSMOImpl;

    @Autowired
    private IUserV1InnerServiceSMO userV1InnerServiceSMOImpl;

    @Autowired
    private IRepairPoolV1InnerServiceSMO repairPoolV1InnerServiceSMOImpl;

    @Autowired
    private IRepairUserV1InnerServiceSMO repairUserV1InnerServiceSMOImpl;

    @Autowired
    private IFileRelInnerServiceSMO fileRelInnerServiceSMOImpl;

    @Autowired
    private IFileInnerServiceSMO fileInnerServiceSMOImpl;

    @Autowired
    private INotepadV1InnerServiceSMO notepadV1InnerServiceSMOImpl;

    @Autowired
    private IRepairSettingV1InnerServiceSMO repairSettingV1InnerServiceSMOImpl;

    //域
    public static final String DOMAIN_COMMON = "DOMAIN.COMMON";

    //键(报修业主未处理费用条数)
    public static final String REPAIR_FEE_NUMBER = "REPAIR_FEE_NUMBER";

    /**
     * 验证报修请求参数
     * 检查必填参数、用户信息、费用状态等
     * @param event 命令事件
     * @param context 数据流上下文
     * @param reqJson 请求JSON对象
     * @throws CmdException 参数验证失败时抛出异常
     */
    @Override
    public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException {
        // 验证必填参数
        Assert.hasKeyAndValue(reqJson, "repairType", "必填,请选择报修类型");
        Assert.hasKeyAndValue(reqJson, "repairName", "必填,请填写报修人名称");
        Assert.hasKeyAndValue(reqJson, "tel", "必填,请填写报修人手机号");
        Assert.hasKeyAndValue(reqJson, "repairObjType", "必填,请填写报修对象类型");
        Assert.hasKeyAndValue(reqJson, "repairObjId", "必填,请填写报修对象ID");
        Assert.hasKeyAndValue(reqJson, "repairObjName", "必填,请填写报修对象名称");
        Assert.hasKeyAndValue(reqJson, "appointmentTime", "必填,请填写预约时间");
        Assert.hasKeyAndValue(reqJson, "context", "必填,请填写报修内容");
        Assert.hasKeyAndValue(reqJson, "communityId", "必填,请填写项目ID");

        // 获取并验证用户信息
        String userId = CmdContextUtils.getUserId(context);
        UserDto userDto = new UserDto();
        userDto.setUserId(userId);
        userDto.setPage(1);
        userDto.setRow(1);
        List<UserDto> userDtos = userV1InnerServiceSMOImpl.queryUsers(userDto);
        Assert.listOnlyOne(userDtos, "未查询到用户");
        // 将用户信息添加到请求参数中
        reqJson.put("userId", userDtos.get(0).getUserId());
        reqJson.put("userName", userDtos.get(0).getName());

        // 查询默认费用项配置
        FeeConfigDto feeConfigDto = new FeeConfigDto();
        feeConfigDto.setCommunityId(reqJson.getString("communityId"));
        feeConfigDto.setFeeTypeCd(FeeTypeConstant.FEE_TYPE_REPAIR); // 设置费用类型为报修费
        feeConfigDto.setIsDefault(FeeConfigDto.DEFAULT_FEE_CONFIG); // 查询默认配置
        List<FeeConfigDto> feeConfigDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(feeConfigDto);
        if (ListUtil.isNull(feeConfigDtos)) {
            return; // 没有配置默认费用项,直接返回
        }
        
        // 查询处理中的报修费用
        FeeDto feeDto = new FeeDto();
        feeDto.setConfigId(feeConfigDtos.get(0).getConfigId()); // 使用第一个默认配置
        feeDto.setPayerObjId(reqJson.getString("repairObjId")); // 设置缴费对象ID
        feeDto.setState(FeeDto.STATE_DOING); // 查询处理中的费用
        List<FeeDto> feeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
        if (ListUtil.isNull(feeDtos)) {
            return; // 没有处理中的费用,允许报修
        }
        
        // 检查未处理费用条数限制
        String repairFeeNumber = MappingCache.getValue(MappingConstant.REPAIR_DOMAIN, REPAIR_FEE_NUMBER);
        if (!StringUtil.isInteger(repairFeeNumber)) {
            return; // 配置值不是数字,不进行限制
        }
        // 如果未处理费用超过配置的限制数量,抛出异常
        if (feeDtos.size() >= Integer.parseInt(repairFeeNumber)) {
            throw new CmdException("该房屋存在" + Integer.parseInt(repairFeeNumber) + "条未处理的费用,请缴费后再进行报修!");
        }
    }

    /**
     * 执行报修命令
     * 创建报修单、报修用户记录、保存图片等
     * @param event 命令事件
     * @param context 数据流上下文
     * @param reqJson 请求JSON对象
     * @throws CmdException 业务处理失败时抛出异常
     * @throws ParseException 时间解析异常
     */
    @Override
    @Java110Transactional
    public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {

        // 查询报修设置信息
        RepairSettingDto repairSettingDto = new RepairSettingDto();
        repairSettingDto.setCommunityId(reqJson.getString("communityId"));
        repairSettingDto.setRepairType(reqJson.getString("repairType"));
        List<RepairSettingDto> repairSettingDtos = repairSettingV1InnerServiceSMOImpl.queryRepairSettings(repairSettingDto);
        if (ListUtil.isNull(repairSettingDtos)) {
            throw new CmdException("报销刘类型不存在");
        }

        // 创建报修池记录
        RepairPoolPo repairPoolPo = BeanConvertUtil.covertBean(reqJson, RepairPoolPo.class);
        repairPoolPo.setRepairId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_repairId));
        repairPoolPo.setState(RepairDto.STATE_WAIT); // 设置初始状态为等待处理
        
        // 计算超时时间
        String appointmentTime = repairPoolPo.getAppointmentTime();
        Date sAppTime = DateUtil.getDateFromStringA(appointmentTime);
        String timeout = DateUtil.getAddHoursStringA(sAppTime, repairSettingDtos.get(0).getDoTime());
        repairPoolPo.setTimeout(timeout);
        
        // 保存报修池记录
        int flag = repairPoolV1InnerServiceSMOImpl.saveRepairPoolNew(repairPoolPo);
        if (flag < 1) {
            throw new CmdException("修改失败");
        }
        
        // 创建报修用户记录
        RepairUserPo repairUserPo = BeanConvertUtil.covertBean(reqJson, RepairUserPo.class);
        repairUserPo.setContext("订单提交");
        repairUserPo.setPreStaffId("-1"); // 设置前一个处理人员ID为默认值
        repairUserPo.setPreStaffName("-1");
        repairUserPo.setPreRuId("-1");
        repairUserPo.setStartTime(DateUtil.getNow(DateUtil.DATE_FORMATE_STRING_A)); // 设置开始时间为当前时间
        repairUserPo.setRepairEvent(RepairUserDto.REPAIR_EVENT_START_USER); // 设置报修事件类型
        repairUserPo.setStaffId(reqJson.getString("userId")); // 设置当前处理人员
        repairUserPo.setStaffName(reqJson.getString("userName"));
        repairUserPo.setRepairId(repairPoolPo.getRepairId()); // 关联报修ID
        repairUserPo.setState(RepairUserDto.STATE_SUBMIT); // 设置状态为已提交
        repairUserPo.setEndTime(DateUtil.getNow(DateUtil.DATE_FORMATE_STRING_A)); // 设置结束时间为当前时间
        repairUserPo.setRuId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_ruId));
        
        // 保存报修用户记录
        flag = repairUserV1InnerServiceSMOImpl.saveRepairUserNew(repairUserPo);
        if (flag < 1) {
            throw new CmdException("修改用户失败");
        }
        
        // 保存报修图片
        saveRepairPhoto(reqJson, repairPoolPo.getRepairId());

        // 如果存在记事本ID,更新记事本关联
        if (StringUtil.jsonHasKayAndValue(reqJson, "noteId")) {
            NotepadPo notepadPo = new NotepadPo();
            notepadPo.setNoteId(reqJson.getString("noteId"));
            notepadPo.setThridId(repairPoolPo.getRepairId()); // 关联报修ID
            flag = notepadV1InnerServiceSMOImpl.updateNotepad(notepadPo);
            if (flag < 1) {
                throw new CmdException("修改业主反馈失败");
            }
        }
    }

    /**
     * 保存报修图片
     * 处理报修相关的图片上传和关联关系
     * @param reqJson 请求JSON对象,包含图片信息
     * @param repairId 报修ID,用于关联图片
     */
    private void saveRepairPhoto(JSONObject reqJson, String repairId) {
        int flag;
        JSONArray photos = reqJson.getJSONArray("photos");
        if (ListUtil.isNull(photos)) {
            return; // 没有图片,直接返回
        }
        
        // 遍历所有图片
        for (int _photoIndex = 0; _photoIndex < photos.size(); _photoIndex++) {
            String _photo = photos.getString(_photoIndex);
            // 跳过无效的图片值
            if (_photo == null || _photo.isEmpty() || "null".equals(_photo)) {
                continue;
            }

            // 如果图片内容过长(base64编码),先保存到文件系统
            if (_photo.length() > 512) {
                FileDto fileDto = new FileDto();
                fileDto.setFileId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_file_id));
                fileDto.setFileName(fileDto.getFileId());
                fileDto.setContext(_photo); // 图片内容
                fileDto.setSuffix("jpeg"); // 设置文件后缀
                fileDto.setCommunityId(reqJson.getString("communityId"));
                _photo = fileInnerServiceSMOImpl.saveFile(fileDto); // 保存文件并返回文件路径
            }
            
            // 创建文件关联记录
            JSONObject businessUnit = new JSONObject();
            businessUnit.put("fileRelId", GenerateCodeFactory.getGeneratorId("12"));
            businessUnit.put("relTypeCd", FileRelDto.REL_TYPE_CD_REPAIR); // 设置关联类型为报修
            businessUnit.put("saveWay", "ftp"); // 设置保存方式
            businessUnit.put("objId", repairId); // 关联报修ID
            businessUnit.put("fileRealName", _photo.toString());
            businessUnit.put("fileSaveName", _photo.toString());
            
            FileRelPo fileRelPo = BeanConvertUtil.covertBean(businessUnit, FileRelPo.class);
            flag = fileRelInnerServiceSMOImpl.saveFileRel(fileRelPo);
            if (flag < 1) {
                throw new CmdException("保存图片失败");
            }
        }
    }
}