From 5f708178b260cabf081f9049cf51e9ad66ae2911 Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期四, 10 九月 2026 14:49:29 +0800
Subject: [PATCH] feat(erp/mes): 新增采购订单/销售订单/计量器具 Excel 导入,含导入菜单权限 SQL
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringServiceImpl.java | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 173 insertions(+), 0 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringServiceImpl.java
index 6c5ccbe..d7e0633 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringServiceImpl.java
@@ -1,6 +1,12 @@
package cn.iocoder.yudao.module.mes.service.dv.metering;
import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.metering.vo.MesDvMeteringImportExcelVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.metering.vo.MesDvMeteringImportRespVO;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -14,9 +20,14 @@
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -54,6 +65,11 @@
@Resource
private ConfigApi configApi;
+ @Resource
+ private DeptApi deptApi;
+ @Resource
+ private AdminUserApi adminUserApi;
+
@Override
public Long createMetering(MesDvMeteringSaveReqVO createReqVO) {
// 鏍¢獙缂栫爜鍞竴
@@ -66,6 +82,163 @@
}
@Override
+ @Transactional(rollbackFor = Exception.class)
+ public MesDvMeteringImportRespVO importMeteringList(List<MesDvMeteringImportExcelVO> importList) {
+ MesDvMeteringImportRespVO respVO = MesDvMeteringImportRespVO.builder()
+ .createList(new ArrayList<>())
+ .updateList(new ArrayList<>())
+ .failureList(new LinkedHashMap<>())
+ .build();
+ if (CollUtil.isEmpty(importList)) {
+ return respVO;
+ }
+
+ // 1. 棰勭儹鈥滈儴闂ㄥ悕绉� -> 閮ㄩ棬缂栧彿鈥濇槧灏勶紙閮ㄩ棬/璐d换浜轰负闈炲繀濉紝鍖归厤涓嶅埌璇ヨ澶辫触锛�
+ Map<String, Long> deptIdMap = new HashMap<>();
+ List<DeptRespDTO> depts = deptApi.getDeptList();
+ if (CollUtil.isNotEmpty(depts)) {
+ depts.forEach(dept -> {
+ if (StrUtil.isNotBlank(dept.getName())) {
+ deptIdMap.putIfAbsent(dept.getName().trim(), dept.getId());
+ }
+ });
+ }
+
+ // 2. 閫愯瀵煎叆锛堝崟琛屽け璐ヤ笉褰卞搷鍏跺畠琛岋級
+ for (int i = 0; i < importList.size(); i++) {
+ MesDvMeteringImportExcelVO row = importList.get(i);
+ if (row == null || (StrUtil.isBlank(row.getCode()) && StrUtil.isBlank(row.getName()))) {
+ continue; // 璺宠繃绌鸿
+ }
+ String label = StrUtil.isNotBlank(row.getCode()) ? row.getCode().trim() : "绗� " + (i + 2) + " 琛�";
+ try {
+ boolean restored = createMeteringByImport(row, deptIdMap);
+ if (restored) {
+ respVO.getUpdateList().add(row.getCode().trim()); // 鎭㈠/瑕嗙洊鏇存柊
+ } else {
+ respVO.getCreateList().add(row.getCode().trim());
+ }
+ } catch (Exception ex) {
+ respVO.getFailureList().put(label, resolveImportErrorMessage(ex));
+ }
+ }
+ return respVO;
+ }
+
+ /**
+ * 渚濇嵁瀵煎叆琛屽垱寤轰竴鏉¤閲忓櫒鍏疯褰�
+ */
+ private boolean createMeteringByImport(MesDvMeteringImportExcelVO row, Map<String, Long> deptIdMap) {
+ // 1. 蹇呭~鏍¢獙
+ if (StrUtil.isBlank(row.getCode())) {
+ throw new IllegalArgumentException("璁¢噺鍣ㄥ叿缂栫爜涓嶈兘涓虹┖");
+ }
+ if (StrUtil.isBlank(row.getName())) {
+ throw new IllegalArgumentException("璁¢噺鍣ㄥ叿鍚嶇О涓嶈兘涓虹┖");
+ }
+ if (row.getCategory() == null) {
+ throw new IllegalArgumentException("鍣ㄥ叿绫诲埆涓嶈兘涓虹┖锛堣濉瓧鍏镐腑鏂囷紝濡� 鍗″昂/鍏朵粬锛�");
+ }
+ if (row.getStatus() == null) {
+ throw new IllegalArgumentException("鐘舵�佷笉鑳戒负绌猴紙璇峰~瀛楀吀涓枃锛屽 鍦ㄧ敤/鍋滅敤/鎶ュ簾锛�");
+ }
+ // 2. 缂栫爜鍒ら噸锛堝惈鈥滃凡琚�昏緫鍒犻櫎鈥濈殑璁板綍锛夛細鏈垹闄� => 鎶ラ敊锛涘凡鍒犻櫎 => 绋嶅悗鎭㈠骞舵洿鏂�
+ MesDvMeteringDO exist = meteringMapper.selectByCodeIncludeDeleted(row.getCode().trim());
+ if (exist != null && !Boolean.TRUE.equals(exist.getDeleted())) {
+ throw new IllegalArgumentException("璁¢噺鍣ㄥ叿缂栫爜宸插瓨鍦細" + row.getCode());
+ }
+
+ // 3. 缁勮
+ MesDvMeteringSaveReqVO reqVO = new MesDvMeteringSaveReqVO();
+ reqVO.setCode(row.getCode().trim());
+ reqVO.setName(row.getName().trim());
+ reqVO.setCategory(row.getCategory());
+ reqVO.setSpecification(row.getSpecification());
+ reqVO.setBrand(row.getBrand());
+ reqVO.setPrecision(row.getPrecision());
+ reqVO.setRange(row.getRange());
+ reqVO.setCheckCycleCount(row.getCheckCycleCount() == null ? 12 : row.getCheckCycleCount());
+ reqVO.setUseDate(parseImportUseDate(row.getUseDate()));
+ reqVO.setStatus(row.getStatus());
+ reqVO.setRemark(row.getRemark());
+ // 浣跨敤閮ㄩ棬锛氭寜鍚嶇О鍖归厤
+ if (StrUtil.isNotBlank(row.getDeptName())) {
+ Long deptId = deptIdMap.get(row.getDeptName().trim());
+ if (deptId == null) {
+ throw new IllegalArgumentException("浣跨敤閮ㄩ棬涓嶅瓨鍦細" + row.getDeptName());
+ }
+ reqVO.setDeptId(deptId);
+ }
+ // 璐d换浜猴細鎸夋樀绉板尮閰�
+ if (StrUtil.isNotBlank(row.getChargeUserName())) {
+ Long userId = matchUserIdByNickname(row.getChargeUserName().trim());
+ if (userId == null) {
+ throw new IllegalArgumentException("璐d换浜轰笉瀛樺湪锛�" + row.getChargeUserName());
+ }
+ reqVO.setChargeUserId(userId);
+ }
+
+ // 4. 钀藉簱锛氬懡涓�滃凡鍒犻櫎鈥濈殑鍚岀紪鐮� => 鍏堟仮澶嶅啀鏇存柊锛涘惁鍒欐柊澧�
+ if (exist != null) {
+ meteringMapper.restoreDeletedById(exist.getId());
+ reqVO.setId(exist.getId());
+ updateMetering(reqVO);
+ return true; // 琛ㄧず鈥滄仮澶�/鏇存柊鈥�
+ }
+ createMetering(reqVO);
+ return false;
+ }
+
+ /**
+ * 鎸夋樀绉板尮閰嶇敤鎴风紪鍙凤紙绮剧‘鍖归厤浼樺厛锛屽彇涓嶅埌鍒欑敤妯$硦缁撴灉绗竴鏉★級
+ */
+ private Long matchUserIdByNickname(String nickname) {
+ List<AdminUserRespDTO> users = adminUserApi.getUserListByNickname(nickname);
+ if (CollUtil.isEmpty(users)) {
+ return null;
+ }
+ return users.stream()
+ .filter(user -> nickname.equals(user.getNickname()))
+ .map(AdminUserRespDTO::getId)
+ .findFirst()
+ .orElseGet(() -> users.get(0).getId());
+ }
+
+ /**
+ * 瑙f瀽鎶曞叆浣跨敤鏃ユ湡锛坹yyy-MM-dd / yyyy/M/d锛夛紱涓虹┖杩斿洖 null
+ */
+ private LocalDate parseImportUseDate(String text) {
+ if (StrUtil.isBlank(text)) {
+ return null;
+ }
+ String value = text.trim();
+ for (String pattern : new String[]{"yyyy-MM-dd", "yyyy/M/d"}) {
+ try {
+ return LocalDate.parse(value, java.time.format.DateTimeFormatter.ofPattern(pattern));
+ } catch (Exception ignored) {
+ // 缁х画灏濊瘯涓嬩竴涓牸寮�
+ }
+ }
+ try {
+ return java.time.LocalDateTime.parse(value,
+ java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toLocalDate();
+ } catch (Exception ignored) {
+ // 蹇界暐
+ }
+ throw new IllegalArgumentException("鎶曞叆浣跨敤鏃ユ湡鏍煎紡涓嶆纭細" + text + "锛岀ず渚� 2026-01-01");
+ }
+
+ /**
+ * 鎻愬彇瀵煎叆澶辫触鍘熷洜锛圫erviceException 鍙栦笟鍔℃彁绀猴級
+ */
+ private String resolveImportErrorMessage(Exception ex) {
+ if (ex instanceof cn.iocoder.yudao.framework.common.exception.ServiceException serviceException) {
+ return serviceException.getMessage();
+ }
+ return StrUtil.blankToDefault(ex.getMessage(), "瀵煎叆澶辫触");
+ }
+
+ @Override
public void updateMetering(MesDvMeteringSaveReqVO updateReqVO) {
// 鏍¢獙瀛樺湪
validateMeteringExists(updateReqVO.getId());
--
Gitblit v1.9.3