PC物料导入添加
This commit is contained in:
@@ -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获取对应月台信息
|
||||
*/
|
||||
|
||||
+10
@@ -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获取对应月台信息失败");
|
||||
|
||||
+460
-1
@@ -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();
|
||||
if (materialGoodsRuleDO != null) {
|
||||
materialGoodsRuleDO.setMaterialBaseInfoId(materialBaseInfoId);
|
||||
materialGoodsRuleDomainService.insert(materialGoodsRuleDO);
|
||||
}
|
||||
//公共信息
|
||||
MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon();
|
||||
if (materialCommonDO != null) {
|
||||
materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId);
|
||||
materialCommonDomainService.insert(materialCommonDO);
|
||||
}
|
||||
//仓库控制信息
|
||||
MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl();
|
||||
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();
|
||||
if (materialGoodsRuleDO != null) {
|
||||
materialGoodsRuleDomainService.update(materialGoodsRuleDO);
|
||||
}
|
||||
//公共信息
|
||||
MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon();
|
||||
if (materialCommonDO != null) {
|
||||
materialCommonDomainService.update(materialCommonDO);
|
||||
}
|
||||
//仓库控制信息
|
||||
MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
@@ -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;
|
||||
|
||||
+2
-2
@@ -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")
|
||||
|
||||
+40
@@ -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;
|
||||
}
|
||||
|
||||
+10
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,3 +9,36 @@ 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 '尺寸';
|
||||
|
||||
-- 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;
|
||||
/
|
||||
Reference in New Issue
Block a user