From b09892a349bf90bceb0b574270db1f7d37d4c55e Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Fri, 23 Jan 2026 17:42:50 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=20=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E8=B4=B4=E7=9A=AE=E5=88=86=E7=B1=BB=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=8E=A5=E5=8F=A3=E3=80=81=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=BB=84=E7=BB=87=E8=B4=B4=E7=9A=AE=E5=88=86=E7=B1=BB=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=E3=80=81=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E6=9D=BFexcel=E5=88=86=E7=B1=BB=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E6=A0=8F=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=A5=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E5=88=86=E7=B1=BB=E5=90=8D=E7=A7=B0=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E8=83=BD=E5=8A=9B=E3=80=81=E5=AF=BC=E5=85=A5=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E7=BB=84=E7=BB=87=E5=88=86=E7=B1=BB=E5=90=8D=E7=A7=B0=E8=83=BD?= =?UTF-8?q?=E5=8A=9B=EF=BC=9B2=E3=80=81=E5=AE=8C=E5=96=84=E8=B4=B4?= =?UTF-8?q?=E7=9A=AE=E7=AE=A1=E7=90=86=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../executor/enums/ErrorCodeConstants.java | 6 + .../admin/veneer/VeneerController.java | 20 +- .../vo/VeneerClassificationNameRespVO.java | 20 ++ .../vo/VeneerClassificationNameSaveReqVO.java | 20 ++ .../veneer/VeneerClassificationNameDO.java | 42 ++++ .../VeneerClassificationNameMapper.java | 15 ++ .../service/veneer/VeneerExcelListener.java | 70 +++--- ...emplateClassificationNameWriteHandler.java | 55 +++++ .../service/veneer/VeneerService.java | 25 ++ .../service/veneer/VeneerServiceImpl.java | 81 ++++++ .../executor/util/file/FileHelperUtil.java | 28 +-- .../src/main/resources/message.properties | 4 +- .../src/main/resources/message_cht.properties | 6 +- .../src/main/resources/message_en.properties | 4 +- .../resources/message_errorcode.properties | 6 +- .../message_errorcode_cht.properties | 6 +- .../resources/message_errorcode_en.properties | 6 +- .../type/veneer/cht/貼皮導入範本.xlsx | Bin 10340 -> 10342 bytes .../veneer/en/veneer_import_template.xlsx | Bin 10351 -> 10325 bytes .../type/veneer/zh/贴皮导入模板.xlsx | Bin 10338 -> 10339 bytes .../admin/veneer/VeneerControllerTest.java | 114 +++++++-- .../service/veneer/VeneerServiceImplTest.java | 232 ++++++++++++++++++ 22 files changed, 674 insertions(+), 86 deletions(-) create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameRespVO.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameSaveReqVO.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/veneer/VeneerClassificationNameDO.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/veneer/VeneerClassificationNameMapper.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelTemplateClassificationNameWriteHandler.java diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java index f907b2f77..53c42f679 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java @@ -7,6 +7,8 @@ import com.cf.imes.framework.common.exception.ErrorCode; * 生产执行服务错误码枚举 使用 1-003-000-000 段 */ public class ErrorCodeConstants { + private ErrorCodeConstants() { + } // ========== 生产单开料排单 public static final ErrorCode PLAN_NOT_EXISTS = new ErrorCode(1_003_107_000, "生产单开料排单不存在"); @@ -177,4 +179,8 @@ public class ErrorCodeConstants { public static final ErrorCode VENEER_IMPORT_DIGITAL_TYPE_ERROR = new ErrorCode(1_003_009_004, "veneer.import.digital.type.error"); public static final ErrorCode VENEER_IMPORT_POSITIVE_NUMBER_ERROR = new ErrorCode(1_003_009_005, "veneer.import.positive.number.error"); public static final ErrorCode VENEER_IMPORT_NUMBER_LENGTH_ERROR = new ErrorCode(1_003_009_006, "veneer.import.number.length.error"); + public static final ErrorCode VENEER_IMPORT_TEMPLATE_DOWNLOAD_ERROR = new ErrorCode(1_003_009_007, "veneer.import.template.download.error"); + public static final ErrorCode VENEER_IMPORT_ORG_CLASSIFICATION_NAME_NOT_EXIST = new ErrorCode(1_003_009_008, "veneer.import.org.classification.name.not.exist"); + public static final ErrorCode VENEER_ORG_CLASSIFICATION_NAME_EXIST = new ErrorCode(1_003_009_009, "veneer.org.classification.name.exist"); + public static final ErrorCode VENEER_ORG_CLASSIFICATION_NAME_EMPTY = new ErrorCode(1_003_009_010, "veneer.org.classification.name.empty"); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerController.java index b5a545a23..e493fb596 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerController.java @@ -6,7 +6,8 @@ import com.cf.imes.framework.common.pojo.PageParam; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.excel.core.util.ExcelUtils; import com.cf.imes.framework.operatelog.core.annotations.OperateLog; -import com.cf.imes.module.executor.constants.file.TemplateFilePathConstants; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerImportExcelVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPageReqVO; @@ -14,13 +15,11 @@ import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO; import com.cf.imes.module.executor.service.veneer.VeneerExcelListener; import com.cf.imes.module.executor.service.veneer.VeneerService; -import com.cf.imes.module.executor.util.file.FileHelperUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; -import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -77,8 +76,7 @@ public class VeneerController { @Operation(summary = "下载贴皮导入模版") @OperateLog(type = EXPORT) public void getVeneerImportTemplate(HttpServletResponse response) { - String veneerImportTemplatePath = TemplateFilePathConstants.getVeneerImportTemplatePath(LocaleContextHolder.getLocale().getLanguage()); - FileHelperUtil.getFirstFile(veneerImportTemplatePath, response); + veneerService.importTemplateDownload(response); } @PostMapping("/import") @@ -128,4 +126,16 @@ public class VeneerController { veneerService.saveDefect(reqVO); return success(true); } + + @PostMapping("/classificationName") + @Operation(summary = "创建分类名称") + public CommonResult createClassificationName(@Valid @RequestBody VeneerClassificationNameSaveReqVO saveReqVO) { + return success(veneerService.addClassificationName(saveReqVO)); + } + + @GetMapping("/org/classificationName") + @Operation(summary = "获取分类名称列表") + public CommonResult> getOrgVeneerClassificationNameList() { + return success(veneerService.getOrgVeneerClassificationNameList()); + } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameRespVO.java new file mode 100644 index 000000000..5cee3436b --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameRespVO.java @@ -0,0 +1,20 @@ +package com.cf.imes.module.executor.controller.admin.veneer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * + * + * @author Gqr + * @since 2026/1/22 17:21 + */ +@Schema(description = "生产管理 - 贴皮分类名称列表 Response VO") +@Data +public class VeneerClassificationNameRespVO { + @Schema(description = "分类名称id") + private Long id; + + @Schema(description = "分类名称") + private String name; +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameSaveReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameSaveReqVO.java new file mode 100644 index 000000000..4ba2710ec --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/veneer/vo/VeneerClassificationNameSaveReqVO.java @@ -0,0 +1,20 @@ +package com.cf.imes.module.executor.controller.admin.veneer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * + * + * @author Gqr + * @since 2026/1/23 10:56 + */ +@Data +public class VeneerClassificationNameSaveReqVO { + @Schema(description = "分类名称") + @NotNull(message = "{veneer.classification.name.save.name.not.null}") + @Length(max = 64, message = "{veneer.classification.name.save.name.length.max}") + private String name; +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/veneer/VeneerClassificationNameDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/veneer/VeneerClassificationNameDO.java new file mode 100644 index 000000000..f8ba68441 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/veneer/VeneerClassificationNameDO.java @@ -0,0 +1,42 @@ +package com.cf.imes.module.executor.dal.dataobject.veneer; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +/** + * 贴皮 veneers_classification_name_{N} DO + * + * @author Gqr + * @since 2026/1/22 17:07 + */ +@TableName("veneers_classification_name") +@KeySequence("veneers_classification_name_n_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class VeneerClassificationNameDO extends BaseDO { + /** + * 主键 + */ + private Long id; + + /** + * 分类名称 + */ + private String name; + + /** + * 组织ID + */ + private Long organId; +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/veneer/VeneerClassificationNameMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/veneer/VeneerClassificationNameMapper.java new file mode 100644 index 000000000..ff1d081bf --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/veneer/VeneerClassificationNameMapper.java @@ -0,0 +1,15 @@ +package com.cf.imes.module.executor.dal.mysql.veneer; + +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerClassificationNameDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 贴皮分类管理 Mapper + * + * @author Gqr + * @since 2026/1/22 17:12 + */ +@Mapper +public interface VeneerClassificationNameMapper extends BaseMapperX { +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelListener.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelListener.java index 44ba487f7..118113a85 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelListener.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelListener.java @@ -10,6 +10,7 @@ import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.util.ListUtils; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerImportExcelVO; import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO; import com.cf.imes.module.executor.enums.veneer.VeneerStatusEnum; @@ -19,10 +20,13 @@ import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_DIGITAL_TYPE_ERROR; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_LENGTH_ERROR; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_NUMBER_LENGTH_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_ORG_CLASSIFICATION_NAME_NOT_EXIST; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_POSITIVE_NUMBER_ERROR; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_REQUIRED_LACK; @@ -33,7 +37,7 @@ import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT * @since 2026/1/5 18:18 */ @Slf4j -public class VeneerExcelListener extends AnalysisEventListener { +public class VeneerExcelListener extends AnalysisEventListener { /** * 每500条操作入库一次 */ @@ -48,6 +52,8 @@ public class VeneerExcelListener extends AnalysisEventListener headMap; + private Set orgClassificationNameSet; + private Long organId; public VeneerExcelListener(VeneerService veneerService) { @@ -55,6 +61,10 @@ public class VeneerExcelListener extends AnalysisEventListener orgVeneerClassificationNameList = veneerService.getOrgVeneerClassificationNameList(); + if (CollUtil.isNotEmpty(orgVeneerClassificationNameList)) { + orgClassificationNameSet = orgVeneerClassificationNameList.stream().map(VeneerClassificationNameRespVO::getName).collect(Collectors.toSet()); + } } /** @@ -74,22 +84,10 @@ public class VeneerExcelListener extends AnalysisEventListener= BATCH_COUNT) { - updateData(); - // 存储完成清理 list - cachedUpdateDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); - } - return; - } + // 校验分类名称组织内是否存在 + validClassificationName(data.getClassificationName(), rowIndex); // 校验属性长度 validFieldLength(headMap.get(0), veneerNo, 32, rowIndex); @@ -108,6 +106,22 @@ public class VeneerExcelListener extends AnalysisEventListener= BATCH_COUNT) { + updateData(); + // 存储完成清理 list + cachedUpdateDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + } + return; + } + // 累计新增列表 cachedInsertDataList.add(data); @@ -119,11 +133,6 @@ public class VeneerExcelListener extends AnalysisEventListener extends AnalysisEventListener headMap, AnalysisContext context) { this.headMap = headMap; @@ -172,6 +176,16 @@ public class VeneerExcelListener extends AnalysisEventListener extends AnalysisEventListener 0) { - return true; - } else { - return false; - } + return number > 0; } catch (NumberFormatException e) { return false; } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelTemplateClassificationNameWriteHandler.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelTemplateClassificationNameWriteHandler.java new file mode 100644 index 000000000..3135934d7 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerExcelTemplateClassificationNameWriteHandler.java @@ -0,0 +1,55 @@ +package com.cf.imes.module.executor.service.veneer; + +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddressList; + +/** + * 贴皮excel模版分类名称填充处理器 + * + * @author Gqr + * @since 2026/1/22 18:50 + */ +public class VeneerExcelTemplateClassificationNameWriteHandler implements SheetWriteHandler { + private final int columnIndex; // 0-based,C 列 = 2 + private final String[] options; + private final int firstRow; + private final int lastRow; + + public VeneerExcelTemplateClassificationNameWriteHandler(int columnIndex, + String[] options, + int firstRow, + int lastRow) { + this.columnIndex = columnIndex; + this.options = options; + this.firstRow = firstRow; + this.lastRow = lastRow; + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder workbookHolder, + WriteSheetHolder sheetHolder) { + + Sheet sheet = sheetHolder.getSheet(); + + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = + helper.createExplicitListConstraint(options); + + CellRangeAddressList addressList = + new CellRangeAddressList(firstRow, lastRow, columnIndex, columnIndex); + + DataValidation validation = + helper.createValidation(constraint, addressList); + + validation.setShowErrorBox(true); + validation.setSuppressDropDownArrow(true); + + sheet.addValidationData(validation); + } +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerService.java index c4bce888f..4b13c63e9 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerService.java @@ -1,11 +1,14 @@ package com.cf.imes.module.executor.service.veneer; import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPageReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO; import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -52,6 +55,13 @@ public interface VeneerService { */ Long uploadPic(MultipartFile file) throws IOException; + /** + * 贴皮导入模版下载 + * + * @throws IOException + */ + void importTemplateDownload(HttpServletResponse response); + /** * 分页查询贴皮 * @@ -96,4 +106,19 @@ public interface VeneerService { * @return */ void saveDefect(VeneerDefectSaveReqVO defectSaveReqVO); + + /** + * 新增分类名称 + * + * @param saveReqVO 名称 + * @return + */ + Long addClassificationName(VeneerClassificationNameSaveReqVO saveReqVO); + + /** + * 获取组织分类名称列表 + * + * @return + */ + List getOrgVeneerClassificationNameList(); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImpl.java index 948f8f265..7519a593a 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImpl.java @@ -1,8 +1,11 @@ package com.cf.imes.module.executor.service.veneer; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.EasyExcelFactory; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.exception.ServiceException; @@ -11,23 +14,33 @@ import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; +import com.cf.imes.module.executor.constants.file.TemplateFilePathConstants; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPageReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO; +import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerClassificationNameDO; import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO; import com.cf.imes.module.executor.dal.mysql.veneer.VeneerBatchMapper; +import com.cf.imes.module.executor.dal.mysql.veneer.VeneerClassificationNameMapper; import com.cf.imes.module.executor.dal.mysql.veneer.VeneerMapper; +import com.cf.imes.module.executor.util.file.FileHelperUtil; import com.cf.imes.module.infra.api.file.FileApi; import com.cf.imes.module.system.api.organ.OrganApi; import com.cf.imes.module.system.api.organ.dto.OrganizationDTO; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import java.io.File; import java.io.IOException; import java.time.LocalDateTime; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; @@ -35,8 +48,11 @@ import java.util.Optional; import java.util.stream.Collectors; import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_TEMPLATE_DOWNLOAD_ERROR; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NOT_EXIST; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NO_EXIST; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_EMPTY; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_EXIST; /** * 贴皮管理ServiceImpl 实现类 @@ -58,6 +74,9 @@ public class VeneerServiceImpl implements VeneerService { @Resource private VeneerBatchMapper veneerBatchMapper; + @Resource + private VeneerClassificationNameMapper veneerClassificationNameMapper; + @Override public Long create(VeneerSaveReqVO reqVO) { // 1、校验贴皮编号 @@ -120,6 +139,39 @@ public class VeneerServiceImpl implements VeneerService { return fileApi.createFileAndReturnId(file.getBytes(), String.format("%s-veneer-pic-file-%s.%s", organizationDTO.getName(), LocalDateTimeUtil.format(LocalDateTime.now(), PURE_DATETIME_PATTERN), getFileExtension(file.getOriginalFilename()))); } + @Override + public void importTemplateDownload(HttpServletResponse response) { + try { + // 根据语种获取模版的路径 + String veneerImportTemplatePath = TemplateFilePathConstants.getVeneerImportTemplatePath(LocaleContextHolder.getLocale().getLanguage()); + + // 获取文件 + File templateFile = FileHelperUtil.getFirstFile(veneerImportTemplatePath); + + // 获取组织分类名称列表 + List orgVeneerClassificationNameList = getOrgVeneerClassificationNameList(); + if (CollUtil.isEmpty(orgVeneerClassificationNameList)) { + throw new ServiceException(VENEER_ORG_CLASSIFICATION_NAME_EMPTY); + } + + String[] options = orgVeneerClassificationNameList.stream().map(VeneerClassificationNameRespVO::getName).toArray(String[]::new); + + // 从第2行开始, 到200行写入数据源 + EasyExcelFactory.write(response.getOutputStream()) + .withTemplate(FileUtil.getInputStream(templateFile)) + .registerWriteHandler(new VeneerExcelTemplateClassificationNameWriteHandler( + 2, + options, + 1, + 200 + )) + .sheet(0) + .doWrite(Collections.emptyList()); + } catch (IOException ie) { + throw new ServiceException(VENEER_IMPORT_TEMPLATE_DOWNLOAD_ERROR); + } + } + @Override public PageResult getPage(VeneerPageReqVO pageReqVO) { PageResult veneerDOPageResult = veneerMapper.selectPage(pageReqVO); @@ -217,4 +269,33 @@ public class VeneerServiceImpl implements VeneerService { .map(ext -> ext.toLowerCase(Locale.ROOT)) .orElse(".jpg"); } + + @Override + public Long addClassificationName(VeneerClassificationNameSaveReqVO saveReqVO) { + String classificationName = saveReqVO.getName(); + // 校验组织下分类名称唯一 + validOrgClassificationName(classificationName); + + VeneerClassificationNameDO veneerClassificationNameDO = new VeneerClassificationNameDO(); + veneerClassificationNameDO.setName(classificationName); + veneerClassificationNameMapper.insert(veneerClassificationNameDO); + return veneerClassificationNameDO.getId(); + } + + /** + * 校验组织下分类名称唯一 + * + * @param classificationName + */ + private void validOrgClassificationName(String classificationName) { + if (veneerClassificationNameMapper.selectCount(new LambdaQueryWrapper() + .eq(VeneerClassificationNameDO::getName, classificationName)) > 0) { + throw new ServiceException(VENEER_ORG_CLASSIFICATION_NAME_EXIST); + } + } + + @Override + public List getOrgVeneerClassificationNameList() { + return BeanUtil.copyToList(veneerClassificationNameMapper.selectList(), VeneerClassificationNameRespVO.class); + } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/file/FileHelperUtil.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/file/FileHelperUtil.java index 7068da420..14c8500f4 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/file/FileHelperUtil.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/file/FileHelperUtil.java @@ -32,7 +32,6 @@ public class FileHelperUtil { OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) { byte[] buffer = new byte[fis.available()]; fis.read(buffer); - fis.close(); response.reset(); response.setCharacterEncoding(CharsetUtil.UTF_8); @@ -67,12 +66,11 @@ public class FileHelperUtil { } /** - * 下载目录下第一个文件 + * 获取目录下第一个文件 * * @param dirPath - * @param response */ - public static void getFirstFile(String dirPath, HttpServletResponse response) { + public static File getFirstFile(String dirPath) { File dir = new File(dirPath); if (!dir.exists() || !dir.isDirectory()) { throw new ServiceException(FILE_NOT_EXISTS); @@ -83,26 +81,6 @@ public class FileHelperUtil { throw new ServiceException(FILE_NOT_EXISTS); } - File file = files[0]; - // 获取文件名 - String filename = file.getName(); - // 将文件写入输入流 - try (FileInputStream fis = new FileInputStream(file); - OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) { - byte[] buffer = new byte[fis.available()]; - fis.read(buffer); - fis.close(); - - response.reset(); - response.setCharacterEncoding(CharsetUtil.UTF_8); - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, CharsetUtil.UTF_8)); - response.addHeader("Content-Length", "" + file.length()); - - response.setContentType("application/octet-stream"); - outputStream.write(buffer); - outputStream.flush(); - } catch (IOException ex) { - throw new ServiceException(FILE_NOT_EXISTS); - } + return files[0]; } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message.properties b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message.properties index d60296ba9..e19b7d112 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message.properties +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message.properties @@ -15,4 +15,6 @@ veneer.save.veneerNo.not.null=贴皮编号不能为空 veneer.save.width.not.null=宽度不能为空 veneer.save.veneerName.not.null=贴皮名称不能为空 veneer.save.veneerName.length.max=贴皮名称不能超过64个字符 -veneer.defect.save.id.not.null=贴皮ID不能为空 \ No newline at end of file +veneer.defect.save.id.not.null=贴皮ID不能为空 +veneer.classification.name.save.name.not.null=分类名称不能为空 +veneer.classification.name.save.name.length.max=分类名称长度不能超过64 \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_cht.properties b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_cht.properties index d86a20658..dd9b18351 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_cht.properties +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_cht.properties @@ -14,5 +14,7 @@ veneer.save.veneerNo.length.max=貼皮編號不能超過32個字元 veneer.save.veneerNo.not.null=貼皮編號不能為空 veneer.save.width.not.null=寬度不能為空 veneer.save.veneerName.not.null=貼皮名稱不能為空 -veneer.save.veneerName.length.max=貼皮名稱不能超过64个字符 -veneer.defect.save.id.not.null=貼皮ID不能為空 \ No newline at end of file +veneer.save.veneerName.length.max=貼皮名稱不能超过64个字元 +veneer.defect.save.id.not.null=貼皮ID不能為空 +veneer.classification.name.save.name.not.null=分類名稱不能為空 +veneer.classification.name.save.name.length.max=分類名稱不能超過64個字元 \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_en.properties b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_en.properties index 36aa2f147..bbe6fddbd 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_en.properties +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_en.properties @@ -15,4 +15,6 @@ veneer.save.veneerNo.not.null=veener no cannot be empty veneer.save.width.not.null=width cannot be empty veneer.save.veneerName.not.null=veneer name cannot be empty veneer.save.veneerName.length.max=veneer name length cannot exceed 64 characters -veneer.defect.save.id.not.null=veneer id cannot be empty \ No newline at end of file +veneer.defect.save.id.not.null=veneer id cannot be empty +veneer.classification.name.save.name.not.null=classification name cannot be empty +veneer.classification.name.save.name.length.max=classification name length cannot exceed 64 characters \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode.properties b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode.properties index 12de73fc6..8a52ec963 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode.properties +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode.properties @@ -20,4 +20,8 @@ veneer.import.required.lack=第{0}行存在带*必填项为空,请检查文件 veneer.import.length.error=第{0}行{1}长度不能超过{2}个字符,请检查文件 veneer.import.digital.type.error=第{0}行{1}只能输入数字,请检查文件 veneer.import.positive.number.error=第{0}行{1}必须大于0,请检查文件 -veneer.import.number.length.error=第{0}行{1}长度不能超过整数{2}位、小数{3}位,请检查文件 \ No newline at end of file +veneer.import.number.length.error=第{0}行{1}长度不能超过整数{2}位、小数{3}位,请检查文件 +veneer.org.classification.name.exist=组织下分类名称已存在,请检查 +veneer.org.classification.name.empty=组织下分类名称不存在,请前往 [新增] 窗口维护分类名称 +veneer.import.template.download.error=导入模版下载失败 +veneer.import.org.classification.name.not.exist=第{0}行分类名称{1}不存在,请前往 [新增] 窗口维护分类名称 \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_cht.properties b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_cht.properties index 0ae72d7a4..7665ecb11 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_cht.properties +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_cht.properties @@ -20,4 +20,8 @@ veneer.import.required.lack=第{0}行存在帶*必填項為空,請檢查檔案 veneer.import.length.error=第{0}行{1}長度不能超過{2}個字元,請檢查檔案 veneer.import.digital.type.error=第{0}行{1}只能輸入數位,請檢查檔案 veneer.import.positive.number.error=第{0}行{1}必須大於0,請檢查檔案 -veneer.import.number.length.error=第{0}行{1}長度不能超過整數{2}位、小數{3}位,請檢查檔案 \ No newline at end of file +veneer.import.number.length.error=第{0}行{1}長度不能超過整數{2}位、小數{3}位,請檢查檔案 +veneer.org.classification.name.exist=組織下分類名稱已存在,請檢查 +veneer.org.classification.name.empty=組織下分類名稱不存在,請前往 [新增] 視窗維護分類名稱 +veneer.import.template.download.error=導入模版下載失敗 +veneer.import.org.classification.name.not.exist=第{0}行分類名稱{1}不存在,請前往[新增]視窗維護分類名稱 \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_en.properties b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_en.properties index 0cd8c16da..4905eb39c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_en.properties +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/message_errorcode_en.properties @@ -20,4 +20,8 @@ veneer.import.required.lack=The required field is empty in line {0}, please chec veneer.import.length.error=The length of the field cannot exceed {0} characters in line {1}, please check the file veneer.import.digital.type.error=The field can only be filled in with numbers in line {0}, please check the file veneer.import.positive.number.error=The field must be greater than 0 in line {0}, please check the file -veneer.import.number.length.error=The length of the field cannot exceed integer {0} digits and decimal {1} digits in line {2}, please check the file \ No newline at end of file +veneer.import.number.length.error=The length of the field cannot exceed integer {0} digits and decimal {1} digits in line {2}, please check the file +veneer.org.classification.name.exist=The classification name already exists under the organization, please check +veneer.org.classification.name.empty=The classification name does not exist under the organization, Please go to the [Add] window to maintain the classification name +veneer.import.template.download.error=Import template download failed +veneer.import.org.classification.name.not.exist=The classification name {1} does not exist in line {0}, please go to the [Add] window to maintain the classification name \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/type/veneer/cht/貼皮導入範本.xlsx b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/type/veneer/cht/貼皮導入範本.xlsx index a4fe4a0b67dbf1c1f0baa584c1041d747cb08f1e..8f5928e2447e43bcb215e61a4e717bf77e171769 100644 GIT binary patch delta 2704 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 K21z6U00002h5u*( delta 2714 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 delta 2930 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 c0K=2HCp-b5llCV&0nC#!C@Tgg$6#xJL diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerControllerTest.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerControllerTest.java index 073921f15..157cead9b 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerControllerTest.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/controller/admin/veneer/VeneerControllerTest.java @@ -1,17 +1,23 @@ package com.cf.imes.module.executor.controller.admin.veneer; +import com.alibaba.excel.EasyExcelFactory; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; +import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.security.test.WithMockLoginUser; import com.cf.imes.framework.test.core.ut.BaseWebUnitTest; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerImportExcelVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO; import com.cf.imes.module.executor.enums.veneer.VeneerProductLevelEnum; +import com.cf.imes.module.executor.service.veneer.VeneerExcelListener; import com.cf.imes.module.executor.service.veneer.VeneerService; -import com.cf.imes.module.executor.util.file.FileHelperUtil; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.Test; +import org.mockito.MockedConstruction; import org.mockito.MockedStatic; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; @@ -22,11 +28,14 @@ import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.MockMvc; +import java.io.InputStream; import java.math.BigDecimal; import java.util.Collections; +import java.util.List; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -161,32 +170,55 @@ class VeneerControllerTest extends BaseWebUnitTest { } @Test - @WithMockLoginUser void importExcel_success() throws Exception { MockMultipartFile file = new MockMultipartFile( - "file", "test.xlsx", - "application/vnd.ms-excel", - new byte[]{1, 2, 3} + "file", + "veneer.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "dummy excel content".getBytes() ); - mockMvc.perform(multipart("/executor/veneer/import").file(file)) - .andExpect(status().isOk()); + try ( + MockedStatic excelMock = + Mockito.mockStatic(EasyExcelFactory.class); + MockedConstruction listenerMock = + Mockito.mockConstruction(VeneerExcelListener.class) + ) { + + ExcelReaderBuilder readerBuilder = Mockito.mock(ExcelReaderBuilder.class); + ExcelReaderSheetBuilder sheetBuilder = Mockito.mock(ExcelReaderSheetBuilder.class); + + excelMock.when(() -> + EasyExcelFactory.read( + any(InputStream.class), + eq(VeneerImportExcelVO.class), + any() + ) + ).thenReturn(readerBuilder); + + Mockito.when(readerBuilder.headRowNumber(anyInt())) + .thenReturn(readerBuilder); + Mockito.when(readerBuilder.sheet()) + .thenReturn(sheetBuilder); + Mockito.doNothing().when(sheetBuilder).doRead(); + + mockMvc.perform( + multipart("/executor/veneer/import").file(file) + ).andExpect(status().isOk()); + } } @Test void getVeneerImportTemplate_success() throws Exception { - try (MockedStatic mocked = - Mockito.mockStatic(FileHelperUtil.class)) { + Mockito.doNothing() + .when(veneerService) + .importTemplateDownload(any(HttpServletResponse.class)); - mocked.when(() -> - FileHelperUtil.getFirstFile( - anyString(), - any(HttpServletResponse.class)) - ).thenAnswer(invocation -> null); + mockMvc.perform(get("/executor/veneer/import/template")) + .andExpect(status().isOk()); - mockMvc.perform(get("/executor/veneer/import/template")) - .andExpect(status().isOk()); - } + Mockito.verify(veneerService) + .importTemplateDownload(any(HttpServletResponse.class)); } @Test @@ -203,4 +235,48 @@ class VeneerControllerTest extends BaseWebUnitTest { .andExpect(jsonPath("$.data").value(true)); } + @Test + void createClassificationName_success() throws Exception { + + VeneerClassificationNameSaveReqVO reqVO = new VeneerClassificationNameSaveReqVO(); + reqVO.setName("测试分类"); + + Mockito.when(veneerService.addClassificationName(any())) + .thenReturn(1L); + + mockMvc.perform( + post("/executor/veneer/classificationName") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(reqVO)) + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data").value(1L)); + + Mockito.verify(veneerService) + .addClassificationName(any(VeneerClassificationNameSaveReqVO.class)); + } + + @Test + void getOrgVeneerClassificationNameList_success() throws Exception { + + VeneerClassificationNameRespVO respVO = new VeneerClassificationNameRespVO(); + respVO.setId(1L); + respVO.setName("测试分类"); + + Mockito.when(veneerService.getOrgVeneerClassificationNameList()) + .thenReturn(List.of(respVO)); + + mockMvc.perform( + get("/executor/veneer/org/classificationName") + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data[0].id").value(1L)) + .andExpect(jsonPath("$.data[0].name").value("测试分类")); + + Mockito.verify(veneerService) + .getOrgVeneerClassificationNameList(); + } + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImplTest.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImplTest.java index 3611e7fea..0c8f418ad 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImplTest.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/veneer/VeneerServiceImplTest.java @@ -1,6 +1,10 @@ package com.cf.imes.module.executor.service.veneer; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.EasyExcelFactory; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; @@ -11,25 +15,41 @@ import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.security.test.WithMockLoginUser; import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.executor.common.WithMockLoginUserExtension; +import com.cf.imes.module.executor.constants.file.TemplateFilePathConstants; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO; +import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPageReqVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO; import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO; +import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerClassificationNameDO; import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO; import com.cf.imes.module.executor.dal.mysql.veneer.VeneerBatchMapper; +import com.cf.imes.module.executor.dal.mysql.veneer.VeneerClassificationNameMapper; import com.cf.imes.module.executor.dal.mysql.veneer.VeneerMapper; import com.cf.imes.module.executor.enums.veneer.VeneerProductLevelEnum; +import com.cf.imes.module.executor.util.file.FileHelperUtil; import com.cf.imes.module.infra.api.file.FileApi; import com.cf.imes.module.system.api.organ.OrganApi; import com.cf.imes.module.system.api.organ.dto.OrganizationDTO; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import org.springframework.mock.web.MockMultipartFile; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -39,6 +59,7 @@ import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceExce import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NOT_EXIST; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NO_EXIST; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_EXIST; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -46,10 +67,13 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -78,6 +102,12 @@ class VeneerServiceImplTest extends BaseMockitoUnitTest { @Mock private VeneerBatchMapper veneerBatchMapper; + @Mock + private VeneerClassificationNameMapper veneerClassificationNameMapper; + + @Mock + private HttpServletResponse response; + @BeforeAll static void init(){ TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), VeneerDO.class); @@ -481,6 +511,208 @@ class VeneerServiceImplTest extends BaseMockitoUnitTest { verify(veneerMapper, never()).update(any()); } + @Test + void addClassificationName_success() { + + // given + VeneerClassificationNameSaveReqVO reqVO = + new VeneerClassificationNameSaveReqVO(); + reqVO.setName("测试分类"); + + // 唯一校验通过 + Mockito.when(veneerClassificationNameMapper.selectCount(any())) + .thenReturn(0L); + + // mock insert 时给 id + Mockito.doAnswer(invocation -> { + VeneerClassificationNameDO entity = invocation.getArgument(0); + entity.setId(1L); + return 1; + }).when(veneerClassificationNameMapper).insert(any(VeneerClassificationNameDO.class)); + + // when + Long id = veneerService.addClassificationName(reqVO); + + // then + assertEquals(1L, id); + + Mockito.verify(veneerClassificationNameMapper) + .selectCount(any()); + Mockito.verify(veneerClassificationNameMapper) + .insert(any(VeneerClassificationNameDO.class)); + } + + @Test + void addClassificationName_exist_throwException() { + + VeneerClassificationNameSaveReqVO reqVO = + new VeneerClassificationNameSaveReqVO(); + reqVO.setName("重复分类"); + + // 已存在 + Mockito.when(veneerClassificationNameMapper.selectCount(any())) + .thenReturn(1L); + + assertServiceException(() -> veneerService.addClassificationName(reqVO), + VENEER_ORG_CLASSIFICATION_NAME_EXIST); + + // insert 一定不会被调用 + Mockito.verify(veneerClassificationNameMapper, Mockito.never()) + .insert(any(VeneerClassificationNameDO.class)); + } + + @Test + void getOrgVeneerClassificationNameList_success() { + + VeneerClassificationNameDO entity = new VeneerClassificationNameDO(); + entity.setId(1L); + entity.setName("分类A"); + + Mockito.when(veneerClassificationNameMapper.selectList()) + .thenReturn(List.of(entity)); + + List result = + veneerService.getOrgVeneerClassificationNameList(); + + assertEquals(1, result.size()); + assertEquals("分类A", result.get(0).getName()); + + Mockito.verify(veneerClassificationNameMapper) + .selectList(); + } + + @Test + void importTemplateDownload_success() throws IOException { + File mockFile = Mockito.mock(File.class); + + try ( + MockedStatic pathMock = + Mockito.mockStatic(TemplateFilePathConstants.class); + MockedStatic fileUtilMock = + Mockito.mockStatic(FileUtil.class); + MockedStatic fileMock = + Mockito.mockStatic(FileHelperUtil.class); + MockedStatic excelMock = + Mockito.mockStatic(EasyExcelFactory.class) + ) { + + VeneerClassificationNameDO veneerClassificationNameDO = new VeneerClassificationNameDO(); + veneerClassificationNameDO.setName("分类名称"); + when(veneerClassificationNameMapper.selectList()).thenReturn(List.of(veneerClassificationNameDO)); + + pathMock.when(() -> + TemplateFilePathConstants.getVeneerImportTemplatePath(any()) + ).thenReturn("/mock/path"); + + fileMock.when(() -> + FileHelperUtil.getFirstFile(anyString()) + ).thenReturn(mockFile); + + // ⭐ 关键 1:mock 模板流(不碰文件) + fileUtilMock.when(() -> FileUtil.getInputStream(any(File.class))) + .thenReturn(new BufferedInputStream(new ByteArrayInputStream(new byte[]{1}))); + + // mock response OutputStream + ServletOutputStream outputStream = Mockito.mock(ServletOutputStream.class); + Mockito.when(response.getOutputStream()) + .thenReturn(outputStream); + + // mock EasyExcel 写链 + ExcelWriterBuilder writerBuilder = Mockito.mock(ExcelWriterBuilder.class); + ExcelWriterSheetBuilder sheetBuilder = Mockito.mock(ExcelWriterSheetBuilder.class); + + excelMock.when(() -> EasyExcelFactory.write(any(OutputStream.class))) + .thenReturn(writerBuilder); + + when(writerBuilder.withTemplate( + any(InputStream.class))) + .thenReturn(writerBuilder); + + when(writerBuilder.registerWriteHandler(any())) + .thenReturn(writerBuilder); + + when(writerBuilder.sheet(anyInt())) + .thenReturn(sheetBuilder); + doNothing().when(sheetBuilder).doWrite(anyList()); + + // 执行 + assertDoesNotThrow(() -> + veneerService.importTemplateDownload(response)); + } + } + + + @Test + void importTemplateDownload_fail_when_org_classification_name_list_is_empty() { + // 1️⃣ mock 模板路径 & 文件 + File mockFile = Mockito.mock(File.class); + + try ( + MockedStatic pathMock = + Mockito.mockStatic(TemplateFilePathConstants.class); + MockedStatic fileMock = + Mockito.mockStatic(FileHelperUtil.class) + ) { + + pathMock.when(() -> + TemplateFilePathConstants.getVeneerImportTemplatePath(any()) + ).thenReturn("/mock/path"); + + fileMock.when(() -> + FileHelperUtil.getFirstFile(anyString()) + ).thenReturn(mockFile); + + // 2️⃣ mock 分类名称列表为空 + Mockito.when(veneerClassificationNameMapper.selectList()) + .thenReturn(new ArrayList<>()); + + // 3️⃣ 验证抛出异常 + assertServiceException(() -> veneerService.importTemplateDownload(response), + com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_EMPTY); + } + } + + @Test + void importTemplateDownload_fail_when_io_exception_occurs() throws Exception { + // 1️⃣ mock 模板路径 & 文件 + File mockFile = Mockito.mock(File.class); + + try ( + MockedStatic pathMock = + Mockito.mockStatic(TemplateFilePathConstants.class); + MockedStatic fileMock = + Mockito.mockStatic(FileHelperUtil.class); + MockedStatic excelMock = + Mockito.mockStatic(EasyExcelFactory.class) + ) { + + pathMock.when(() -> + TemplateFilePathConstants.getVeneerImportTemplatePath(any()) + ).thenReturn("/mock/path"); + + fileMock.when(() -> + FileHelperUtil.getFirstFile(anyString()) + ).thenReturn(mockFile); + + // 2️⃣ mock 分类名称列表 + VeneerClassificationNameDO entity = new VeneerClassificationNameDO(); + entity.setName("分类A"); + + Mockito.when(veneerClassificationNameMapper.selectList()) + .thenReturn(List.of(entity)); + + // 3️⃣ mock response OutputStream 并抛出IOException + Mockito.when(response.getOutputStream()) + .thenThrow(new java.io.IOException("IO Error")); + + // 4️⃣ 验证抛出异常 + assertServiceException(() -> veneerService.importTemplateDownload(response), + com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_TEMPLATE_DOWNLOAD_ERROR); + } + } + + + @Test void getFileExtension_whenEmpty() { assertEquals(".jpg", veneerService.getFileExtension("file."));