feat(file): support seven delivery document categories
This commit is contained in:
+1
-1
@@ -24,7 +24,7 @@ class InternalBusinessFileControllerTest {
|
||||
@Test void zeroTenantUploadAndMetadataRemainBehindInternalToken() {
|
||||
var file = new MockMultipartFile("file", "clearance.pdf", "application/pdf", "%PDF-1.4".getBytes());
|
||||
var metadata = new InternalBusinessFileService.Metadata(81L, "PLATFORM", 0L, "CONTAINER_CLEARANCE_DOCUMENT",
|
||||
"41", "clearance.pdf", "hash", "application/pdf", file.getSize());
|
||||
"41", "clearance.pdf", "hash", "application/pdf", file.getSize(), java.time.LocalDateTime.of(2026, 9, 9, 12, 0));
|
||||
when(service.upload(0L, "CONTAINER_CLEARANCE_DOCUMENT", "41", 7L, file)).thenReturn(metadata);
|
||||
when(service.metadata(0L, "CONTAINER_CLEARANCE_DOCUMENT", "41", 81L)).thenReturn(metadata);
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.baiyue.file.service;
|
||||
|
||||
import com.baiyue.file.entity.FileObjectEntity;
|
||||
import com.baiyue.file.mapper.FileObjectMapper;
|
||||
import com.baiyue.file.controller.InternalBusinessFileController;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
class DeliveryBusinessFileTest {
|
||||
@TempDir Path root;
|
||||
@BeforeAll static void metadata() {
|
||||
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), "delivery-files"), FileObjectEntity.class);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings={"DELIVERY_BOL","DELIVERY_CUSTOMER_DOCUMENT","DELIVERY_BILL_OF_LADING","DELIVERY_POD","DELIVERY_PHOTO","DELIVERY_LOADING_PHOTO","DELIVERY_EXPRESS_RECEIPT"})
|
||||
void immutableUploadsPreserveOldContentAndRealTimestamp(String type) {
|
||||
var storage = storage();
|
||||
var files = mock(FileObjectMapper.class);
|
||||
var service = service(files, storage);
|
||||
var ids = new AtomicLong(800);
|
||||
when(files.insert(any(FileObjectEntity.class))).thenAnswer(call -> {
|
||||
FileObjectEntity row = call.getArgument(0); row.setId(ids.incrementAndGet()); return 1;
|
||||
});
|
||||
var first = service.upload(11, type, "71", 9, new MockMultipartFile("file", "资料 🚢.bin", "application/octet-stream", new byte[]{0,1,2}));
|
||||
var second = service.upload(11, type, "71", 9, new MockMultipartFile("file", "资料 🚢.bin", "application/octet-stream", new byte[]{3,4}));
|
||||
var captor = org.mockito.ArgumentCaptor.forClass(FileObjectEntity.class);
|
||||
verify(files, times(2)).insert(captor.capture());
|
||||
assertThat(first.fileId()).isNotEqualTo(second.fileId());
|
||||
assertThat(first.createdAt()).isEqualTo(captor.getAllValues().get(0).getCreatedAt()).isNotNull();
|
||||
assertThat(first.ownerScope()).isEqualTo("CUSTOMER");
|
||||
assertThat(storage.read(captor.getAllValues().get(0).getObjectKey())).containsExactly(0,1,2);
|
||||
assertThat(storage.read(captor.getAllValues().get(1).getObjectKey())).containsExactly(3,4);
|
||||
verify(files, never()).updateById(any(FileObjectEntity.class));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings={"DELIVERY_BOL","DELIVERY_CUSTOMER_DOCUMENT","DELIVERY_BILL_OF_LADING","DELIVERY_POD","DELIVERY_PHOTO","DELIVERY_LOADING_PHOTO","DELIVERY_EXPRESS_RECEIPT"})
|
||||
void enforcesFiftyMibAndNonemptyBoundary(String type) throws Exception {
|
||||
var storage = storage(); var category = BusinessFileCategory.require(type);
|
||||
assertThatThrownBy(() -> storage.store(11,"71",new MockMultipartFile("file",new byte[0]),category)).isInstanceOf(BizException.class);
|
||||
var file = mock(MultipartFile.class);
|
||||
when(file.isEmpty()).thenReturn(false); when(file.getSize()).thenReturn(52428801L);
|
||||
assertThatThrownBy(() -> storage.store(11,"71",file,category)).isInstanceOf(BizException.class).hasMessageContaining("50MB");
|
||||
when(file.getSize()).thenReturn(52428800L); when(file.getContentType()).thenReturn("application/x-custom");
|
||||
when(file.getOriginalFilename()).thenReturn("boundary.custom");
|
||||
doAnswer(call -> { try (var out=new java.io.RandomAccessFile(((Path)call.getArgument(0)).toFile(),"rw")) { out.setLength(52428800L); } return null; }).when(file).transferTo(any(Path.class));
|
||||
var stored=storage.store(11,"71",file,category);
|
||||
assertThat(java.nio.file.Files.size(root.resolve(stored.objectKey()))).isEqualTo(52428800L);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings={"DELIVERY_BOL","DELIVERY_CUSTOMER_DOCUMENT","DELIVERY_BILL_OF_LADING","DELIVERY_POD","DELIVERY_PHOTO","DELIVERY_LOADING_PHOTO","DELIVERY_EXPRESS_RECEIPT"})
|
||||
void downloadQueriesEveryOwnershipKeyAndRejectsUnauthorizedAccess(String type) {
|
||||
var files=mock(FileObjectMapper.class); var storage=mock(BusinessFileStorage.class); var service=service(files,storage);
|
||||
when(files.selectOne(any())).thenAnswer(call -> {
|
||||
LambdaQueryWrapper<FileObjectEntity> query=call.getArgument(0);
|
||||
assertThat(query.getSqlSegment()).contains("tenant_id", "business_type", "business_id", "id", "status", "deleted");
|
||||
assertThat(query.getParamNameValuePairs().values()).containsExactlyInAnyOrder(12L,type,"72",802L,"ACTIVE",false);
|
||||
return null;
|
||||
});
|
||||
assertThatThrownBy(() -> service.download(12,type,"72",802)).isInstanceOf(BizException.class).hasMessageContaining("归属不匹配");
|
||||
assertThatThrownBy(() -> service.metadata(0,type,"71",801)).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> service.metadata(11,type,"not-an-id",801)).isInstanceOf(BizException.class);
|
||||
var controller=new InternalBusinessFileController();
|
||||
ReflectionTestUtils.setField(controller,"expected","test-internal"); ReflectionTestUtils.setField(controller,"service",service);
|
||||
assertThatThrownBy(() -> controller.download("bad",11,type,"71",801)).isInstanceOf(BizException.class);
|
||||
verifyNoInteractions(storage);
|
||||
}
|
||||
private BusinessFileStorage storage() {
|
||||
var storage=new BusinessFileStorage(); ReflectionTestUtils.setField(storage,"configuredRoot",root); storage.initializeRoot(); return storage;
|
||||
}
|
||||
private InternalBusinessFileService service(FileObjectMapper files, BusinessFileStorage storage) {
|
||||
var service=new InternalBusinessFileService(); ReflectionTestUtils.setField(service,"files",files); ReflectionTestUtils.setField(service,"storage",storage); return service;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user