DeliveryRecordServiceImpl.java 10 KB
package vion.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.crypto.SecureUtil;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import vion.dto.ContractDTO;
import vion.dto.DeliveryRecordDTO;
import vion.mapper.DeliveryRecordMapper;
import vion.model.*;
import vion.service.*;
import vion.third.DingMod;
import vion.vo.DeliveryRecordVO;
import vion.vo.UserVO;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author HlQ
 * @date 2023/12/5
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecordMapper, DeliveryRecord> implements IDeliveryRecordService {

    private final IFileService fileService;
    private final IContractService contractService;
    private final IRContractUserService contractUserService;
    private final IPointInfoService pointInfoService;
    private final DingMod dingMod;
    private final Converter converter;

    @Value("${fileUrl:}")
    private String fileUrl;

    @Override
    public Page<DeliveryRecordVO> list(DeliveryRecordDTO dto) {
        MPJLambdaWrapper<DeliveryRecord> wrapper = new MPJLambdaWrapper<>(converter.convert(dto, DeliveryRecord.class))
                .selectAll(DeliveryRecord.class)
                .selectAs(Contract::getName, DeliveryRecordVO::getContractName)
                .selectAs(Contract::getCustomerName, DeliveryRecordVO::getCustomerName)
                .leftJoin(Contract.class, Contract::getContractNo, DeliveryRecord::getContractNo)
                .like(StrUtil.isNotBlank(dto.getContractName()), Contract::getName, dto.getContractName())
                .like(StrUtil.isNotBlank(dto.getCustomerName()), Contract::getCustomerName, dto.getCustomerName())
                .orderByDesc(DeliveryRecord::getCreateTime);
        Page<DeliveryRecordVO> voPage = this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), DeliveryRecordVO.class, wrapper);
        Opt.ofEmptyAble(voPage.getRecords())
                .map(recs -> recs.stream().map(DeliveryRecordVO::getId).collect(Collectors.toList()))
                .map(ids -> {
                    List<FileInfo> fileInfos = fileService.lambdaQuery().in(FileInfo::getSourceId, ids).eq(FileInfo::getSourceType, 6).list();
                    return fileInfos.stream().collect(Collectors.groupingBy(FileInfo::getSourceId));
                })
                .filter(MapUtil::isNotEmpty)
                .ifPresent(map -> voPage.getRecords().forEach(rec -> rec.setFileList(map.get(rec.getId()))));
        return voPage;
    }

    @Override
    public String save(DeliveryRecordDTO dto) {
        DeliveryRecord deliveryRecord = converter.convert(dto, DeliveryRecord.class);
        if (this.save(deliveryRecord)) {
            updStatusAndPushMsg(deliveryRecord);
            saveFile(dto, deliveryRecord);
            return "新增成功";
        } else {
            return "新增失败";
        }
    }

    @Override
    public String saveBatch(List<DeliveryRecordDTO> dto) {
        List<DeliveryRecord> records = converter.convert(dto, DeliveryRecord.class);
        if (this.saveBatch(records)) {
            records.forEach(this::updStatusAndPushMsg);
            return "新增成功";
        } else {
            return "新增失败";
        }
    }

    @Override
    public String updateById(DeliveryRecordDTO dto) {
        DeliveryRecord record = converter.convert(dto, DeliveryRecord.class);
        if (this.updateById(record)) {
            DeliveryRecord deliveryRecord = this.getById(dto.getId());
            saveFile(dto, deliveryRecord);
            return "更新成功";
        } else {
            return "更新失败";
        }
    }

    /**
     * 更新合同状态和点位设计记录状态,并推送发货消息提醒
     *
     * @param record 发货记录
     */
    private void updStatusAndPushMsg(DeliveryRecord record) {
        ContractDTO contractDTO = new ContractDTO();
        contractDTO.setStatus(2);
        Contract existContract = contractService.lambdaQuery().eq(Contract::getContractNo, record.getContractNo()).one();
        if (ObjUtil.isNull(existContract) || ObjUtil.isNull(existContract.getStatus())) {
            log.error("根据发货记录,更新合同状态出错。该合同不存在或合同状态为空:{}", record.getContractNo());
        }
        if (ObjUtil.isNotNull(existContract) && existContract.getStatus() < 2) {
            // todo 发货后,更新对应合同的付款的节点时间字段 合同id获取不到
            /*contractPaymentService.lambdaUpdate()
                    .set(ContractPayment::getNodeDate, record.getShipDate())
                    .eq(ContractPayment::getContractId, )
                    .update(new ContractPayment());*/
            contractService.updateById(null, record.getContractNo(), contractDTO);

            List<String> useridList = contractUserService.listObjs(Wrappers.<RContractUser>lambdaQuery().select(RContractUser::getUserId).eq(RContractUser::getContractId, existContract.getId()), Object::toString);
            dingMod.workMsg(buildMsg(useridList.stream().distinct().collect(Collectors.joining(",")), record, existContract));
        }
        // 更新点位信息的发货状态
        pointInfoService.lambdaUpdate().set(PointInfo::getShippingStatus, 1)
                .set(PointInfo::getCourierCompany, record.getCourierCompany())
                .set(PointInfo::getTrackingNumber, record.getTrackingNumber())
                .set(PointInfo::getStatus, 9)
                .eq(PointInfo::getContractNo, record.getContractNo()).update(new PointInfo());

        Opt.ofNullable(pointInfoService.lambdaQuery().eq(PointInfo::getContractNo, record.getContractNo()).one())
                .ifPresent(p -> pointInfoService.designPush(null, p, "发货"));
    }

    JSONObject buildMsg(String userid, DeliveryRecord rec, Contract contract) {
        var jsonObj = JSONUtil.ofObj()
                .set("agent_id", 2358374016L)
                .set("userid_list", userid);

        var msg = JSONUtil.ofObj();
        var content = JSONUtil.ofObj().set("title", "设备发货提醒");
        String template = """
                #### 发货通知
                #### 合同名称:**{}**
                #### 合同编号:**{}**
                #### 快递公司:{}
                #### 快递单号:{}
                #### 收件人:{}
                #### 发货日期:{}
                #### 发送时间:{}
                """;
        String markdown = StrUtil.format(template,
                contract.getName(), contract.getContractNo(), rec.getCourierCompany(), rec.getTrackingNumber(), rec.getConsignee(), DateUtil.formatDate(rec.getShipDate()), DateUtil.now());
        content.set("markdown", markdown).set("btn_orientation", "1");

        var jsonArray = JSONUtil.ofArray()
                .put(JSONUtil.ofObj()
                        .set("title", "查看详情")
                        .set("action_url", """
                                https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingkrzwks0jpi2di3uo&response_type=code&scope=snsapi_auth&state=STATE&redirect_uri=https%3A%2F%2Fyunwei.vionyun.com%3A8443%2Fyunwei%2Fapi%2Fding%2Fcallback%2Finside%3FdeliveryId%3D""" + rec.getId()));
        content.set("btn_json_list", jsonArray);

        msg.set("msgtype", "action_card").set("action_card", content);
        jsonObj.set("msg", msg);
        return jsonObj;
    }

    private void saveFile(DeliveryRecordDTO dto, DeliveryRecord deliveryRecord) {
        Opt.ofNullable(dto.getFiles())
                .ifPresent(fileList -> {
                    UserVO userVO = (UserVO) StpUtil.getTokenSession().get("curLoginUser");

                    Arrays.stream(fileList).forEach(infile -> {
                        String orgName = infile.getOriginalFilename();
                        String mainName = FileNameUtil.mainName(orgName);
                        String fileExt = FileNameUtil.extName(orgName);
                        String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmssSSS"), fileExt);
                        String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + deliveryRecord.getId() + FileUtil.FILE_SEPARATOR + filename;
                        File file = FileUtil.touch(path);
                        try {
                            infile.transferTo(file);
                        } catch (IOException e) {
                            log.error("保存文件出错", e);
                        }

                        FileInfo fileInfo = new FileInfo();
                        fileInfo.setStoreId(0L);
                        fileInfo.setSourceId(deliveryRecord.getId());
                        fileInfo.setContractId(deliveryRecord.getContractId());
                        fileInfo.setSourceType(6);
                        fileInfo.setName(filename);
                        fileInfo.setUrl(path);
                        fileInfo.setType(FileNameUtil.extName(file));
                        fileInfo.setSha256(SecureUtil.sha256(file).toUpperCase());
                        fileInfo.setUploader(userVO.getUsername());
                        fileService.save(fileInfo);
                    });
                });
    }
}