han\hanst 2 months ago
parent
commit
e4d4e0d157
  1. 389
      src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelExcelTXServiceImpl.java
  2. BIN
      src/main/resources/templates/YB/declaration-all-template-pdf.xlsx
  3. BIN
      src/main/resources/templates/YB/declaration-all-template.xlsx
  4. BIN
      src/main/resources/templates/YB/declaration-packingList-template.xlsx

389
src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelExcelTXServiceImpl.java

@ -7,6 +7,7 @@ import com.aspose.cells.SaveFormat;
import com.xujie.sys.common.utils.DateUtils;
import com.xujie.sys.common.utils.ExcelTemplateTX;
import com.xujie.sys.common.utils.ExcelTemplateALPHA;
import com.xujie.sys.common.utils.ExcelTemplateYB;
import com.xujie.sys.modules.ecss.data.*;
import com.xujie.sys.modules.ecss.dto.SheetErrorInfo;
import com.fasterxml.jackson.core.type.TypeReference;
@ -1040,6 +1041,69 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
delegate.setRowHeight(startListIndex, endListIndex, height);
}
}
private static class Yb2ExcelTemplateAdapter implements ExcelTemplateAdapter {
private final ExcelTemplateYB delegate;
private Yb2ExcelTemplateAdapter(ExcelTemplateYB delegate) {
this.delegate = delegate;
}
@Override
public void clearAll() {
delegate.clearAll();
}
@Override
public void setMoveSeal(boolean moveSeal) {
delegate.setMoveSeal(moveSeal);
}
@Override
public void setDelRight(boolean delRight) {
delegate.setDelRight(delRight);
}
@Override
public void setMoveShape(boolean moveShape) {
delegate.setMoveShape(moveShape);
}
@Override
public void setCellStyle(boolean cellStyle) {
delegate.setCellStyle(cellStyle);
}
@Override
public void setRangeStyle(boolean rangeStyle) {
delegate.setRangeStyle(rangeStyle);
}
@Override
public void setPriceRight(boolean priceRight) {
delegate.setPriceRight(priceRight);
}
@Override
public void setInvoiceLie(boolean invoiceLie) {
delegate.setInvoiceLie(invoiceLie);
}
@Override
public void addVar(String key, Object value) {
delegate.addVar(key, value);
}
@Override
public void addListVarAll(Collection rows) {
delegate.addListVarAll(rows);
}
@Override
public void setRowHeight(int startListIndex, int endListIndex, int height) {
delegate.setRowHeight(startListIndex, endListIndex, height);
}
}
/**
* 导出发票
*/
@ -1070,14 +1134,22 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
public void downloadPackingList(HttpServletResponse response, EcssDeclarationHeaderData data) {
try {
EcssCoDelNotifyHeaderData notifyHeader = coDelMapper.getEcssCoDelNotifyHeader(data.getSite(), data.getDelNo());
String buNo = notifyHeader == null ? "" : notifyHeader.getBuNo();
// RFID和RF不需要序号列declaration-packingList-template.xlsx其他需要序列号declaration-packingList2-template.xlsx
if ("04-MHM".equalsIgnoreCase(notifyHeader.getBuNo())) {
if ("04-MHM".equalsIgnoreCase(buNo)) {
String xlsx = "templates/TX/declaration-packingList-template.xlsx";
ExcelTemplateTX template = ExcelTemplateTX.load(new ClassPathResource(xlsx).getInputStream());
exportPackingList(data, template, notifyHeader, 0);
try (XSSFWorkbook workbook = template.render(0)) {
workbook.write(response.getOutputStream());
}
} else if ("02-Hardtag".equalsIgnoreCase(buNo)) {
String xlsx = "templates/YB/declaration-packingList-template.xlsx";
ExcelTemplateYB template = ExcelTemplateYB.load(new ClassPathResource(xlsx).getInputStream());
exportPackingListYB(data, template, notifyHeader, 0);
try (XSSFWorkbook workbook = template.render(0)) {
workbook.write(response.getOutputStream());
}
} else {
String xlsx = "templates/ALPHA/declaration-packingList-template.xlsx";
ExcelTemplateALPHA template = ExcelTemplateALPHA.load(new ClassPathResource(xlsx).getInputStream());
@ -1208,6 +1280,7 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
XSSFWorkbook workbook = null;
try {
boolean isMhm = notifyHeader != null && "04-MHM".equalsIgnoreCase(notifyHeader.getBuNo());
boolean isHardtag = notifyHeader != null && "02-Hardtag".equalsIgnoreCase(notifyHeader.getBuNo());
if (isMhm) {
ExcelTemplateTX template = ExcelTemplateTX.load(new ClassPathResource("templates/TX/declaration-all-template.xlsx").getInputStream());
ExcelTemplateAdapter templateAdapter = new TxExcelTemplateAdapter(template);
@ -1231,6 +1304,37 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
extractedDeclaration(data, templateAdapter);
template.render(3);
// 第五个sheet - 申报要素
templateAdapter.clearAll();
extractedElements(data, templateAdapter);
template.render(4);
// 第六个sheet - 合同
templateAdapter.clearAll();
extractedContract(data, templateAdapter);
template.render(5);
} else if (isHardtag) {
ExcelTemplateYB template = ExcelTemplateYB.load(new ClassPathResource("templates/YB/declaration-all-template.xlsx").getInputStream());
ExcelTemplateAdapter templateAdapter = new Yb2ExcelTemplateAdapter(template);
// 第一个sheet - 出口货物委托书
extractedExportGoods(data, templateAdapter);
workbook = template.render(0);
// 第二个sheet - 发票
templateAdapter.clearAll();
extractedInvoice(data, templateAdapter, notifyHeader);
template.render(1);
// 第三个sheet - 箱单
templateAdapter.clearAll();
exportPackingListYB(data, template, notifyHeader, 0);
template.render(2);
// 第四个sheet - 报关单
templateAdapter.clearAll();
extractedDeclaration(data, templateAdapter);
template.render(3);
// 第五个sheet - 申报要素
templateAdapter.clearAll();
extractedElements(data, templateAdapter);
@ -1301,6 +1405,7 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
XSSFWorkbook excelWorkbook = null;
try {
boolean isMhm = notifyHeader != null && "04-MHM".equalsIgnoreCase(notifyHeader.getBuNo());
boolean isHardtag = notifyHeader != null && "02-Hardtag".equalsIgnoreCase(notifyHeader.getBuNo());
if (isMhm) {
String xlsx = "templates/TX/declaration-all-template-pdf.xlsx";
ExcelTemplateTX template = ExcelTemplateTX.load(new ClassPathResource(xlsx).getInputStream());
@ -1325,6 +1430,34 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
extractedElements(data, templateAdapter);
template.render(3);
// 第五个sheet - 合同
templateAdapter.clearAll();
extractedContract(data, templateAdapter);
template.render(4);
} else if (isHardtag) {
String xlsx = "templates/YB/declaration-all-template-pdf.xlsx";
ExcelTemplateYB template = ExcelTemplateYB.load(new ClassPathResource(xlsx).getInputStream());
ExcelTemplateAdapter templateAdapter = new Yb2ExcelTemplateAdapter(template);
// 第一个sheet - 发票PDF导出时跳过出口货物委托书
extractedInvoice(data, templateAdapter, notifyHeader);
excelWorkbook = template.render(0);
// 第二个sheet - 箱单
templateAdapter.clearAll();
exportPackingListYB(data, template, notifyHeader, 0);
template.render(1);
// 第三个sheet - 报关单
templateAdapter.clearAll();
extractedDeclaration(data, templateAdapter);
template.render(2);
// 第四个sheet - 申报要素
templateAdapter.clearAll();
extractedElements(data, templateAdapter);
template.render(3);
// 第五个sheet - 合同
templateAdapter.clearAll();
extractedContract(data, templateAdapter);
@ -2244,6 +2377,260 @@ public class CoDelExcelTXServiceImpl implements CoDelExcelTXService {
template.addListVarAll(exportList);
}
/**
* YB装箱单导出
* 第一列展示托号pallet_no
* @param data
* @param template
* @param notifyHeader
* @param type
*/
private void exportPackingListYB(EcssDeclarationHeaderData data, ExcelTemplateYB template,
EcssCoDelNotifyHeaderData notifyHeader,int type) {
List<EcssCoDelNotifyDetailData> notifyDetailList;
if (type==0) {
coDelMapper.updateEcssDeclarationHeader(data);
notifyDetailList = data.getNotifyPartDetailList();
for (EcssCoDelNotifyDetailData nData:notifyDetailList){
coDelMapper.updateEcssCoDelNotifyDetail(nData);
}
}
template.setCellStyle(true);
template.setRangeStyle(true);
template.setMoveSeal(true);
template.setIntRight(true);
if (notifyHeader.getBuNo().equals("03-RFID") || notifyHeader.getBuNo().equals("01-Label")){
template.setCellStyle2(true);
}
template.addVar("remark", data.getXdremark());
template.addVar("localShipper", notifyHeader.getCustomerName());
template.addVar("localShipAddress", notifyHeader.getLocalShipAddress());
template.addVar("ccusname", stringInput(notifyHeader.getOverseasShipper()));
template.addVar("cDeliverAdd", stringInput(notifyHeader.getOverseasAddress()));
template.addVar("dateStr", notifyHeader.getReadyDate() == null ? "" :
new java.text.SimpleDateFormat("d-MMM-yyyy", java.util.Locale.ENGLISH).format(notifyHeader.getReadyDate()));
template.addVar("cmc_invoice", notifyHeader.getCmcInvoice());
template.addVar("shippingMode", stringInput(notifyHeader.getShippingMode()));
Map poNoMap = new HashMap<>();
// 装箱数据
List<EcssCoDelPalletHeaderData> palletHeaderDataList = coDelMapper.searchEcssCoDelPalletHeaderData(notifyHeader);
// 总托数
Integer totalPlt = palletHeaderDataList.stream()
.map(EcssCoDelPalletHeaderData::getPalletQty)
.filter(Objects::nonNull) // 防止空指针
.reduce(0, Integer::sum);
// 发货通知单明细
List<Map> detailList = coDelMapper.exportEcssCoDelNotifyDetail(data);
// 获取poNo
for (int i = 0; i < detailList.size(); i++) {
Map eorder = detailList.get(i);
poNoMap.put(eorder.get("customerPO"), eorder.get("customerPO"));
}
StringBuilder ponos = new StringBuilder();
poNoMap.forEach((key, value) -> ponos.append(key + " "));
template.addVar("poNo", ponos);
List<Map> list = coDelMapper.selectBoxListTX(notifyHeader);
// DB中item_no可能是字符串区间"127~127""2~26"直接查询顺序可能不稳定导出前做自然排序
sortBoxListBySeqAndItemNo(list);
BigDecimal totalCartons = BigDecimal.valueOf(0.0);
BigDecimal grossWeight = BigDecimal.valueOf(0.0);
BigDecimal netWeight = BigDecimal.valueOf(0.0);
BigDecimal totalQty = BigDecimal.valueOf(0.0);
// 托盘序号 -> 托盘数用于托盘数列展示
Map<String, Integer> palletQtyMap = palletHeaderDataList.stream()
.filter(palletHeader -> palletHeader.getSeqNo() != null)
.collect(Collectors.toMap(
palletHeader -> palletHeader.getSeqNo().toString(),
palletHeader -> palletHeader.getPalletQty() != null ? palletHeader.getPalletQty() : 1,
(existing, replacement) -> existing,
LinkedHashMap::new
));
// 托盘序号 -> 托号第一列展示来源ecss_CoDelPalletHeader.pallet_no
Map<String, String> palletNoMap = palletHeaderDataList.stream()
.filter(palletHeader -> palletHeader.getSeqNo() != null)
.collect(Collectors.toMap(
palletHeader -> palletHeader.getSeqNo().toString(),
palletHeader -> StringUtils.defaultString(palletHeader.getPalletNo()),
(existing, replacement) -> existing,
LinkedHashMap::new
));
// 记录每个托盘是否已经在明细中显示过托盘数只显示在该托盘首行
Set<String> displayedPalletSeqSet = new HashSet<>();
List<Map> exportList = new ArrayList<>();//全部需要导出的明细
EcssCoDelPalletHeaderData boxData = new EcssCoDelPalletHeaderData();
boxData.setSite(data.getSite());
boxData.setBuNo(notifyHeader.getBuNo());
boxData.setDelNo(notifyHeader.getDelNo());
List<Map> allBoxDetailList = coDelMapper.selectPalletDetailList(boxData);
Map<String, List<Map>> boxDetailMap = allBoxDetailList == null ? new HashMap<>() :
allBoxDetailList.stream()
.filter(detail -> detail.get("seq_no") != null)
.collect(Collectors.groupingBy(detail -> detail.get("seq_no").toString()));
int palletStartIndex = -1;
String previousPalletSeqNo = null;
for (int m = 0; m < list.size(); m++) {
String boxNo = list.get(m).get("item_no") != null ? list.get(m).get("item_no").toString() : "";
String palletSeqNo = list.get(m).get("seq_no") != null ? list.get(m).get("seq_no").toString() : "";
String palletNo = StringUtils.defaultString(palletNoMap.get(palletSeqNo), palletSeqNo);
List<Map> checkList = boxDetailMap.getOrDefault(boxNo, Collections.emptyList());
// 记录当前箱子对应的exportList起始索引
int boxStartIndex = exportList.size();
// 当前托盘的起始行用于托盘数列跨箱合并
if (!Objects.equals(palletSeqNo, previousPalletSeqNo)) {
palletStartIndex = boxStartIndex;
}
// 获取box的rolls
BigDecimal boxRolls = list.get(m).get("rolls") != null ?
((BigDecimal) list.get(m).get("rolls")).setScale(0, RoundingMode.HALF_UP) : BigDecimal.ZERO;
// 获取box的volume
BigDecimal volume = list.get(m).get("volume") != null ?
((BigDecimal) list.get(m).get("volume")).setScale(6, RoundingMode.HALF_UP) : BigDecimal.ZERO;
for (int i = 0; i < checkList.size(); i++) {
Map eorder = checkList.get(i);
BigDecimal qty = ((BigDecimal)eorder.get("qty")).setScale(6, RoundingMode.HALF_UP);
totalQty = totalQty.add(qty);
eorder.put("total_qty", ((BigDecimal)eorder.get("qty")).setScale(6, RoundingMode.HALF_UP));
// 合箱时第一行显示数值用于合并单元格居中显示
boolean isFirstRow = (i == 0);
eorder.put("noCartons", isFirstRow ? ((BigDecimal)eorder.get("box_qty")).setScale(0, RoundingMode.HALF_UP) : "");
eorder.put("qty_percarton", ((BigDecimal)eorder.get("rolls")).setScale(0, RoundingMode.HALF_UP));
// 托盘数一个托盘对应多个箱仅在该托盘第一条明细显示其他行留空后续按托盘合并
boolean showPalletQty = StringUtils.isNotEmpty(palletSeqNo) && !displayedPalletSeqSet.contains(palletSeqNo);
if (showPalletQty) {
displayedPalletSeqSet.add(palletSeqNo);
}
Integer palletQty = palletQtyMap.get(palletSeqNo);
// 第一列展示托号pallet_no按托盘首行显示后续行留空再做按托合并
eorder.put("seq_no", showPalletQty ? palletNo : "");
eorder.put("total_pallets", showPalletQty ? (palletQty != null ? palletQty : 1) : "");
eorder.put("volume", isFirstRow ? volume : "");
eorder.put("gross_weight", isFirstRow ? ((BigDecimal) list.get(m).get("gross_weight")).setScale(2, RoundingMode.HALF_UP) : "");
eorder.put("net_weight", isFirstRow ? ((BigDecimal) list.get(m).get("net_weight")).setScale(2, RoundingMode.HALF_UP) : "");
// 构建artNo内容
String artNoContent = eorder.get("pn")+" " + eorder.get("part_description") + "\n"
+ " PO#" + eorder.get("po_no");
eorder.put("artNo", artNoContent);
// 计算artNo内容的行数动态设置行高
int lineCount = calculateLineCount(artNoContent);
// 基础行高16点 + 每额外行增加15点可根据实际字体大小调整
int rowHeight = 16 + (lineCount - 1) * 15;
// 设置当前行的行高exportList的当前索引
template.setRowHeight(exportList.size(), exportList.size(), rowHeight);
exportList.add(eorder);
}
// 如果当前箱子对应多个物料合箱添加合并单元格区域
int boxEndIndex = exportList.size() - 1;
if (boxEndIndex >= boxStartIndex) {
// 箱级字段按箱明细范围合并一个箱可能有多条箱明细
// 箱数列第5列索引4按箱明细范围合并
template.addMergeRegion(boxStartIndex, boxEndIndex, 4);
// 净重列第7列索引6按箱明细范围合并
template.addMergeRegion(boxStartIndex, boxEndIndex, 6);
// 毛重列第8列索引7按箱明细范围合并
template.addMergeRegion(boxStartIndex, boxEndIndex, 7);
}
// 托盘数列按托盘(seq_no)跨箱合并一个托盘下多个箱共享同一托盘数
String nextPalletSeqNo = "";
if (m + 1 < list.size()) {
Object nextSeqNo = list.get(m + 1).get("seq_no");
nextPalletSeqNo = nextSeqNo != null ? nextSeqNo.toString() : "";
}
boolean isCurrentPalletEnd = (m == list.size() - 1) || !Objects.equals(palletSeqNo, nextPalletSeqNo);
if (isCurrentPalletEnd && palletStartIndex >= 0 && boxEndIndex >= palletStartIndex) {
// 托盘数列第9列索引8按托盘合并一个托盘下多个箱共享同一托盘数
template.addMergeRegion(palletStartIndex, boxEndIndex, 8);
}
previousPalletSeqNo = palletSeqNo;
totalCartons = totalCartons.add(list.get(m).get("box_qty") !=null? new BigDecimal(list.get(m).get("box_qty").toString()) : BigDecimal.valueOf(0.0));
grossWeight = grossWeight.add(list.get(m).get("gross_weight") !=null?new BigDecimal(list.get(m).get("gross_weight").toString()):BigDecimal.valueOf(0.0));
netWeight = netWeight.add(list.get(m).get("net_weight") !=null?new BigDecimal(list.get(m).get("net_weight").toString()):BigDecimal.valueOf(0.0));
}
// 托盘重量=根据每个pallet的重量*数量累加
BigDecimal palletWeight = BigDecimal.ZERO;
for (EcssCoDelPalletHeaderData palletHeader : palletHeaderDataList) {
if (palletHeader.getPallet() != null && !palletHeader.getPallet().isEmpty()) {
// 根据pallet编号查询EcssPallet信息
List<EcssPalletData> palletDataList = coDelMapper.getPallet(notifyHeader.getSite(), notifyHeader.getBuNo(), palletHeader.getPallet());
if (!palletDataList.isEmpty()) {
EcssPalletData palletData = palletDataList.get(0);
if (palletData.getPalletWeight() != null && palletHeader.getPalletQty() != null) {
// 栈板重量 = 单个栈板重量 * 数量
palletWeight = palletWeight.add(palletHeader.getVolume());
}
}
}
}
template.addVar("Total_Cartons", totalCartons.setScale(0, RoundingMode.HALF_UP));
template.addVar("Gross_Weight", (grossWeight.add(palletWeight)).setScale(2, RoundingMode.HALF_UP));
template.addVar("Net_Weight", netWeight.setScale(2, RoundingMode.HALF_UP));
template.addVar("total_grossweight", grossWeight.setScale(2, RoundingMode.HALF_UP));
template.addVar("total_netweight", netWeight.setScale(2, RoundingMode.HALF_UP));
template.addVar("total_box", totalCartons.setScale(0, RoundingMode.HALF_UP));
template.addVar("goods_total_qty", totalQty);
// YB模板Total Weight (kg)行占位符后5列箱数/总数量/净重/毛重/托盘
template.addVar("total_ctn", totalCartons.setScale(0, RoundingMode.HALF_UP));
template.addVar("all_total_qty", totalQty);
// 下面是可选的或者手动维护的
// RFID需要的
if (notifyHeader.getBuNo().equals("01-Label") || notifyHeader.getBuNo().equals("03-RFID")) {
template.addVar("total:", "total:");
template.addVar("madein", stringInput(data.getOrigin()));
template.addVar("shippingNo", "shipping no");
template.addVar("sp_cmc_invoice", notifyHeader.getCmcInvoice());
// 如果palletWeight==0不显示
template.addVar("pallet_weight_name", palletWeight.compareTo(BigDecimal.ZERO)==0?"":"pallet weight:");
template.addVar("pallet_weight", palletWeight.compareTo(BigDecimal.ZERO)==0?"":palletWeight.setScale(0, RoundingMode.HALF_UP));
}
String plt = "CTN";
if (!palletHeaderDataList.isEmpty()) {
plt = "PLT";
} else {
totalPlt = totalCartons.setScale(0, RoundingMode.HALF_UP).intValue();
}
template.addVar("total_plt", totalPlt+plt);
template.addVar("total_pallet", totalPlt);
// 孟加拉需要的
if (data.getMaterial()!=null && data.getMaterial()) {
template.addVar("RFIDBase", "RFID Base Material");
template.addVar("HSCode", "& H.S.Code:"+stringInput(data.getHsCode()));
}
// 欧洲地区需要
if (data.getPackaging()!=null && data.getPackaging()) {
template.addVar("packaging", "Non-Reusable plastic packaging:");
// 根据维护参数计算出KGS=总托数*plastic packaging维护参数
BigDecimal totalKgs = data.getKgs()!=null?data.getKgs():BigDecimal.ZERO;
if (palletHeaderDataList.isEmpty()) {
totalKgs = BigDecimal.valueOf(0.1);
}
template.addVar("KGS_qty", data.getKgs()!=null?(totalKgs.multiply(BigDecimal.valueOf(totalPlt))).setScale(2, RoundingMode.HALF_UP):"");
template.addVar("KGS", "KGS");
}
// 新加的 货物明细单选框 勾选显示
if (data.getGoodsLabel()!=null && data.getGoodsLabel()) {
template.addVar("nameLabel", "Name of goods"+(notifyHeader.getBuNo().equals("03-RFID")?" RFID LABEL":" RF LABEL"));
template.addVar("originLabel", "Origin of goods Made in China");
template.addVar("sellerLabel", "Name of seller Checkpoint Commercial (Shanghai) Co.. Ltd.");
}
template.addVar("originLabel", "Country of Origin China");
template.addVar("Shipping_Mark", stringInput(data.getShippingMark()));
// 体积计算优先使用栈板体积栈板不存在时根据装箱明细的物料计算体积
BigDecimal totalVolume = BigDecimal.ZERO;
if (!palletHeaderDataList.isEmpty()) {
// 计算所有栈板的体积总和
for (EcssCoDelPalletHeaderData palletHeader : palletHeaderDataList) {
totalVolume = totalVolume.add(palletHeader.getVolume());
}
totalVolume = totalVolume.setScale(2, RoundingMode.HALF_UP);
} else {
// 栈板不存在时根据装箱明细的物料计算体积
totalVolume = calculateVolumeByMaterials(notifyHeader);
}
template.addVar("Measurement", totalVolume);
template.addListVarAll(exportList);
}
private void extractedExportGoods(EcssDeclarationHeaderData data, ExcelTemplateAdapter template) {
EcssDeclarationHeaderData ecHeader = coDelMapper.getDeclarationHeaderByDelNo(data);
// 发货通知单

BIN
src/main/resources/templates/YB/declaration-all-template-pdf.xlsx

BIN
src/main/resources/templates/YB/declaration-all-template.xlsx

BIN
src/main/resources/templates/YB/declaration-packingList-template.xlsx

Loading…
Cancel
Save