docs/srm_supplier_import_export_integration.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,116 @@ # SRM ä¾åºåæ¡£æ¡ å¯¼åº / å¯¼å ¥ - å端èè°æ¹æ¡ ## æ¶åé¡µé¢ | é¡µé¢ | å端ç»ä»¶ | å端æ¥å£åç¼ | 说æ | |------|----------|--------------|------| | ä¾åºåæ¡£æ¡ | `srm/supplier/index`ï¼ç»ä»¶å SrmSupplierï¼ | `/srm/supplier` | æ°å¢"导åºãå¯¼å ¥ãä¸è½½æ¨¡æ¿"å·¥å ·æ å ¥å£ | ## æéï¼æé®æ¾éï¼ä¸å端 @PreAuthorize ä¸è´ï¼ | æä½ | æé®æé | å端æ¥å£æ ¡éª | |------|----------|--------------| | å¯¼åº | `srm:supplier:export` | `/srm/supplier/export-excel` | | ä¸è½½æ¨¡æ¿ / å¯¼å ¥ | `srm:supplier:import` | `/srm/supplier/get-import-template`ã`/srm/supplier/import-excel` | > æ°æé®èå SQL è§ `sql/mysql/srm_supplier_import_export_menu.sql`ï¼å¹çï¼å«æ®éè§è²ææï¼ï¼è¶ 级管çåèªå¨æ¥æå ¨é¨èåã > è¥åå²åºä¸ `srm:supplier:export` æé®èåå·²åå¨ä½è§è²æªåé ï¼æ§è¡è¯¥èæ¬å³å¯è¡¥é½ã ## API ä¸è§ | æ¹æ³ | è·¯å¾ | 说æ | æé | |------|------|------|------| | GET | `/srm/supplier/export-excel` | æå½åå表æ¥è¯¢æ¡ä»¶å¯¼åºå ¨é¨å½ä¸è¡ï¼ä¸åé¡µï¼ | å¯¼åºæé | | GET | `/srm/supplier/get-import-template` | ä¸è½½å¯¼å ¥æ¨¡æ¿ï¼å« 1 è¡ç¤ºä¾æ°æ®ï¼å¯å åå¡«åï¼ | å¯¼å ¥æé | | POST | `/srm/supplier/import-excel` | ä¸ä¼ Excel å¯¼å ¥ï¼multipartï¼ | å¯¼å ¥æé | ### å¯¼å ¥æ¥å£åæ° | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | file | MultipartFile | æ¯ | å¾ å¯¼å ¥ç Excelï¼.xls/.xlsxï¼ | | updateSupport | Boolean | å¦ | æ¯å¦æ¯ææ´æ°ï¼`true`=æ"ä¾åºåç¼ç "å·²åå¨åæ´æ°ï¼é»è®¤ `false`=ä» æ°å¢ï¼å·²åå¨åè¯¥è¡æ¥"ä¾åºåç¼ç å·²åå¨" | ### å¯¼å ¥ååºç»æ `code: 0` 表示æ¥å£æ§è¡å®æï¼é 0 ä¸ºåæ°/ç³»ç»å¼å¸¸ï¼ãä¸å¡å±çé¨åæåéè¿ `data` è¿åï¼ ```json { "code": 0, "data": { "createList": ["æ°å¢æåçä¾åºååç§°"], "updateList": ["æ´æ°æåçä¾åºååç§°"], "failureList": { "失败çä¾åºååç§°": "失败åå " } } } ``` > å端约å®ï¼`failureList` é空å³è§ä¸º"é¨å失败"ï¼åºå¼¹çªéè¡æç¤ºå¤±è´¥åå ï¼`createList`/`updateList` ç¨äºæ±æ»æç¤º"æåæ°å¢ x æ¡ãæ´æ° y æ¡"ã ## å¯¼åºæ¥å£ - å¤ç¨å表æ¥è¯¢è¿æ»¤æ¡ä»¶ï¼GET æ¥è¯¢åæ°ï¼code/name/type/status/contactName/contactMobileï¼ï¼å¯¼åºå ¨é¨å½ä¸è¡ï¼æ éä¼ é¡µç ã - æåè¿åäºè¿å¶æä»¶æµï¼æä»¶åï¼`ä¾åºåæ°æ®.xlsx`ï¼å¤±è´¥æ¶å¯è½è¿å HTTP 200 + JSONï¼éåºåäºè¿å¶ä¸ JSONã - 导åºè¡¨å¤´ä¸ºä¸æï¼**ç±»ååæ¾ç¤ºåç§°ï¼ç产å/è´¸æå/æå¡å/å ¶ä»ï¼ï¼ç¶æåæ¾ç¤º å¯ç¨/ç¦ç¨**ï¼ä¸é¡µé¢æ ç¾ä¸è´ï¼ï¼ä¾¿äºé è¯»ï¼ | åå | 对åºå段 | 说æ | |------|----------|------| | ä¾åºåç¼ç | code | | | ä¾åºååç§° | name | | | ä¾åºåç®ç§° | shortName | | | ä¾åºåç±»å | type | 导åºä¸ºä¸æåç§° | | ä¼ä¸æ§è´¨ | companyNature | | | 注åèµé(ä¸å ) | registeredCapital | | | è¥ä¸æ§ç §ç¼å· | businessLicenseNo | | | ç¨å· | taxNo | | | æ³äººä»£è¡¨ | legalPerson | | | å ¬å¸å°å | address | | | å ¬å¸ç½å | website | | | è系人 | contactName | | | èç³»çµè¯ | contactMobile | | | é®ç®± | contactEmail | | | 弿·é¶è¡ | bankName | | | é¶è¡è´¦å· | bankAccount | | | ç¶æ | status | 导åºä¸º å¯ç¨/ç¦ç¨ | | 夿³¨ | remark | | | å建æ¶é´ | createTime | | > 说æï¼æ¤å导åºç´æ¥ä½¿ç¨ `SrmSupplierRespVO` è¾åºï¼è¡¨å¤´ä¸ºè±æå段åï¼æ¬æ¬¡æ¹é 为ç¬ç« `SrmSupplierExcelVO`ï¼è¡¨å¤´ä¸åå¼å£å¾ååå¦ä¸ï¼å¯¼åºæä»¶ä¸å¯ç´æ¥å导ï¼å导请ç¨å¯¼å ¥æ¨¡æ¿ï¼ã ## å¯¼å ¥æ¨¡æ¿è¯´æï¼ä¸å¡è§åï¼ ä¸è½½æ¨¡æ¿æä»¶åï¼`ä¾åºåå¯¼å ¥æ¨¡æ¿.xlsx`ï¼å å« 1 è¡ç¤ºä¾æ°æ®ï¼å¯å é¤åæ´è¡¨å¡«åï¼ã | åå | å¿ å¡« | å¡«åè§å | |------|------|----------| | ä¾åºåç¼ç | æ¯ | å ¨å±å¯ä¸ï¼éå¤ç¼ç æ `updateSupport` å³å®æ¥éææ´æ° | | ä¾åºååç§° | æ¯ | | | ä¾åºåç®ç§° | å¦ | | | ä¾åºåç±»å(ç产å/è´¸æå/æå¡å/å ¶ä») | å¦ | å¯å¡«ä¸æåç§°æç¼ç 1/2/3/4ï¼æ æ³è¯å«æ¶æåæ ·ä¿å | | ä¼ä¸æ§è´¨(å½ä¼/æ°è¥/å¤èµ/åèµ) | å¦ | å¡«å®é ææ¬ | | 注åèµé(ä¸å ) | å¦ | æ°å¼ | | è¥ä¸æ§ç §ç¼å· / ç¨å· | å¦ | | | æ³äººä»£è¡¨ | å¦ | | | å ¬å¸å°å / å ¬å¸ç½å | å¦ | | | è系人 / èç³»çµè¯ / é®ç®± | å¦ | | | 弿·é¶è¡ / é¶è¡è´¦å· | å¦ | | | ç¶æ(0å¯ç¨/1ç¦ç¨) | å¦ | å¡« 0/1ï¼ç空é»è®¤ 0ï¼å¯ç¨ï¼ | | 夿³¨ | å¦ | | è¡çº§å¤çè§åï¼ | åºæ¯ | è§å | |------|------| | ç¼ç æå称为空 | 该è¡å¤±è´¥ï¼"ä¾åºåç¼ç åä¾åºååç§°ä¸è½ä¸ºç©º" | | ç¼ç å·²åå¨ ä¸ updateSupport=false | 该è¡å¤±è´¥ï¼"ä¾åºåç¼ç å·²åå¨" | | ç¼ç å·²åå¨ ä¸ updateSupport=true | æ´æ°è¯¥ä¾åºåæ¡£æ¡ | | ç¼ç ä¸åå¨ | æ°å¢ä¾åºåæ¡£æ¡ | | åè¡å ¶å®æ ¡éªå¼å¸¸ï¼å¦ç¼ç å¯ä¸å²çªï¼ | 该è¡å¤±è´¥å¹¶è®°å½åå ï¼ä¸å½±åå ¶å®è¡å¯¼å ¥ | ## 注æäºé¡¹ 1. 建议å¨ä¾åºåæ¡£æ¡å·¥å ·æ å¢å "å¯¼å ¥""ä¸è½½æ¨¡æ¿"ä¸¤ä¸ªå ¥å£ï¼å¯¼å ¥äº¤äºéå å« `updateSupport` é项ï¼å¤éæ¡"æ´æ°å·²åå¨çä¾åºå"ï¼é»è®¤ä¸å¾éï¼ï¼å¯¼å ¥ç»ææä¸æååºç»æç»åºæå/å¤±è´¥æ±æ»ä¸å¤±è´¥åå ã 2. "导åº"æé®ç°æå®ç°ä¿æä¸åï¼`export-excel`ï¼ï¼ä» å端è¾åºå/表头ä¼åã 3. ä¾åºåæ°æ®å¯éè¿åå ¥å®¡æ¹èªå¨åå»ºï¼æ¤ç±»è®°å½å¯è½ç¼ºå°ç¼ç /ç±»åï¼å¯¼å ¥æ¨¡æ¿ä¸åå½±åï¼æç¼ç å¹é ï¼ç©ºç¼ç ä¸å½±åæ¢ææ°æ®ï¼ã 4. æé说æï¼æ¨¡æ¿ä¸è½½ä¸å¯¼å ¥ä½¿ç¨å䏿é `srm:supplier:import`ã yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/supplier/SrmSupplierController.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.*; import cn.iocoder.yudao.module.srm.dal.dataobject.SrmSupplierDO; import cn.iocoder.yudao.module.srm.enums.SupplierTypeEnum; import cn.iocoder.yudao.module.srm.service.supplier.SrmSupplierService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -17,8 +18,11 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -88,12 +92,82 @@ } @GetMapping("/export-excel") @Operation(summary = "导åºä¾åºå Excel") @Operation(summary = "导åºä¾åºåæ¡£æ¡ Excel") @PreAuthorize("@ss.hasPermission('srm:supplier:export')") public void exportSupplierExcel(@Valid SrmSupplierPageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); // å¤ç¨åé¡µè¿æ»¤æ¡ä»¶ï¼å¯¼åºå 容ä¸å表ä¸è´ List<SrmSupplierDO> list = supplierService.getSupplierPage(pageReqVO).getList(); ExcelUtils.write(response, "ä¾åºåæ°æ®.xlsx", "ä¾åºå", SrmSupplierRespVO.class, BeanUtils.toBean(list, SrmSupplierRespVO.class)); List<SrmSupplierExcelVO> excelList = new ArrayList<>(); for (SrmSupplierDO supplier : list) { SrmSupplierExcelVO excelVO = BeanUtils.toBean(supplier, SrmSupplierExcelVO.class); excelVO.setType(toTypeLabel(supplier.getType())); excelVO.setStatus(toStatusLabel(supplier.getStatus())); excelList.add(excelVO); } ExcelUtils.write(response, "ä¾åºåæ°æ®.xlsx", "ä¾åºå", SrmSupplierExcelVO.class, excelList); } @GetMapping("/get-import-template") @Operation(summary = "è·å¾å¯¼å ¥ä¾åºåæ¡£æ¡æ¨¡æ¿") @PreAuthorize("@ss.hasPermission('srm:supplier:import')") public void getImportTemplate(HttpServletResponse response) throws IOException { SrmSupplierImportExcelVO sample = new SrmSupplierImportExcelVO(); sample.setCode("GYS0001"); sample.setName("示ä¾ä¾åºå"); sample.setShortName("示ä¾"); sample.setType("ç产å"); sample.setCompanyNature("æ°è¥"); sample.setRegisteredCapital(new java.math.BigDecimal("1000")); sample.setBusinessLicenseNo("91320000XXXXXXXXXX"); sample.setTaxNo("91320000XXXXXXXXXX"); sample.setLegalPerson("å¼ ä¸"); sample.setAddress("示ä¾å¸ç¤ºä¾åºç¤ºä¾è·¯1å·"); sample.setWebsite("http://www.example.com"); sample.setContactName("æå"); sample.setContactMobile("13800000000"); sample.setContactEmail("contact@example.com"); sample.setBankName("示ä¾é¶è¡ç¤ºä¾æ¯è¡"); sample.setBankAccount("6222020000000000000"); sample.setStatus(0); sample.setRemark("å¯¼å ¥æ¨¡æ¿ç¤ºä¾è¡ï¼å¯å é¤"); ExcelUtils.write(response, "ä¾åºåå¯¼å ¥æ¨¡æ¿.xlsx", "ä¾åºå", SrmSupplierImportExcelVO.class, Arrays.asList(sample)); } @PostMapping("/import-excel") @Operation(summary = "å¯¼å ¥ä¾åºåæ¡£æ¡ Excel") @PreAuthorize("@ss.hasPermission('srm:supplier:import')") public CommonResult<SrmSupplierImportRespVO> importSupplierExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { List<SrmSupplierImportExcelVO> list = ExcelUtils.read(file, SrmSupplierImportExcelVO.class); return success(supplierService.importSupplierList(list, updateSupport)); } // ========== Excel å±ç¤ºè¾ å© ========== /** * ä¾åºåç±»åç¼ç -> 䏿åç§°ï¼å¦ 1 -> ç产åï¼ï¼æ æ³è¯å«æ¶åæ ·è¿å */ private static String toTypeLabel(String typeCode) { if (typeCode == null) { return null; } for (SupplierTypeEnum e : SupplierTypeEnum.values()) { if (typeCode.equals(String.valueOf(e.getCode()))) { return e.getName(); } } return typeCode; } /** * ç¶æ 0 å¯ç¨ / 1 ç¦ç¨ -> ä¸æææ¡ï¼ç©ºå¼è¿å空 */ private static String toStatusLabel(Integer status) { if (status == null) { return null; } return status == 0 ? "å¯ç¨" : "ç¦ç¨"; } } yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/supplier/vo/SrmSupplierExcelVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,74 @@ package cn.iocoder.yudao.module.srm.controller.admin.supplier.vo; import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; /** * SRM ä¾åºåæ¡£æ¡å¯¼åº Excel VO * * ä¸å表å±ç¤ºå£å¾ä¸è´ï¼ç±»åãç¶æå导åºä¸ºå¯è¯»ææ¬ï¼å¦ ç产å / å¯ç¨ï¼ï¼æ¹ä¾¿ä¸å¡é 读 */ @Data public class SrmSupplierExcelVO { @ExcelProperty("ä¾åºåç¼ç ") private String code; @ExcelProperty("ä¾åºååç§°") private String name; @ExcelProperty("ä¾åºåç®ç§°") private String shortName; @ExcelProperty("ä¾åºåç±»å") private String type; @ExcelProperty("ä¼ä¸æ§è´¨") private String companyNature; @ExcelProperty("注åèµé(ä¸å )") private BigDecimal registeredCapital; @ExcelProperty("è¥ä¸æ§ç §ç¼å·") private String businessLicenseNo; @ExcelProperty("ç¨å·") private String taxNo; @ExcelProperty("æ³äººä»£è¡¨") private String legalPerson; @ExcelProperty("å ¬å¸å°å") private String address; @ExcelProperty("å ¬å¸ç½å") private String website; @ExcelProperty("è系人") private String contactName; @ExcelProperty("èç³»çµè¯") private String contactMobile; @ExcelProperty("é®ç®±") private String contactEmail; @ExcelProperty("弿·é¶è¡") private String bankName; @ExcelProperty("é¶è¡è´¦å·") private String bankAccount; @ExcelProperty("ç¶æ") private String status; @ExcelProperty("夿³¨") private String remark; @ExcelProperty("å建æ¶é´") private LocalDateTime createTime; } yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/supplier/vo/SrmSupplierImportExcelVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,71 @@ package cn.iocoder.yudao.module.srm.controller.admin.supplier.vo; import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; import java.math.BigDecimal; /** * SRM ä¾åºåæ¡£æ¡å¯¼å ¥ Excel VO * * ç¼ç ãåç§°ä¸ºå¿ å¡«ï¼ç±»åæ¯æå¡«ä¸æåç§°ï¼ç产å/è´¸æå/æå¡å/å ¶ä»ï¼æç¼ç ï¼1/2/3/4ï¼ï¼ * ç¶æ 0=å¯ç¨ã1=ç¦ç¨ï¼ç空é»è®¤å¯ç¨ */ @Data public class SrmSupplierImportExcelVO { @ExcelProperty("ä¾åºåç¼ç ") private String code; @ExcelProperty("ä¾åºååç§°") private String name; @ExcelProperty("ä¾åºåç®ç§°") private String shortName; @ExcelProperty("ä¾åºåç±»å(ç产å/è´¸æå/æå¡å/å ¶ä»)") private String type; @ExcelProperty("ä¼ä¸æ§è´¨(å½ä¼/æ°è¥/å¤èµ/åèµ)") private String companyNature; @ExcelProperty("注åèµé(ä¸å )") private BigDecimal registeredCapital; @ExcelProperty("è¥ä¸æ§ç §ç¼å·") private String businessLicenseNo; @ExcelProperty("ç¨å·") private String taxNo; @ExcelProperty("æ³äººä»£è¡¨") private String legalPerson; @ExcelProperty("å ¬å¸å°å") private String address; @ExcelProperty("å ¬å¸ç½å") private String website; @ExcelProperty("è系人") private String contactName; @ExcelProperty("èç³»çµè¯") private String contactMobile; @ExcelProperty("é®ç®±") private String contactEmail; @ExcelProperty("弿·é¶è¡") private String bankName; @ExcelProperty("é¶è¡è´¦å·") private String bankAccount; @ExcelProperty("ç¶æ(0å¯ç¨/1ç¦ç¨)") private Integer status; @ExcelProperty("夿³¨") private String remark; } yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/supplier/vo/SrmSupplierImportRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,24 @@ package cn.iocoder.yudao.module.srm.controller.admin.supplier.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import java.util.List; import java.util.Map; @Schema(description = "管çåå° - SRM ä¾åºåå¯¼å ¥ Response VO") @Data @Builder public class SrmSupplierImportRespVO { @Schema(description = "æ°å¢æåçä¾åºååç§°æ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) private List<String> createList; @Schema(description = "æ´æ°æåçä¾åºååç§°æ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) private List<String> updateList; @Schema(description = "å¯¼å ¥å¤±è´¥çä¾åºåéå key 为ä¾åºååç§°ï¼value 为失败åå ", requiredMode = Schema.RequiredMode.REQUIRED) private Map<String, String> failureList; } yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java
@@ -14,6 +14,7 @@ ErrorCode SUPPLIER_EXISTS_REFERENCE = new ErrorCode(1_040_100_002, "ä¾åºå被ä¸å¡å¼ç¨ï¼æ æ³å é¤"); ErrorCode SUPPLIER_CONTACT_NOT_EXISTS = new ErrorCode(1_040_100_003, "ä¾åºåè系人ä¸åå¨"); ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_040_100_004, "ä¾åºåå·²åç¨ï¼æ æ³å䏿æ "); ErrorCode SUPPLIER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_100_005, "å¯¼å ¥çä¾åºåæ°æ®ä¸è½ä¸ºç©º"); // ========== ä¾åºååå ¥ 1_040_200_000 ========== ErrorCode APPLY_NOT_EXISTS = new ErrorCode(1_040_200_000, "åå ¥ç³è¯·ä¸åå¨"); yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/supplier/SrmSupplierService.java
@@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.srm.service.supplier; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierImportExcelVO; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierImportRespVO; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierPageReqVO; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierSaveReqVO; import cn.iocoder.yudao.module.srm.dal.dataobject.SrmSupplierDO; @@ -41,6 +43,15 @@ PageResult<SrmSupplierDO> getSupplierPage(SrmSupplierPageReqVO pageReqVO); /** * æ¹éå¯¼å ¥ä¾åºåæ¡£æ¡ * * @param importList å¯¼å ¥æ°æ® * @param updateSupport æ¯å¦æ´æ°å·²åå¨çä¾åºåï¼æç¼ç 夿ï¼ï¼false æ¶éå¤ç¼ç 记为失败 * @return å¯¼å ¥ç»æï¼æ°å¢/æ´æ°/失败 æç»ï¼ */ SrmSupplierImportRespVO importSupplierList(List<SrmSupplierImportExcelVO> importList, Boolean updateSupport); /** * è·åä¾åºåå表ï¼ä» è¿åå·²éè¿åå ¥å®¡æ¹çä¾åºåï¼ç¨äºä¸æéæ©ï¼ */ List<SrmSupplierDO> getSupplierSimpleList(); yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/supplier/SrmSupplierServiceImpl.java
@@ -1,10 +1,15 @@ package cn.iocoder.yudao.module.srm.service.supplier; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierImportExcelVO; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierImportRespVO; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierPageReqVO; import cn.iocoder.yudao.module.srm.controller.admin.supplier.vo.SrmSupplierSaveReqVO; import cn.iocoder.yudao.module.srm.dal.dataobject.*; @@ -17,18 +22,19 @@ import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierMapper; import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderBidMapper; import cn.iocoder.yudao.module.srm.enums.ErrorCodeConstants; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.module.srm.enums.SupplierTypeEnum; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.hutool.core.collection.CollUtil; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Service @Validated @@ -104,6 +110,49 @@ } @Override @Transactional(rollbackFor = Exception.class) public SrmSupplierImportRespVO importSupplierList(List<SrmSupplierImportExcelVO> importList, Boolean updateSupport) { if (CollUtil.isEmpty(importList)) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.SUPPLIER_IMPORT_LIST_IS_EMPTY); } SrmSupplierImportRespVO respVO = SrmSupplierImportRespVO.builder() .createList(new ArrayList<>()) .updateList(new ArrayList<>()) .failureList(new LinkedHashMap<>()) .build(); // éè¡å¯¼å ¥ï¼åè¡å¤±è´¥è®°å½å° failureListï¼ä¸å½±åå ¶å®è¡ for (SrmSupplierImportExcelVO importVO : importList) { String code = StrUtil.trim(importVO.getCode()); String name = StrUtil.trim(importVO.getName()); if (StrUtil.isBlank(code) || StrUtil.isBlank(name)) { respVO.getFailureList().put(StrUtil.blankToDefault(name, code), "ä¾åºåç¼ç åä¾åºååç§°ä¸è½ä¸ºç©º"); continue; } SrmSupplierSaveReqVO saveReqVO = toSaveReqVO(importVO); try { SrmSupplierDO existByCode = supplierMapper.selectByCode(code); if (existByCode != null) { if (!Boolean.TRUE.equals(updateSupport)) { respVO.getFailureList().put(name, "ä¾åºåç¼ç å·²åå¨"); continue; } saveReqVO.setId(existByCode.getId()); updateSupplier(saveReqVO); respVO.getUpdateList().add(name); } else { createSupplier(saveReqVO); respVO.getCreateList().add(name); } } catch (Exception ex) { // åæ¡å¤±è´¥ï¼è®°å½å¹¶ç»§ç» String reason = ex instanceof ServiceException ? ((ServiceException) ex).getMessage() : ex.getMessage(); respVO.getFailureList().put(name, reason == null ? "å¯¼å ¥å¤±è´¥" : reason); } } return respVO; } @Override public List<SrmSupplierDO> getSupplierSimpleList() { return supplierMapper.selectApprovedList(); } @@ -126,6 +175,64 @@ return supplierMapper.selectBatchIds(ids); } // ========== å¯¼å ¥è¾ å©æ¹æ³ ========== /** * å¯¼å ¥ VO -> ä¿å VOï¼å¤ç¨ create/update é»è¾ï¼ * ç±»åæ¯æä¸æåç§°æç¼ç ï¼1~4ï¼ï¼ç¶æç空é»è®¤å¯ç¨ */ private SrmSupplierSaveReqVO toSaveReqVO(SrmSupplierImportExcelVO importVO) { SrmSupplierSaveReqVO saveReqVO = new SrmSupplierSaveReqVO(); saveReqVO.setCode(StrUtil.trim(importVO.getCode())); saveReqVO.setName(StrUtil.trim(importVO.getName())); saveReqVO.setShortName(StrUtil.trimToNull(importVO.getShortName())); saveReqVO.setType(parseTypeCode(importVO.getType())); saveReqVO.setCompanyNature(StrUtil.trimToNull(importVO.getCompanyNature())); saveReqVO.setRegisteredCapital(importVO.getRegisteredCapital()); saveReqVO.setBusinessLicenseNo(StrUtil.trimToNull(importVO.getBusinessLicenseNo())); saveReqVO.setTaxNo(StrUtil.trimToNull(importVO.getTaxNo())); saveReqVO.setLegalPerson(StrUtil.trimToNull(importVO.getLegalPerson())); saveReqVO.setAddress(StrUtil.trimToNull(importVO.getAddress())); saveReqVO.setWebsite(StrUtil.trimToNull(importVO.getWebsite())); saveReqVO.setContactName(StrUtil.trimToNull(importVO.getContactName())); saveReqVO.setContactMobile(StrUtil.trimToNull(importVO.getContactMobile())); saveReqVO.setContactEmail(StrUtil.trimToNull(importVO.getContactEmail())); saveReqVO.setBankName(StrUtil.trimToNull(importVO.getBankName())); saveReqVO.setBankAccount(StrUtil.trimToNull(importVO.getBankAccount())); saveReqVO.setStatus(importVO.getStatus() != null ? importVO.getStatus() : CommonStatusEnum.ENABLE.getStatus()); saveReqVO.setRemark(StrUtil.trimToNull(importVO.getRemark())); return saveReqVO; } /** * ä¾åºåç±»åè§£æï¼ä¸æåç§°æç¼ç ï¼1~4ï¼å转æ¢ä¸ºç¼ç åç¬¦ä¸²ï¼ * æ æ³è¯å«æ¶ä¿çåå¼ï¼é¿å å¯¼å ¥è¢«é»å¡ */ private String parseTypeCode(String type) { String t = StrUtil.trimToNull(type); if (t == null) { return null; } for (SupplierTypeEnum e : SupplierTypeEnum.values()) { if (t.equalsIgnoreCase(e.getName()) || t.equals(String.valueOf(e.getCode()))) { return String.valueOf(e.getCode()); } } // å ¼å®¹ Excel æ°ååå æ ¼è¢«è¯»æ "1.0" ç另尿°å½¢å¼ try { BigDecimal bd = new BigDecimal(t); if (bd.stripTrailingZeros().scale() <= 0) { int i = bd.intValueExact(); if (i >= 1 && i <= 4) { return String.valueOf(i); } } } catch (NumberFormatException ignored) { // 忽ç¥ï¼ä¿æåå¼ } return t; } // ========== æ ¡éªæ¹æ³ ========== private void validateSupplierExists(Long id) { yudao-ui/yudao-ui-admin-vue3/src/api/srm/supplier/index.ts
@@ -67,6 +67,14 @@ exportSupplierExcel: async (params: any) => request.download({ url: '/srm/supplier/export-excel', params }), // ä¸è½½å¯¼å ¥æ¨¡æ¿ getImportTemplate: async () => request.download({ url: '/srm/supplier/get-import-template' }), // å¯¼å ¥ Excelï¼formData éå å« fileãupdateSupportï¼ importSupplierExcel: async (formData: any) => request.upload({ url: '/srm/supplier/import-excel', data: formData }), // è系人å表 getContactList: async (supplierId: number) => request.get({ url: '/srm/supplier-contact/list-by-supplier', params: { supplierId } }), yudao-ui/yudao-ui-admin-vue3/src/views/srm/supplier/index.vue
@@ -26,6 +26,9 @@ <el-button type="primary" plain @click="openForm()" v-hasPermi="['srm:supplier:create']"> <Icon icon="ep:plus" class="mr-5px" /> æ°å¢ </el-button> <el-button type="warning" plain @click="handleImport" v-hasPermi="['srm:supplier:import']"> <Icon icon="ep:upload" class="mr-5px" /> å¯¼å ¥ </el-button> <el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['srm:supplier:export']"> <Icon icon="ep:download" class="mr-5px" /> å¯¼åº </el-button> @@ -198,10 +201,43 @@ <el-descriptions-item label="夿³¨" :span="2">{{ detailData.remark }}</el-descriptions-item> </el-descriptions> </el-dialog> <!-- å¯¼å ¥å¯¹è¯æ¡ --> <el-dialog title="ä¾åºåæ¡£æ¡å¯¼å ¥" v-model="importVisible" width="440px" @closed="resetImport"> <el-upload ref="importUploadRef" v-model:file-list="fileList" :auto-upload="false" :disabled="importLoading" :limit="1" :on-exceed="handleImportExceed" accept=".xlsx, .xls" action="none" drag > <Icon icon="ep:upload" /> <div class="el-upload__text">å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em></div> <template #tip> <div class="el-upload__tip text-center"> <div class="el-upload__tip"> <el-checkbox v-model="updateSupport" /> æ¯å¦æ´æ°å·²ç»åå¨çä¾åºåï¼æä¾åºåç¼ç å¤æï¼ </div> <span>ä» å è®¸å¯¼å ¥ xlsãxlsx æ ¼å¼æä»¶ã</span> <el-link :underline="false" style="font-size: 12px; vertical-align: baseline" type="primary" @click="handleDownloadTemplate">ä¸è½½æ¨¡æ¿</el-link> </div> </template> </el-upload> <template #footer> <el-button :disabled="importLoading" type="primary" @click="handleImportSubmit">ç¡® å®</el-button> <el-button @click="importVisible = false">å æ¶</el-button> </template> </el-dialog> </template> <script setup lang="ts"> import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' import { SrmSupplierApi, SrmSupplierVO, SrmSupplierContactVO } from '@/api/srm/supplier' defineOptions({ name: 'SrmSupplier' }) @@ -318,13 +354,88 @@ try { await message.exportConfirm() exportLoading.value = true await SrmSupplierApi.exportSupplierExcel(queryParams) const data = await SrmSupplierApi.exportSupplierExcel(queryParams) download.excel(data, 'ä¾åºåæ°æ®.xlsx') } catch { } finally { exportLoading.value = false } } // ========== å¯¼å ¥ ========== const importVisible = ref(false) const importLoading = ref(false) const importUploadRef = ref() const fileList = ref<any[]>([]) const updateSupport = ref(false) /** æå¼å¯¼å ¥å¼¹çª */ const handleImport = () => { resetImport() importVisible.value = true } /** ä¸è½½å¯¼å ¥æ¨¡æ¿ */ const handleDownloadTemplate = async () => { try { const data = await SrmSupplierApi.getImportTemplate() download.excel(data, 'ä¾åºåå¯¼å ¥æ¨¡æ¿.xlsx') } catch { } } /** ä¸ä¼ æä»¶æ°éè¶ é */ const handleImportExceed = () => { message.error('æå¤åªè½ä¸ä¼ ä¸ä¸ªæä»¶ï¼') } /** éç½®å¯¼å ¥ç¶æ */ const resetImport = () => { importLoading.value = false fileList.value = [] updateSupport.value = false importUploadRef.value?.clearFiles() } /** æäº¤å¯¼å ¥ */ const handleImportSubmit = async () => { if (fileList.value.length === 0) { message.error('请ä¸ä¼ æä»¶') return } importLoading.value = true try { const formData = new FormData() formData.append('updateSupport', updateSupport.value ? 'true' : 'false') formData.append('file', fileList.value[0].raw as Blob) const res = await SrmSupplierApi.importSupplierExcel(formData) if (res.code !== 0) { message.error(res.msg) return } // æ±æ»å¯¼å ¥ç»æï¼æ°å¢/æ´æ°/失败 const data = res.data || {} const createList = data.createList || [] const updateList = data.updateList || [] const failureList = data.failureList || {} let text = 'æåæ°å¢æ°éï¼' + createList.length + 'ï¼' text += 'æåæ´æ°æ°éï¼' + updateList.length + 'ï¼' text += '失败æ°éï¼' + Object.keys(failureList).length + 'ã' const failureNames = Object.keys(failureList) for (const name of failureNames) { text += 'ã' + name + 'ï¼' + failureList[name] + 'ã' } message.alert(text) importVisible.value = false await getList() } catch { message.error('ä¸ä¼ 失败ï¼è¯·æ¨éæ°ä¸ä¼ ï¼') } finally { importLoading.value = false resetImport() } } onMounted(() => { getList() })