package cn.iocoder.yudao.module.crm.service.contract;
|
|
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.core.io.ClassPathResource;
|
import java.io.*;
|
import java.math.BigDecimal;
|
import java.nio.charset.StandardCharsets;
|
import java.nio.file.*;
|
import java.time.LocalDateTime;
|
import java.util.*;
|
import java.util.zip.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
|
class CrmContractDocumentRendererTest {
|
private CrmContractRespVO contract() {
|
var contract = new CrmContractRespVO();
|
contract.setNo("HT20261015001"); contract.setCustomerName("中国科学院西北高原生物研究所");
|
contract.setOrderDate(LocalDateTime.of(2026,10,15,0,0));
|
var product = new CrmContractRespVO.Product();
|
product.setItemName("冻干冬虫夏草"); product.setItemSpecification("2500级一等"); product.setItemUnitName("g");
|
product.setCount(new BigDecimal("200")); product.setContractPrice(new BigDecimal("50")); product.setTotalPrice(new BigDecimal("10000"));
|
contract.setProducts(List.of(product)); contract.setTotalPrice(new BigDecimal("10000"));
|
return contract;
|
}
|
private Map<String,byte[]> unzip(byte[] bytes) throws IOException {
|
Map<String,byte[]> parts = new HashMap<>();
|
try (var input = new ZipInputStream(new ByteArrayInputStream(bytes))) {
|
ZipEntry entry; while ((entry=input.getNextEntry())!=null) parts.put(entry.getName(),input.readAllBytes());
|
}
|
return parts;
|
}
|
@Test void fillsContractAndPreservesTemplateParts() throws Exception {
|
byte[] bytes = CrmContractDocumentRenderer.render(contract());
|
var parts = unzip(bytes);
|
String xml = new String(parts.get("word/document.xml"), StandardCharsets.UTF_8);
|
assertTrue(xml.contains("HT20261015001")); assertTrue(xml.contains("2026年10月15日"));
|
assertTrue(xml.contains("10000.00")); assertTrue(xml.contains("壹万元整"));
|
assertTrue(xml.contains("冻干冬虫夏草(2500级一等)")); assertTrue(xml.contains("诚信合规"));
|
assertFalse(xml.contains("${"));
|
try(var template = new ClassPathResource("templates/contract/sale-contract.docx").getInputStream()) {
|
var original = unzip(template.readAllBytes()); assertEquals(original.keySet(),parts.keySet());
|
for (var name : original.keySet()) if (!name.equals("word/document.xml")) assertArrayEquals(original.get(name), parts.get(name), name);
|
}
|
String output = System.getProperty("contract.document.sample");
|
if (output != null) Files.write(Path.of(output),bytes);
|
}
|
@Test void supportsManyProductsDiscountAndXmlCharacters() throws Exception {
|
var contract = contract(); contract.setCustomerName("客户<&>公司");
|
contract.setProducts(Collections.nCopies(25,contract.getProducts().getFirst()));
|
contract.setTotalPrice(new BigDecimal("249000"));
|
String xml = new String(unzip(CrmContractDocumentRenderer.render(contract)).get("word/document.xml"),StandardCharsets.UTF_8);
|
assertTrue(xml.contains("客户<&>公司")); assertTrue(xml.contains("整单优惠 1000.00 元"));
|
assertEquals(25,xml.split("冻干冬虫夏草(2500级一等)",-1).length-1);
|
assertEquals(25,xml.split("<w:cantSplit",-1).length-1);
|
assertTrue(xml.contains("249000.00")); assertFalse(xml.contains("${"));
|
assertFalse(xml.contains("乙方(需方):中国科学院西北高原生物研究所"));
|
String output = System.getProperty("contract.document.sample");
|
if (output != null) Files.write(Path.of(output).resolveSibling("generated-contract-many.docx"), CrmContractDocumentRenderer.render(contract));
|
}
|
@Test void missingDateAndOptionalFieldsStayBlankWithoutInventingData() throws Exception {
|
var contract = contract(); contract.setOrderDate(null);
|
contract.getProducts().getFirst().setItemSpecification(null); contract.getProducts().getFirst().setItemUnitName(null);
|
contract.getProducts().getFirst().setTotalPrice(null);
|
String xml = new String(unzip(CrmContractDocumentRenderer.render(contract)).get("word/document.xml"),StandardCharsets.UTF_8);
|
assertTrue(xml.contains("____________")); assertTrue(xml.contains("10000.00")); assertFalse(xml.contains("null"));
|
}
|
@Test void emptyContractCannotProduceUnrelatedTemplateProducts() {
|
var contract = contract(); contract.setProducts(List.of());
|
assertThrows(IllegalArgumentException.class,()->CrmContractDocumentRenderer.render(contract));
|
}
|
}
|