增加提单功能

This commit is contained in:
wuweihua
2026-11-03 17:50:35 +08:00
parent c87f49a14b
commit 98ae525403
14 changed files with 1087 additions and 0 deletions
@@ -0,0 +1,36 @@
package com.bms.price.airbill.domain;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/** 空运提单主表 srv_bill_air */
@Data
public class SrvBillAir
{
private String guid;
private String billCode;
private Integer billType;
private Integer blStatus;
private Integer warningStatus;
private Integer warningCount;
private String startAirport;
private String endAirport;
private String desPort;
private String routeName;
private String airType;
private Integer pieceNumber;
private BigDecimal volume;
private BigDecimal actualWeight;
private BigDecimal actualVolume;
private BigDecimal volumeWeight;
private String airCompany;
private String sendManCode;
private String acceptManCode;
private String dataFrom;
private String createManCode;
private Date createTime;
private String modifierCode;
private Date modifyTime;
private String remark;
}
@@ -0,0 +1,31 @@
package com.bms.price.airbill.domain;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/** 空运提单财务表 srv_bill_air_finance */
@Data
public class SrvBillAirFinance
{
private String guid;
private String billCode;
private Integer blCheck;
private String checkRemark;
private Integer blConfirm;
private String confirmManCode;
private Date confirmTime;
private BigDecimal price;
private BigDecimal amount;
private String calcExp;
private String calcRe;
private String priceRemark;
private BigDecimal baoguanFee;
private BigDecimal baoguanOtherFee;
private BigDecimal stockFee;
private BigDecimal desPortAgentFee;
private BigDecimal airOtherFee;
private BigDecimal otherFee;
private String compensateRemark;
private String chargeManCode;
}
@@ -0,0 +1,26 @@
package com.bms.price.airbill.domain;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/** 空运航班干线表 srv_bill_air_flight */
@Data
public class SrvBillAirFlight
{
private String guid;
private String billCode;
private String airNo;
private String actualAirNo;
private String airOmpanyAgent;
private String desPortAgentCode;
private String boardNo;
private Integer bandBoxCount;
private BigDecimal bandVolume;
private BigDecimal bandBoxWeight;
private BigDecimal divisorValue;
private Date firstLandingTime;
private Date secondTakeoffTime;
private Date airDelayTime;
private String trunkDestinations;
}
@@ -0,0 +1,31 @@
package com.bms.price.airbill.domain;
import java.util.Date;
import lombok.Data;
/** 空运提单操作派送表 srv_bill_air_op */
@Data
public class SrvBillAirOp
{
private String guid;
private String billCode;
private Integer blRetrieval;
private Date retrievalDate;
private String retrievalManCode;
private Integer pickBoxCount;
private Integer pickCountReal;
private String declareCode;
private String clearanceCode;
private String qingguanAgent;
private String clearanceOpCode;
private String stockAddr;
private String stockOutRemark;
private Integer deliverCount;
private Integer firstDeliverCount;
private Integer lastDeliverCount;
private String acDeliverDiff;
private String deliverEndDiff;
private Integer checkOrderCount;
private Integer checkLeaveCount;
private Date internalCheckTime;
}
@@ -0,0 +1,50 @@
package com.bms.price.airbill.domain;
import java.util.Date;
import lombok.Data;
/** 空运提单时效轨迹表 srv_bill_air_track */
@Data
public class SrvBillAirTrack
{
private String guid;
private String billCode;
private Date startTimePlan;
private Date arriveTimePlan;
private Date shippingDate;
private Date startTime;
private Date arriveTime;
private Date arriveStockTime;
private Date clearanceTime;
private Date endOprateTime;
private Integer blBgfx;
private Date bgfxTime;
private Date updateTimeBgfx;
private Integer blSjqf;
private Date sjqfTime;
private Date updateTimeSjqf;
private Integer blSjdd;
private Date sjddTime;
private Date updateTimeSjdd;
private Integer blTzdc;
private Date tzdcTime;
private String updateTimeTzdc;
private Integer blThdc;
private Date thdcTime;
private Date updateTimeThdc;
private Integer blQgwc;
private Date qgwcTime;
private Date updateTimeQgwc;
private Integer blGxfc;
private Date gxfcTime;
private String updateTimeGxfc;
private Integer blFjh;
private Date fjhTime;
private String updateTimeFjh;
private Integer blTrackGenBg;
private Integer blTrackGenBgfx;
private Integer blTrackGenQf;
private Integer blTrackGenDd;
private Integer blTrackGenQg;
private Integer blTrackGenDc;
}
@@ -0,0 +1,12 @@
package com.bms.price.airbill.mapper;
import java.util.List;
import java.util.Map;
/**
* Oracle WEISHI_USER.TAB_BILL_AIR 只读
*/
public interface OracleBillAirMapper
{
List<Map<String, Object>> selectAllBillAir();
}
@@ -0,0 +1,25 @@
package com.bms.price.airbill.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.bms.price.airbill.domain.SrvBillAir;
import com.bms.price.airbill.domain.SrvBillAirFinance;
import com.bms.price.airbill.domain.SrvBillAirFlight;
import com.bms.price.airbill.domain.SrvBillAirOp;
import com.bms.price.airbill.domain.SrvBillAirTrack;
/**
* 空运提单镜像表 upsert
*/
public interface SrvBillAirSyncMapper
{
int upsertBillAir(@Param("list") List<SrvBillAir> list);
int upsertBillAirFinance(@Param("list") List<SrvBillAirFinance> list);
int upsertBillAirFlight(@Param("list") List<SrvBillAirFlight> list);
int upsertBillAirOp(@Param("list") List<SrvBillAirOp> list);
int upsertBillAirTrack(@Param("list") List<SrvBillAirTrack> list);
}
@@ -0,0 +1,322 @@
package com.bms.price.airbill.sync;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bms.price.airbill.domain.SrvBillAir;
import com.bms.price.airbill.domain.SrvBillAirFinance;
import com.bms.price.airbill.domain.SrvBillAirFlight;
import com.bms.price.airbill.domain.SrvBillAirOp;
import com.bms.price.airbill.domain.SrvBillAirTrack;
/**
* Oracle TAB_BILL_AIR -> srv_bill_air* 全量同步编排(按 guid 幂等 upsert)
*/
@Service
public class BillAirSyncService
{
private static final Logger log = LoggerFactory.getLogger(BillAirSyncService.class);
@Autowired
private OracleBillAirReader reader;
@Autowired
private BillAirSyncWriter writer;
public String syncFromOracle()
{
long start = System.currentTimeMillis();
List<Map<String, Object>> rows = reader.readAll();
List<SrvBillAir> airList = new ArrayList<>(rows.size());
List<SrvBillAirFinance> financeList = new ArrayList<>(rows.size());
List<SrvBillAirFlight> flightList = new ArrayList<>(rows.size());
List<SrvBillAirOp> opList = new ArrayList<>(rows.size());
List<SrvBillAirTrack> trackList = new ArrayList<>(rows.size());
int skip = 0;
for (Map<String, Object> row : rows)
{
String guid = str(row, "GUID");
String billCode = str(row, "BILL_CODE");
if (guid == null || billCode == null)
{
skip++;
continue;
}
airList.add(toAir(row, guid, billCode));
financeList.add(toFinance(row, guid, billCode));
flightList.add(toFlight(row, guid, billCode));
opList.add(toOp(row, guid, billCode));
trackList.add(toTrack(row, guid, billCode));
}
int airN = writer.writeAir(airList);
int finN = writer.writeFinance(financeList);
int flightN = writer.writeFlight(flightList);
int opN = writer.writeOp(opList);
int trackN = writer.writeTrack(trackList);
String summary = String.format(
"billAir sync done: oracle=%d skip=%d air=%d finance=%d flight=%d op=%d track=%d costMs=%d",
rows.size(), skip, airN, finN, flightN, opN, trackN, System.currentTimeMillis() - start);
log.info(summary);
return summary;
}
private static SrvBillAir toAir(Map<String, Object> row, String guid, String billCode)
{
SrvBillAir a = new SrvBillAir();
a.setGuid(guid);
a.setBillCode(billCode);
a.setBillType(integer(row, "BILL_TYPE"));
a.setBlStatus(integer(row, "BL_STATUS"));
a.setWarningStatus(integer(row, "WARNING_STATUS"));
a.setWarningCount(integer(row, "WARNING_COUNT"));
a.setStartAirport(str(row, "START_AIRPORT"));
a.setEndAirport(str(row, "END_AIRPORT"));
a.setDesPort(str(row, "DES_PORT"));
a.setRouteName(str(row, "ROUTE_NAME"));
a.setAirType(str(row, "AIR_TYPE"));
a.setPieceNumber(integer(row, "PIECE_NUMBER"));
a.setVolume(decimal(row, "VOLUME"));
a.setActualWeight(decimal(row, "ACTUAL_WEIGHT"));
a.setActualVolume(decimal(row, "ACTUAL_VOLUME"));
a.setVolumeWeight(decimal(row, "VOLUME_WEIGHT"));
a.setAirCompany(str(row, "AIR_COMPANY"));
a.setSendManCode(str(row, "SEND_MAN_CODE"));
a.setAcceptManCode(str(row, "ACCEPT_MAN_CODE"));
a.setDataFrom(str(row, "DATA_FROM"));
a.setCreateManCode(str(row, "CREATE_MAN_CODE"));
a.setCreateTime(date(row, "CREATE_TIME"));
a.setModifierCode(str(row, "MODIFIER_CODE"));
a.setModifyTime(date(row, "MODIFY_TIME"));
a.setRemark(str(row, "REMARK"));
return a;
}
private static SrvBillAirFinance toFinance(Map<String, Object> row, String guid, String billCode)
{
SrvBillAirFinance f = new SrvBillAirFinance();
f.setGuid(guid);
f.setBillCode(billCode);
f.setBlCheck(integer(row, "BL_CHECK"));
f.setCheckRemark(str(row, "CHECK_REMARK"));
f.setBlConfirm(integer(row, "BL_CONFIRM"));
f.setConfirmManCode(str(row, "CONFIRM_MAN_CODE"));
f.setConfirmTime(date(row, "CONFIRM_TIME"));
f.setPrice(decimal(row, "PRICE"));
f.setAmount(decimal(row, "AMOUNT"));
f.setCalcExp(str(row, "CALC_EXP"));
f.setCalcRe(asText(row, "CALC_RE"));
f.setPriceRemark(str(row, "PRICE_REMARK"));
f.setBaoguanFee(decimal(row, "BAOGUAN_FEE"));
f.setBaoguanOtherFee(decimal(row, "BAOGUAN_OTHER_FEE"));
f.setStockFee(decimal(row, "STOCK_FEE"));
f.setDesPortAgentFee(decimal(row, "DES_PORT_AGENT_FEE"));
f.setAirOtherFee(decimal(row, "AIR_OTHER_FEE"));
f.setOtherFee(decimal(row, "OTHER_FEE"));
f.setCompensateRemark(str(row, "COMPENSATE_REMARK"));
f.setChargeManCode(str(row, "CHARGE_MAN_CODE"));
return f;
}
private static SrvBillAirFlight toFlight(Map<String, Object> row, String guid, String billCode)
{
SrvBillAirFlight fl = new SrvBillAirFlight();
fl.setGuid(guid);
fl.setBillCode(billCode);
fl.setAirNo(str(row, "AIR_NO"));
fl.setActualAirNo(str(row, "ACTUAL_AIR_NO"));
fl.setAirOmpanyAgent(str(row, "AIR_OMPANY_AGENT"));
fl.setDesPortAgentCode(str(row, "DES_PORT_AGENT"));
fl.setBoardNo(str(row, "BOARD_NO"));
fl.setBandBoxCount(integer(row, "BAND_BOX_COUNT"));
fl.setBandVolume(decimal(row, "BAND_VOLUME"));
fl.setBandBoxWeight(decimal(row, "BAND_BOX_WEIGHT"));
fl.setDivisorValue(decimal(row, "DIVISOR_VALUE"));
fl.setFirstLandingTime(date(row, "FIRST_LANDING_TIME"));
fl.setSecondTakeoffTime(date(row, "SECOND_TAKEOFF_TIME"));
fl.setAirDelayTime(date(row, "AIR_DELAY_TIME"));
fl.setTrunkDestinations(str(row, "TRUNK_DESTINATIONS"));
return fl;
}
private static SrvBillAirOp toOp(Map<String, Object> row, String guid, String billCode)
{
SrvBillAirOp o = new SrvBillAirOp();
o.setGuid(guid);
o.setBillCode(billCode);
o.setBlRetrieval(integer(row, "BL_RETRIEVAL"));
o.setRetrievalDate(date(row, "RETRIEVAL_DATE"));
o.setRetrievalManCode(str(row, "RETRIEVAL_MAN_CODE"));
o.setPickBoxCount(integer(row, "PICK_BOX_COUNT"));
o.setPickCountReal(integer(row, "PICK_COUNT_REAL"));
o.setDeclareCode(str(row, "DECLARE_CODE"));
o.setClearanceCode(str(row, "CLEARANCE_CODE"));
o.setQingguanAgent(str(row, "QINGGUAN_AGENT"));
o.setClearanceOpCode(str(row, "CLEARANCE_OP_CODE"));
o.setStockAddr(str(row, "STOCK_ADDR"));
o.setStockOutRemark(str(row, "STOCK_OUT_REMARK"));
o.setDeliverCount(integer(row, "DELIVER_COUNT"));
o.setFirstDeliverCount(integer(row, "FIRST_DELIVER_COUNT"));
o.setLastDeliverCount(integer(row, "LAST_DELIVER_COUNT"));
o.setAcDeliverDiff(asText(row, "AC_DELIVER_DIFF"));
o.setDeliverEndDiff(asText(row, "DELIVER_END_DIFF"));
o.setCheckOrderCount(integer(row, "CHECK_ORDER_COUNT"));
o.setCheckLeaveCount(integer(row, "CHECK_LEAVE_COUNT"));
o.setInternalCheckTime(date(row, "INTERNAL_CHECK_TIME"));
return o;
}
private static SrvBillAirTrack toTrack(Map<String, Object> row, String guid, String billCode)
{
SrvBillAirTrack t = new SrvBillAirTrack();
t.setGuid(guid);
t.setBillCode(billCode);
t.setStartTimePlan(date(row, "START_TIME_PLAN"));
t.setArriveTimePlan(date(row, "ARRIVE_TIME_PLAN"));
t.setShippingDate(date(row, "SHIPPING_DATE"));
t.setStartTime(date(row, "START_TIME"));
t.setArriveTime(date(row, "ARRIVE_TIME"));
t.setArriveStockTime(date(row, "ARRIVE_STOCK_TIME"));
t.setClearanceTime(date(row, "CLEARANCE_TIME"));
t.setEndOprateTime(date(row, "END_OPRATE_TIME"));
t.setBlBgfx(integer(row, "BL_BGFX"));
t.setBgfxTime(date(row, "BGFX_TIME"));
t.setUpdateTimeBgfx(date(row, "UPDATE_TIME_BGFX"));
t.setBlSjqf(integer(row, "BL_SJQF"));
t.setSjqfTime(date(row, "SJQF_TIME"));
t.setUpdateTimeSjqf(date(row, "UPDATE_TIME_SJQF"));
t.setBlSjdd(integer(row, "BL_SJDD"));
t.setSjddTime(date(row, "SJDD_TIME"));
t.setUpdateTimeSjdd(date(row, "UPDATE_TIME_SJDD"));
t.setBlTzdc(integer(row, "BL_TZDC"));
t.setTzdcTime(date(row, "TZDC_TIME"));
t.setUpdateTimeTzdc(dateText(row, "UPDATE_TIME_TZDC"));
t.setBlThdc(integer(row, "BL_THDC"));
t.setThdcTime(date(row, "THDC_TIME"));
t.setUpdateTimeThdc(date(row, "UPDATE_TIME_THDC"));
t.setBlQgwc(integer(row, "BL_QGWC"));
t.setQgwcTime(date(row, "QGWC_TIME"));
t.setUpdateTimeQgwc(date(row, "UPDATE_TIME_QGWC"));
t.setBlGxfc(integer(row, "BL_GXFC"));
t.setGxfcTime(date(row, "GXFC_TIME"));
t.setUpdateTimeGxfc(dateText(row, "UPDATE_TIME_GXFC"));
t.setBlFjh(integer(row, "BL_FJH"));
t.setFjhTime(date(row, "FJH_TIME"));
t.setUpdateTimeFjh(dateText(row, "UPDATE_TIME_FJH"));
t.setBlTrackGenBg(integer(row, "BL_TRACK_GEN_BG"));
t.setBlTrackGenBgfx(integer(row, "BL_TRACK_GEN_BGFX"));
t.setBlTrackGenQf(integer(row, "BL_TRACK_GEN_QF"));
t.setBlTrackGenDd(integer(row, "BL_TRACK_GEN_DD"));
t.setBlTrackGenQg(integer(row, "BL_TRACK_GEN_QG"));
t.setBlTrackGenDc(integer(row, "BL_TRACK_GEN_DC"));
return t;
}
private static String str(Map<String, Object> row, String key)
{
Object v = row.get(key);
if (v == null)
{
v = row.get(key.toLowerCase());
}
if (v == null)
{
return null;
}
String s = String.valueOf(v).trim();
return s.isEmpty() ? null : s;
}
private static String asText(Map<String, Object> row, String key)
{
Object v = get(row, key);
if (v == null)
{
return null;
}
return String.valueOf(v);
}
private static String dateText(Map<String, Object> row, String key)
{
Date d = date(row, key);
if (d == null)
{
String s = str(row, key);
return s;
}
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d);
}
private static Object get(Map<String, Object> row, String key)
{
Object v = row.get(key);
return v != null ? v : row.get(key.toLowerCase());
}
private static Integer integer(Map<String, Object> row, String key)
{
Object v = get(row, key);
if (v == null)
{
return null;
}
if (v instanceof Number)
{
return ((Number) v).intValue();
}
try
{
return Integer.valueOf(String.valueOf(v).trim());
}
catch (Exception e)
{
return null;
}
}
private static BigDecimal decimal(Map<String, Object> row, String key)
{
Object v = get(row, key);
if (v == null)
{
return null;
}
if (v instanceof BigDecimal)
{
return (BigDecimal) v;
}
if (v instanceof Number)
{
return BigDecimal.valueOf(((Number) v).doubleValue());
}
try
{
return new BigDecimal(String.valueOf(v).trim());
}
catch (Exception e)
{
return null;
}
}
private static Date date(Map<String, Object> row, String key)
{
Object v = get(row, key);
if (v == null)
{
return null;
}
if (v instanceof Date)
{
return (Date) v;
}
return null;
}
}
@@ -0,0 +1,64 @@
package com.bms.price.airbill.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.price.airbill.domain.SrvBillAir;
import com.bms.price.airbill.domain.SrvBillAirFinance;
import com.bms.price.airbill.domain.SrvBillAirFlight;
import com.bms.price.airbill.domain.SrvBillAirOp;
import com.bms.price.airbill.domain.SrvBillAirTrack;
import com.bms.price.airbill.mapper.SrvBillAirSyncMapper;
/**
* 空运提单镜像表写库(MASTER,分批 upsert)
*/
@Service
public class BillAirSyncWriter
{
private static final int BATCH_SIZE = 200;
@Autowired
private SrvBillAirSyncMapper mapper;
@Transactional(rollbackFor = Exception.class)
public int writeAir(List<SrvBillAir> list)
{
return batch(list, mapper::upsertBillAir);
}
@Transactional(rollbackFor = Exception.class)
public int writeFinance(List<SrvBillAirFinance> list)
{
return batch(list, mapper::upsertBillAirFinance);
}
@Transactional(rollbackFor = Exception.class)
public int writeFlight(List<SrvBillAirFlight> list)
{
return batch(list, mapper::upsertBillAirFlight);
}
@Transactional(rollbackFor = Exception.class)
public int writeOp(List<SrvBillAirOp> list)
{
return batch(list, mapper::upsertBillAirOp);
}
@Transactional(rollbackFor = Exception.class)
public int writeTrack(List<SrvBillAirTrack> list)
{
return batch(list, mapper::upsertBillAirTrack);
}
private <T> int batch(List<T> list, java.util.function.ToIntFunction<List<T>> fn)
{
int rows = 0;
for (int from = 0; from < list.size(); from += BATCH_SIZE)
{
rows += fn.applyAsInt(list.subList(from, Math.min(from + BATCH_SIZE, list.size())));
}
return rows;
}
}
@@ -0,0 +1,34 @@
package com.bms.price.airbill.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.price.airbill.mapper.OracleBillAirMapper;
/**
* Oracle 空运提单只读(SLAVE)。独立 Bean,保证 @DataSource 切面生效。
*/
@Service
public class OracleBillAirReader
{
@Autowired
private OracleBillAirMapper oracleBillAirMapper;
@DataSource(DataSourceType.SLAVE)
public List<Map<String, Object>> readAll()
{
try
{
PageHelper.clearPage();
return oracleBillAirMapper.selectAllBillAir();
}
finally
{
PageHelper.clearPage();
}
}
}
@@ -0,0 +1,29 @@
package com.bms.price.airbill.task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.bms.common.utils.StringUtils;
import com.bms.price.airbill.sync.BillAirSyncService;
/**
* 老系统空运提单每日同步任务。
* sys_job.invoke_target = billAirSyncTask.syncFromOracle()
*/
@Component("billAirSyncTask")
public class BillAirSyncTask
{
@Autowired
private BillAirSyncService billAirSyncService;
/**
* 全量同步 Oracle TAB_BILL_AIR -> srv_bill_air / finance / flight / op / track
*/
public void syncFromOracle()
{
String summary = billAirSyncService.syncFromOracle();
if (StringUtils.isEmpty(summary))
{
throw new RuntimeException("老系统空运提单同步未返回结果");
}
}
}