feat(procurement): implement sample fulfillment and settled fee workflow

This commit is contained in:
2026-10-10 02:19:38 +08:00
parent 040f3bbd93
commit a973be2103
104 changed files with 9823 additions and 714 deletions
@@ -37,7 +37,7 @@ public class HttpProcurementFileGateway implements ProcurementFileGateway {
@Override public String getFilename() { return file.getOriginalFilename(); }
}).contentType(file.getContentType() == null ? MediaType.APPLICATION_OCTET_STREAM : MediaType.parseMediaType(file.getContentType()));
} catch (Exception exception) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "采购文件无法读取", exception); }
String businessType = "RECEIPT".equals(category) ? "OVERSEAS_PROCUREMENT_RECEIPT" : "OVERSEAS_PROCUREMENT_VOUCHER";
String businessType = ProcurementFileCategory.parse(category).businessType();
Envelope response = client.post().uri("/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}",
Long.parseLong(customerId), businessType, orderId)
.header("X-Internal-Service-Token", token).header("X-Operator-Id", String.valueOf(operatorId))
@@ -51,5 +51,16 @@ public class HttpProcurementFileGateway implements ProcurementFileGateway {
return new UploadedFile(data.fileId(), data.fileName(), data.contentType(), data.sizeBytes() == null ? 0 : data.sizeBytes());
}
private record Envelope(String code, String message, Metadata data) { }
@Override
public Download download(String customerId,long orderId,String category,long fileId) {
var response=client.get().uri("/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}/{fileId}/content",
Long.parseLong(customerId),ProcurementFileCategory.parse(category).businessType(),orderId,fileId)
.header("X-Internal-Service-Token",token).retrieve()
.onStatus(HttpStatusCode::isError,(request,result)->{throw new ResponseStatusException(
result.getStatusCode().is4xxClientError()?HttpStatus.NOT_FOUND:HttpStatus.SERVICE_UNAVAILABLE,"采购文件暂不可读取");})
.toEntity(byte[].class);
if(response.getBody()==null)throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,"文件服务没有返回文件内容");
return new Download(response.getBody(),response.getHeaders().getContentType()==null?MediaType.APPLICATION_OCTET_STREAM_VALUE:response.getHeaders().getContentType().toString());
}
private record Metadata(Long fileId, String fileName, String contentType, Long sizeBytes) { }
}
@@ -0,0 +1,14 @@
package com.baiyue.lastleg.procurement.gateway;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;
import java.util.Locale;
public enum ProcurementFileCategory {
RECEIPT,VOUCHER,LABEL,PURCHASE,BUDGET,EXCEPTION;
public String businessType(){return "OVERSEAS_PROCUREMENT_"+name();}
public static ProcurementFileCategory parse(String value){
try{return valueOf(value==null?"":value.trim().toUpperCase(Locale.ROOT));}
catch(IllegalArgumentException exception){throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"采购文件用途不受支持");}
}
}
@@ -2,5 +2,7 @@ package com.baiyue.lastleg.procurement.gateway;
import org.springframework.web.multipart.MultipartFile;
public interface ProcurementFileGateway {
UploadedFile upload(String customerId, long orderId, long operatorId, String category, MultipartFile file);
Download download(String customerId,long orderId,String category,long fileId);
record Download(byte[] content,String contentType) { }
record UploadedFile(long fileId, String fileName, String contentType, long sizeBytes) { }
}