feat: generate dispatch BOL PDFs

This commit is contained in:
2026-09-11 10:09:06 +08:00
parent 81f4f9163c
commit 220d159cec
16 changed files with 484 additions and 4 deletions
@@ -6,6 +6,7 @@ import com.baiyue.common.security.AuthenticatedUser;
import com.baiyue.lastleg.dispatch.dto.DispatchRequests;
import com.baiyue.lastleg.dispatch.dto.DispatchResponse;
import com.baiyue.lastleg.dispatch.service.DispatchService;
import com.baiyue.lastleg.dispatch.service.DispatchBolPrintService;
import com.baiyue.lastleg.security.OverseasPermissions;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -13,6 +14,11 @@ import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.http.CacheControl;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
@@ -20,6 +26,8 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
@RestController
@ConditionalOnProperty(name = "lastleg.dispatch-query-api.enabled", havingValue = "true")
@@ -27,6 +35,7 @@ import org.springframework.web.server.ResponseStatusException;
@Tag(name = "Tail-leg vehicle dispatch query")
public class DispatchQueryController {
@Resource private DispatchService service;
@Resource private DispatchBolPrintService printService;
@GetMapping
@PreAuthorize("hasAuthority('" + OverseasPermissions.DISPATCH_LIST + "')")
@@ -48,6 +57,21 @@ public class DispatchQueryController {
return ApiResponse.success(service.platformDetail(dispatchNo));
}
@GetMapping(value = "/{dispatchNo}/prints/bol", produces = MediaType.APPLICATION_PDF_VALUE)
@PreAuthorize("hasAuthority('" + OverseasPermissions.DISPATCH_LIST + "')")
@Operation(summary = "Generate dispatch BOL as an A4 PDF")
public ResponseEntity<byte[]> printBol(@AuthenticationPrincipal AuthenticatedUser user,
@PathVariable String dispatchNo, HttpServletRequest request) {
requirePlatform(user);
DispatchBolPrintService.GeneratedPdf pdf = printService.generate(dispatchNo, request.getHeader("X-Request-Id"));
ResponseEntity.BodyBuilder response = ResponseEntity.ok().contentType(MediaType.APPLICATION_PDF)
.cacheControl(CacheControl.noStore()).header(HttpHeaders.PRAGMA, "no-cache")
.header(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename(pdf.fileName(), StandardCharsets.UTF_8).build().toString())
.header("X-Content-Type-Options", "nosniff");
if (pdf.pageCount() != null) response.header("X-Print-Page-Count", pdf.pageCount());
return response.contentLength(pdf.content().length).body(pdf.content());
}
private void requirePlatform(AuthenticatedUser user) {
if (user == null || user.tenantId() == null) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);