完善招投标导入测试与文档
This commit is contained in:
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||
import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionVO;
|
||||
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
|
||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||
@@ -33,12 +34,12 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 采购交易信息Controller
|
||||
* 招投标信息维护Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
*/
|
||||
@Tag(name = "采购交易信息管理")
|
||||
@Tag(name = "招投标信息维护")
|
||||
@RestController
|
||||
@RequestMapping("/ccdi/purchaseTransaction")
|
||||
public class CcdiPurchaseTransactionController extends BaseController {
|
||||
@@ -50,9 +51,9 @@ public class CcdiPurchaseTransactionController extends BaseController {
|
||||
private ICcdiPurchaseTransactionImportService transactionImportService;
|
||||
|
||||
/**
|
||||
* 查询采购交易列表
|
||||
* 查询招投标信息列表
|
||||
*/
|
||||
@Operation(summary = "查询采购交易列表")
|
||||
@Operation(summary = "查询招投标信息列表")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(CcdiPurchaseTransactionQueryDTO queryDTO) {
|
||||
@@ -64,9 +65,9 @@ public class CcdiPurchaseTransactionController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取采购交易详细信息
|
||||
* 获取招投标信息详细信息
|
||||
*/
|
||||
@Operation(summary = "获取采购交易详细信息")
|
||||
@Operation(summary = "获取招投标信息详细信息")
|
||||
@Parameter(name = "purchaseId", description = "采购事项ID", required = true)
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:query')")
|
||||
@GetMapping(value = "/{purchaseId}")
|
||||
@@ -75,66 +76,81 @@ public class CcdiPurchaseTransactionController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增采购交易
|
||||
* 新增招投标信息
|
||||
*/
|
||||
@Operation(summary = "新增采购交易")
|
||||
@Operation(summary = "新增招投标信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:add')")
|
||||
@Log(title = "采购交易信息", businessType = BusinessType.INSERT)
|
||||
@Log(title = "招投标信息维护", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody CcdiPurchaseTransactionAddDTO addDTO) {
|
||||
return toAjax(transactionService.insertTransaction(addDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改采购交易
|
||||
* 修改招投标信息
|
||||
*/
|
||||
@Operation(summary = "修改采购交易")
|
||||
@Operation(summary = "修改招投标信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:edit')")
|
||||
@Log(title = "采购交易信息", businessType = BusinessType.UPDATE)
|
||||
@Log(title = "招投标信息维护", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody CcdiPurchaseTransactionEditDTO editDTO) {
|
||||
return toAjax(transactionService.updateTransaction(editDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除采购交易
|
||||
* 删除招投标信息
|
||||
*/
|
||||
@Operation(summary = "删除采购交易")
|
||||
@Operation(summary = "删除招投标信息")
|
||||
@Parameter(name = "purchaseIds", description = "采购事项ID数组", required = true)
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:remove')")
|
||||
@Log(title = "采购交易信息", businessType = BusinessType.DELETE)
|
||||
@Log(title = "招投标信息维护", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{purchaseIds}")
|
||||
public AjaxResult remove(@PathVariable String[] purchaseIds) {
|
||||
return toAjax(transactionService.deleteTransactionByIds(purchaseIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载带字典下拉框的导入模板
|
||||
* 使用@DictDropdown注解自动添加下拉框
|
||||
* 下载双Sheet导入模板
|
||||
*/
|
||||
@Operation(summary = "下载导入模板")
|
||||
@PostMapping("/importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiPurchaseTransactionExcel.class, "采购交易信息");
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||
response,
|
||||
CcdiPurchaseTransactionExcel.class,
|
||||
"招投标主信息",
|
||||
CcdiPurchaseTransactionSupplierExcel.class,
|
||||
"供应商明细",
|
||||
"招投标信息维护导入模板"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步导入采购交易
|
||||
* 异步导入招投标信息
|
||||
*/
|
||||
@Operation(summary = "异步导入采购交易")
|
||||
@Operation(summary = "异步导入招投标信息")
|
||||
@Parameter(name = "file", description = "导入文件", required = true)
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:import')")
|
||||
@Log(title = "采购交易信息", businessType = BusinessType.IMPORT)
|
||||
@Log(title = "招投标信息维护", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importData")
|
||||
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
||||
List<CcdiPurchaseTransactionExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiPurchaseTransactionExcel.class);
|
||||
List<CcdiPurchaseTransactionExcel> mainList = EasyExcelUtil.importExcel(
|
||||
file.getInputStream(),
|
||||
CcdiPurchaseTransactionExcel.class,
|
||||
"招投标主信息"
|
||||
);
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierList = EasyExcelUtil.importExcel(
|
||||
file.getInputStream(),
|
||||
CcdiPurchaseTransactionSupplierExcel.class,
|
||||
"供应商明细"
|
||||
);
|
||||
|
||||
if (list == null || list.isEmpty()) {
|
||||
if ((mainList == null || mainList.isEmpty()) && (supplierList == null || supplierList.isEmpty())) {
|
||||
return error("至少需要一条数据");
|
||||
}
|
||||
|
||||
// 提交异步任务
|
||||
String taskId = transactionService.importTransaction(list);
|
||||
String taskId = transactionService.importTransaction(mainList, supplierList);
|
||||
|
||||
// 立即返回,不等待后台任务完成
|
||||
ImportResultVO result = new ImportResultVO();
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.ruoyi.info.collection.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 招投标供应商明细对象 ccdi_purchase_transaction_supplier
|
||||
*/
|
||||
@Data
|
||||
public class CcdiPurchaseTransactionSupplier implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 采购事项ID */
|
||||
private String purchaseId;
|
||||
|
||||
/** 供应商名称 */
|
||||
private String supplierName;
|
||||
|
||||
/** 供应商统一信用代码 */
|
||||
private String supplierUscc;
|
||||
|
||||
/** 供应商联系人 */
|
||||
private String contactPerson;
|
||||
|
||||
/** 供应商联系电话 */
|
||||
private String contactPhone;
|
||||
|
||||
/** 供应商银行账户 */
|
||||
private String supplierBankAccount;
|
||||
|
||||
/** 是否中标:1-是,0-否 */
|
||||
private Integer isBidWinner;
|
||||
|
||||
/** 排序 */
|
||||
private Integer sortOrder;
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
/** 创建人 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createdBy;
|
||||
|
||||
/** 更新人 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updatedBy;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,15 +10,16 @@ import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 采购交易信息新增DTO
|
||||
* 招投标信息新增DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "采购交易信息新增")
|
||||
@Schema(description = "招投标信息新增")
|
||||
public class CcdiPurchaseTransactionAddDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
@@ -88,30 +90,10 @@ public class CcdiPurchaseTransactionAddDTO implements Serializable {
|
||||
@Schema(description = "采购方式")
|
||||
private String purchaseMethod;
|
||||
|
||||
/** 中标供应商名称 */
|
||||
@Size(max = 200, message = "中标供应商名称长度不能超过200个字符")
|
||||
@Schema(description = "中标供应商名称")
|
||||
private String supplierName;
|
||||
|
||||
/** 供应商联系人 */
|
||||
@Size(max = 50, message = "供应商联系人长度不能超过50个字符")
|
||||
@Schema(description = "供应商联系人")
|
||||
private String contactPerson;
|
||||
|
||||
/** 供应商联系电话 */
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$", message = "供应商联系电话格式不正确")
|
||||
@Schema(description = "供应商联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
/** 供应商统一信用代码 */
|
||||
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "供应商统一信用代码格式不正确")
|
||||
@Schema(description = "供应商统一信用代码")
|
||||
private String supplierUscc;
|
||||
|
||||
/** 供应商银行账户 */
|
||||
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
|
||||
@Schema(description = "供应商银行账户")
|
||||
private String supplierBankAccount;
|
||||
/** 供应商明细 */
|
||||
@Valid
|
||||
@Schema(description = "供应商明细列表")
|
||||
private List<CcdiPurchaseTransactionSupplierDTO> supplierList;
|
||||
|
||||
/** 采购申请日期(或立项日期) */
|
||||
@NotNull(message = "采购申请日期不能为空")
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,15 +10,16 @@ import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 采购交易信息编辑DTO
|
||||
* 招投标信息编辑DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "采购交易信息编辑")
|
||||
@Schema(description = "招投标信息编辑")
|
||||
public class CcdiPurchaseTransactionEditDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
@@ -88,30 +90,10 @@ public class CcdiPurchaseTransactionEditDTO implements Serializable {
|
||||
@Schema(description = "采购方式")
|
||||
private String purchaseMethod;
|
||||
|
||||
/** 中标供应商名称 */
|
||||
@Size(max = 200, message = "中标供应商名称长度不能超过200个字符")
|
||||
@Schema(description = "中标供应商名称")
|
||||
private String supplierName;
|
||||
|
||||
/** 供应商联系人 */
|
||||
@Size(max = 50, message = "供应商联系人长度不能超过50个字符")
|
||||
@Schema(description = "供应商联系人")
|
||||
private String contactPerson;
|
||||
|
||||
/** 供应商联系电话 */
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$", message = "供应商联系电话格式不正确")
|
||||
@Schema(description = "供应商联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
/** 供应商统一信用代码 */
|
||||
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "供应商统一信用代码格式不正确")
|
||||
@Schema(description = "供应商统一信用代码")
|
||||
private String supplierUscc;
|
||||
|
||||
/** 供应商银行账户 */
|
||||
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
|
||||
@Schema(description = "供应商银行账户")
|
||||
private String supplierBankAccount;
|
||||
/** 供应商明细 */
|
||||
@Valid
|
||||
@Schema(description = "供应商明细列表")
|
||||
private List<CcdiPurchaseTransactionSupplierDTO> supplierList;
|
||||
|
||||
/** 采购申请日期(或立项日期) */
|
||||
@NotNull(message = "采购申请日期不能为空")
|
||||
|
||||
@@ -9,13 +9,13 @@ import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 采购交易信息查询DTO
|
||||
* 招投标信息查询DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "采购交易信息查询条件")
|
||||
@Schema(description = "招投标信息查询条件")
|
||||
public class CcdiPurchaseTransactionQueryDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.ruoyi.info.collection.domain.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 招投标供应商明细DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "招投标供应商明细")
|
||||
public class CcdiPurchaseTransactionSupplierDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotBlank(message = "供应商名称不能为空")
|
||||
@Size(max = 200, message = "供应商名称长度不能超过200个字符")
|
||||
@Schema(description = "供应商名称")
|
||||
private String supplierName;
|
||||
|
||||
@Pattern(
|
||||
regexp = "^$|^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$",
|
||||
message = "供应商统一信用代码格式不正确"
|
||||
)
|
||||
@Schema(description = "供应商统一信用代码")
|
||||
private String supplierUscc;
|
||||
|
||||
@Size(max = 50, message = "供应商联系人长度不能超过50个字符")
|
||||
@Schema(description = "供应商联系人")
|
||||
private String contactPerson;
|
||||
|
||||
@Pattern(
|
||||
regexp = "^$|^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$",
|
||||
message = "供应商联系电话格式不正确"
|
||||
)
|
||||
@Schema(description = "供应商联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
|
||||
@Schema(description = "供应商银行账户")
|
||||
private String supplierBankAccount;
|
||||
|
||||
@Schema(description = "是否中标:1-是,0-否")
|
||||
private Integer isBidWinner;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortOrder;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 采购交易信息Excel导入导出对象
|
||||
* 招投标主信息Excel导入导出对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
@@ -88,107 +88,82 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
|
||||
@Required
|
||||
private String purchaseMethod;
|
||||
|
||||
/** 中标供应商名称 */
|
||||
@ExcelProperty(value = "中标供应商名称", index = 12)
|
||||
@ColumnWidth(25)
|
||||
private String supplierName;
|
||||
|
||||
/** 供应商联系人 */
|
||||
@ExcelProperty(value = "供应商联系人", index = 13)
|
||||
@ColumnWidth(15)
|
||||
private String contactPerson;
|
||||
|
||||
/** 供应商联系电话 */
|
||||
@ExcelProperty(value = "供应商联系电话", index = 14)
|
||||
@ColumnWidth(18)
|
||||
private String contactPhone;
|
||||
|
||||
/** 供应商统一信用代码 */
|
||||
@ExcelProperty(value = "供应商统一信用代码", index = 15)
|
||||
@ColumnWidth(25)
|
||||
private String supplierUscc;
|
||||
|
||||
/** 供应商银行账户 */
|
||||
@ExcelProperty(value = "供应商银行账户", index = 16)
|
||||
@ColumnWidth(20)
|
||||
private String supplierBankAccount;
|
||||
|
||||
/** 采购申请日期(或立项日期) */
|
||||
@ExcelProperty(value = "采购申请日期", index = 17)
|
||||
@ExcelProperty(value = "采购申请日期", index = 12)
|
||||
@ColumnWidth(18)
|
||||
@Required
|
||||
private Date applyDate;
|
||||
|
||||
/** 采购计划批准日期 */
|
||||
@ExcelProperty(value = "采购计划批准日期", index = 18)
|
||||
@ExcelProperty(value = "采购计划批准日期", index = 13)
|
||||
@ColumnWidth(18)
|
||||
private Date planApproveDate;
|
||||
|
||||
/** 采购公告发布日期 */
|
||||
@ExcelProperty(value = "采购公告发布日期", index = 19)
|
||||
@ExcelProperty(value = "采购公告发布日期", index = 14)
|
||||
@ColumnWidth(18)
|
||||
private Date announceDate;
|
||||
|
||||
/** 开标日期 */
|
||||
@ExcelProperty(value = "开标日期", index = 20)
|
||||
@ExcelProperty(value = "开标日期", index = 15)
|
||||
@ColumnWidth(18)
|
||||
private Date bidOpenDate;
|
||||
|
||||
/** 合同签订日期 */
|
||||
@ExcelProperty(value = "合同签订日期", index = 21)
|
||||
@ExcelProperty(value = "合同签订日期", index = 16)
|
||||
@ColumnWidth(18)
|
||||
private Date contractSignDate;
|
||||
|
||||
/** 预计交货日期 */
|
||||
@ExcelProperty(value = "预计交货日期", index = 22)
|
||||
@ExcelProperty(value = "预计交货日期", index = 17)
|
||||
@ColumnWidth(18)
|
||||
private Date expectedDeliveryDate;
|
||||
|
||||
/** 实际交货日期 */
|
||||
@ExcelProperty(value = "实际交货日期", index = 23)
|
||||
@ExcelProperty(value = "实际交货日期", index = 18)
|
||||
@ColumnWidth(18)
|
||||
private Date actualDeliveryDate;
|
||||
|
||||
/** 验收日期 */
|
||||
@ExcelProperty(value = "验收日期", index = 24)
|
||||
@ExcelProperty(value = "验收日期", index = 19)
|
||||
@ColumnWidth(18)
|
||||
private Date acceptanceDate;
|
||||
|
||||
/** 结算日期 */
|
||||
@ExcelProperty(value = "结算日期", index = 25)
|
||||
@ExcelProperty(value = "结算日期", index = 20)
|
||||
@ColumnWidth(18)
|
||||
private Date settlementDate;
|
||||
|
||||
/** 申请人工号 */
|
||||
@ExcelProperty(value = "申请人工号", index = 26)
|
||||
@ExcelProperty(value = "申请人工号", index = 21)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String applicantId;
|
||||
|
||||
/** 申请人姓名 */
|
||||
@ExcelProperty(value = "申请人姓名", index = 27)
|
||||
@ExcelProperty(value = "申请人姓名", index = 22)
|
||||
@ColumnWidth(15)
|
||||
@Required
|
||||
private String applicantName;
|
||||
|
||||
/** 申请部门 */
|
||||
@ExcelProperty(value = "申请部门", index = 28)
|
||||
@ExcelProperty(value = "申请部门", index = 23)
|
||||
@ColumnWidth(18)
|
||||
@Required
|
||||
private String applyDepartment;
|
||||
|
||||
/** 采购负责人工号 */
|
||||
@ExcelProperty(value = "采购负责人工号", index = 29)
|
||||
@ExcelProperty(value = "采购负责人工号", index = 24)
|
||||
@ColumnWidth(15)
|
||||
private String purchaseLeaderId;
|
||||
|
||||
/** 采购负责人姓名 */
|
||||
@ExcelProperty(value = "采购负责人姓名", index = 30)
|
||||
@ExcelProperty(value = "采购负责人姓名", index = 25)
|
||||
@ColumnWidth(15)
|
||||
private String purchaseLeaderName;
|
||||
|
||||
/** 采购部门 */
|
||||
@ExcelProperty(value = "采购部门", index = 31)
|
||||
@ExcelProperty(value = "采购部门", index = 26)
|
||||
@ColumnWidth(18)
|
||||
private String purchaseDepartment;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ruoyi.info.collection.domain.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import com.ruoyi.common.annotation.DictDropdown;
|
||||
import com.ruoyi.common.annotation.Required;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 招投标供应商明细Excel对象
|
||||
*/
|
||||
@Data
|
||||
public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ExcelProperty(value = "采购事项ID", index = 0)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String purchaseId;
|
||||
|
||||
@ExcelProperty(value = "供应商名称", index = 1)
|
||||
@ColumnWidth(25)
|
||||
@Required
|
||||
private String supplierName;
|
||||
|
||||
@ExcelProperty(value = "供应商统一信用代码", index = 2)
|
||||
@ColumnWidth(25)
|
||||
private String supplierUscc;
|
||||
|
||||
@ExcelProperty(value = "供应商联系人", index = 3)
|
||||
@ColumnWidth(15)
|
||||
private String contactPerson;
|
||||
|
||||
@ExcelProperty(value = "供应商联系电话", index = 4)
|
||||
@ColumnWidth(18)
|
||||
private String contactPhone;
|
||||
|
||||
@ExcelProperty(value = "供应商银行账户", index = 5)
|
||||
@ColumnWidth(20)
|
||||
private String supplierBankAccount;
|
||||
|
||||
@ExcelProperty(value = "是否中标", index = 6)
|
||||
@ColumnWidth(12)
|
||||
@DictDropdown(dictType = "ccdi_yes_no_flag")
|
||||
private String isBidWinner;
|
||||
|
||||
@ExcelProperty(value = "排序", index = 7)
|
||||
@ColumnWidth(10)
|
||||
private Integer sortOrder;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.info.collection.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 招投标供应商明细VO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "招投标供应商明细")
|
||||
public class CcdiPurchaseTransactionSupplierVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "采购事项ID")
|
||||
private String purchaseId;
|
||||
|
||||
@Schema(description = "供应商名称")
|
||||
private String supplierName;
|
||||
|
||||
@Schema(description = "供应商统一信用代码")
|
||||
private String supplierUscc;
|
||||
|
||||
@Schema(description = "供应商联系人")
|
||||
private String contactPerson;
|
||||
|
||||
@Schema(description = "供应商联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
@Schema(description = "供应商银行账户")
|
||||
private String supplierBankAccount;
|
||||
|
||||
@Schema(description = "是否中标:1-是,0-否")
|
||||
private Integer isBidWinner;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortOrder;
|
||||
}
|
||||
@@ -8,15 +8,16 @@ import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 采购交易信息VO
|
||||
* 招投标信息VO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "采购交易信息")
|
||||
@Schema(description = "招投标信息")
|
||||
public class CcdiPurchaseTransactionVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
@@ -90,6 +91,14 @@ public class CcdiPurchaseTransactionVO implements Serializable {
|
||||
@Schema(description = "供应商银行账户")
|
||||
private String supplierBankAccount;
|
||||
|
||||
/** 参与供应商数 */
|
||||
@Schema(description = "参与供应商数")
|
||||
private Integer supplierCount;
|
||||
|
||||
/** 供应商明细 */
|
||||
@Schema(description = "供应商明细列表")
|
||||
private List<CcdiPurchaseTransactionSupplierVO> supplierList;
|
||||
|
||||
/** 采购申请日期(或立项日期) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Schema(description = "采购申请日期")
|
||||
|
||||
@@ -6,13 +6,13 @@ import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 采购交易信息导入失败记录VO
|
||||
* 招投标信息导入失败记录VO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-06
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "采购交易信息导入失败记录")
|
||||
@Schema(description = "招投标信息导入失败记录")
|
||||
public class PurchaseTransactionImportFailureVO {
|
||||
|
||||
/** 采购事项ID */
|
||||
|
||||
@@ -35,6 +35,14 @@ public interface CcdiPurchaseTransactionMapper extends BaseMapper<CcdiPurchaseTr
|
||||
*/
|
||||
CcdiPurchaseTransactionVO selectTransactionById(@Param("purchaseId") String purchaseId);
|
||||
|
||||
/**
|
||||
* 删除指定采购事项ID对应的供应商明细
|
||||
*
|
||||
* @param purchaseIds 采购事项ID列表
|
||||
* @return 删除行数
|
||||
*/
|
||||
int deleteSuppliersByPurchaseIds(@Param("purchaseIds") List<String> purchaseIds);
|
||||
|
||||
/**
|
||||
* 批量插入采购交易数据
|
||||
*
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.info.collection.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransactionSupplier;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 招投标供应商明细Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface CcdiPurchaseTransactionSupplierMapper extends BaseMapper<CcdiPurchaseTransactionSupplier> {
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.info.collection.service;
|
||||
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||
import com.ruoyi.info.collection.domain.vo.PurchaseTransactionImportFailureVO;
|
||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||
|
||||
@@ -17,11 +18,17 @@ public interface ICcdiPurchaseTransactionImportService {
|
||||
/**
|
||||
* 异步导入采购交易数据
|
||||
*
|
||||
* @param excelList Excel数据列表
|
||||
* @param taskId 任务ID
|
||||
* @param userName 当前用户名
|
||||
* @param mainExcelList 主信息Excel数据列表
|
||||
* @param supplierExcelList 供应商明细Excel数据列表
|
||||
* @param taskId 任务ID
|
||||
* @param userName 当前用户名
|
||||
*/
|
||||
void importTransactionAsync(List<CcdiPurchaseTransactionExcel> excelList, String taskId, String userName);
|
||||
void importTransactionAsync(
|
||||
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList,
|
||||
String taskId,
|
||||
String userName
|
||||
);
|
||||
|
||||
/**
|
||||
* 查询导入状态
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||
import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionVO;
|
||||
|
||||
import java.util.List;
|
||||
@@ -77,8 +78,12 @@ public interface ICcdiPurchaseTransactionService {
|
||||
/**
|
||||
* 导入采购交易数据(异步)
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param mainExcelList 主信息Excel实体列表
|
||||
* @param supplierExcelList 供应商明细Excel实体列表
|
||||
* @return 任务ID
|
||||
*/
|
||||
String importTransaction(List<CcdiPurchaseTransactionExcel> excelList);
|
||||
String importTransaction(
|
||||
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@ package com.ruoyi.info.collection.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransaction;
|
||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransactionSupplier;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||
import com.ruoyi.info.collection.domain.vo.ImportResult;
|
||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||
import com.ruoyi.info.collection.domain.vo.PurchaseTransactionImportFailureVO;
|
||||
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper;
|
||||
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionSupplierMapper;
|
||||
import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionImportService;
|
||||
import com.ruoyi.info.collection.utils.ImportLogUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
@@ -41,79 +44,119 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
@Resource
|
||||
private CcdiPurchaseTransactionMapper transactionMapper;
|
||||
|
||||
@Resource
|
||||
private CcdiPurchaseTransactionSupplierMapper supplierMapper;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
@Transactional
|
||||
public void importTransactionAsync(List<CcdiPurchaseTransactionExcel> excelList, String taskId, String userName) {
|
||||
public void importTransactionAsync(
|
||||
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList,
|
||||
String taskId,
|
||||
String userName
|
||||
) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
List<CcdiPurchaseTransactionExcel> safeMainList = mainExcelList == null ? List.of() : mainExcelList;
|
||||
List<CcdiPurchaseTransactionSupplierExcel> safeSupplierList = supplierExcelList == null ? List.of() : supplierExcelList;
|
||||
int totalCount = countImportUnits(safeMainList, safeSupplierList);
|
||||
|
||||
// 记录导入开始
|
||||
ImportLogUtils.logImportStart(log, taskId, "采购交易信息", excelList.size(), userName);
|
||||
ImportLogUtils.logImportStart(log, taskId, "招投标信息维护", totalCount, userName);
|
||||
|
||||
List<CcdiPurchaseTransaction> newRecords = new ArrayList<>();
|
||||
List<CcdiPurchaseTransaction> newTransactions = new ArrayList<>();
|
||||
List<CcdiPurchaseTransactionSupplier> newSuppliers = new ArrayList<>();
|
||||
List<PurchaseTransactionImportFailureVO> failures = new ArrayList<>();
|
||||
|
||||
// 批量查询已存在的采购事项ID
|
||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的采购事项ID", excelList.size());
|
||||
Set<String> existingIds = getExistingPurchaseIds(excelList);
|
||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的采购事项ID", safeMainList.size());
|
||||
Set<String> existingIds = getExistingPurchaseIds(safeMainList);
|
||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "采购事项ID", existingIds.size());
|
||||
|
||||
// 用于跟踪Excel文件内已处理的采购事项ID
|
||||
Set<String> processedIds = new HashSet<>();
|
||||
Map<String, List<CcdiPurchaseTransactionExcel>> mainGroupMap = safeMainList.stream()
|
||||
.filter(item -> StringUtils.isNotEmpty(item.getPurchaseId()))
|
||||
.collect(Collectors.groupingBy(
|
||||
CcdiPurchaseTransactionExcel::getPurchaseId,
|
||||
LinkedHashMap::new,
|
||||
Collectors.toList()
|
||||
));
|
||||
Map<String, List<CcdiPurchaseTransactionSupplierExcel>> supplierGroupMap = safeSupplierList.stream()
|
||||
.filter(item -> StringUtils.isNotEmpty(item.getPurchaseId()))
|
||||
.collect(Collectors.groupingBy(
|
||||
CcdiPurchaseTransactionSupplierExcel::getPurchaseId,
|
||||
LinkedHashMap::new,
|
||||
Collectors.toList()
|
||||
));
|
||||
LinkedHashSet<String> purchaseIds = new LinkedHashSet<>();
|
||||
purchaseIds.addAll(mainGroupMap.keySet());
|
||||
purchaseIds.addAll(supplierGroupMap.keySet());
|
||||
|
||||
// 分类数据
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
CcdiPurchaseTransactionExcel excel = excelList.get(i);
|
||||
for (CcdiPurchaseTransactionSupplierExcel supplierExcel : safeSupplierList) {
|
||||
if (StringUtils.isEmpty(supplierExcel.getPurchaseId())) {
|
||||
failures.add(buildFailure(null, null, "供应商明细Sheet中的采购事项ID不能为空"));
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (String purchaseId : purchaseIds) {
|
||||
index++;
|
||||
List<CcdiPurchaseTransactionExcel> mainRows = mainGroupMap.getOrDefault(purchaseId, List.of());
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierRows = supplierGroupMap.getOrDefault(purchaseId, List.of());
|
||||
|
||||
try {
|
||||
// 转换为AddDTO进行验证
|
||||
CcdiPurchaseTransactionAddDTO addDTO = new CcdiPurchaseTransactionAddDTO();
|
||||
BeanUtils.copyProperties(excel, addDTO);
|
||||
|
||||
// 验证数据
|
||||
validateTransactionData(addDTO, existingIds);
|
||||
|
||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||
BeanUtils.copyProperties(excel, transaction);
|
||||
|
||||
if (existingIds.contains(excel.getPurchaseId())) {
|
||||
// 采购事项ID已存在,直接报错
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]已存在,请勿重复导入", excel.getPurchaseId()));
|
||||
} else if (processedIds.contains(excel.getPurchaseId())) {
|
||||
// Excel文件内部重复
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]在导入文件中重复,已跳过此条记录", excel.getPurchaseId()));
|
||||
} else {
|
||||
transaction.setCreatedBy(userName);
|
||||
transaction.setUpdatedBy(userName);
|
||||
newRecords.add(transaction);
|
||||
processedIds.add(excel.getPurchaseId()); // 标记为已处理
|
||||
if (existingIds.contains(purchaseId)) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]已存在,请勿重复导入", purchaseId));
|
||||
}
|
||||
if (mainRows.isEmpty()) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]缺少招投标主信息", purchaseId));
|
||||
}
|
||||
if (mainRows.size() > 1) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]在招投标主信息Sheet中重复", purchaseId));
|
||||
}
|
||||
|
||||
CcdiPurchaseTransactionExcel mainExcel = mainRows.getFirst();
|
||||
CcdiPurchaseTransactionAddDTO addDTO = new CcdiPurchaseTransactionAddDTO();
|
||||
BeanUtils.copyProperties(mainExcel, addDTO);
|
||||
|
||||
validateTransactionData(addDTO);
|
||||
List<CcdiPurchaseTransactionSupplier> suppliers = buildSupplierEntities(purchaseId, supplierRows, userName);
|
||||
|
||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||
BeanUtils.copyProperties(mainExcel, transaction);
|
||||
fillWinnerSummary(transaction, suppliers);
|
||||
transaction.setCreatedBy(userName);
|
||||
transaction.setUpdatedBy(userName);
|
||||
newTransactions.add(transaction);
|
||||
newSuppliers.addAll(suppliers);
|
||||
|
||||
// 记录进度
|
||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
||||
newRecords.size(), failures.size());
|
||||
ImportLogUtils.logProgress(log, taskId, index, Math.max(totalCount, purchaseIds.size()),
|
||||
newTransactions.size(), failures.size());
|
||||
|
||||
} catch (Exception e) {
|
||||
PurchaseTransactionImportFailureVO failure = new PurchaseTransactionImportFailureVO();
|
||||
BeanUtils.copyProperties(excel, failure);
|
||||
failure.setErrorMessage(e.getMessage());
|
||||
failures.add(failure);
|
||||
CcdiPurchaseTransactionExcel mainExcel = mainRows.isEmpty() ? null : mainRows.getFirst();
|
||||
failures.add(buildFailure(mainExcel, purchaseId, e.getMessage()));
|
||||
|
||||
// 记录验证失败日志
|
||||
String keyData = String.format("采购事项ID=%s, 采购类别=%s, 标的物=%s",
|
||||
excel.getPurchaseId(), excel.getPurchaseCategory(), excel.getSubjectName());
|
||||
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData);
|
||||
purchaseId,
|
||||
mainExcel == null ? "" : mainExcel.getPurchaseCategory(),
|
||||
mainExcel == null ? "" : mainExcel.getSubjectName());
|
||||
ImportLogUtils.logValidationError(log, taskId, index, e.getMessage(), keyData);
|
||||
}
|
||||
}
|
||||
|
||||
// 批量插入新数据
|
||||
if (!newRecords.isEmpty()) {
|
||||
if (!newTransactions.isEmpty()) {
|
||||
ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
|
||||
(newRecords.size() + 499) / 500, 500);
|
||||
saveBatch(newRecords, 500);
|
||||
(newTransactions.size() + 499) / 500, 500);
|
||||
saveBatch(newTransactions, 500);
|
||||
}
|
||||
if (!newSuppliers.isEmpty()) {
|
||||
saveSupplierBatch(newSuppliers, 500);
|
||||
}
|
||||
|
||||
// 保存失败记录到Redis
|
||||
@@ -128,8 +171,8 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
}
|
||||
|
||||
ImportResult result = new ImportResult();
|
||||
result.setTotalCount(excelList.size());
|
||||
result.setSuccessCount(newRecords.size());
|
||||
result.setTotalCount(totalCount);
|
||||
result.setSuccessCount(newTransactions.size());
|
||||
result.setFailureCount(failures.size());
|
||||
|
||||
// 更新最终状态
|
||||
@@ -138,8 +181,8 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
|
||||
// 记录导入完成
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
ImportLogUtils.logImportComplete(log, taskId, "采购交易信息",
|
||||
excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration);
|
||||
ImportLogUtils.logImportComplete(log, taskId, "招投标信息维护",
|
||||
totalCount, result.getSuccessCount(), result.getFailureCount(), duration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,13 +286,22 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
}
|
||||
}
|
||||
|
||||
private void saveSupplierBatch(List<CcdiPurchaseTransactionSupplier> list, int batchSize) {
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, list.size());
|
||||
List<CcdiPurchaseTransactionSupplier> subList = list.subList(i, end);
|
||||
for (CcdiPurchaseTransactionSupplier supplier : subList) {
|
||||
supplierMapper.insert(supplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证采购交易数据
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
* @param existingIds 已存在的采购事项ID集合
|
||||
* @param addDTO 新增DTO
|
||||
*/
|
||||
private void validateTransactionData(CcdiPurchaseTransactionAddDTO addDTO, Set<String> existingIds) {
|
||||
private void validateTransactionData(CcdiPurchaseTransactionAddDTO addDTO) {
|
||||
// 验证必填字段
|
||||
if (StringUtils.isEmpty(addDTO.getPurchaseId())) {
|
||||
throw new RuntimeException("采购事项ID不能为空");
|
||||
@@ -310,4 +362,161 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
throw new RuntimeException("结算金额必须大于0");
|
||||
}
|
||||
}
|
||||
|
||||
private List<CcdiPurchaseTransactionSupplier> buildSupplierEntities(
|
||||
String purchaseId,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierRows,
|
||||
String userName
|
||||
) {
|
||||
List<CcdiPurchaseTransactionSupplierExcel> normalizedRows = supplierRows == null
|
||||
? List.of()
|
||||
: supplierRows.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(this::hasAnySupplierValue)
|
||||
.toList();
|
||||
|
||||
long winnerCount = normalizedRows.stream()
|
||||
.filter(item -> parseIsBidWinner(item.getIsBidWinner()) == 1)
|
||||
.count();
|
||||
if (winnerCount > 1) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]存在多条中标供应商", purchaseId));
|
||||
}
|
||||
|
||||
Set<String> duplicateSupplierKeys = new LinkedHashSet<>();
|
||||
List<CcdiPurchaseTransactionSupplier> result = new ArrayList<>();
|
||||
for (int i = 0; i < normalizedRows.size(); i++) {
|
||||
CcdiPurchaseTransactionSupplierExcel supplierRow = normalizedRows.get(i);
|
||||
validateSupplierRow(supplierRow);
|
||||
|
||||
String duplicateKey = StringUtils.trimToEmpty(supplierRow.getSupplierName()) + "|"
|
||||
+ StringUtils.trimToEmpty(supplierRow.getSupplierUscc());
|
||||
if (!duplicateSupplierKeys.add(duplicateKey)) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]存在重复供应商", purchaseId));
|
||||
}
|
||||
|
||||
CcdiPurchaseTransactionSupplier supplier = new CcdiPurchaseTransactionSupplier();
|
||||
supplier.setPurchaseId(purchaseId);
|
||||
supplier.setSupplierName(StringUtils.trim(supplierRow.getSupplierName()));
|
||||
supplier.setSupplierUscc(StringUtils.trimToNull(supplierRow.getSupplierUscc()));
|
||||
supplier.setContactPerson(StringUtils.trimToNull(supplierRow.getContactPerson()));
|
||||
supplier.setContactPhone(StringUtils.trimToNull(supplierRow.getContactPhone()));
|
||||
supplier.setSupplierBankAccount(StringUtils.trimToNull(supplierRow.getSupplierBankAccount()));
|
||||
supplier.setIsBidWinner(parseIsBidWinner(supplierRow.getIsBidWinner()));
|
||||
supplier.setSortOrder(supplierRow.getSortOrder() == null ? i + 1 : supplierRow.getSortOrder());
|
||||
supplier.setCreatedBy(userName);
|
||||
supplier.setUpdatedBy(userName);
|
||||
result.add(supplier);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void validateSupplierRow(CcdiPurchaseTransactionSupplierExcel supplierRow) {
|
||||
if (StringUtils.isEmpty(supplierRow.getSupplierName())) {
|
||||
throw new RuntimeException("供应商名称不能为空");
|
||||
}
|
||||
if (StringUtils.length(supplierRow.getSupplierName()) > 200) {
|
||||
throw new RuntimeException("供应商名称长度不能超过200个字符");
|
||||
}
|
||||
if (StringUtils.length(supplierRow.getContactPerson()) > 50) {
|
||||
throw new RuntimeException("供应商联系人长度不能超过50个字符");
|
||||
}
|
||||
if (StringUtils.length(supplierRow.getSupplierBankAccount()) > 50) {
|
||||
throw new RuntimeException("供应商银行账户长度不能超过50个字符");
|
||||
}
|
||||
if (StringUtils.isNotEmpty(supplierRow.getContactPhone())
|
||||
&& !supplierRow.getContactPhone().matches("^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$")) {
|
||||
throw new RuntimeException("供应商联系电话格式不正确");
|
||||
}
|
||||
if (StringUtils.isNotEmpty(supplierRow.getSupplierUscc())
|
||||
&& !supplierRow.getSupplierUscc().matches("^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$")) {
|
||||
throw new RuntimeException("供应商统一信用代码格式不正确");
|
||||
}
|
||||
parseIsBidWinner(supplierRow.getIsBidWinner());
|
||||
}
|
||||
|
||||
private boolean hasAnySupplierValue(CcdiPurchaseTransactionSupplierExcel supplierRow) {
|
||||
return StringUtils.isNotEmpty(supplierRow.getPurchaseId())
|
||||
|| StringUtils.isNotEmpty(supplierRow.getSupplierName())
|
||||
|| StringUtils.isNotEmpty(supplierRow.getSupplierUscc())
|
||||
|| StringUtils.isNotEmpty(supplierRow.getContactPerson())
|
||||
|| StringUtils.isNotEmpty(supplierRow.getContactPhone())
|
||||
|| StringUtils.isNotEmpty(supplierRow.getSupplierBankAccount())
|
||||
|| StringUtils.isNotEmpty(supplierRow.getIsBidWinner())
|
||||
|| supplierRow.getSortOrder() != null;
|
||||
}
|
||||
|
||||
private int parseIsBidWinner(String rawValue) {
|
||||
if (StringUtils.isEmpty(rawValue)) {
|
||||
return 0;
|
||||
}
|
||||
String normalized = StringUtils.trim(rawValue);
|
||||
if ("1".equals(normalized) || "是".equals(normalized) || "Y".equalsIgnoreCase(normalized)
|
||||
|| "TRUE".equalsIgnoreCase(normalized)) {
|
||||
return 1;
|
||||
}
|
||||
if ("0".equals(normalized) || "否".equals(normalized) || "N".equalsIgnoreCase(normalized)
|
||||
|| "FALSE".equalsIgnoreCase(normalized)) {
|
||||
return 0;
|
||||
}
|
||||
throw new RuntimeException("是否中标仅支持填写“是/否”或“1/0”");
|
||||
}
|
||||
|
||||
private void fillWinnerSummary(
|
||||
CcdiPurchaseTransaction transaction,
|
||||
List<CcdiPurchaseTransactionSupplier> supplierList
|
||||
) {
|
||||
CcdiPurchaseTransactionSupplier winner = supplierList.stream()
|
||||
.filter(item -> Objects.equals(item.getIsBidWinner(), 1))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (winner == null) {
|
||||
transaction.setSupplierName(null);
|
||||
transaction.setSupplierUscc(null);
|
||||
transaction.setContactPerson(null);
|
||||
transaction.setContactPhone(null);
|
||||
transaction.setSupplierBankAccount(null);
|
||||
return;
|
||||
}
|
||||
transaction.setSupplierName(winner.getSupplierName());
|
||||
transaction.setSupplierUscc(winner.getSupplierUscc());
|
||||
transaction.setContactPerson(winner.getContactPerson());
|
||||
transaction.setContactPhone(winner.getContactPhone());
|
||||
transaction.setSupplierBankAccount(winner.getSupplierBankAccount());
|
||||
}
|
||||
|
||||
private PurchaseTransactionImportFailureVO buildFailure(
|
||||
CcdiPurchaseTransactionExcel mainExcel,
|
||||
String purchaseId,
|
||||
String errorMessage
|
||||
) {
|
||||
PurchaseTransactionImportFailureVO failure = new PurchaseTransactionImportFailureVO();
|
||||
if (mainExcel != null) {
|
||||
BeanUtils.copyProperties(mainExcel, failure);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(purchaseId)) {
|
||||
failure.setPurchaseId(purchaseId);
|
||||
}
|
||||
failure.setErrorMessage(errorMessage);
|
||||
return failure;
|
||||
}
|
||||
|
||||
private int countImportUnits(
|
||||
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||
) {
|
||||
LinkedHashSet<String> purchaseIds = new LinkedHashSet<>();
|
||||
purchaseIds.addAll(
|
||||
mainExcelList.stream()
|
||||
.map(CcdiPurchaseTransactionExcel::getPurchaseId)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||
);
|
||||
purchaseIds.addAll(
|
||||
supplierExcelList.stream()
|
||||
.map(CcdiPurchaseTransactionSupplierExcel::getPurchaseId)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||
);
|
||||
return purchaseIds.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,34 @@ package com.ruoyi.info.collection.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransaction;
|
||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransactionSupplier;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionSupplierDTO;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||
import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionVO;
|
||||
import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionSupplierVO;
|
||||
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper;
|
||||
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionSupplierMapper;
|
||||
import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionImportService;
|
||||
import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionService;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -39,6 +49,9 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
@Resource
|
||||
private ICcdiPurchaseTransactionImportService transactionImportService;
|
||||
|
||||
@Resource
|
||||
private CcdiPurchaseTransactionSupplierMapper supplierMapper;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@@ -93,7 +106,14 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
*/
|
||||
@Override
|
||||
public CcdiPurchaseTransactionVO selectTransactionById(String purchaseId) {
|
||||
return transactionMapper.selectTransactionById(purchaseId);
|
||||
CcdiPurchaseTransactionVO detail = transactionMapper.selectTransactionById(purchaseId);
|
||||
if (detail == null) {
|
||||
return null;
|
||||
}
|
||||
List<CcdiPurchaseTransactionSupplierVO> supplierList = selectSupplierListByPurchaseId(purchaseId);
|
||||
detail.setSupplierList(supplierList);
|
||||
detail.setSupplierCount(supplierList.size());
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,9 +130,12 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
throw new RuntimeException("该采购事项ID已存在");
|
||||
}
|
||||
|
||||
List<CcdiPurchaseTransactionSupplier> supplierList = buildSupplierEntities(addDTO.getPurchaseId(), addDTO.getSupplierList());
|
||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||
BeanUtils.copyProperties(addDTO, transaction);
|
||||
fillWinnerSummary(transaction, supplierList);
|
||||
int result = transactionMapper.insert(transaction);
|
||||
saveSuppliers(supplierList);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -126,9 +149,13 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
@Override
|
||||
@Transactional
|
||||
public int updateTransaction(CcdiPurchaseTransactionEditDTO editDTO) {
|
||||
List<CcdiPurchaseTransactionSupplier> supplierList = buildSupplierEntities(editDTO.getPurchaseId(), editDTO.getSupplierList());
|
||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||
BeanUtils.copyProperties(editDTO, transaction);
|
||||
fillWinnerSummary(transaction, supplierList);
|
||||
int result = transactionMapper.updateById(transaction);
|
||||
transactionMapper.deleteSuppliersByPurchaseIds(List.of(editDTO.getPurchaseId()));
|
||||
saveSuppliers(supplierList);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -142,19 +169,24 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteTransactionByIds(String[] purchaseIds) {
|
||||
transactionMapper.deleteSuppliersByPurchaseIds(List.of(purchaseIds));
|
||||
return transactionMapper.deleteBatchIds(java.util.List.of(purchaseIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入采购交易数据(异步)
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param mainExcelList 主信息Excel实体列表
|
||||
* @param supplierExcelList 供应商明细Excel实体列表
|
||||
* @return 任务ID
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public String importTransaction(java.util.List<CcdiPurchaseTransactionExcel> excelList) {
|
||||
if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
|
||||
public String importTransaction(
|
||||
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||
) {
|
||||
if ((mainExcelList == null || mainExcelList.isEmpty()) && (supplierExcelList == null || supplierExcelList.isEmpty())) {
|
||||
throw new RuntimeException("至少需要一条数据");
|
||||
}
|
||||
|
||||
@@ -170,7 +202,7 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
Map<String, Object> statusData = new HashMap<>();
|
||||
statusData.put("taskId", taskId);
|
||||
statusData.put("status", "PROCESSING");
|
||||
statusData.put("totalCount", excelList.size());
|
||||
statusData.put("totalCount", countImportUnits(mainExcelList, supplierExcelList));
|
||||
statusData.put("successCount", 0);
|
||||
statusData.put("failureCount", 0);
|
||||
statusData.put("progress", 0);
|
||||
@@ -181,8 +213,134 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
||||
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
||||
|
||||
// 调用异步导入服务
|
||||
transactionImportService.importTransactionAsync(excelList, taskId, userName);
|
||||
transactionImportService.importTransactionAsync(mainExcelList, supplierExcelList, taskId, userName);
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
private int countImportUnits(
|
||||
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||
) {
|
||||
LinkedHashSet<String> purchaseIds = new LinkedHashSet<>();
|
||||
if (mainExcelList != null) {
|
||||
purchaseIds.addAll(
|
||||
mainExcelList.stream()
|
||||
.map(CcdiPurchaseTransactionExcel::getPurchaseId)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||
);
|
||||
}
|
||||
if (supplierExcelList != null) {
|
||||
purchaseIds.addAll(
|
||||
supplierExcelList.stream()
|
||||
.map(CcdiPurchaseTransactionSupplierExcel::getPurchaseId)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||
);
|
||||
}
|
||||
return purchaseIds.isEmpty() ? 0 : purchaseIds.size();
|
||||
}
|
||||
|
||||
private List<CcdiPurchaseTransactionSupplier> buildSupplierEntities(
|
||||
String purchaseId,
|
||||
List<CcdiPurchaseTransactionSupplierDTO> supplierDTOList
|
||||
) {
|
||||
List<CcdiPurchaseTransactionSupplierDTO> normalizedList = normalizeSupplierList(supplierDTOList);
|
||||
validateSupplierList(normalizedList);
|
||||
|
||||
List<CcdiPurchaseTransactionSupplier> supplierList = new ArrayList<>();
|
||||
for (int i = 0; i < normalizedList.size(); i++) {
|
||||
CcdiPurchaseTransactionSupplierDTO dto = normalizedList.get(i);
|
||||
CcdiPurchaseTransactionSupplier supplier = new CcdiPurchaseTransactionSupplier();
|
||||
BeanUtils.copyProperties(dto, supplier);
|
||||
supplier.setPurchaseId(purchaseId);
|
||||
supplier.setIsBidWinner(Objects.equals(dto.getIsBidWinner(), 1) ? 1 : 0);
|
||||
supplier.setSortOrder(dto.getSortOrder() == null ? i + 1 : dto.getSortOrder());
|
||||
supplierList.add(supplier);
|
||||
}
|
||||
return supplierList;
|
||||
}
|
||||
|
||||
private List<CcdiPurchaseTransactionSupplierDTO> normalizeSupplierList(
|
||||
List<CcdiPurchaseTransactionSupplierDTO> supplierDTOList
|
||||
) {
|
||||
if (supplierDTOList == null) {
|
||||
return List.of();
|
||||
}
|
||||
return supplierDTOList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(this::hasAnySupplierValue)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private boolean hasAnySupplierValue(CcdiPurchaseTransactionSupplierDTO supplierDTO) {
|
||||
return StringUtils.isNotEmpty(supplierDTO.getSupplierName())
|
||||
|| StringUtils.isNotEmpty(supplierDTO.getSupplierUscc())
|
||||
|| StringUtils.isNotEmpty(supplierDTO.getContactPerson())
|
||||
|| StringUtils.isNotEmpty(supplierDTO.getContactPhone())
|
||||
|| StringUtils.isNotEmpty(supplierDTO.getSupplierBankAccount())
|
||||
|| supplierDTO.getIsBidWinner() != null
|
||||
|| supplierDTO.getSortOrder() != null;
|
||||
}
|
||||
|
||||
private void validateSupplierList(List<CcdiPurchaseTransactionSupplierDTO> supplierList) {
|
||||
long winnerCount = supplierList.stream()
|
||||
.filter(item -> Objects.equals(item.getIsBidWinner(), 1))
|
||||
.count();
|
||||
if (winnerCount > 1) {
|
||||
throw new RuntimeException("同一招投标事项仅允许维护一条中标供应商");
|
||||
}
|
||||
|
||||
LinkedHashSet<String> duplicateKeys = new LinkedHashSet<>();
|
||||
for (CcdiPurchaseTransactionSupplierDTO supplier : supplierList) {
|
||||
String duplicateKey = StringUtils.trimToEmpty(supplier.getSupplierName()) + "|"
|
||||
+ StringUtils.trimToEmpty(supplier.getSupplierUscc());
|
||||
if (!duplicateKeys.add(duplicateKey)) {
|
||||
throw new RuntimeException("同一招投标事项存在重复供应商,请检查供应商名称和统一信用代码");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fillWinnerSummary(
|
||||
CcdiPurchaseTransaction transaction,
|
||||
List<CcdiPurchaseTransactionSupplier> supplierList
|
||||
) {
|
||||
CcdiPurchaseTransactionSupplier winnerSupplier = supplierList.stream()
|
||||
.filter(item -> Objects.equals(item.getIsBidWinner(), 1))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (winnerSupplier == null) {
|
||||
transaction.setSupplierName(null);
|
||||
transaction.setSupplierUscc(null);
|
||||
transaction.setContactPerson(null);
|
||||
transaction.setContactPhone(null);
|
||||
transaction.setSupplierBankAccount(null);
|
||||
return;
|
||||
}
|
||||
transaction.setSupplierName(winnerSupplier.getSupplierName());
|
||||
transaction.setSupplierUscc(winnerSupplier.getSupplierUscc());
|
||||
transaction.setContactPerson(winnerSupplier.getContactPerson());
|
||||
transaction.setContactPhone(winnerSupplier.getContactPhone());
|
||||
transaction.setSupplierBankAccount(winnerSupplier.getSupplierBankAccount());
|
||||
}
|
||||
|
||||
private void saveSuppliers(List<CcdiPurchaseTransactionSupplier> supplierList) {
|
||||
for (CcdiPurchaseTransactionSupplier supplier : supplierList) {
|
||||
supplierMapper.insert(supplier);
|
||||
}
|
||||
}
|
||||
|
||||
private List<CcdiPurchaseTransactionSupplierVO> selectSupplierListByPurchaseId(String purchaseId) {
|
||||
return supplierMapper.selectList(
|
||||
new LambdaQueryWrapper<CcdiPurchaseTransactionSupplier>()
|
||||
.eq(CcdiPurchaseTransactionSupplier::getPurchaseId, purchaseId)
|
||||
.orderByAsc(CcdiPurchaseTransactionSupplier::getSortOrder)
|
||||
.orderByAsc(CcdiPurchaseTransactionSupplier::getId)
|
||||
).stream().map(entity -> {
|
||||
CcdiPurchaseTransactionSupplierVO vo = new CcdiPurchaseTransactionSupplierVO();
|
||||
BeanUtils.copyProperties(entity, vo);
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.ruoyi.info.collection.utils;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
import com.alibaba.excel.write.handler.WriteHandler;
|
||||
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
|
||||
import com.ruoyi.info.collection.handler.DictDropdownWriteHandler;
|
||||
@@ -98,6 +100,23 @@ public class EasyExcelUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入Excel(按指定Sheet名称)
|
||||
*
|
||||
* @param inputStream 输入流
|
||||
* @param clazz 实体类
|
||||
* @param sheetName 工作表名称
|
||||
* @param <T> 泛型
|
||||
* @return 数据列表
|
||||
*/
|
||||
public static <T> List<T> importExcel(java.io.InputStream inputStream, Class<T> clazz, String sheetName) {
|
||||
try {
|
||||
return EasyExcel.read(inputStream).head(clazz).sheet(sheetName).doReadSync();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("导入Excel失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载导入模板
|
||||
*
|
||||
@@ -210,6 +229,45 @@ public class EasyExcelUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载双Sheet导入模板(带字典下拉框)
|
||||
*
|
||||
* @param response 响应对象
|
||||
* @param firstClazz 第一张Sheet实体类
|
||||
* @param firstSheetName 第一张Sheet名称
|
||||
* @param secondClazz 第二张Sheet实体类
|
||||
* @param secondSheetName 第二张Sheet名称
|
||||
* @param fileName 文件名称
|
||||
* @param <T1> 第一张Sheet泛型
|
||||
* @param <T2> 第二张Sheet泛型
|
||||
*/
|
||||
public static <T1, T2> void importTemplateWithDictDropdown(
|
||||
HttpServletResponse response,
|
||||
Class<T1> firstClazz,
|
||||
String firstSheetName,
|
||||
Class<T2> secondClazz,
|
||||
String secondSheetName,
|
||||
String fileName
|
||||
) {
|
||||
setResponseHeader(response, fileName);
|
||||
try (ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build()) {
|
||||
writer.write(List.of(), buildTemplateSheet(0, firstClazz, firstSheetName));
|
||||
writer.write(List.of(), buildTemplateSheet(1, secondClazz, secondSheetName));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("下载双Sheet导入模板失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> WriteSheet buildTemplateSheet(int sheetNo, Class<T> clazz, String sheetName) {
|
||||
return EasyExcel.writerSheet(sheetNo, sheetName)
|
||||
.head(clazz)
|
||||
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
|
||||
.registerWriteHandler(new DictDropdownWriteHandler(clazz))
|
||||
.registerWriteHandler(new TextFormatWriteHandler(clazz))
|
||||
.registerWriteHandler(new RequiredFieldWriteHandler(clazz))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出Excel(带字典下拉框)
|
||||
* 导出的数据包含实际值,但模板中有下拉框供后续编辑使用
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<result property="contactPhone" column="contact_phone"/>
|
||||
<result property="supplierUscc" column="supplier_uscc"/>
|
||||
<result property="supplierBankAccount" column="supplier_bank_account"/>
|
||||
<result property="supplierCount" column="supplier_count"/>
|
||||
<result property="applyDate" column="apply_date"/>
|
||||
<result property="planApproveDate" column="plan_approve_date"/>
|
||||
<result property="announceDate" column="announce_date"/>
|
||||
@@ -47,49 +48,61 @@
|
||||
<!-- 分页查询采购交易列表 -->
|
||||
<select id="selectTransactionPage" resultMap="CcdiPurchaseTransactionVOResult">
|
||||
SELECT
|
||||
purchase_id, purchase_category, project_name, subject_name, subject_desc,
|
||||
purchase_qty, budget_amount, bid_amount, actual_amount, contract_amount, settlement_amount,
|
||||
purchase_method, supplier_name, contact_person, contact_phone, supplier_uscc, supplier_bank_account,
|
||||
apply_date, plan_approve_date, announce_date, bid_open_date, contract_sign_date,
|
||||
expected_delivery_date, actual_delivery_date, acceptance_date, settlement_date,
|
||||
applicant_id, applicant_name, apply_department, purchase_leader_id, purchase_leader_name, purchase_department,
|
||||
created_by, create_time, updated_by, update_time
|
||||
FROM ccdi_purchase_transaction
|
||||
t.purchase_id, t.purchase_category, t.project_name, t.subject_name, t.subject_desc,
|
||||
t.purchase_qty, t.budget_amount, t.bid_amount, t.actual_amount, t.contract_amount, t.settlement_amount,
|
||||
t.purchase_method, t.supplier_name, t.contact_person, t.contact_phone, t.supplier_uscc, t.supplier_bank_account,
|
||||
IFNULL(supplier_stats.supplier_count, 0) AS supplier_count,
|
||||
t.apply_date, t.plan_approve_date, t.announce_date, t.bid_open_date, t.contract_sign_date,
|
||||
t.expected_delivery_date, t.actual_delivery_date, t.acceptance_date, t.settlement_date,
|
||||
t.applicant_id, t.applicant_name, t.apply_department, t.purchase_leader_id, t.purchase_leader_name, t.purchase_department,
|
||||
t.created_by, t.create_time, t.updated_by, t.update_time
|
||||
FROM ccdi_purchase_transaction t
|
||||
LEFT JOIN (
|
||||
SELECT purchase_id, COUNT(*) AS supplier_count
|
||||
FROM ccdi_purchase_transaction_supplier
|
||||
GROUP BY purchase_id
|
||||
) supplier_stats ON supplier_stats.purchase_id = t.purchase_id
|
||||
<where>
|
||||
<if test="query.projectName != null and query.projectName != ''">
|
||||
AND project_name LIKE CONCAT('%', #{query.projectName}, '%')
|
||||
AND t.project_name LIKE CONCAT('%', #{query.projectName}, '%')
|
||||
</if>
|
||||
<if test="query.subjectName != null and query.subjectName != ''">
|
||||
AND subject_name LIKE CONCAT('%', #{query.subjectName}, '%')
|
||||
AND t.subject_name LIKE CONCAT('%', #{query.subjectName}, '%')
|
||||
</if>
|
||||
<if test="query.applicantName != null and query.applicantName != ''">
|
||||
AND applicant_name LIKE CONCAT('%', #{query.applicantName}, '%')
|
||||
AND t.applicant_name LIKE CONCAT('%', #{query.applicantName}, '%')
|
||||
</if>
|
||||
<if test="query.applicantId != null and query.applicantId != ''">
|
||||
AND applicant_id = #{query.applicantId}
|
||||
AND t.applicant_id = #{query.applicantId}
|
||||
</if>
|
||||
<if test="query.applyDateStart != null">
|
||||
AND apply_date >= #{query.applyDateStart}
|
||||
AND t.apply_date >= #{query.applyDateStart}
|
||||
</if>
|
||||
<if test="query.applyDateEnd != null">
|
||||
AND apply_date <= #{query.applyDateEnd}
|
||||
AND t.apply_date <= #{query.applyDateEnd}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
ORDER BY t.create_time DESC
|
||||
</select>
|
||||
|
||||
<!-- 查询采购交易详情 -->
|
||||
<select id="selectTransactionById" resultMap="CcdiPurchaseTransactionVOResult">
|
||||
SELECT
|
||||
purchase_id, purchase_category, project_name, subject_name, subject_desc,
|
||||
purchase_qty, budget_amount, bid_amount, actual_amount, contract_amount, settlement_amount,
|
||||
purchase_method, supplier_name, contact_person, contact_phone, supplier_uscc, supplier_bank_account,
|
||||
apply_date, plan_approve_date, announce_date, bid_open_date, contract_sign_date,
|
||||
expected_delivery_date, actual_delivery_date, acceptance_date, settlement_date,
|
||||
applicant_id, applicant_name, apply_department, purchase_leader_id, purchase_leader_name, purchase_department,
|
||||
created_by, create_time, updated_by, update_time
|
||||
FROM ccdi_purchase_transaction
|
||||
WHERE purchase_id = #{purchaseId}
|
||||
t.purchase_id, t.purchase_category, t.project_name, t.subject_name, t.subject_desc,
|
||||
t.purchase_qty, t.budget_amount, t.bid_amount, t.actual_amount, t.contract_amount, t.settlement_amount,
|
||||
t.purchase_method, t.supplier_name, t.contact_person, t.contact_phone, t.supplier_uscc, t.supplier_bank_account,
|
||||
IFNULL(supplier_stats.supplier_count, 0) AS supplier_count,
|
||||
t.apply_date, t.plan_approve_date, t.announce_date, t.bid_open_date, t.contract_sign_date,
|
||||
t.expected_delivery_date, t.actual_delivery_date, t.acceptance_date, t.settlement_date,
|
||||
t.applicant_id, t.applicant_name, t.apply_department, t.purchase_leader_id, t.purchase_leader_name, t.purchase_department,
|
||||
t.created_by, t.create_time, t.updated_by, t.update_time
|
||||
FROM ccdi_purchase_transaction t
|
||||
LEFT JOIN (
|
||||
SELECT purchase_id, COUNT(*) AS supplier_count
|
||||
FROM ccdi_purchase_transaction_supplier
|
||||
GROUP BY purchase_id
|
||||
) supplier_stats ON supplier_stats.purchase_id = t.purchase_id
|
||||
WHERE t.purchase_id = #{purchaseId}
|
||||
</select>
|
||||
|
||||
<!-- 批量插入采购交易数据 -->
|
||||
@@ -137,4 +150,12 @@
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteSuppliersByPurchaseIds">
|
||||
DELETE FROM ccdi_purchase_transaction_supplier
|
||||
WHERE purchase_id IN
|
||||
<foreach collection="purchaseIds" item="purchaseId" open="(" separator="," close=")">
|
||||
#{purchaseId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user