package com.trust.controller;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import com.baomidou.mybatisplus.extension.api.ApiController;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.BorderStyle;
import com.deepoove.poi.data.style.RowStyle;
import com.deepoove.poi.data.style.TableStyle;
import com.deepoove.poi.util.PoitlIOUtils;
import com.trust.agri.response.ResponseResult;
import com.trust.agri.sign.validate.SaveValidate;
import com.trust.agri.sign.validate.UpdateValidate;
import com.trust.annotation.SYQLog;
import com.trust.entity.SaleRelease;
import com.trust.entity.basic.Breed;
import com.trust.entity.basic.BreedDetail;
import com.trust.entity.farm.FarmCollect;
import com.trust.entity.farm.FarmPlant;
import com.trust.entity.farm.FarmSeed;
import com.trust.entity.order.*;
import com.trust.entity.order.Process;
import com.trust.entity.storehouse.InventoryMaterial;
import com.trust.model.dto.DeliveryOrderDTO;
import com.trust.model.param.DeliveryOrderListParam;
import com.trust.model.vo.order.DeliveryOrderVO;
import com.trust.service.*;
import com.trust.util.QrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jodconverter.core.document.DefaultDocumentFormatRegistry;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.local.JodConverter;
import org.jodconverter.local.office.LocalOfficeManager;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import static org.apache.poi.xwpf.usermodel.XWPFTable.XWPFBorderType.SINGLE;
/**
* 销售管理-发货单(DeliveryOrder)表控制层
*
* @author makejava
* @since 2024-11-18 20:59:46
*/
@RestController
@RequestMapping("/api/deliveryOrder")
@Api(value = "销售管理-发货单", tags = "销售管理-发货单")
@Slf4j
public class DeliveryOrderController extends ApiController {
/**
* 服务对象
*/
@Resource
private DeliveryOrderService deliveryOrderService;
@Resource
private DeliveryOrderDetailService deliveryOrderDetailService;
@Resource
private PackageDetailService packageDetailService;
@Resource
private SaleReleaseService saleReleaseService;
@Resource
private PackageService packageService;
@Resource
private QrUtil qrUtil;
@PostMapping("/save")
@ApiOperation("新增销售管理-发货单")
@SYQLog(type = "新增销售管理-发货单", name = "销售管理-发货单")
public ResponseResult<DeliveryOrder> save(@Validated(SaveValidate.class) @RequestBody DeliveryOrderDTO param) {
DeliveryOrder entity = deliveryOrderService.saveAndUpdate(param);
return ResponseResult.ok(entity);
}
@PostMapping("/update")
@ApiOperation("更新销售管理-发货单")
@SYQLog(type = "更新销售管理-发货单", name = "销售管理-发货单")
public ResponseResult<DeliveryOrder> update(@Validated(UpdateValidate.class) @RequestBody DeliveryOrderDTO param) {
DeliveryOrder entity = deliveryOrderService.saveAndUpdate(param);
return ResponseResult.ok(entity);
}
@PostMapping("/remove")
@ApiOperation("删除销售管理-发货单")
@SYQLog(type = "删除销售管理-发货单", name = "销售管理-发货单", tagGet = SYQLog.PARAM)
public ResponseResult<String> remove(@RequestBody List<Integer> ids) {
deliveryOrderService.removeByIds(ids);
return ResponseResult.ok();
}
@PostMapping("/list")
@ApiOperation("销售管理-发货单列表")
public ResponseResult<Page<DeliveryOrderVO>> list(@RequestBody DeliveryOrderListParam param) {
Page<DeliveryOrderVO> page = deliveryOrderService.list(param);
return ResponseResult.ok(page);
}
@PostMapping("/export")
public void export(Long orderId, HttpServletResponse response) throws IOException {
DeliveryOrder record = deliveryOrderService.getById(orderId);
byte[] exportDocStream = getExportDocStream(orderId);
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment;filename=\"" + record.getReleaseCode() + ".docx" + "\"");
ServletOutputStream rout = response.getOutputStream();
IoUtil.write(rout, true, exportDocStream);
rout.flush();
}
@PostMapping("/exportBase64")
@ApiOperation("导出销售送货单并返回Base64编码")
public ResponseResult<String> exportBase64(@RequestParam Long orderId) {
log.info("接收到的 orderId 参数值为:{}", orderId);
// 复用原有生成文件的逻辑
byte[] exportDocStream = getExportDocStream(orderId);
// 将二进制数据编码为 Base64 字符串
String base64Str = Base64.getEncoder().encodeToString(exportDocStream);
// 通过统一响应格式返回
return ResponseResult.ok(base64Str);
}
@GetMapping("/listToInspection")
@ApiOperation("销售管理-下拉选择检验编号")
public ResponseResult<List<Map<String, String>>> listToInspection() {
List<Map<String, String>> res = deliveryOrderService.list().stream()
.map(order -> {
Map<String, String> map = new HashMap<>();
map.put("code", order.getReleaseCode());
return map;
})
.distinct()
.collect(Collectors.toList());
return ResponseResult.ok(res);
}
private byte[] getExportDocStream(Long orderId) {
XWPFTemplate template = null;
try {
//查询订单客户信息
DeliveryOrder record = deliveryOrderService.getById(orderId);
// 创建一个SimpleDateFormat对象,指定日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Map<String, Object> args = new HashMap<>();
args.put("plantingSeriesName", Texts.of(record.getPlantingSeriesName()).fontFamily("宋体").fontSize(12).create());
args.put("plantTime", Texts.of(record.getPlantTime()).fontFamily("宋体").fontSize(12).create());
args.put("releaseCode", Texts.of(record.getReleaseCode()).fontFamily("宋体").fontSize(12).create());
args.put("code", Texts.of(record.getCode()).fontFamily("宋体").fontSize(12).create());
// 获取采收地块数据
String landCodes = record.getLandCodes();
// 根据文本长度动态调整字体大小
int fontSize = 12;
if (landCodes.length() > 10) {
fontSize = 11;
}
if (landCodes.length() > 25) {
fontSize = 10;
}
if (landCodes.length() > 35) {
fontSize = 9;
}
if (landCodes.length() > 45) {
fontSize = 8;
}
if (landCodes.length() > 55) {
fontSize = 7;
}
if (landCodes.length() > 65) {
fontSize = 6;
}
if (landCodes.length() > 75) {
fontSize = 5;
}
// 创建文本对象,设置自适应字体大小
args.put("landCodes", Texts.of(landCodes)
.fontFamily("宋体")
.fontSize(fontSize)
.create());
args.put("landArea", Texts.of(record.getLandArea()).fontFamily("宋体").fontSize(12).create());
args.put("harvestTime", Texts.of(record.getHarvestTime()).fontFamily("宋体").fontSize(12).create());
args.put("customerName", Texts.of(record.getCustomerName()).fontFamily("宋体").fontSize(12).create());
args.put("saleDate", Texts.of(sdf.format(record.getSaleDate())).fontFamily("宋体").fontSize(12).create());
args.put("deliveryDate", Texts.of(sdf.format(record.getDeliveryDate())).fontFamily("宋体").fontSize(12).create());
args.put("qrCodeNumber", Texts.of(record.getQrCodeNumber()).fontFamily("宋体").fontSize(12).create());
String base64Image = qrUtil.getDeliveryQrCode(record.getId().toString()).replace("data:image/png;base64,","");
// 将Base64字符串转换为字节数组
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
// 插入图片,指定图片字节数组、图片格式(如:png)、宽度和高度(单位:px)
PictureRenderData picture = new PictureRenderData(60,60,PictureType.PNG, imageBytes);
args.put("qrCode", picture);
double totalWidth = 19.0;// 表格总宽度(厘米)
double[] colWidths = new double[] {2.5, 2.1, 2.60, 6.0, 2.2, 3.2};
RowRenderData header = Rows.of(
Texts.of("品名").fontFamily("宋体").fontSize(12).bold().create(),
Texts.of("等级").fontFamily("宋体").fontSize(12).bold().create(),
Texts.of("包装规格").fontFamily("宋体").fontSize(12).bold().create(),
Texts.of("产地").fontFamily("宋体").fontSize(12).bold().create(),
Texts.of("件数").fontFamily("宋体").fontSize(12).bold().create(),
Texts.of("数量(公斤)").fontFamily("宋体").fontSize(12).bold().create())
.center().bgColor("FFFFFF").rowAtleastHeight(0.7).create();
List<DeliveryOrderDetail> deliveryOrderDetails = deliveryOrderDetailService.lambdaQuery().
eq(DeliveryOrderDetail::getDeliveryId, record.getId()).list();
TableRenderData table = Tables.of()
.width(totalWidth, colWidths) // 关键步骤:总宽度 + 比例数组
.create();
table.addRow(header);
for (DeliveryOrderDetail detail : deliveryOrderDetails) {
RowRenderData row = Rows.of(
Texts.of(detail.getMaterialName()).fontFamily("宋体").fontSize(12).create(),
Texts.of(detail.getGrade()).fontFamily("宋体").fontSize(12).create(),
Texts.of(detail.getSpec().toString() + " KG/框").fontFamily("宋体").fontSize(12).create(),
Texts.of(detail.getOrigin()).fontFamily("宋体").fontSize(12).create(),
Texts.of(detail.getPackageCount().toString()).fontFamily("宋体").fontSize(12).create(),
Texts.of(detail.getWeight().stripTrailingZeros().toPlainString()).fontFamily("宋体").fontSize(12).create())
.center().rowAtleastHeight(0.7).create();
table.addRow(row);
}
if (deliveryOrderDetails.size() < 3) {
for (Integer i = 0; i < 3 - deliveryOrderDetails.size(); i++) {
table.addRow(Rows.of(
Texts.of("").fontFamily("宋体").fontSize(12).create(),
Texts.of("").fontFamily("宋体").fontSize(12).create(),
Texts.of("").fontFamily("宋体").fontSize(12).create(),
Texts.of("").fontFamily("宋体").fontSize(12).create(),
Texts.of("").fontFamily("宋体").fontSize(12).create(),
Texts.of("").fontFamily("宋体").fontSize(12).create())
.center().rowAtleastHeight(0.7).create());
}
}
args.put("table", table);
InputStream stream = ResourceUtil.getStream("templates/sales_order_delivery02.docx");
template = XWPFTemplate.compile(stream);
template.render(args);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
template.write(outputStream);
return outputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
PoitlIOUtils.closeQuietlyMulti(template);
}
}
public byte[] wordToPdf(byte[] wordBytes) {
try {
// // 启动本地 LibreOffice 办公室管理器(默认连接到 localhost:8100)
// LocalOfficeManager officeManager = LocalOfficeManager.builder()
// .officeHome("D:\\application\\LibreOffice\\") // 自动检测LibreOffice安装目录
// .portNumbers(8100) // 确保与上面soffice命令中的端口号一致
// .build();
// if(!officeManager.isRunning()){
// officeManager.start();
// }
// 创建输入流和输出流
ByteArrayInputStream inputStream = new ByteArrayInputStream(wordBytes);
OutputStream outputStream = new FileOutputStream("output.pdf");
// // 执行转换(支持 DOC/DOCX)
// JodConverter.convert(inputStream)
// .as(DefaultDocumentFormatRegistry.DOCX)
// .to(outputStream)
// .as(DefaultDocumentFormatRegistry.PDF)
// .execute();
// 执行转换
JodConverter.convert(inputStream)
.to(outputStream)
.as(DefaultDocumentFormatRegistry.PDF) // 指定输出格式为PDF
.execute();
// 获取 PDF 字节数组
byte[] pdfBytes = new byte[]{};
System.out.println("PDF 文件大小:" + pdfBytes.length + " bytes");
// 停止办公套件
// officeManager.stop();
return pdfBytes;
} catch (OfficeException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
return wordBytes;
}
@PostMapping("/getNewSaleCode")
public ResponseResult<String> getNewSaleCode(Integer id, Integer type) {
if(type == 1){
List<SaleRelease> saleReleaseList = saleReleaseService.lambdaQuery().
isNotNull(SaleRelease::getReleaseCode).
ne(SaleRelease::getId,id).
orderByDesc(SaleRelease::getCreatedTime).list();
if(!saleReleaseList.isEmpty()){
return ResponseResult.ok(saleReleaseList.get(0).getReleaseCode());
}
}else{
List<DeliveryOrder> deliveryOrderList = deliveryOrderService.lambdaQuery().
isNotNull(DeliveryOrder::getReleaseCode).
ne(DeliveryOrder::getId,id).
orderByDesc(DeliveryOrder::getCreatedTime).list();
if(!deliveryOrderList.isEmpty()){
return ResponseResult.ok(deliveryOrderList.get(0).getReleaseCode());
}
}
return ResponseResult.ok();
}
@GetMapping("/getQrCodeNumberByDeliveryDate")
public ResponseResult<String> getQrCodeNumberByDeliveryDate(String deliveryDateString){
// 将目标日期字符串转换为 LocalDate 对象
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate targetDate = LocalDate.parse(deliveryDateString, formatter);
List<DeliveryOrder> deliveryOrderList = deliveryOrderService.lambdaQuery().isNotNull(DeliveryOrder::getDeliveryDate).list();
// 使用 Stream API 筛选并统计数量
long count = deliveryOrderList.stream()
.filter(order -> {
// 获取 deliveryDate 并转换为 LocalDate 对象进行比较
Date deliveryDate = order.getDeliveryDate();
if (deliveryDate == null) {
return false; // 跳过 null 值
}
// 将 Date 转换为 LocalDate
LocalDate orderDate = deliveryDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
return orderDate.equals(targetDate);
})
.count();
String result = "";
String formatString = deliveryDateString.replace("-","").substring(2);
result = formatString + "-" + String.format("%02d", count + 1);
return ResponseResult.ok(result);
}
@PostMapping("/exportMedicinalLabel")
public void exportMedicinalLabel(Long orderId, HttpServletResponse response) throws IOException {
DeliveryOrder record = deliveryOrderService.getById(orderId);
byte[] exportDocStream = getExportMedicinalLabelDocStream(orderId);
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment;filename=\"" + record.getReleaseCode() + ".docx" + "\"");
ServletOutputStream rout = response.getOutputStream();
IoUtil.write(rout, true, exportDocStream);
rout.flush();
}
private byte[] getExportMedicinalLabelDocStream(Long orderId) {
XWPFTemplate template = null;
try {
// 查询订单客户信息
DeliveryOrder record = deliveryOrderService.getById(orderId);
Map<String, Object> args = new HashMap<>();
List<DeliveryOrderDetail> deliveryOrderDetails = deliveryOrderDetailService.lambdaQuery().
eq(DeliveryOrderDetail::getDeliveryId, record.getId()).list();
Integer i = 0;
// 创建日期格式化对象
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");
for (DeliveryOrderDetail detail : deliveryOrderDetails) {
BorderStyle borderStyle = new BorderStyle();
borderStyle.setSize(1);
borderStyle.setColor("000000");
borderStyle.setType(SINGLE);
// 二维码处理
String base64Image = qrUtil.getTraceabilityQrCode(record.getId().toString())
.replace("data:image/png;base64,", "");
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
PictureRenderData picture = new PictureRenderData(50, 50, PictureType.PNG, imageBytes);
// 表头表格(调整字体大小:原18→14)
int[] colWidths = new int[]{2585, 1134};
TableRenderData tableHeader = Tables.create();
RowRenderData rowHeader = Rows.of(
Cells.of().addParagraph(Texts.of("中药材标签").bold().create()).create(),
Cells.of(picture).create()
)
.rowHeight(0.7)
.textFontSize(10).textBold().center().create();
tableHeader.addRow(rowHeader);
TableStyle tableStyle = new TableStyle();
tableStyle.setWidth("3719");
tableStyle.setLeftBorder(borderStyle);
tableStyle.setRightBorder(borderStyle);
tableStyle.setTopBorder(borderStyle);
tableStyle.setBottomBorder(borderStyle);
tableStyle.setColWidths(colWidths);
tableHeader.setTableStyle(tableStyle);
// 表主体内容(调整字体大小:原10→8;原13→10)
TableRenderData table = Tables.create();
String tableRow = "编号:" + record.getCode() +
"品名:" + detail.getMaterialName() +
"基原:" + getBreedDetail(detail.getStockBatchCode()) +
"销售批次:" + record.getReleaseCode() +
"规格:" + detail.getSpec() +
"等级:" + detail.getGrade() +
"产地:" + detail.getOrigin() +
"数量:" + detail.getPackageCount() + "框" +
"种植日期:" + sdf1.format(detail.getPlantTime()) +
"采收日期:" + sdf2.format(detail.getHarvestTime()) +
"包装日期:" + sdf2.format(getPackDate(detail.getStockBatchCode())) +
"采收区块:" + insertNewlineIfNeeded(detail.getLandCodes()) +
"区块面积:" + detail.getLandArea() + "亩" +
"保质期:8天(采收日期起)";
// RowStyle rowStyle = new RowStyle();
// rowStyle.setHeight(1);
RowRenderData row = Rows.of(Cells.of(tableRow).create())
.textFontSize(6)
// .rowStyle(rowStyle)
.rowHeight(0.1)
.create();
table.addRow(row);
// 公司名称行(字体从13缩小到10)
RowRenderData rowUnit = Rows.of(Cells.of("浙江广胜农业科技发展有限公司").create())
.textFontSize(7)
.rowHeight(0.2)
.center().create();
table.addRow(rowUnit);
TableStyle tableStyle1 = new TableStyle();
tableStyle1.setWidth("3719");
tableStyle1.setLeftBorder(borderStyle);
tableStyle1.setRightBorder(borderStyle);
tableStyle1.setTopBorder(borderStyle);
tableStyle1.setBottomBorder(borderStyle);
table.setTableStyle(tableStyle1);
args.put("tableHeader" + i, tableHeader);
args.put("table" + i, table);
i++;
}
InputStream stream = ResourceUtil.getStream("templates/medicinal_label.docx");
template = XWPFTemplate.compile(stream);
template.render(args);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
template.write(outputStream);
return outputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
PoitlIOUtils.closeQuietlyMulti(template);
}
}
// 获取包装日期
public Date getPackDate(String stockBatchCode){
PackageDetail packageDetail = packageDetailService.lambdaQuery().
eq(PackageDetail::getPackageCode,stockBatchCode).list().get(0);
ProcessPackage processPackage = packageService.getById(packageDetail.getPackageId());
return processPackage.getPackTime();
}
// 如果字符串长度大于20,在第20位后加上换行符,否则返回原字符串。
public String insertNewlineIfNeeded(String input) {
if (input == null) {
return null; // 或者可以根据需求处理 null 情况
}
if (input.length() > 36) {
// 在第20个字符后插入换行符
return input.substring(0, 36) + "\n" + input.substring(36);
} else {
// 返回原字符串
return input;
}
}
@Resource
private ProcessService processService;
@Resource
private ProcessMaterialService processMaterialService;
@Resource
private FarmCollectService farmCollectService;
@Resource
private FarmPlantService farmPlantService;
@Resource
private InventoryMaterialService inventoryMaterialService;
@Resource
private FarmSeedService farmSeedService;
@Resource
private BreedDetailService breedDetailService;
@Resource
private BreedService breedService;
// 获取基源信息
public String getBreedDetail(String stockBatchCode){
PackageDetail packageDetail = packageDetailService.lambdaQuery().
eq(PackageDetail::getPackageCode,stockBatchCode).list().get(0);
ProcessPackage processPackage = packageService.getById(packageDetail.getPackageId());
// 查找包装单中第一个加工单号,获取该加工单
Integer processId = Integer.parseInt(processPackage.getDocketCode().split(",")[0]);
Process process = processService.getById(processId);
// 获取加工原料
ProcessMaterial processMaterial = processMaterialService.getByProcessId(processId).get(0);
// 获取采收信息
FarmCollect farmCollect = farmCollectService.lambdaQuery().eq(FarmCollect::getCode,processMaterial.getStockCode()).list().get(0);
// 获取种植信息
FarmPlant farmPlant = farmPlantService.lambdaQuery().eq(FarmPlant::getCode,farmCollect.getPlantCode()).list().get(0);
// 获取第一个种苗检验编号
Integer breedCode = Integer.parseInt(farmPlant.getBreedCode().split(",")[0]);
InventoryMaterial inventoryMaterial = inventoryMaterialService.getById(breedCode);
// 种苗出圃
FarmCollect farmCollect1 = farmCollectService.lambdaQuery().eq(FarmCollect::getCode,inventoryMaterial.getCode()).list().get(0);
// 育苗
FarmSeed farmSeed = farmSeedService.lambdaQuery().eq(FarmSeed::getCode,farmCollect1.getPlantCode()).list().get(0);
// 品种品系
BreedDetail breedDetail = breedDetailService.getById(farmSeed.getBreedId());
Breed breed = breedService.getById(breedDetail.getBreedId());
return breed.getSourceName();
}
}
根据这个修改
最新发布