feat: finalize dropship pallet print documents

This commit is contained in:
2026-09-14 17:52:01 +08:00
parent b3d74c5441
commit 3910b8fcce
15 changed files with 34 additions and 50 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
- 服务发现名:`print-service`。
- 内部地址:`POST /internal/print/v1/pdfs/inbound-marks`。
- 一件代发 A4 托盘信息单:`POST /internal/print/v1/pdfs/dropship-pallet-a4-documents`;模板固定为 `DROPSHIP_PALLET_A4_V2`,采用黑白打印版,每托一页 A4,包含托盘 Code 128 一维码、目的仓、托盘序号、最多 10 行入仓码/客户昵称汇总和最多 34 行 SKU 汇总,不展示作业状态、重量或体积。
- 一件代发 A4 托盘信息单:`POST /internal/print/v1/pdfs/dropship-pallet-a4-documents`;模板固定为 `DROPSHIP_PALLET_A4_V2`,采用黑白打印版,每托一页 A4,包含托盘 Code 128 一维码、目的仓、最多 10 行入仓码/客户昵称汇总和最多 34 行 SKU 汇总,不展示托盘序号、作业状态、重量或体积。
- A4 海运单据内部地址:`POST /internal/print/v1/pdfs/freight-a4-documents`。
- 海外仓排车 BOL 内部地址:`POST /internal/print/v1/pdfs/dispatch-bol-documents`;模板固定为 `DISPATCH_BILL_OF_LADING_A4_V2`,每个 document 对应一张 A4、包含 1-26 行明细。调用方首张按 18 行、续页按 26 行稳定分页;同页连续相同柜号和托盘号由 Print 纵向合并显示。
- 本地直连:`http://127.0.0.1:9207`。
Binary file not shown.
@@ -15,7 +15,6 @@ public final class DropshipPalletA4PdfDtos {
public record PageSpec(BigDecimal widthMm, BigDecimal heightMm) {}
public record Document(String palletNo, String destinationWarehouse,
int palletSequence, int totalPallets,
String barcodeContent, List<InboundRow> inboundRows,
List<SkuRow> skuRows) {}
@@ -35,9 +35,6 @@ public class DropshipPalletA4Renderer {
stream.setLineWidth(PdfUnits.mmToPt(.25));
border(stream, units);
colorText(stream, units, font, "一件代发备货托", 14, 18, 22, INK);
rightText(stream, units, font,
"第 " + data.palletSequence() + " 托 / 共 " + data.totalPallets() + " 托",
10, 192, 22, new Color(75, 75, 75));
barcodeRenderer.draw(stream, barcodeMatrix, PdfUnits.mmToPt(18), units.topDownMmToPdfY(51),
PdfUnits.mmToPt(80), PdfUnits.mmToPt(22));
@@ -157,12 +154,6 @@ public class DropshipPalletA4Renderer {
colorText(s, u, f, fit(f, value, size, PdfUnits.mmToPt(widthMm)), size, x, y, color);
}
private void rightText(PDPageContentStream s, PdfUnits u, PDFont f, String value, float size,
double right, double y, Color color) throws IOException {
double widthMm = f.getStringWidth(value) / 1000 * size / PdfUnits.mmToPt(1);
colorText(s, u, f, value, size, right - widthMm, y, color);
}
private void centeredCell(PDPageContentStream s, PdfUnits u, PDFont f, String value, float size,
double x1, double x2, double y) throws IOException {
String fitted = fit(f, value, size, PdfUnits.mmToPt(x2 - x1));
@@ -68,8 +68,6 @@ public class DropshipPalletA4PdfService {
private DropshipPalletA4PdfDtos.Document normalizeDocument(DropshipPalletA4PdfDtos.Document value, int index) {
if (value == null) invalid("documents[" + index + "] is required");
if (value.palletSequence() <= 0 || value.totalPallets() <= 0
|| value.palletSequence() > value.totalPallets()) invalid("documents[" + index + "] pallet position is invalid");
if (value.inboundRows() == null || value.inboundRows().isEmpty()
|| value.inboundRows().size() > MAX_INBOUND_ROWS) invalid("documents[" + index + "].inboundRows exceeds the one-page A4 capacity");
if (value.skuRows() == null || value.skuRows().size() > MAX_SKU_ROWS) invalid("documents[" + index + "].skuRows exceeds the one-page A4 capacity");
@@ -86,8 +84,8 @@ public class DropshipPalletA4PdfService {
row.itemQuantity(), text(row.unitsPerCarton(), 30)));
}
return new DropshipPalletA4PdfDtos.Document(text(value.palletNo(), 80),
text(value.destinationWarehouse(), 200), value.palletSequence(), value.totalPallets(),
barcode(value.barcodeContent()), List.copyOf(inboundRows), List.copyOf(rows));
text(value.destinationWarehouse(), 200), barcode(value.barcodeContent()),
List.copyOf(inboundRows), List.copyOf(rows));
}
private String barcode(String value) {
@@ -290,12 +290,10 @@ components:
items: { $ref: '#/components/schemas/DropshipPalletA4Document' }
DropshipPalletA4Document:
type: object
required: [palletNo, destinationWarehouse, palletSequence, totalPallets, barcodeContent, inboundRows, skuRows]
required: [palletNo, destinationWarehouse, barcodeContent, inboundRows, skuRows]
properties:
palletNo: { type: string, maxLength: 80 }
destinationWarehouse: { type: string, maxLength: 200 }
palletSequence: { type: integer, minimum: 1 }
totalPallets: { type: integer, minimum: 1 }
barcodeContent:
type: string
maxLength: 80
@@ -274,8 +274,6 @@ class InternalPdfControllerTest {
"documents": [{
"palletNo": "DP-260911-0034",
"destinationWarehouse": "NJDF",
"palletSequence": 1,
"totalPallets": 3,
"barcodeContent": "DP-260911-0034",
"inboundRows": [{
"inboundCode": "NYEXX2609110249",
@@ -27,7 +27,7 @@ class DropshipPalletA4PdfServiceGenerationTest {
@Test
void generatesOneA4PageWithPalletBarcodeAndSkuDetails() throws Exception {
DropshipPalletA4PdfDtos.Document document = new DropshipPalletA4PdfDtos.Document(
"DP-260911-0034", "NJDF", 1, 3, "DP-260911-0034",
"DP-260911-0034", "NJDF", "DP-260911-0034",
List.of(new DropshipPalletA4PdfDtos.InboundRow(
"NYEXX2609110249", "小虫科技", 3, 90)),
List.of(
@@ -64,8 +64,7 @@ class DropshipPalletA4PdfServiceGenerationTest {
"SKU-" + String.format("%03d", index), 2, index * 5, "5-10"));
}
DropshipPalletA4PdfDtos.Document document = new DropshipPalletA4PdfDtos.Document(
"DP-260911-0034", "NJDF", 1, 1,
"DP-260911-0034", inboundRows, rows);
"DP-260911-0034", "NJDF", "DP-260911-0034", inboundRows, rows);
var generated = service.generate(new DropshipPalletA4PdfDtos.Request(
DropshipPalletA4PdfDtos.TEMPLATE,
new DropshipPalletA4PdfDtos.PageSpec(new BigDecimal("210"), new BigDecimal("297")),
@@ -85,7 +84,7 @@ class DropshipPalletA4PdfServiceGenerationTest {
rows.add(new DropshipPalletA4PdfDtos.SkuRow("SKU-" + index, 1, 1, "1"));
}
DropshipPalletA4PdfDtos.Document document = new DropshipPalletA4PdfDtos.Document(
"DP-260911-0034", "NJDF", 1, 1, "DP-260911-0034",
"DP-260911-0034", "NJDF", "DP-260911-0034",
List.of(new DropshipPalletA4PdfDtos.InboundRow("INBOUND", "客户", 35, 35)), rows);
assertThatThrownBy(() -> service.generate(new DropshipPalletA4PdfDtos.Request(