去除供应商类型多余代码

This commit is contained in:
liuminghui
2026-10-28 17:14:42 +08:00
parent 2bd417b84e
commit 1e4711326c
19 changed files with 159 additions and 948 deletions
@@ -46,8 +46,8 @@ public class BmsSupplier extends BaseEntity
@Excel(name = "统一社会信用代码")
private String creditCode;
/** 供应商类型(1卡车行 2航司代理 3报关行 4清关行 5尾派服务商 6报关代理) */
@Excel(name = "供应商类型", readConverterExp = "1=卡车行,2=航司代理,3=报关行,4=清关行,5=尾派服务商,6=报关代理")
/** 供应商类型(字典 bms_supplier_type) */
@Excel(name = "供应商类型", dictType = "bms_supplier_type")
private String supplierType;
/** 开票类型(1增值税普通发票 2增值税专用发票 3增值税电子普通发票 4其他普通发票) */
@@ -127,11 +127,6 @@ public class BmsSupplier extends BaseEntity
@Excel(name = "合作开始日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date cooperationStartDate;
/** 合同开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "合同开始时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date contractStartDate;
/** 合同结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "合同结束时间", width = 30, dateFormat = "yyyy-MM-dd")
@@ -5,15 +5,18 @@ import java.util.List;
import com.bms.common.annotation.DataScope;
import com.bms.common.exception.ServiceException;
import com.bms.common.core.domain.entity.SysDictData;
import com.bms.common.core.domain.entity.SysUser;
import com.bms.common.utils.DateUtils;
import com.bms.common.utils.SecurityUtils;
import com.bms.common.utils.StringUtils;
import com.bms.customer.supplierinfo.domain.BmsSupplier;
import com.bms.customer.supplierinfo.domain.BmsSupplierAttachment;
import com.bms.customer.supplierinfo.domain.BmsSupplierCompany;
import com.bms.customer.supplierinfo.domain.BmsSupplierContact;
import com.bms.customer.supplierinfo.mapper.BmsSupplierMapper;
import com.bms.customer.supplierinfo.service.IBmsSupplierService;
import com.bms.system.service.ISysDictTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -27,9 +30,15 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class BmsSupplierServiceImpl implements IBmsSupplierService
{
/** 供应商类型只认系统字典,不另建类型表 */
private static final String DICT_SUPPLIER_TYPE = "bms_supplier_type";
@Autowired
private BmsSupplierMapper bmsSupplierMapper;
@Autowired
private ISysDictTypeService dictTypeService;
@Override
public BmsSupplier selectBmsSupplierBySupplierId(Long supplierId)
{
@@ -252,7 +261,8 @@ public class BmsSupplierServiceImpl implements IBmsSupplierService
@Override
public int insertBmsSupplier(BmsSupplier bmsSupplier)
{
checkContractDate(bmsSupplier.getContractStartDate(), bmsSupplier.getContractEndDate());
checkContractDate(bmsSupplier.getCooperationStartDate(), bmsSupplier.getContractEndDate());
checkSupplierType(bmsSupplier);
SysUser user = SecurityUtils.getLoginUser().getUser();
bmsSupplier.setCreateTime(DateUtils.getNowDate());
bmsSupplier.setCreateBy(user.getUserName());
@@ -270,7 +280,8 @@ public class BmsSupplierServiceImpl implements IBmsSupplierService
@Override
public int updateBmsSupplier(BmsSupplier bmsSupplier)
{
checkContractDate(bmsSupplier.getContractStartDate(), bmsSupplier.getContractEndDate());
checkContractDate(bmsSupplier.getCooperationStartDate(), bmsSupplier.getContractEndDate());
checkSupplierType(bmsSupplier);
SysUser user = SecurityUtils.getLoginUser().getUser();
bmsSupplier.setUpdateTime(DateUtils.getNowDate());
bmsSupplier.setUpdateBy(user.getUserName());
@@ -319,7 +330,30 @@ public class BmsSupplierServiceImpl implements IBmsSupplierService
{
if (start != null && end != null && end.before(start))
{
throw new ServiceException("合同结束时间不能早于开始时间");
throw new ServiceException("合同结束时间不能早于合作开始日期");
}
}
/**
* 供应商类型允许为空;有值时必须是字典 bms_supplier_type 中启用的键值。
*/
private void checkSupplierType(BmsSupplier bmsSupplier)
{
if (bmsSupplier.getSupplierType() == null)
{
return;
}
String supplierType = bmsSupplier.getSupplierType().trim();
bmsSupplier.setSupplierType(supplierType);
if (StringUtils.isEmpty(supplierType))
{
return;
}
List<SysDictData> datas = dictTypeService.selectDictDataByType(DICT_SUPPLIER_TYPE);
boolean exists = datas != null && datas.stream().anyMatch(d -> supplierType.equals(d.getDictValue()));
if (!exists)
{
throw new ServiceException("供应商类型不存在或已停用");
}
}
}
@@ -1,6 +1,7 @@
package com.bms.customer.supplierinfo.sync;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -12,8 +13,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bms.common.core.domain.entity.SysDictData;
import com.bms.common.utils.StringUtils;
import com.bms.customer.supplierinfo.domain.BmsSupplier;
import com.bms.customer.supplierinfo.mapper.SupplierSyncMapper;
import com.bms.system.service.ISysDictTypeService;
/**
* 老系统 Oracle 服务商数据 -> sup_supplier 每日同步。
@@ -35,11 +39,17 @@ public class SupplierSyncService
/** 写库人标记,便于事后甄别同步数据 */
public static final String SYNC_MARKER = "oracle-sync";
/** 源中文服务商类型 -> sup_supplier.supplier_type 字典码(4清关行 5尾派服务商) */
private static final String TYPE_QINGGUAN = "清关";
private static final String TYPE_WEICHENG = "尾程渠道";
private static final String CODE_QINGGUAN_HANG = "4";
private static final String CODE_WEIPAI = "5";
/** 供应商类型字典。老系统中文与字典标签不一致时,先折成标签再取键值 */
private static final String DICT_SUPPLIER_TYPE = "bms_supplier_type";
private static final Map<String, String> SOURCE_TYPE_LABEL;
static
{
Map<String, String> labels = new LinkedHashMap<>();
labels.put("尾程渠道", "尾派服务商");
labels.put("清关", "清关行");
SOURCE_TYPE_LABEL = Collections.unmodifiableMap(labels);
}
/** sup_supplier 字符串列长度 */
private static final int LEN_CODE = 50;
@@ -59,6 +69,9 @@ public class SupplierSyncService
@Autowired
private SupplierSyncMapper supplierSyncMapper;
@Autowired
private ISysDictTypeService dictTypeService;
/**
* 执行一次全量同步。
*
@@ -84,6 +97,11 @@ public class SupplierSyncService
}
Set<String> existingCodes = new HashSet<>(supplierSyncMapper.selectExistingCodes());
List<SysDictData> supplierTypes = dictTypeService.selectDictDataByType(DICT_SUPPLIER_TYPE);
if (supplierTypes == null)
{
supplierTypes = Collections.emptyList();
}
List<BmsSupplier> inserts = new ArrayList<>();
List<BmsSupplier> updates = new ArrayList<>();
@@ -120,7 +138,7 @@ public class SupplierSyncService
}
LinkedHashSet<String> channels = channelMap.getOrDefault(code, new LinkedHashSet<>());
BmsSupplier s = mapRow(row, code, name, channels, warnings);
BmsSupplier s = mapRow(row, code, name, channels, supplierTypes, warnings);
if (existingCodes.contains(code))
{
s.setUpdateBy(SYNC_MARKER);
@@ -159,14 +177,15 @@ public class SupplierSyncService
* 单行映射
*/
private BmsSupplier mapRow(Map<String, Object> row, String code, String name,
LinkedHashSet<String> channels, List<String> warnings)
LinkedHashSet<String> channels, List<SysDictData> supplierTypes,
List<String> warnings)
{
BmsSupplier s = new BmsSupplier();
s.setSupplierCode(truncate(code, LEN_CODE, code, "supplier_code", warnings));
s.setSupplierName(truncate(name, LEN_NAME, code, "supplier_name", warnings));
s.setDelFlag("0");
s.setSupplierType(mapServiceType(getStr(row, "SERVICE_TYPE"), code, warnings));
s.setSupplierType(mapServiceType(getStr(row, "SERVICE_TYPE"), code, supplierTypes, warnings));
s.setIsEnable(mapEnable(getStr(row, "BL_OPEN")));
s.setRemark(truncate(getStr(row, "REMARK"), LEN_REMARK, code, "remark", warnings));
@@ -178,25 +197,35 @@ public class SupplierSyncService
}
/**
* 源 SERVICE_TYPE 为中文:尾程渠道 -> 5(尾派服务商),清关 -> 4(清关行);
* 其他/空值置空并告警,由业务人员手工选择。
* 源 SERVICE_TYPE 按字典 bms_supplier_type 解析。
* 老系统「尾程渠道」「清关」先折成字典标签,再取启用项的键值;对不上则置空。
*/
private static String mapServiceType(String raw, String supplierCode, List<String> warnings)
private static String mapServiceType(String raw, String supplierCode, List<SysDictData> supplierTypes,
List<String> warnings)
{
String v = clean(raw);
if (v == null)
{
return null;
}
if (TYPE_WEICHENG.equals(v))
if (supplierTypes == null || supplierTypes.isEmpty())
{
return CODE_WEIPAI;
warnings.add(supplierCode + ": 字典 " + DICT_SUPPLIER_TYPE + " 无可用数据,类型置空");
return null;
}
if (TYPE_QINGGUAN.equals(v))
String label = SOURCE_TYPE_LABEL.getOrDefault(v, v);
for (SysDictData dict : supplierTypes)
{
return CODE_QINGGUAN_HANG;
if (dict == null || StringUtils.isEmpty(dict.getDictValue()))
{
continue;
}
if (label.equals(dict.getDictLabel()) || v.equals(dict.getDictLabel()) || v.equals(dict.getDictValue()))
{
return dict.getDictValue();
}
}
warnings.add(supplierCode + ": 未知服务商类型 " + v + ",类型置空");
warnings.add(supplierCode + ": 服务商类型「" + v + "」不在字典 " + DICT_SUPPLIER_TYPE + " 中,类型置空");
return null;
}
@@ -1,112 +0,0 @@
package com.bms.system.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.bms.common.annotation.Excel;
import com.bms.common.core.domain.BaseEntity;
/**
* 供应商类型 bms_supplier_type
* 类型编码与字典 bms_supplier_type 的字典键值一致,供供应商档案引用。
*
* @author bms
*/
public class BmsSupplierType extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 类型ID */
private Long typeId;
/** 类型编码(字典键值) */
@Excel(name = "类型编码")
private String typeCode;
/** 类型名称 */
@Excel(name = "类型名称")
private String typeName;
/** 显示排序 */
@Excel(name = "显示排序")
private Integer typeSort;
/** 状态(0正常 1停用) */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标记(0存在 1删除) */
private String delFlag;
public Long getTypeId()
{
return typeId;
}
public void setTypeId(Long typeId)
{
this.typeId = typeId;
}
public String getTypeCode()
{
return typeCode;
}
public void setTypeCode(String typeCode)
{
this.typeCode = typeCode;
}
public String getTypeName()
{
return typeName;
}
public void setTypeName(String typeName)
{
this.typeName = typeName;
}
public Integer getTypeSort()
{
return typeSort;
}
public void setTypeSort(Integer typeSort)
{
this.typeSort = typeSort;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getDelFlag()
{
return delFlag;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
@Override
public String toString()
{
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("typeId", getTypeId())
.append("typeCode", getTypeCode())
.append("typeName", getTypeName())
.append("typeSort", getTypeSort())
.append("status", getStatus())
.append("remark", getRemark())
.toString();
}
}
@@ -1,112 +0,0 @@
package com.bms.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.bms.system.domain.BmsSupplierType;
/**
* 供应商类型数据层
*
* @author bms
*/
public interface BmsSupplierTypeMapper
{
/**
* 按名称、状态查询供应商类型
*
* @param query 查询条件
* @return 类型列表
*/
List<BmsSupplierType> selectList(BmsSupplierType query);
/**
* 按主键查询未删除的类型
*
* @param typeId 类型ID
* @return 类型
*/
BmsSupplierType selectById(Long typeId);
/**
* 统计未删除的同编码数量
*
* @param typeCode 类型编码
* @param excludeId 排除的类型ID,新增时为空
* @return 数量
*/
int countByTypeCode(@Param("typeCode") String typeCode, @Param("excludeId") Long excludeId);
/**
* 统计未删除的同名称数量
*
* @param typeName 类型名称
* @param excludeId 排除的类型ID,新增时为空
* @return 数量
*/
int countByTypeName(@Param("typeName") String typeName, @Param("excludeId") Long excludeId);
/**
* 新增供应商类型
*
* @param row 类型
* @return 影响行数
*/
int insert(BmsSupplierType row);
/**
* 修改供应商类型(不改编码,避免已引用的供应商失联)
*
* @param row 类型
* @return 影响行数
*/
int update(BmsSupplierType row);
/**
* 只更新启用状态
*
* @param row 含 typeId、status、updateBy
* @return 影响行数
*/
int updateStatus(BmsSupplierType row);
/**
* 逻辑删除
*
* @param typeIds 类型ID
* @return 影响行数
*/
int deleteByIds(Long[] typeIds);
/**
* 按字典类型和键值取字典编码
*
* @param dictType 字典类型
* @param dictValue 字典键值
* @return 字典编码,不存在时为空
*/
Long selectDictCode(@Param("dictType") String dictType, @Param("dictValue") String dictValue);
/**
* 写入字典数据
*
* @param row 类型,字典类型由调用方放入 remark 以外的固定值,见 XML
* @return 影响行数
*/
int insertDict(BmsSupplierType row);
/**
* 按类型编码更新字典标签、排序和状态
*
* @param row 类型
* @return 影响行数
*/
int updateDict(BmsSupplierType row);
/**
* 按类型编码删除字典数据
*
* @param typeCode 类型编码
* @return 影响行数
*/
int deleteDictByCode(String typeCode);
}
@@ -1,60 +0,0 @@
package com.bms.system.service;
import java.util.List;
import com.bms.system.domain.BmsSupplierType;
/**
* 供应商类型服务
*
* @author bms
*/
public interface IBmsSupplierTypeService
{
/**
* 分页前的条件查询,分页由调用方开启
*
* @param query 名称、状态
* @return 类型列表
*/
List<BmsSupplierType> selectList(BmsSupplierType query);
/**
* 查询单个类型
*
* @param typeId 类型ID
* @return 类型
*/
BmsSupplierType selectById(Long typeId);
/**
* 新增类型,并同步字典 bms_supplier_type
*
* @param row 类型
* @return 影响行数
*/
int insert(BmsSupplierType row);
/**
* 修改类型名称、排序、状态、备注,并同步字典
*
* @param row 类型
* @return 影响行数
*/
int update(BmsSupplierType row);
/**
* 启用或停用,并同步字典状态
*
* @param row 含 typeId 与 status
* @return 影响行数
*/
int changeStatus(BmsSupplierType row);
/**
* 逻辑删除,并从字典中移除对应键值
*
* @param typeIds 类型ID
* @return 影响行数
*/
int deleteByIds(Long[] typeIds);
}
@@ -1,232 +0,0 @@
package com.bms.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.bms.common.core.domain.entity.SysDictData;
import com.bms.common.exception.ServiceException;
import com.bms.common.utils.DictUtils;
import com.bms.common.utils.StringUtils;
import com.bms.system.domain.BmsSupplierType;
import com.bms.system.mapper.BmsSupplierTypeMapper;
import com.bms.system.mapper.SysDictDataMapper;
import com.bms.system.service.IBmsSupplierTypeService;
/**
* 供应商类型服务实现。
* 供应商类型服务实现。_DETAIL
*
* @author bms
*/
@Service
public class BmsSupplierTypeServiceImpl implements IBmsSupplierTypeService
{
/** 字典类型,与系统字典管理中的类型编码一致 */
public static final String DICT_TYPE = "bms_supplier_type";
@Autowired
private BmsSupplierTypeMapper supplierTypeMapper;
@Autowired
private SysDictDataMapper dictDataMapper;
@Override
public List<BmsSupplierType> selectList(BmsSupplierType query)
{
return supplierTypeMapper.selectList(query);
}
@Override
public BmsSupplierType selectById(Long typeId)
{
return supplierTypeMapper.selectById(typeId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int insert(BmsSupplierType row)
{
normalize(row);
validate(row, null);
if (row.getTypeSort() == null)
{
row.setTypeSort(0);
}
if (StringUtils.isEmpty(row.getStatus()))
{
row.setStatus("0");
}
int rows = supplierTypeMapper.insert(row);
syncDict(row);
return rows;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int update(BmsSupplierType row)
{
if (row.getTypeId() == null)
{
throw new ServiceException("类型ID不能为空");
}
BmsSupplierType existing = requireActive(row.getTypeId());
normalize(row);
if (StringUtils.isEmpty(row.getTypeName()))
{
row.setTypeName(existing.getTypeName());
}
if (row.getTypeSort() == null)
{
row.setTypeSort(existing.getTypeSort());
}
if (StringUtils.isEmpty(row.getStatus()))
{
row.setStatus(existing.getStatus());
}
validateNameAndStatus(row, row.getTypeId());
row.setTypeCode(existing.getTypeCode());
int rows = supplierTypeMapper.update(row);
syncDict(row);
return rows;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int changeStatus(BmsSupplierType row)
{
if (row.getTypeId() == null)
{
throw new ServiceException("类型ID不能为空");
}
if (!"0".equals(row.getStatus()) && !"1".equals(row.getStatus()))
{
throw new ServiceException("状态只能是正常或停用");
}
BmsSupplierType existing = requireActive(row.getTypeId());
existing.setStatus(row.getStatus());
existing.setUpdateBy(row.getUpdateBy());
int rows = supplierTypeMapper.updateStatus(existing);
syncDict(existing);
return rows;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteByIds(Long[] typeIds)
{
if (typeIds == null || typeIds.length == 0)
{
return 0;
}
for (Long typeId : typeIds)
{
BmsSupplierType existing = supplierTypeMapper.selectById(typeId);
if (existing != null && StringUtils.isNotEmpty(existing.getTypeCode()))
{
supplierTypeMapper.deleteDictByCode(existing.getTypeCode());
}
}
int rows = supplierTypeMapper.deleteByIds(typeIds);
refreshDictCache();
return rows;
}
/**
* 校验编码、名称唯一,并整理状态
*/
private void validate(BmsSupplierType row, Long excludeId)
{
if (StringUtils.isEmpty(row.getTypeCode()))
{
throw new ServiceException("类型编码不能为空");
}
if (!row.getTypeCode().matches("[0-9A-Za-z_-]{1,32}"))
{
throw new ServiceException("类型编码只能是字母、数字、下划线或中划线,最长32位");
}
if (supplierTypeMapper.countByTypeCode(row.getTypeCode(), excludeId) > 0)
{
throw new ServiceException("类型编码已存在:" + row.getTypeCode());
}
validateNameAndStatus(row, excludeId);
}
private void validateNameAndStatus(BmsSupplierType row, Long excludeId)
{
if (StringUtils.isEmpty(row.getTypeName()))
{
throw new ServiceException("类型名称不能为空");
}
if (row.getTypeName().length() > 100)
{
throw new ServiceException("类型名称不能超过100个字符");
}
if (supplierTypeMapper.countByTypeName(row.getTypeName(), excludeId) > 0)
{
throw new ServiceException("类型名称已存在:" + row.getTypeName());
}
if (StringUtils.isNotEmpty(row.getStatus())
&& !"0".equals(row.getStatus()) && !"1".equals(row.getStatus()))
{
throw new ServiceException("状态只能是正常或停用");
}
}
private BmsSupplierType requireActive(Long typeId)
{
BmsSupplierType existing = supplierTypeMapper.selectById(typeId);
if (existing == null)
{
throw new ServiceException("供应商类型不存在或已删除");
}
return existing;
}
private void normalize(BmsSupplierType row)
{
if (row.getTypeCode() != null)
{
row.setTypeCode(row.getTypeCode().trim());
}
if (row.getTypeName() != null)
{
row.setTypeName(row.getTypeName().trim());
}
if (row.getRemark() != null)
{
row.setRemark(row.getRemark().trim());
}
}
/**
* 按类型编码新增或更新字典项,并刷新该字典缓存
*/
private void syncDict(BmsSupplierType row)
{
Long dictCode = supplierTypeMapper.selectDictCode(DICT_TYPE, row.getTypeCode());
if (dictCode == null)
{
if (StringUtils.isEmpty(row.getCreateBy()))
{
row.setCreateBy(row.getUpdateBy());
}
supplierTypeMapper.insertDict(row);
}
else
{
supplierTypeMapper.updateDict(row);
}
refreshDictCache();
}
/**
* 只缓存正常状态的字典项,停用后下拉不再出现
*/
private void refreshDictCache()
{
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(DICT_TYPE);
DictUtils.setDictCache(DICT_TYPE, dictDatas == null ? new ArrayList<SysDictData>() : dictDatas);
}
}