From 6910611c61da71ea37d4dfae82376e086412219c Mon Sep 17 00:00:00 2001 From: zhanghuibin <18531122171@163.com> Date: Wed, 19 Nov 2025 17:06:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=87=87=E8=B4=AD=E5=90=88?= =?UTF-8?q?=E5=90=8C=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConPurchaseController.java | 2 +- .../contract/domain/ConPurchaseMedia.java | 5 + .../domain/bo/ConPurchaseMediaBo.java | 6 + .../domain/vo/ConPurchaseImportVO.java | 15 +- .../contract/service/IConPurchaseService.java | 2 +- .../service/impl/ConPurchaseServiceImpl.java | 233 +++++++++++------- .../contract/ConPurchaseMediaMapper.xml | 1 + 7 files changed, 164 insertions(+), 100 deletions(-) diff --git a/ruoyi-system/src/main/java/com/ruoyi/contract/controller/ConPurchaseController.java b/ruoyi-system/src/main/java/com/ruoyi/contract/controller/ConPurchaseController.java index 93c5de1..ce35ceb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/contract/controller/ConPurchaseController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/contract/controller/ConPurchaseController.java @@ -222,7 +222,7 @@ public class ConPurchaseController extends BaseController { try { return R.ok(iConPurchaseService.importPurchase(file)); } catch (Exception e) { - return R.fail("导入失败"); + return R.fail(e.getMessage()); } } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/contract/domain/ConPurchaseMedia.java b/ruoyi-system/src/main/java/com/ruoyi/contract/domain/ConPurchaseMedia.java index c657eee..d642cba 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/contract/domain/ConPurchaseMedia.java +++ b/ruoyi-system/src/main/java/com/ruoyi/contract/domain/ConPurchaseMedia.java @@ -115,6 +115,11 @@ public class ConPurchaseMedia extends BaseEntity { */ @FieldNameApi(name ="媒体费") private Double mediaFee; + /** + * 媒体费单位 + */ + @FieldNameApi(name ="媒体费单位") + private String mediaFeeUnit; /** * 制作费 */ diff --git a/ruoyi-system/src/main/java/com/ruoyi/contract/domain/bo/ConPurchaseMediaBo.java b/ruoyi-system/src/main/java/com/ruoyi/contract/domain/bo/ConPurchaseMediaBo.java index ff97b69..577879e 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/contract/domain/bo/ConPurchaseMediaBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/contract/domain/bo/ConPurchaseMediaBo.java @@ -151,6 +151,12 @@ public class ConPurchaseMediaBo extends BaseEntity { @CustomBaenAnnotation(value = "媒体费") private Double mediaFee; + /** + * 媒体费单位 + */ + @CustomBaenAnnotation(value = "媒体费单位") + private String mediaFeeUnit; + /** * 制作费 */ diff --git a/ruoyi-system/src/main/java/com/ruoyi/contract/domain/vo/ConPurchaseImportVO.java b/ruoyi-system/src/main/java/com/ruoyi/contract/domain/vo/ConPurchaseImportVO.java index 6ce2db4..9a7cfd7 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/contract/domain/vo/ConPurchaseImportVO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/contract/domain/vo/ConPurchaseImportVO.java @@ -1,7 +1,10 @@ package com.ruoyi.contract.domain.vo; import cn.hutool.core.annotation.Alias; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + import java.util.Date; /** @@ -28,9 +31,13 @@ public class ConPurchaseImportVO { @Alias("城市") private String cityName; + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd") @Alias("发布开始时间") private Date startTime; + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd") @Alias("发布结束时间") private Date endTime; @@ -74,21 +81,23 @@ public class ConPurchaseImportVO { private String firstName; @Alias("供应商名称") - private String supplierName; + private String secondName; @Alias("媒介部门") private String mediaDeptName; @Alias("发票类型") - private String invoiceType; + private String invoiceName; @Alias("税率") - private String taxRate; + private String taxPoints; @Alias("发票内容") private String invoiceContent; @Alias("签订日期") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd") private Date signTime; @Alias("合同附件") diff --git a/ruoyi-system/src/main/java/com/ruoyi/contract/service/IConPurchaseService.java b/ruoyi-system/src/main/java/com/ruoyi/contract/service/IConPurchaseService.java index cb2137f..c9c0b96 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/contract/service/IConPurchaseService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/contract/service/IConPurchaseService.java @@ -106,5 +106,5 @@ public interface IConPurchaseService { * @return 结果 * @throws Exception */ - int importPurchase(MultipartFile file); + int importPurchase(MultipartFile file) throws Exception; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/contract/service/impl/ConPurchaseServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/contract/service/impl/ConPurchaseServiceImpl.java index 81bd3f0..e018624 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/contract/service/impl/ConPurchaseServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/contract/service/impl/ConPurchaseServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil; @@ -22,6 +23,7 @@ import com.ruoyi.common.utils.sql.HeadExcelUtils; import com.ruoyi.contract.domain.*; import com.ruoyi.contract.domain.bo.*; import com.ruoyi.contract.domain.bo.conpurchase.ConPurchaseBoExtend; +import com.ruoyi.contract.domain.dto.ConSaleImportDto; import com.ruoyi.contract.domain.vo.*; import com.ruoyi.contract.domain.vo.conpurchasevo.ConPurchaseTotalVo; import com.ruoyi.contract.mapper.*; @@ -125,125 +127,166 @@ public class ConPurchaseServiceImpl implements IConPurchaseService { @Resource private Validator validator; + /** + * 导入采购合同信息 + * @param file 导入文件 + * @return + * @throws Exception + */ @Override @Transactional(rollbackFor = Exception.class) - public int importPurchase(MultipartFile file) { - List list; - try (InputStream inputStream = file.getInputStream()) { - ExcelReader reader = ExcelUtil.getReader(inputStream); - list = reader.readAll(ConPurchaseImportVO.class); - } catch (IOException e) { - throw new ServiceException("导入采购合同失败"); - } + public int importPurchase(MultipartFile file) throws Exception { + ExcelReader reader = ExcelUtil.getReader(file.getInputStream()); + List list = reader.readAll(ConPurchaseImportVO.class); + reader.close(); if (CollectionUtil.isEmpty(list)) { throw new ServiceException("导入数据不能为空"); } - for (int i = 0; i < list.size(); i++) { - ConPurchaseImportVO vo = list.get(i); - try { - // 校验必填项 - if (StringUtils.isBlank(vo.getContractNumber())) { - throw new ServiceException("合同编号不能为空"); - } + // 按合同编号对导入数据进行分组 + Map> mapByContractNumber = list.stream() + .filter(vo -> StringUtils.isNotBlank(vo.getContractNumber())) + .collect(Collectors.groupingBy(ConPurchaseImportVO::getContractNumber)); - ConPurchase conPurchase = baseMapper.selectOne(new LambdaQueryWrapper() - .eq(ConPurchase::getContractNumber, vo.getContractNumber())); + // 遍历每个合同分组 + for (Map.Entry> entry : mapByContractNumber.entrySet()) { + String contractNumber = entry.getKey(); + List rows = entry.getValue(); + ConPurchaseImportVO firstRow = rows.get(0); // 使用第一行数据作为主信息 - if (conPurchase == null) { - // 不存在,新增合同 - conPurchase = new ConPurchase(); - // 手动进行字段映射 - conPurchase.setContractNumber(vo.getContractNumber()); - conPurchase.setProjNumber(vo.getProjNumber()); - conPurchase.setProjName(vo.getProjName()); - conPurchase.setStartTime(vo.getStartTime()); - conPurchase.setEndTime(vo.getEndTime()); - conPurchase.setContractMoney(vo.getContractMoney()); - conPurchase.setInvoiceContent(vo.getInvoiceContent()); - conPurchase.setSignTime(vo.getSignTime()); - conPurchase.setUpPrint(vo.getUpPrint()); - conPurchase.setExchangePrint(vo.getExchangePrint()); - conPurchase.setNextPrint(vo.getNextPrint()); - conPurchase.setMediaLink(vo.getMediaLink()); - String state = "生效".equals(vo.getState()) ? "1" : "0"; - conPurchase.setState(state); - conPurchase.setFirstName(vo.getFirstName()); - conPurchase.setMediaDeptName(vo.getMediaDeptName()); - // 供应商名称(乙方名称) - conPurchase.setSecondName(vo.getSupplierName()); - //税率(税点) - conPurchase.setTaxPoints(vo.getTaxRate()); + // 判断合同是否存在 + ConPurchase existingContract = baseMapper.selectOne(new LambdaQueryWrapper() + .eq(ConPurchase::getContractNumber, contractNumber)); - //甲方 - if (StringUtils.isNotBlank(vo.getFirstName())) { - ConFirst conFirst = conFirstMapper.selectOne(new LambdaQueryWrapper().eq(ConFirst::getFirstName, vo.getFirstName())); - if (conFirst != null) { - conPurchase.setFirstId(conFirst.getId()); - } - } - //媒介部门 - if (StringUtils.isNotBlank(vo.getMediaDeptName())) { - ConMediaDept conMediaDept = conMediaDeptMapper.selectOne(new LambdaQueryWrapper().eq(ConMediaDept::getMediaDeptName, vo.getMediaDeptName())); - if (conMediaDept != null) { - conPurchase.setMediaDeptId(conMediaDept.getId()); - } - } - //发票类型 - if (StringUtils.isNotBlank(vo.getInvoiceType())) { - ConInvoice conInvoice = conInvoiceMapper.selectOne(new LambdaQueryWrapper().eq(ConInvoice::getInvoiceName, vo.getInvoiceType())); - if (conInvoice != null) { - conPurchase.setInvoiceId(conInvoice.getId()); - } - } + if (existingContract == null) { + // 合同不存在 -> 调用 insertByBo 新增 + ConPurchaseBo purchaseBo = new ConPurchaseBo(); + // 手动映射主表字段 + purchaseBo.setContractNumber(firstRow.getContractNumber()); + purchaseBo.setProjNumber(firstRow.getProjNumber()); + purchaseBo.setProjName(firstRow.getProjName()); + purchaseBo.setStartTime(firstRow.getStartTime()); + purchaseBo.setEndTime(firstRow.getEndTime()); + purchaseBo.setContractMoney(firstRow.getContractMoney()); + purchaseBo.setInvoiceContent(firstRow.getInvoiceContent()); + purchaseBo.setSignTime(firstRow.getSignTime()); + purchaseBo.setUpPrint(firstRow.getUpPrint()); + purchaseBo.setExchangePrint(firstRow.getExchangePrint()); + purchaseBo.setNextPrint(firstRow.getNextPrint()); + purchaseBo.setMediaLink(firstRow.getMediaLink()); + purchaseBo.setFirstName(firstRow.getFirstName()); + purchaseBo.setMediaDeptName(firstRow.getMediaDeptName()); + purchaseBo.setSecondName(firstRow.getSecondName()); // 供应商名称(乙方名称) + purchaseBo.setTaxPoints(firstRow.getTaxPoints()); // 税率(税点) + purchaseBo.setMediaLink(firstRow.getMediaLink()); - validEntityBeforeSave(conPurchase); - baseMapper.insert(conPurchase); - } + // 状态转换 + String state = "生效".equals(firstRow.getState()) ? "1" : "0"; + purchaseBo.setState(state); - // 新增媒体数据 - ConPurchaseMedia conPurchaseMedia = new ConPurchaseMedia(); - conPurchaseMedia.setPurchaseId(conPurchase.getId()); - - // 媒体类型 - if (StringUtils.isNotBlank(vo.getMediaType())) { - ConMediaType conMediaType = conMediaTypeMapper.selectOne(new LambdaQueryWrapper().eq(ConMediaType::getMediaType, vo.getMediaType())); - if (conMediaType != null) { - conPurchaseMedia.setMediaId(conMediaType.getId()); + // 关联客户ID + if (StringUtils.isNotBlank(firstRow.getClientName())) { + ConClient conClient = conClientMapper.selectOne(new LambdaQueryWrapper().eq(ConClient::getClientName, firstRow.getClientName())); + if (conClient != null) { + purchaseBo.setClientId(conClient.getId()); } } - //城市 - if (StringUtils.isNotBlank(vo.getCityName())) { - ConCity conCity = conCityMapper.selectList(new LambdaQueryWrapper().likeRight(ConCity::getCityName, vo.getCityName())).stream().findFirst().orElse(null); - if (conCity != null) { - conPurchaseMedia.setCityId(conCity.getId()); - String cityIds = iConCityService.selectTreeIds(conCity.getId()); - conPurchaseMedia.setCityIds(cityIds); + + // 关联甲方ID + if (StringUtils.isNotBlank(firstRow.getFirstName())) { + ConFirst conFirst = conFirstMapper.selectOne(new LambdaQueryWrapper().eq(ConFirst::getFirstName, firstRow.getFirstName())); + if (conFirst != null) { + purchaseBo.setFirstId(conFirst.getId()); + } + } + // 关联媒介部门ID + if (StringUtils.isNotBlank(firstRow.getMediaDeptName())) { + ConMediaDept conMediaDept = conMediaDeptMapper.selectOne(new LambdaQueryWrapper().eq(ConMediaDept::getMediaDeptName, firstRow.getMediaDeptName())); + if (conMediaDept != null) { + purchaseBo.setMediaDeptId(conMediaDept.getId()); + } + } + // 关联发票类型ID + if (StringUtils.isNotBlank(firstRow.getInvoiceName())) { + ConInvoice conInvoice = conInvoiceMapper.selectOne(new LambdaQueryWrapper().eq(ConInvoice::getInvoiceName, firstRow.getInvoiceName())); + if (conInvoice != null) { + purchaseBo.setInvoiceId(conInvoice.getId()); } } - conPurchaseMedia.setMediaPosition(vo.getMediaLocation()); - conPurchaseMedia.setAccountNumber(safeParseDouble(vo.getPurchaseQuantity())); - conPurchaseMedia.setReleaseFrequency(vo.getFrequency()); - conPurchaseMedia.setUpTime(vo.getStartTime()); - conPurchaseMedia.setDownTime(vo.getEndTime()); - conPurchaseMedia.setPeriod(safeParseDouble(vo.getPublishDays())); - conPurchaseMedia.setPrintPrice(safeParseDouble(vo.getListPrice())); - conPurchaseMedia.setPrintPriceUnit(vo.getListPriceUnit()); - conPurchaseMedia.setDiscount(vo.getDiscount()); - conPurchaseMedia.setMediaFee(safeParseDouble(vo.getNetPrice())); - conPurchaseMedia.setProductFee(safeParseDouble(vo.getProductionFee())); - conPurchaseMediaMapper.insert(conPurchaseMedia); + // 映射媒体子表信息 + List mediaBoList = rows.stream().map(row -> { + ConPurchaseMediaBo mediaBo = new ConPurchaseMediaBo(); + this.mapRowToMediaBo(row, mediaBo); + return mediaBo; + }).collect(Collectors.toList()); + purchaseBo.setPurchaseMediaBoList(mediaBoList); + this.insertByBo(purchaseBo); - } catch (Exception e) { - log.error("导入采购合同失败", e); + } else { + // 合同已存在 -> 调用 updateByBo 追加媒体信息 + ConPurchaseVo existingVo = this.queryById(existingContract.getId()); + ConPurchaseBo purchaseBo = BeanUtil.toBean(existingVo, ConPurchaseBo.class); + + // 获取已有的媒体信息 + List existingMedia = purchaseBo.getPurchaseMediaBoList(); + if (existingMedia == null) { + existingMedia = new ArrayList<>(); + } + + // 创建并添加本次导入的新媒体信息 + List newMediaList = rows.stream().map(row -> { + ConPurchaseMediaBo mediaBo = new ConPurchaseMediaBo(); + this.mapRowToMediaBo(row, mediaBo); + return mediaBo; + }).collect(Collectors.toList()); + existingMedia.addAll(newMediaList); + purchaseBo.setPurchaseMediaBoList(existingMedia); + + this.updateByBo(purchaseBo); } } return list.size(); } + /** + * 辅助方法:将导入行数据映射到媒体BO + */ + private void mapRowToMediaBo(ConPurchaseImportVO row, ConPurchaseMediaBo mediaBo) { + // 媒体类型 + if (StringUtils.isNotBlank(row.getMediaType())) { + ConMediaType conMediaType = conMediaTypeMapper.selectOne(new LambdaQueryWrapper().eq(ConMediaType::getMediaType, row.getMediaType())); + if (conMediaType != null) { + mediaBo.setMediaId(conMediaType.getId()); + mediaBo.setMediaName(conMediaType.getMediaType()); + } + } + // 城市 + if (StringUtils.isNotBlank(row.getCityName())) { + ConCity conCity = conCityMapper.selectList(new LambdaQueryWrapper().likeRight(ConCity::getCityName, row.getCityName())).stream().findFirst().orElse(null); + if (conCity != null) { + mediaBo.setCityId(conCity.getId()); + mediaBo.setCityName(conCity.getCityName()); + String cityIds = iConCityService.selectTreeIds(conCity.getId()); + mediaBo.setCityIds(cityIds); + } + } + mediaBo.setMediaPosition(row.getMediaLocation()); + mediaBo.setAccountNumber(safeParseDouble(row.getPurchaseQuantity())); + mediaBo.setReleaseFrequency(row.getFrequency()); + mediaBo.setUpTime(row.getStartTime()); + mediaBo.setDownTime(row.getEndTime()); + mediaBo.setPeriod(safeParseDouble(row.getPublishDays())); + mediaBo.setPrintPrice(safeParseDouble(row.getListPrice())); + mediaBo.setPrintPriceUnit(row.getListPriceUnit()); + mediaBo.setDiscount(StrUtil.isNotBlank(row.getDiscount()) ? row.getDiscount() : "0"); + mediaBo.setMediaFee(safeParseDouble(row.getNetPrice())); + mediaBo.setMediaFeeUnit(row.getNetPriceUnit()); + mediaBo.setProductFee(safeParseDouble(row.getProductionFee())); + } + private Double safeParseDouble(String str) { if (StringUtils.isBlank(str) || "-".equals(str)) { return null; diff --git a/ruoyi-system/src/main/resources/mapper/contract/ConPurchaseMediaMapper.xml b/ruoyi-system/src/main/resources/mapper/contract/ConPurchaseMediaMapper.xml index d809904..6075291 100644 --- a/ruoyi-system/src/main/resources/mapper/contract/ConPurchaseMediaMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/contract/ConPurchaseMediaMapper.xml @@ -18,6 +18,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" +