定时任务同步供应商数据

This commit is contained in:
luojiaquan
2026-09-29 11:28:15 +08:00
parent ff57be1116
commit b9746e3801
15 changed files with 660 additions and 13 deletions
@@ -44,10 +44,18 @@ public class BmsSupplier extends BaseEntity
@Excel(name = "统一社会信用代码")
private String creditCode;
/** 供应商类型(0生产商 1代理商 2个人 3物流商 4其他) */
@Excel(name = "供应商类型", readConverterExp = "0=生产商,1=代理商,2=个人,3=物流商,4=其他")
/** 供应商类型(1卡车行 2航司代理 3报关行 4清关行 5尾派服务商 6报关代理) */
@Excel(name = "供应商类型", readConverterExp = "1=卡车行,2=航司代理,3=报关行,4=清关行,5=尾派服务商,6=报关代理")
private String supplierType;
/** 开票类型(1增值税普通发票 2增值税专用发票 3增值税电子普通发票 4其他普通发票) */
@Excel(name = "开票类型", readConverterExp = "1=增值税普通发票,2=增值税专用发票,3=增值税电子普通发票,4=其他普通发票")
private String invoiceType;
/** 卡车行类型(0国内 1国外) */
@Excel(name = "卡车行类型", readConverterExp = "0=国内,1=国外")
private String kacheType;
/** 启用状态(0正常 1停用) */
@Excel(name = "启用状态", readConverterExp = "0=正常,1=停用")
private String isEnable;
@@ -0,0 +1,17 @@
package com.bms.customer.supplierinfo.mapper;
import java.util.List;
import java.util.Map;
/**
* 老系统 Oracle TAB_SUPPLIER 只读查询(SLAVE 数据源,账号只读)
*
* @author bms
*/
public interface OracleSupplierSyncMapper
{
/**
* 全量读取 TAB_SUPPLIER 同步所需列(数据量约数百行,单次读取)
*/
List<Map<String, Object>> selectAllTabSupplier();
}
@@ -0,0 +1,27 @@
package com.bms.customer.supplierinfo.mapper;
import java.util.List;
import com.bms.customer.supplierinfo.domain.BmsSupplier;
/**
* 供应商主表 sup_supplier 同步写库(MASTER 数据源)
*
* @author bms
*/
public interface SupplierSyncMapper
{
/**
* 库中未删除的全部供应商编码,用于判定新增/更新
*/
List<String> selectExistingCodes();
/**
* 新增供应商(同步专用)
*/
int insertSyncSupplier(BmsSupplier supplier);
/**
* 按供应商编码更新供应商(同步专用)
*/
int updateSyncSupplierByCode(BmsSupplier supplier);
}
@@ -0,0 +1,39 @@
package com.bms.customer.supplierinfo.sync;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.bms.common.annotation.DataSource;
import com.bms.common.enums.DataSourceType;
import com.bms.customer.supplierinfo.mapper.OracleSupplierSyncMapper;
/**
* Oracle TAB_SUPPLIER 读取器。
* 走 SLAVE(Oracle 只读账号)数据源;必须独立 Bean,
* 否则 @DataSource 切面在同类自调用时不生效。
*
* @author bms
*/
@Service
public class OracleSupplierReader
{
@Autowired
private OracleSupplierSyncMapper oracleSupplierSyncMapper;
@DataSource(DataSourceType.SLAVE)
public List<Map<String, Object>> readAll()
{
try
{
// 避免 PageHelper 把 Oracle 查询包成分页语句
PageHelper.clearPage();
return oracleSupplierSyncMapper.selectAllTabSupplier();
}
finally
{
PageHelper.clearPage();
}
}
}
@@ -0,0 +1,301 @@
package com.bms.customer.supplierinfo.sync;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bms.common.utils.StringUtils;
import com.bms.customer.supplierinfo.domain.BmsSupplier;
import com.bms.customer.supplierinfo.mapper.SupplierSyncMapper;
/**
* 老系统 Oracle TAB_SUPPLIER -> sup_supplier 每日同步。
*
* 范围:只同步 sup_supplier 现有列能承接的字段;三个类型字段口径完全以 TAB_SUPPLIER 为准
* (供应商类型 SUP_TYPE、开票类型 INVOICE_TYPE、卡车行类型 KACHE_TYPE)。
* 按 supplier_code 判定新增/更新;源为空的非类型字段不写(新增走默认值/更新保留原值)。
*
* @author bms
*/
@Service
public class SupplierSyncService
{
private static final Logger log = LoggerFactory.getLogger(SupplierSyncService.class);
/** 写库人标记,便于事后甄别同步数据 */
public static final String SYNC_MARKER = "oracle-sync";
/** 三个类型字段的合法字典值(以老系统 TAB_SUPPLIER 为准) */
private static final Set<String> SUP_TYPE_CODES = new HashSet<>(Arrays.asList("1", "2", "3", "4", "5", "6"));
private static final Set<String> INVOICE_TYPE_CODES = new HashSet<>(Arrays.asList("1", "2", "3", "4"));
private static final Set<String> KACHE_TYPE_CODES = new HashSet<>(Arrays.asList("0", "1"));
/** sup_supplier 字符串列长度 */
private static final int LEN_CODE = 50;
private static final int LEN_NAME = 100;
private static final int LEN_REMARK = 500;
/** 告警明细最多打印条数 */
private static final int WARN_LOG_LIMIT = 50;
@Autowired
private OracleSupplierReader oracleSupplierReader;
@Autowired
private SupplierSyncWriter supplierSyncWriter;
@Autowired
private SupplierSyncMapper supplierSyncMapper;
/**
* 执行一次全量同步。
*
* @return 同步结果摘要
*/
public String syncFromOracle()
{
long t0 = System.currentTimeMillis();
List<Map<String, Object>> rows = oracleSupplierReader.readAll();
Set<String> existingCodes = new HashSet<>(supplierSyncMapper.selectExistingCodes());
List<BmsSupplier> inserts = new ArrayList<>();
List<BmsSupplier> updates = new ArrayList<>();
Set<String> seenCodes = new HashSet<>();
int blankRows = 0;
List<String> errors = new ArrayList<>();
List<String> warnings = new ArrayList<>();
for (int i = 0; i < rows.size(); i++)
{
int rowNo = i + 1;
Map<String, Object> row = rows.get(i);
String code = clean(getStr(row, "SUP_CODE"));
String name = clean(getStr(row, "SUP_NAME"));
if (code == null && name == null)
{
blankRows++;
continue;
}
if (code == null)
{
errors.add("行" + rowNo + ": SUP_CODE 为空,跳过");
continue;
}
if (name == null)
{
errors.add("行" + rowNo + " " + code + ": SUP_NAME 为空,跳过");
continue;
}
if (!seenCodes.add(code))
{
errors.add("行" + rowNo + " " + code + ": Oracle 源内编码重复,跳过");
continue;
}
BmsSupplier s = mapRow(row, code, name, warnings);
if (existingCodes.contains(code))
{
s.setUpdateBy(SYNC_MARKER);
s.setUpdateTime(new Date());
updates.add(s);
}
else
{
s.setCreateBy(SYNC_MARKER);
inserts.add(s);
}
}
int[] written = supplierSyncWriter.writeBatch(inserts, updates);
long costMs = System.currentTimeMillis() - t0;
String summary = String.format(
"Oracle供应商同步完成:源行 %d,空行 %d,新增 %d,更新 %d,跳过错误 %d,告警 %d,耗时 %dms",
rows.size(), blankRows, written[0], written[1], errors.size(), warnings.size(), costMs);
log.info(summary);
errors.forEach(e -> log.warn(" 同步跳过: {}", e));
warnings.stream().limit(WARN_LOG_LIMIT).forEach(w -> log.warn(" 同步告警: {}", w));
if (warnings.size() > WARN_LOG_LIMIT)
{
log.warn(" 其余 {} 条告警略", warnings.size() - WARN_LOG_LIMIT);
}
if (!errors.isEmpty())
{
log.warn("同步存在 {} 条跳过记录,请核对 TAB_SUPPLIER 源数据", errors.size());
}
return summary;
}
/**
* 单行映射
*/
private BmsSupplier mapRow(Map<String, Object> row, String code, String name, 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(toCode(row, "SUP_TYPE", SUP_TYPE_CODES, code, "供应商类型", warnings));
s.setInvoiceType(toCode(row, "INVOICE_TYPE", INVOICE_TYPE_CODES, code, "开票类型", warnings));
s.setKacheType(toCode(row, "KACHE_TYPE", KACHE_TYPE_CODES, code, "卡车行类型", warnings));
s.setIsEnable(mapEnable(getStr(row, "BL_OPEN")));
s.setEd(toDecimal(row, "QUOTA", code, warnings));
Long period = toLong(row, "SETTLEMENT_PERIOD", code, warnings);
s.setZq(period);
s.setRemark(truncate(getStr(row, "REMARK"), LEN_REMARK, code, "remark", warnings));
Date createTime = getDate(row, "CREATE_TIME");
s.setCreateTime(createTime);
return s;
}
/** BL_OPEN:1启用 -> is_enable=0(正常);0停用 -> 1;空按正常 */
private static String mapEnable(String v)
{
String s = clean(v);
if (s == null)
{
return "0";
}
return "1".equals(s) ? "0" : "1";
}
/**
* Oracle NUMBER(1) 经 JDBC 多为 BigDecimal(String.valueOf 可能带 ".0"),
* 统一按整数取值后校验字典合法性;源为 null 返回 null(更新时以源为准置空)。
*/
private static String toCode(Map<String, Object> row, String key, Set<String> validCodes,
String supplierCode, String label, List<String> warnings)
{
Object v = getIgnoreCase(row, key);
if (v == null || StringUtils.isEmpty(String.valueOf(v).trim()))
{
return null;
}
String code;
if (v instanceof Number)
{
code = String.valueOf(((Number) v).longValue());
}
else
{
code = String.valueOf(v).trim();
int dot = code.indexOf('.');
if (dot >= 0)
{
code = code.substring(0, dot);
}
}
if (!validCodes.contains(code))
{
warnings.add(supplierCode + ": 未知" + label + " " + v + ",该类型置空");
return null;
}
return code;
}
private static String clean(String v)
{
if (v == null)
{
return null;
}
String s = v.trim();
return s.isEmpty() ? null : s;
}
/**
* 超长截断并记告警(夜间无人值守,截断比整行失败更稳)
*/
private static String truncate(String value, int maxLen, String code, String column, List<String> warnings)
{
String s = clean(value);
if (s != null && s.length() > maxLen)
{
warnings.add(String.format("%s: %s 超长(%d>%d)已截断: %s...", code, column, s.length(), maxLen, s.substring(0, 20)));
s = s.substring(0, maxLen);
}
return s;
}
private static BigDecimal toDecimal(Map<String, Object> row, String key, String code, List<String> warnings)
{
Object v = getIgnoreCase(row, key);
if (v == null || StringUtils.isEmpty(String.valueOf(v).trim()))
{
return null;
}
try
{
BigDecimal d = (v instanceof BigDecimal) ? (BigDecimal) v
: (v instanceof Number ? BigDecimal.valueOf(((Number) v).doubleValue())
: new BigDecimal(String.valueOf(v).trim()));
return d.setScale(2, RoundingMode.HALF_UP);
}
catch (Exception e)
{
warnings.add(code + ": 字段 " + key + " 非法数值 " + v + ",该字段不写入");
return null;
}
}
private static Long toLong(Map<String, Object> row, String key, String code, List<String> warnings)
{
Object v = getIgnoreCase(row, key);
if (v == null || StringUtils.isEmpty(String.valueOf(v).trim()))
{
return null;
}
try
{
return (v instanceof Number) ? ((Number) v).longValue() : Long.parseLong(String.valueOf(v).trim());
}
catch (Exception e)
{
warnings.add(code + ": 字段 " + key + " 非法整数 " + v + ",该字段不写入");
return null;
}
}
private static Date getDate(Map<String, Object> row, String key)
{
Object v = getIgnoreCase(row, key);
return (v instanceof Date) ? (Date) v : null;
}
private static String getStr(Map<String, Object> row, String key)
{
Object v = getIgnoreCase(row, key);
return v == null ? null : String.valueOf(v);
}
/** Oracle HashMap 列名按大写返回,这里做兼容查找 */
private static Object getIgnoreCase(Map<String, Object> row, String key)
{
if (row.containsKey(key))
{
return row.get(key);
}
for (Map.Entry<String, Object> e : row.entrySet())
{
if (e.getKey() != null && e.getKey().equalsIgnoreCase(key))
{
return e.getValue();
}
}
return null;
}
}
@@ -0,0 +1,40 @@
package com.bms.customer.supplierinfo.sync;
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.customer.supplierinfo.domain.BmsSupplier;
import com.bms.customer.supplierinfo.mapper.SupplierSyncMapper;
/**
* 供应商同步写库器(MASTER 数据源,整批一个事务)。
* 独立 Bean:保证 @Transactional 经代理生效,且与 SLAVE 读连接隔离。
*
* @author bms
*/
@Service
public class SupplierSyncWriter
{
@Autowired
private SupplierSyncMapper supplierSyncMapper;
/**
* @return 实际写入行数(新增+更新);任一行 SQL 失败整批回滚
*/
@Transactional(rollbackFor = Exception.class)
public int[] writeBatch(List<BmsSupplier> inserts, List<BmsSupplier> updates)
{
int insertCount = 0;
int updateCount = 0;
for (BmsSupplier s : inserts)
{
insertCount += supplierSyncMapper.insertSyncSupplier(s);
}
for (BmsSupplier s : updates)
{
updateCount += supplierSyncMapper.updateSyncSupplierByCode(s);
}
return new int[] {insertCount, updateCount};
}
}
@@ -0,0 +1,25 @@
package com.bms.customer.supplierinfo.task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.bms.customer.supplierinfo.sync.SupplierSyncService;
/**
* 老系统供应商资料定时同步任务(sys_job 调用目标:supplierSyncTask.syncFromOracle)
*
* @author bms
*/
@Component("supplierSyncTask")
public class SupplierSyncTask
{
@Autowired
private SupplierSyncService supplierSyncService;
/**
* 每天 00:00 从 Oracle TAB_SUPPLIER 全量同步供应商主数据到 sup_supplier
*/
public void syncFromOracle()
{
supplierSyncService.syncFromOracle();
}
}
@@ -11,6 +11,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="supplierCodeDw" column="supplier_code_dw" />
<result property="creditCode" column="credit_code" />
<result property="supplierType" column="supplier_type" />
<result property="invoiceType" column="invoice_type" />
<result property="kacheType" column="kache_type" />
<result property="isEnable" column="is_enable" />
<result property="purchaserUserId" column="purchaser_user_id" />
<result property="purchaserUser" column="purchaser_user" />
@@ -40,6 +42,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectBmsSupplierVo">
select s.supplier_id, s.supplier_code, s.supplier_name, s.supplier_code_dw, s.credit_code, s.supplier_type,
s.invoice_type, s.kache_type,
s.is_enable, s.purchaser_user_id, s.purchaser_user, s.settlement_user_id, s.settlement_user,
s.service_user_id, s.service_user, s.ed, s.zq, s.settlement_type, s.temp_ed, s.account_balance,
s.foreign_currency_balance, s.credit_ed, s.weight_threshold, s.throw_ratio, s.cooperation_start_date,
@@ -59,6 +62,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="supplierCodeDw != null and supplierCodeDw != ''"> and s.supplier_code_dw = #{supplierCodeDw}</if>
<if test="creditCode != null and creditCode != ''"> and s.credit_code = #{creditCode}</if>
<if test="supplierType != null and supplierType != ''"> and s.supplier_type = #{supplierType}</if>
<if test="invoiceType != null and invoiceType != ''"> and s.invoice_type = #{invoiceType}</if>
<if test="kacheType != null and kacheType != ''"> and s.kache_type = #{kacheType}</if>
<if test="isEnable != null and isEnable != ''"> and s.is_enable = #{isEnable}</if>
<if test="purchaserUserId != null and purchaserUserId != ''"> and s.purchaser_user_id = #{purchaserUserId}</if>
<if test="purchaserUser != null and purchaserUser != ''"> and s.purchaser_user = #{purchaserUser}</if>
@@ -86,6 +91,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="supplierCodeDw != null">supplier_code_dw,</if>
<if test="creditCode != null">credit_code,</if>
<if test="supplierType != null">supplier_type,</if>
<if test="invoiceType != null">invoice_type,</if>
<if test="kacheType != null">kache_type,</if>
<if test="isEnable != null">is_enable,</if>
<if test="purchaserUserId != null">purchaser_user_id,</if>
<if test="purchaserUser != null">purchaser_user,</if>
@@ -116,6 +123,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="supplierCodeDw != null">#{supplierCodeDw},</if>
<if test="creditCode != null">#{creditCode},</if>
<if test="supplierType != null">#{supplierType},</if>
<if test="invoiceType != null">#{invoiceType},</if>
<if test="kacheType != null">#{kacheType},</if>
<if test="isEnable != null">#{isEnable},</if>
<if test="purchaserUserId != null">#{purchaserUserId},</if>
<if test="purchaserUser != null">#{purchaserUser},</if>
@@ -150,6 +159,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="supplierCodeDw != null">supplier_code_dw = #{supplierCodeDw},</if>
<if test="creditCode != null">credit_code = #{creditCode},</if>
<if test="supplierType != null">supplier_type = #{supplierType},</if>
<if test="invoiceType != null">invoice_type = #{invoiceType},</if>
<if test="kacheType != null">kache_type = #{kacheType},</if>
<if test="isEnable != null">is_enable = #{isEnable},</if>
purchaser_user_id = #{purchaserUserId},
purchaser_user = #{purchaserUser},
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bms.customer.supplierinfo.mapper.OracleSupplierSyncMapper">
<!-- 老系统供应商主表全量读取;只取 sup_supplier 能承接的列。
三个类型字段口径以 TAB_SUPPLIER 为准:
SUP_TYPE 1卡车行 2航司代理 3报关行 4清关行 5尾派服务商 6报关代理
INVOICE_TYPE 1增普 2增专 3电普 4其他普票;KACHE_TYPE 0国内 1国外 -->
<select id="selectAllTabSupplier" resultType="java.util.HashMap" fetchSize="500">
SELECT SUP_CODE, SUP_NAME, SUP_TYPE, INVOICE_TYPE, KACHE_TYPE,
BL_OPEN, QUOTA, SETTLEMENT_PERIOD, REMARK, CREATE_TIME
FROM WEISHI_USER.TAB_SUPPLIER
</select>
</mapper>
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bms.customer.supplierinfo.mapper.SupplierSyncMapper">
<select id="selectExistingCodes" resultType="java.lang.String">
SELECT supplier_code FROM sup_supplier WHERE del_flag = '0'
</select>
<insert id="insertSyncSupplier" parameterType="com.bms.customer.supplierinfo.domain.BmsSupplier">
INSERT INTO sup_supplier (
supplier_code, supplier_name, is_enable, del_flag, create_by
<if test="supplierType != null">, supplier_type</if>
<if test="invoiceType != null">, invoice_type</if>
<if test="kacheType != null">, kache_type</if>
<if test="ed != null">, ed</if>
<if test="zq != null">, zq</if>
<if test="remark != null">, remark</if>
<if test="createTime != null">, create_time</if>
) VALUES (
#{supplierCode}, #{supplierName}, #{isEnable}, '0', #{createBy}
<if test="supplierType != null">, #{supplierType}</if>
<if test="invoiceType != null">, #{invoiceType}</if>
<if test="kacheType != null">, #{kacheType}</if>
<if test="ed != null">, #{ed}</if>
<if test="zq != null">, #{zq}</if>
<if test="remark != null">, #{remark}</if>
<if test="createTime != null">, #{createTime}</if>
)
</insert>
<update id="updateSyncSupplierByCode" parameterType="com.bms.customer.supplierinfo.domain.BmsSupplier">
UPDATE sup_supplier
SET supplier_name = #{supplierName}
, is_enable = #{isEnable}
, supplier_type = #{supplierType}
, invoice_type = #{invoiceType}
, kache_type = #{kacheType}
<if test="ed != null">, ed = #{ed}</if>
<if test="zq != null">, zq = #{zq}</if>
<if test="remark != null">, remark = #{remark}</if>
, update_by = #{updateBy}
, update_time = #{updateTime}
WHERE supplier_code = #{supplierCode} AND del_flag = '0'
</update>
</mapper>
+3 -1
View File
@@ -1717,7 +1717,9 @@ CREATE TABLE `sup_supplier` (
`supplier_name` varchar(100) NOT NULL COMMENT '供应商名称',
`supplier_code_dw` varchar(50) DEFAULT '' COMMENT '对外代码',
`credit_code` varchar(18) DEFAULT '' COMMENT '统一社会信用代码',
`supplier_type` char(1) DEFAULT '0' COMMENT '供应商类型(0生产商 1代理商 2个人 3物流商 4其他)',
`supplier_type` char(1) DEFAULT NULL COMMENT '供应商类型(1卡车行 2航司代理 3报关行 4清关行 5尾派服务商 6报关代理)',
`invoice_type` char(1) DEFAULT NULL COMMENT '开票类型(1增值税普通发票 2增值税专用发票 3增值税电子普通发票 4其他普通发票)',
`kache_type` char(1) DEFAULT NULL COMMENT '卡车行类型(0国内 1国外)',
`is_enable` char(1) DEFAULT '0' COMMENT '启用状态(0正常 1停用)',
`purchaser_user_id` varchar(64) DEFAULT '' COMMENT '采购员用户ID',
`purchaser_user` varchar(50) DEFAULT '' COMMENT '采购员姓名',
@@ -0,0 +1,20 @@
-- ============================================================
-- 供应商 Oracle(TAB_SUPPLIER) 定时同步 —— sup_supplier 三个类型字段对齐
-- 日期:2026-09-29
-- 字典口径以老系统 TAB_SUPPLIER 为准:
-- supplier_type 供应商类型(已有列,改口径):1卡车行 2航司代理 3报关行 4清关行 5尾派服务商 6报关代理
-- invoice_type 开票类型(新增列):1增值税普通发票 2增值税专用发票 3增值税电子普通发票 4其他普通发票
-- kache_type 卡车行类型(新增列):0国内 1国外
-- ============================================================
-- 1. supplier_type:旧口径(0生产商 1代理商 2个人 3物流商 4其他)废弃,默认值放开为 NULL
ALTER TABLE `sup_supplier`
MODIFY COLUMN `supplier_type` char(1) DEFAULT NULL COMMENT '供应商类型(1卡车行 2航司代理 3报关行 4清关行 5尾派服务商 6报关代理)';
-- 2. invoice_type 开票类型(新增)
ALTER TABLE `sup_supplier`
ADD COLUMN `invoice_type` char(1) DEFAULT NULL COMMENT '开票类型(1增值税普通发票 2增值税专用发票 3增值税电子普通发票 4其他普通发票)' AFTER `supplier_type`;
-- 3. kache_type 卡车行类型(新增)
ALTER TABLE `sup_supplier`
ADD COLUMN `kache_type` char(1) DEFAULT NULL COMMENT '卡车行类型(0国内 1国外)' AFTER `invoice_type`;
@@ -0,0 +1,13 @@
-- ----------------------------
-- 定时任务:老系统 Oracle TAB_SUPPLIER -> sup_supplier 供应商资料每日同步
-- 调用目标对应 Bean:com.bms.customer.supplierinfo.task.SupplierSyncTask#syncFromOracle
-- cron 0 0 0 * * ? = 每天 00:00:00;concurrent=1 禁止并发;misfire=3 放弃错过的执行
-- 幂等:按 supplier_code 新增/更新,可重复执行
-- ----------------------------
INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression,
misfire_policy, concurrent, status, create_by, create_time, remark)
SELECT '老系统供应商资料每日同步', 'DEFAULT', 'supplierSyncTask.syncFromOracle()', '0 0 0 * * ?',
'3', '1', '0', 'admin', NOW(),
'每天00:00从Oracle(WSDB.TAB_SUPPLIER,只读账号)全量同步供应商主数据到sup_supplier;供应商/开票/卡车行类型以老系统为准;写库标记 create_by/update_by=oracle-sync'
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM sys_job WHERE invoke_target = 'supplierSyncTask.syncFromOracle()');
@@ -26,6 +26,39 @@
/>
</el-form-item>
<el-form-item label="供应商类型" prop="supplierType">
<el-select
v-model="queryParams.supplierType"
placeholder="请选择供应商类型"
clearable
@change="handleQuery"
>
<el-option v-for="item in supplierTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="开票类型" prop="invoiceType">
<el-select
v-model="queryParams.invoiceType"
placeholder="请选择开票类型"
clearable
@change="handleQuery"
>
<el-option v-for="item in invoiceTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="卡车行类型" prop="kacheType">
<el-select
v-model="queryParams.kacheType"
placeholder="请选择卡车行类型"
clearable
@change="handleQuery"
>
<el-option v-for="item in kacheTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="启用状态" prop="isEnable">
<el-select
v-model="queryParams.isEnable"
@@ -108,6 +141,12 @@
<el-table-column v-if="isColVisible('supplierType')" label="供应商类型" align="center" prop="supplierType">
<template #default="scope">{{ formatOption(supplierTypeOptions, scope.row.supplierType) }}</template>
</el-table-column>
<el-table-column v-if="isColVisible('invoiceType')" label="开票类型" align="center" prop="invoiceType">
<template #default="scope">{{ formatOption(invoiceTypeOptions, scope.row.invoiceType) }}</template>
</el-table-column>
<el-table-column v-if="isColVisible('kacheType')" label="卡车行类型" align="center" prop="kacheType">
<template #default="scope">{{ formatOption(kacheTypeOptions, scope.row.kacheType) }}</template>
</el-table-column>
<el-table-column v-if="isColVisible('isEnable')" label="启用状态" align="center" prop="isEnable">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.isEnable" />
@@ -174,6 +213,8 @@ const columnDefs = [
{ key: 'supplierCodeDw', label: '对外代码' },
{ key: 'creditCode', label: '统一社会信用代码' },
{ key: 'supplierType', label: '供应商类型' },
{ key: 'invoiceType', label: '开票类型' },
{ key: 'kacheType', label: '卡车行类型' },
{ key: 'isEnable', label: '启用状态' },
{ key: 'purchaserUserId', label: '采购员' },
{ key: 'ed', label: '应付额度' },
@@ -205,11 +246,22 @@ const total = ref(0)
const { sys_normal_disable, settlement_type } = useDict("sys_normal_disable", "settlement_type")
const supplierTypeOptions = ref([
{ value: "0", label: "生产商" },
{ value: "1", label: "代理商" },
{ value: "2", label: "个人" },
{ value: "3", label: "物流商" },
{ value: "4", label: "其他" }
{ value: "1", label: "卡车行" },
{ value: "2", label: "航司代理" },
{ value: "3", label: "报关行" },
{ value: "4", label: "清关行" },
{ value: "5", label: "尾派服务商" },
{ value: "6", label: "报关代理" }
])
const invoiceTypeOptions = ref([
{ value: "1", label: "增值税普通发票" },
{ value: "2", label: "增值税专用发票" },
{ value: "3", label: "增值税电子普通发票" },
{ value: "4", label: "其他普通发票" }
])
const kacheTypeOptions = ref([
{ value: "0", label: "国内" },
{ value: "1", label: "国外" }
])
const cooperationStatusOptions = ref([
{ value: "0", label: "正常" },
@@ -238,6 +290,8 @@ const data = reactive({
supplierCodeDw: undefined,
creditCode: undefined,
supplierType: undefined,
invoiceType: undefined,
kacheType: undefined,
isEnable: undefined,
purchaserUserId: undefined,
purchaserUser: undefined,
@@ -55,6 +55,20 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开票类型" prop="invoiceType">
<el-select v-model="form.invoiceType" placeholder="请选择开票类型" clearable style="width: 100%;">
<el-option v-for="opt in invoiceTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="卡车行类型" prop="kacheType">
<el-select v-model="form.kacheType" placeholder="请选择卡车行类型" clearable style="width: 100%;">
<el-option v-for="opt in kacheTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="启用状态" prop="isEnable">
<el-select v-model="form.isEnable" placeholder="请选择启用状态" clearable style="width: 100%;">
@@ -595,11 +609,22 @@ const rules = {
}
const supplierTypeOptions = ref([
{ value: '0', label: '生产商' },
{ value: '1', label: '代理商' },
{ value: '2', label: '个人' },
{ value: '3', label: '物流商' },
{ value: '4', label: '其他' }
{ value: '1', label: '卡车行' },
{ value: '2', label: '航司代理' },
{ value: '3', label: '报关行' },
{ value: '4', label: '清关行' },
{ value: '5', label: '尾派服务商' },
{ value: '6', label: '报关代理' }
])
const invoiceTypeOptions = ref([
{ value: '1', label: '增值税普通发票' },
{ value: '2', label: '增值税专用发票' },
{ value: '3', label: '增值税电子普通发票' },
{ value: '4', label: '其他普通发票' }
])
const kacheTypeOptions = ref([
{ value: '0', label: '国内' },
{ value: '1', label: '国外' }
])
const cooperationStatusOptions = ref([
{ value: '0', label: '正常' },
@@ -616,6 +641,8 @@ function buildEmptyForm() {
supplierCodeDw: null,
creditCode: null,
supplierType: null,
invoiceType: null,
kacheType: null,
isEnable: null,
purchaserUserId: null,
purchaserUser: null,