PC物料导入添加

This commit is contained in:
秦鸿展
2026-03-31 16:35:41 +08:00
parent 88a179c8c5
commit 9b08712b31
9 changed files with 585 additions and 14 deletions
@@ -201,6 +201,13 @@ public interface SystemServiceFeign {
@GetMapping("/batchApi/getInfo/{batchId}")
public AjaxResult getBatchInfoByBatchId(@PathVariable("batchId") Long batchId);
/**
* 根据批次名称查询批次列表(导入用)
*/
@GetMapping("/batchApi/list")
public Object getBatchListByName(@RequestParam("batchName") String batchName,
@RequestParam("organizationId") Long organizationId);
/**
* 根据batchId获取对应批次详情信息
*/
@@ -251,6 +258,14 @@ public interface SystemServiceFeign {
@GetMapping("/packApi/getInfoByPackIdAndUnitCode/{packId}/{unitCode}")
public AjaxResult getInfoByPackIdAndUnitCode(@PathVariable("packId") Long packId, @PathVariable("unitCode") String unitCode);
/**
* 根据包装编码/名称查询包装(导入用)
*/
@GetMapping("/packApi/list")
public Object getPackList(@RequestParam(value = "packCode", required = false) String packCode,
@RequestParam(value = "packName", required = false) String packName,
@RequestParam(value = "organizationId", required = false) Long organizationId);
/**
* 根据platformId获取对应月台信息
*/
@@ -154,6 +154,11 @@ public class RemoteSystemFeignFallbackFactory implements FallbackFactory<SystemS
return AjaxResult.error("根据批次ID获取批次信息失败");
}
@Override
public Object getBatchListByName(String batchName, Long organizationId) {
return AjaxResult.error("根据批次名称查询批次列表失败");
}
@Override
public AjaxResult getBatchDetailListByBatchId(Long batchId) {
return AjaxResult.error("根据batchId获取对应批次详情信息失败");
@@ -199,6 +204,11 @@ public class RemoteSystemFeignFallbackFactory implements FallbackFactory<SystemS
return AjaxResult.error("根据包装ID和单位编码获取信息失败");
}
@Override
public Object getPackList(String packCode, String packName, Long organizationId) {
return AjaxResult.error("根据包装编码/名称查询包装列表失败");
}
@Override
public AjaxResult getPlatformInfoByPlatformId(Long platformId) {
return AjaxResult.error("根据platformId获取对应月台信息失败");
@@ -1,14 +1,23 @@
package com.mhd.wms.application.service.materialBaseInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.enums.DictCode;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.domain.BatchFeignPO;
import com.mhd.system.api.domain.PackDetailFeignPO;
import com.mhd.system.api.domain.SysDictData;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.materialBarCode.service.MaterialBarCodeDomainService;
import com.mhd.wms.domain.materialBarCode.repository.todo.MaterialBarCodeDO;
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO;
import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO;
import com.mhd.wms.domain.materialBaseInfo.service.MaterialBaseInfoDomainService;
@@ -24,15 +33,22 @@ import com.mhd.wms.domain.materialInventoryWarning.repository.po.MaterialInvento
import com.mhd.wms.domain.materialInventoryWarning.service.MaterialInventoryWarningDomainService;
import com.mhd.wms.domain.materialWarehouseControl.repository.todo.MaterialWarehouseControlDO;
import com.mhd.wms.domain.materialWarehouseControl.service.MaterialWarehouseControlDomainService;
import com.mhd.wms.interfaces.dto.materialBaseInfo.MaterialBaseInfoDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -65,6 +81,8 @@ public class MaterialBaseInfoApplicationService {
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private IMaterialBaseInfoService materialBaseInfoService;
/**
* 分页查询物料基础信息列表
@@ -193,16 +211,22 @@ public class MaterialBaseInfoApplicationService {
materialBaseInfoDO.setMaterialBaseInfoId(materialBaseInfoId);
//商品规则
MaterialGoodsRuleDO materialGoodsRuleDO = materialBaseInfoDO.getMaterialGoodsRule();
materialGoodsRuleDO.setMaterialBaseInfoId(materialBaseInfoId);
materialGoodsRuleDomainService.insert(materialGoodsRuleDO);
if (materialGoodsRuleDO != null) {
materialGoodsRuleDO.setMaterialBaseInfoId(materialBaseInfoId);
materialGoodsRuleDomainService.insert(materialGoodsRuleDO);
}
//公共信息
MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon();
materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId);
materialCommonDomainService.insert(materialCommonDO);
if (materialCommonDO != null) {
materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId);
materialCommonDomainService.insert(materialCommonDO);
}
//仓库控制信息
MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl();
materialWarehouseControlDO.setMaterialBaseInfoId(materialBaseInfoId);
materialWarehouseControlDomainService.insert(materialWarehouseControlDO);
if (materialWarehouseControlDO != null) {
materialWarehouseControlDO.setMaterialBaseInfoId(materialBaseInfoId);
materialWarehouseControlDomainService.insert(materialWarehouseControlDO);
}
//库存预警
materialInventoryWarningDomainService.batchInsertOrUpdate(materialBaseInfoDO);
//条码信息
@@ -217,13 +241,19 @@ public class MaterialBaseInfoApplicationService {
materialBaseInfoDomainService.update(materialBaseInfoDO);
//商品规则
MaterialGoodsRuleDO materialGoodsRuleDO = materialBaseInfoDO.getMaterialGoodsRule();
materialGoodsRuleDomainService.update(materialGoodsRuleDO);
if (materialGoodsRuleDO != null) {
materialGoodsRuleDomainService.update(materialGoodsRuleDO);
}
//公共信息
MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon();
materialCommonDomainService.update(materialCommonDO);
if (materialCommonDO != null) {
materialCommonDomainService.update(materialCommonDO);
}
//仓库控制信息
MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl();
materialWarehouseControlDomainService.update(materialWarehouseControlDO);
if (materialWarehouseControlDO != null) {
materialWarehouseControlDomainService.update(materialWarehouseControlDO);
}
//库存预警
materialInventoryWarningDomainService.batchInsertOrUpdate(materialBaseInfoDO);
//条码信息
@@ -257,4 +287,433 @@ public class MaterialBaseInfoApplicationService {
return materialBaseInfoDomainService.getInfoByNoOrderReceipt(materialBaseInfoDO);
}
/**
* 导入物料主数据(仅导入主表字段)
*/
@Transactional(rollbackFor = Exception.class)
public AjaxResult importData(MultipartFile file) {
if (file == null || file.isEmpty()) {
throw new ServiceException("上传文件不能为空");
}
String fileName = file.getOriginalFilename();
if (StringUtils.isBlank(fileName) || (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx"))) {
throw new ServiceException("请上传xls或xlsx格式文件");
}
final List<MaterialBaseInfoDTO> rows;
try (InputStream is = file.getInputStream()) {
ExcelUtil<MaterialBaseInfoDTO> util = new ExcelUtil<>(MaterialBaseInfoDTO.class);
rows = util.importExcel(is);
} catch (Exception e) {
throw new ServiceException("导入模板解析失败:" + e.getMessage());
}
if (CollectionUtils.isEmpty(rows)) {
throw new ServiceException("导入数据为空");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
Long loginOrgId = null;
Long loginTopOrgId = null;
if (loginUser != null && loginUser.getUserPo() != null) {
loginOrgId = loginUser.getUserPo().getOrganizationId();
loginTopOrgId = loginUser.getUserPo().getTopOrganizationId();
}
StringBuilder errors = new StringBuilder();
Set<String> duplicateInFile = new HashSet<>();
int successCount = 0;
for (int i = 0; i < rows.size(); i++) {
MaterialBaseInfoDTO row = rows.get(i);
int rowNum = i + 2;
if (row == null) {
continue;
}
if (StringUtils.isBlank(row.getMaterialCode())) {
errors.append("").append(rowNum).append("行:物料编码不能为空;");
continue;
}
if (StringUtils.isBlank(row.getMaterialName())) {
errors.append("").append(rowNum).append("行:物料名称不能为空;");
continue;
}
if (row.getOrganizationId() == null && loginOrgId != null) {
row.setOrganizationId(loginOrgId);
}
if (row.getTopOrganizationId() == null && loginTopOrgId != null) {
row.setTopOrganizationId(loginTopOrgId);
}
if (row.getNullify() == null) {
row.setNullify(2);
}
if (row.getCommon() == null) {
row.setCommon(2);
}
if (StringUtils.isBlank(row.getHsCode()) && StringUtils.isNotBlank(row.getHsCodeImport())) {
row.setHsCode(row.getHsCodeImport().trim());
}
fillOrganizationName(row, loginUser);
String shipperCode = StringUtils.defaultString(row.getShipperCode(), "");
String duplicateKey = row.getOrganizationId() + "|" + shipperCode + "|" + row.getMaterialCode();
if (!duplicateInFile.add(duplicateKey)) {
errors.append("").append(rowNum).append("行:文件内存在重复物料(组织+货主编码+物料编码);");
continue;
}
LambdaQueryWrapper<MaterialBaseInfo> wrapper = new LambdaQueryWrapper<MaterialBaseInfo>()
.eq(MaterialBaseInfo::getDelFlag, 1)
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
.eq(MaterialBaseInfo::getMaterialCode, row.getMaterialCode());
if (StringUtils.isBlank(row.getShipperCode())) {
wrapper.and(w -> w.isNull(MaterialBaseInfo::getShipperCode).or().eq(MaterialBaseInfo::getShipperCode, ""));
} else {
wrapper.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode());
}
if (materialBaseInfoService.count(wrapper) > 0) {
errors.append("").append(rowNum).append("行:物料已存在(组织+货主编码+物料编码);");
continue;
}
// 根据导入的名称/编码回填现有ID,避免要求模板传ID
fillIdsFromExistingMasterData(row);
fillClassifyTypeAndUnit(row);
MaterialBaseInfoDO materialBaseInfoDO = new MaterialBaseInfoDO();
BeanUtils.copyProperties(row, materialBaseInfoDO);
materialBaseInfoDO.setMaterialGoodsRule(buildImportMaterialGoodsRule(row));
materialBaseInfoDO.setMaterialCommon(null);
materialBaseInfoDO.setMaterialWarehouseControl(null);
materialBaseInfoDO.setMaterialBarCodeList(buildImportBarCodeList(row));
insert(materialBaseInfoDO);
successCount++;
}
if (errors.length() > 0) {
return AjaxResult.error("导入完成:成功" + successCount + "条,失败" + (rows.size() - successCount) + "条。失败原因:" + errors);
}
return AjaxResult.success("导入成功,共" + successCount + "");
}
/**
* 使用已存在主数据按名称/编码反查并回填ID
*/
private void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) {
if (StringUtils.isBlank(row.getPackName()) && StringUtils.isNotBlank(row.getPackImport())) {
row.setPackName(row.getPackImport().trim());
}
// 货主
if (row.getShipperId() == null && (StringUtils.isNotBlank(row.getShipperCode()) || StringUtils.isNotBlank(row.getShipperName()))) {
MaterialBaseInfo matched = materialBaseInfoService.getOne(new LambdaQueryWrapper<MaterialBaseInfo>()
.eq(MaterialBaseInfo::getDelFlag, 1)
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
.and(w -> {
if (StringUtils.isNotBlank(row.getShipperCode())) {
w.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode());
}
if (StringUtils.isNotBlank(row.getShipperName())) {
if (StringUtils.isNotBlank(row.getShipperCode())) {
w.or();
}
w.eq(MaterialBaseInfo::getShipperName, row.getShipperName());
}
})
.last("limit 1"));
if (matched != null) {
row.setShipperId(matched.getShipperId());
if (StringUtils.isBlank(row.getShipperCode())) {
row.setShipperCode(matched.getShipperCode());
}
if (StringUtils.isBlank(row.getShipperName())) {
row.setShipperName(matched.getShipperName());
}
}
}
// 包装规格
if (row.getPackId() == null && (StringUtils.isNotBlank(row.getPackCode()) || StringUtils.isNotBlank(row.getPackName()))) {
Long packId = queryPackIdByCodeOrName(row.getPackCode(), row.getPackName(), row.getOrganizationId());
if (packId != null) {
row.setPackId(packId);
}
MaterialBaseInfo matched = materialBaseInfoService.getOne(new LambdaQueryWrapper<MaterialBaseInfo>()
.eq(MaterialBaseInfo::getDelFlag, 1)
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
.and(w -> {
if (StringUtils.isNotBlank(row.getPackCode())) {
w.eq(MaterialBaseInfo::getPackCode, row.getPackCode());
}
if (StringUtils.isNotBlank(row.getPackName())) {
if (StringUtils.isNotBlank(row.getPackCode())) {
w.or();
}
w.eq(MaterialBaseInfo::getPackName, row.getPackName());
}
})
.last("limit 1"));
if (matched != null) {
row.setPackId(matched.getPackId());
if (StringUtils.isBlank(row.getPackCode())) {
row.setPackCode(matched.getPackCode());
}
if (StringUtils.isBlank(row.getPackName())) {
row.setPackName(matched.getPackName());
}
}
}
// 品牌
if (row.getBrandId() == null && (StringUtils.isNotBlank(row.getBrandCode()) || StringUtils.isNotBlank(row.getBrandName()))) {
MaterialBaseInfo matched = materialBaseInfoService.getOne(new LambdaQueryWrapper<MaterialBaseInfo>()
.eq(MaterialBaseInfo::getDelFlag, 1)
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
.and(w -> {
if (StringUtils.isNotBlank(row.getBrandCode())) {
w.eq(MaterialBaseInfo::getBrandCode, row.getBrandCode());
}
if (StringUtils.isNotBlank(row.getBrandName())) {
if (StringUtils.isNotBlank(row.getBrandCode())) {
w.or();
}
w.eq(MaterialBaseInfo::getBrandName, row.getBrandName());
}
})
.last("limit 1"));
if (matched != null) {
row.setBrandId(matched.getBrandId());
if (StringUtils.isBlank(row.getBrandCode())) {
row.setBrandCode(matched.getBrandCode());
}
if (StringUtils.isBlank(row.getBrandName())) {
row.setBrandName(matched.getBrandName());
}
}
}
}
private void fillOrganizationName(MaterialBaseInfoDTO row, LoginUser loginUser) {
if (StringUtils.isNotBlank(row.getOrganizationName())) {
return;
}
if (loginUser != null && loginUser.getUserPo() != null
&& row.getOrganizationId() != null
&& row.getOrganizationId().equals(loginUser.getUserPo().getOrganizationId())) {
row.setOrganizationName(loginUser.getUserPo().getOrganizationName());
return;
}
MaterialBaseInfo matched = materialBaseInfoService.getOne(new LambdaQueryWrapper<MaterialBaseInfo>()
.eq(MaterialBaseInfo::getDelFlag, 1)
.eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId())
.isNotNull(MaterialBaseInfo::getOrganizationName)
.last("limit 1"));
if (matched != null && StringUtils.isNotBlank(matched.getOrganizationName())) {
row.setOrganizationName(matched.getOrganizationName());
}
}
private void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) {
// 物料分类:模板常用“物料分类”单列,回填到名称列表
if (CollectionUtils.isEmpty(row.getMaterialClassifyName()) && StringUtils.isNotBlank(row.getMaterialClassifyImport())) {
List<String> names = new ArrayList<>();
names.add(row.getMaterialClassifyImport().trim());
row.setMaterialClassifyName(names);
}
// 物料种类:可传编码或名称,统一回填编码+名称
if ((StringUtils.isBlank(row.getMaterialType()) || StringUtils.isBlank(row.getMaterialTypeName()))
&& StringUtils.isNotBlank(row.getMaterialTypeImport())) {
AjaxResult dictResult = systemServiceFeign.selectListByDictType(DictCode.MATERIAL_TYPE.getCode());
if ("200".equals(String.valueOf(dictResult.get("code"))) && dictResult.get("data") != null) {
List<SysDictData> dictList = JSON.parseObject(JSONObject.toJSONString(dictResult.get("data")),
new TypeReference<List<SysDictData>>() {});
String input = row.getMaterialTypeImport().trim();
if (!CollectionUtils.isEmpty(dictList)) {
for (SysDictData d : dictList) {
if (input.equals(d.getDictValue()) || input.equals(d.getDictLabel())) {
row.setMaterialType(d.getDictValue());
row.setMaterialTypeName(d.getDictLabel());
break;
}
}
}
}
}
// 物料单位:模板常用“物料单位”,按包装规格EA明细回填单位编码/名称
String unitInput = StringUtils.isNotBlank(row.getUnitImport()) ? row.getUnitImport().trim() : StringUtils.trimToEmpty(row.getUnitImport2());
if ((StringUtils.isBlank(row.getUnitCode()) || StringUtils.isBlank(row.getUnitName()))
&& StringUtils.isNotBlank(unitInput)
&& row.getPackId() != null) {
String[] unitCodes = {"EA", "IP", "CS", "PL", "OT"};
for (String unitCode : unitCodes) {
AjaxResult packDetailResult = systemServiceFeign.getInfoByPackIdAndUnitCode(row.getPackId(), unitCode);
if (!"200".equals(String.valueOf(packDetailResult.get("code"))) || packDetailResult.get("data") == null) {
continue;
}
PackDetailFeignPO pd = JSON.parseObject(JSONObject.toJSONString(packDetailResult.get("data")), PackDetailFeignPO.class);
if (pd == null) {
continue;
}
if (unitInput.equals(pd.getUnitCode()) || unitInput.equals(pd.getName())) {
row.setUnitCode(pd.getUnitCode());
row.setUnitName(pd.getName());
break;
}
}
}
// 兜底:导入模板给了“物料单位/单位”,但包装明细未命中时至少保留单位名称
if (StringUtils.isBlank(row.getUnitName()) && StringUtils.isNotBlank(unitInput)) {
row.setUnitName(unitInput);
}
if (StringUtils.isBlank(row.getUnitCode()) && StringUtils.isNotBlank(unitInput)
&& ("EA".equalsIgnoreCase(unitInput) || "IP".equalsIgnoreCase(unitInput)
|| "CS".equalsIgnoreCase(unitInput) || "PL".equalsIgnoreCase(unitInput)
|| "OT".equalsIgnoreCase(unitInput))) {
row.setUnitCode(unitInput.toUpperCase());
}
}
private List<MaterialBarCodeDO> buildImportBarCodeList(MaterialBaseInfoDTO row) {
if (StringUtils.isBlank(row.getBarCode())) {
return null;
}
MaterialBarCodeDO barCodeDO = new MaterialBarCodeDO();
barCodeDO.setBarCode(row.getBarCode().trim());
barCodeDO.setPackId(row.getPackId());
barCodeDO.setPackCode(row.getPackCode());
barCodeDO.setPackName(row.getPackName());
barCodeDO.setUnitCode(row.getUnitCode());
barCodeDO.setName(row.getUnitName());
List<MaterialBarCodeDO> list = new ArrayList<>();
list.add(barCodeDO);
return list;
}
private Long queryPackIdByCodeOrName(String packCode, String packName, Long organizationId) {
Object result = systemServiceFeign.getPackList(StringUtils.trimToNull(packCode), StringUtils.trimToNull(packName), organizationId);
if (result == null) {
return null;
}
Map<String, Object> resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference<Map<String, Object>>() {});
List<Map<String, Object>> rows = extractTableDataRows(resultMap);
if (CollectionUtils.isEmpty(rows)) {
return null;
}
String code = StringUtils.trimToEmpty(packCode);
String name = StringUtils.trimToEmpty(packName);
for (Map<String, Object> p : rows) {
String c = p.get("packCode") == null ? "" : String.valueOf(p.get("packCode"));
String n = p.get("packName") == null ? "" : String.valueOf(p.get("packName"));
if ((StringUtils.isNotBlank(code) && code.equals(c)) || (StringUtils.isNotBlank(name) && name.equals(n))) {
Object idObj = p.get("packId");
return idObj == null ? null : Long.valueOf(String.valueOf(idObj));
}
}
Object idObj = rows.get(0).get("packId");
return idObj == null ? null : Long.valueOf(String.valueOf(idObj));
}
private MaterialGoodsRuleDO buildImportMaterialGoodsRule(MaterialBaseInfoDTO row) {
String batchName = StringUtils.isNotBlank(row.getBatchRuleNameImport())
? row.getBatchRuleNameImport().trim()
: (StringUtils.isNotBlank(row.getBatchName())
? row.getBatchName().trim()
: StringUtils.trimToEmpty(row.getBatchImport()));
if (StringUtils.isBlank(batchName)) {
return null;
}
StringBuilder queryDebug = new StringBuilder();
Long batchId = queryBatchIdByName(batchName, row.getOrganizationId(), queryDebug);
if (batchId == null) {
String normalizedBatchName = normalizeBatchKeyword(batchName);
List<Long> orgCandidates = buildBatchOrgCandidates(row.getOrganizationId());
throw new ServiceException("批次规则【" + batchName + "】不存在,请先在基础资料维护批次"
+ "(匹配值:" + normalizedBatchName + ",组织范围:" + orgCandidates
+ ",远端返回:" + (queryDebug.length() == 0 ? "" : queryDebug.toString()) + "");
}
MaterialGoodsRuleDO goodsRuleDO = new MaterialGoodsRuleDO();
goodsRuleDO.setBatchId(batchId);
return goodsRuleDO;
}
private Long queryBatchIdByName(String batchName, Long organizationId, StringBuilder queryDebug) {
String normalizedInput = normalizeBatchKeyword(batchName);
if (StringUtils.isBlank(normalizedInput)) {
return null;
}
List<String> debugTraces = new ArrayList<>();
// 批次主数据通常维护在system模块,且可能挂在一级组织下;这里做组织维度兜底查询
List<Long> orgCandidates = buildBatchOrgCandidates(organizationId);
for (Long orgId : orgCandidates) {
Object result = systemServiceFeign.getBatchListByName(batchName, orgId);
if (result == null) {
debugTraces.add("org=" + orgId + ",result=null");
continue;
}
Map<String, Object> resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference<Map<String, Object>>() {});
Object codeObj = resultMap.get("code");
Object totalObj = resultMap.get("total");
List<Map<String, Object>> rows = extractTableDataRows(resultMap);
if (CollectionUtils.isEmpty(rows)) {
debugTraces.add("org=" + orgId + ",code=" + codeObj + ",total=" + totalObj + ",rows=0");
continue;
}
debugTraces.add("org=" + orgId + ",code=" + codeObj + ",total=" + totalObj + ",rows=" + rows.size());
for (Map<String, Object> p : rows) {
if (p == null) {
continue;
}
String rowBatchName = normalizeBatchKeyword(p.get("batchName") == null ? "" : String.valueOf(p.get("batchName")));
if (StringUtils.equals(normalizedInput, rowBatchName)) {
Object idObj = p.get("batchId");
if (queryDebug != null) {
queryDebug.append(String.join(" | ", debugTraces));
}
return idObj == null ? null : Long.valueOf(String.valueOf(idObj));
}
}
}
if (queryDebug != null) {
queryDebug.append(String.join(" | ", debugTraces));
}
return null;
}
private String normalizeBatchKeyword(String text) {
if (text == null) {
return "";
}
return text.replace("\u3000", " ")
.replaceAll("\\s+", "")
.trim();
}
private List<Map<String, Object>> extractTableDataRows(Map<String, Object> resultMap) {
if (resultMap == null) {
return new ArrayList<>();
}
Object listObj = resultMap.get("data");
if (listObj == null) {
listObj = resultMap.get("rows");
}
if (listObj == null) {
return new ArrayList<>();
}
List<Map<String, Object>> rows = JSON.parseObject(JSONObject.toJSONString(listObj), new TypeReference<List<Map<String, Object>>>() {});
return rows == null ? new ArrayList<>() : rows;
}
private List<Long> buildBatchOrgCandidates(Long organizationId) {
List<Long> orgCandidates = new ArrayList<>();
if (organizationId != null) {
orgCandidates.add(organizationId);
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null && loginUser.getUserPo() != null && loginUser.getUserPo().getTopOrganizationId() != null) {
Long topOrgId = loginUser.getUserPo().getTopOrganizationId();
if (!orgCandidates.contains(topOrgId)) {
orgCandidates.add(topOrgId);
}
}
return orgCandidates;
}
}
@@ -27,7 +27,7 @@ public class MaterialBaseInfo extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("物料基础信息id")
@TableId(type = IdType.INPUT)
@TableId(type = IdType.AUTO)
private Long materialBaseInfoId;
@ApiModelProperty("组织表ID")
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
@@ -82,6 +83,9 @@ public class MaterialBaseInfoImpl extends ServiceImpl<MaterialBaseInfoMapper, Ma
@Override
public MaterialBaseInfoPO getInfo(Long materialBaseInfoId) {
MaterialBaseInfo materialBaseInfo = materialBaseInfoMapper.selectOne(new QueryWrapper<MaterialBaseInfo>().lambda().eq(MaterialBaseInfo::getMaterialBaseInfoId, materialBaseInfoId));
if (materialBaseInfo == null) {
throw new ServiceException("物料基础信息不存在,materialBaseInfoId=" + materialBaseInfoId);
}
MaterialBaseInfoPO materialBaseInfoPO = new MaterialBaseInfoPO();
BeanUtils.copyProperties(materialBaseInfo,materialBaseInfoPO);
return materialBaseInfoPO;
@@ -46,8 +46,8 @@ public class MaterialGoodsRuleDO extends BaseVOEntity {
@Excel(name = "批次编码")
private String batchCode;
@ApiModelProperty("批次名称")
@Excel(name = "批次名称")
@ApiModelProperty("批次规则")
@Excel(name = "批次规则")
private String batchName;
@ApiModelProperty("上架库区id")
@@ -13,6 +13,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
@@ -74,6 +75,9 @@ public class MaterialBaseInfoDTO extends BaseVOEntity {
@Excel(name = "物料分类名称")
@TableField(typeHandler = ListTypeHandler.class)
private List<String> materialClassifyName;
@ApiModelProperty("物料分类(导入)")
@Excel(name = "物料分类")
private String materialClassifyImport;
@ApiModelProperty("物料种类编码 数据字典")
@Excel(name = "物料种类编码 数据字典")
@@ -82,6 +86,9 @@ public class MaterialBaseInfoDTO extends BaseVOEntity {
@ApiModelProperty("物料种类名称 数据字典")
@Excel(name = "物料种类名称 数据字典")
private String materialTypeName;
@ApiModelProperty("物料种类(导入)")
@Excel(name = "物料种类")
private String materialTypeImport;
@ApiModelProperty("包装规格id")
@Excel(name = "包装规格id")
@@ -94,6 +101,9 @@ public class MaterialBaseInfoDTO extends BaseVOEntity {
@ApiModelProperty("包装规格名称")
@Excel(name = "包装规格名称")
private String packName;
@ApiModelProperty("包装规格(导入)")
@Excel(name = "包装规格")
private String packImport;
@ApiModelProperty("包装单位编码")
@Excel(name = "包装单位编码")
@@ -102,6 +112,12 @@ public class MaterialBaseInfoDTO extends BaseVOEntity {
@ApiModelProperty("包装单位名称")
@Excel(name = "包装单位名称")
private String unitName;
@ApiModelProperty("物料单位(导入)")
@Excel(name = "物料单位")
private String unitImport;
@ApiModelProperty("单位(导入)")
@Excel(name = "单位")
private String unitImport2;
@ApiModelProperty("品牌id")
@Excel(name = "品牌id")
@@ -192,32 +208,56 @@ public class MaterialBaseInfoDTO extends BaseVOEntity {
private Integer common;
@ApiModelProperty("SKU码")
@Excel(name = "SKU码")
private String skuCode;
@ApiModelProperty("单价")
@Excel(name = "单价")
private BigDecimal unitPrice;
@ApiModelProperty("币制")
@Excel(name = "币制")
private String currency;
@ApiModelProperty("原产国")
@Excel(name = "原产国")
private String originCountry;
@ApiModelProperty("HS码")
@Excel(name = "HS码")
private String hsCode;
@ApiModelProperty("HS编码(导入)")
@Excel(name = "HS编码")
private String hsCodeImport;
@ApiModelProperty("申报单位")
@Excel(name = "申报单位")
private String declarationUnit;
@ApiModelProperty("法定单位")
@Excel(name = "法定单位")
private String statutoryUnit;
@ApiModelProperty("法定第二单位")
@Excel(name = "法定第二单位")
private String statutorySecondUnit;
@ApiModelProperty("规格型号")
@Excel(name = "规格型号")
private String specificationModel;
@ApiModelProperty("批次ID")
private Long batchId;
@ApiModelProperty("批次规则(导入:批次名称)")
@Excel(name = "批次规则")
private String batchRuleNameImport;
@ApiModelProperty("批次名称(导入)")
@Excel(name = "批次名称")
private String batchName;
@ApiModelProperty("批次(导入)")
@Excel(name = "批次")
private String batchImport;
}
@@ -13,6 +13,7 @@ import com.mhd.wms.interfaces.dto.materialBaseInfo.MaterialBaseInfoDTO;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
@@ -95,6 +96,15 @@ public class MaterialBaseInfoApi extends BaseController {
return R.ok(materialBaseInfoApplicationService.getInfoByNoOrderReceipt(materialBaseInfoDO));
}
/**
* 导入物料主数据
*/
@ApiOperation("导入物料主数据")
@PostMapping("/importData")
public AjaxResult importData(@RequestParam("file") MultipartFile file) {
return materialBaseInfoApplicationService.importData(file);
}
+34 -1
View File
@@ -8,4 +8,37 @@ COMMENT ON COLUMN SHELF_MATERIAL_DETAIL.DIMENSIONS IS '尺寸';
-- 拣货单明细新增规格字段 (SIZE)
ALTER TABLE PICKING_MATERIAL_DETAIL ADD "SIZE" VARCHAR2(255);
COMMENT ON COLUMN PICKING_MATERIAL_DETAIL."SIZE" IS '尺寸';
COMMENT ON COLUMN PICKING_MATERIAL_DETAIL."SIZE" IS '尺寸';
-- 1) 创建序列(若已存在会报错,可先跳过或改名)
CREATE SEQUENCE SEQ_MATERIAL_BASE_INFO_ID
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
-- 2) 将序列起始值调整到“当前最大ID+1”
DECLARE
v_next BIGINT;
BEGIN
SELECT NVL(MAX(MATERIAL_BASE_INFO_ID), 0) + 1
INTO v_next
FROM MATERIAL_BASE_INFO;
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_MATERIAL_BASE_INFO_ID';
EXECUTE IMMEDIATE 'CREATE SEQUENCE SEQ_MATERIAL_BASE_INFO_ID START WITH ' || v_next || ' INCREMENT BY 1 NOCACHE NOCYCLE';
END;
/
-- 3) 创建触发器:仅在主键为空时自动赋值
CREATE OR REPLACE TRIGGER TRG_MATERIAL_BASE_INFO_BI
BEFORE INSERT ON MATERIAL_BASE_INFO
FOR EACH ROW
BEGIN
IF :NEW.MATERIAL_BASE_INFO_ID IS NULL THEN
SELECT SEQ_MATERIAL_BASE_INFO_ID.NEXTVAL
INTO :NEW.MATERIAL_BASE_INFO_ID
FROM DUAL;
END IF;
END;
/