feat(fleet): enforce reviewed trips and original fee coverage for dispatch
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
package com.baiyue.lastleg.fleet.maintenance;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class HttpVehicleCareFileGatewayTest {
|
||||
@Test void aSuccessfulHttpEnvelopeCannotBeReturnedAsImageBytes() {
|
||||
var json = org.springframework.http.ResponseEntity.ok().contentType(org.springframework.http.MediaType.APPLICATION_JSON).body("{\"code\":\"A0404\"}".getBytes());
|
||||
assertThatThrownBy(() -> HttpVehicleCareFileGateway.imageContent(json)).hasMessageContaining("不可用");
|
||||
var image = org.springframework.http.ResponseEntity.ok().contentType(org.springframework.http.MediaType.IMAGE_PNG).body(new byte[]{1, 2, 3});
|
||||
assertThat(HttpVehicleCareFileGateway.imageContent(image)).containsExactly(1, 2, 3);
|
||||
}
|
||||
@Test void metadataMustMatchPlatformRecordCategoryAndFileIdentity() {
|
||||
assertThat(HttpVehicleCareFileGateway.verified(envelope(0, "FLEET_VEHICLE_RECORD_PHOTO", "71", 81, "image/png"), 71, 81L).fileId()).isEqualTo("81");
|
||||
assertThatThrownBy(() -> HttpVehicleCareFileGateway.verified(envelope(9, "FLEET_VEHICLE_RECORD_PHOTO", "71", 81, "image/png"), 71, 81L)).hasMessageContaining("不属于");
|
||||
assertThatThrownBy(() -> HttpVehicleCareFileGateway.verified(envelope(0, "FLEET_DRIVER_LICENSE", "71", 81, "image/png"), 71, 81L)).hasMessageContaining("不属于");
|
||||
assertThatThrownBy(() -> HttpVehicleCareFileGateway.verified(envelope(0, "FLEET_VEHICLE_RECORD_PHOTO", "72", 81, "image/png"), 71, 81L)).hasMessageContaining("不属于");
|
||||
assertThatThrownBy(() -> HttpVehicleCareFileGateway.verified(envelope(0, "FLEET_VEHICLE_RECORD_PHOTO", "71", 82, "image/png"), 71, 81L)).hasMessageContaining("不属于");
|
||||
assertThatThrownBy(() -> HttpVehicleCareFileGateway.verified(envelope(0, "FLEET_VEHICLE_RECORD_PHOTO", "71", 81, "text/html"), 71, 81L)).hasMessageContaining("有效照片");
|
||||
}
|
||||
private HttpVehicleCareFileGateway.Envelope envelope(long owner, String type, String record, long file, String mime) {
|
||||
return new HttpVehicleCareFileGateway.Envelope("200", new HttpVehicleCareFileGateway.Metadata(file, owner, type, record, "meter.png", mime, 8L));
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.baiyue.lastleg.fleet.maintenance;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class VehicleCareApiContractTest {
|
||||
@Test void operationsPermissionsAndSchemasMatchTheirPublishedContracts() throws Exception {
|
||||
Map<String,Object> document = new Yaml().load(Files.readString(Path.of("src/main/resources/openapi/fleet-vehicle-records-v1.yaml")));
|
||||
Map<?,?> paths = (Map<?,?>)document.get("paths");
|
||||
String permissionSql = Files.readString(Path.of("../iam/src/main/resources/db/lastleg-permissions.sql"));
|
||||
String initialization = Files.readString(Path.of("../deploy/sql/头程数据库统一增量-MySQL8.sql"));
|
||||
String base = PlatformVehicleCareController.class.getAnnotation(RequestMapping.class).value()[0];
|
||||
int count = 0;
|
||||
for (var method : PlatformVehicleCareController.class.getDeclaredMethods()) {
|
||||
String verb = null; String[] suffix = null;
|
||||
if (method.isAnnotationPresent(GetMapping.class)) { verb = "get"; suffix = method.getAnnotation(GetMapping.class).value(); }
|
||||
if (method.isAnnotationPresent(PostMapping.class)) { verb = "post"; suffix = method.getAnnotation(PostMapping.class).value(); }
|
||||
if (method.isAnnotationPresent(PutMapping.class)) { verb = "put"; suffix = method.getAnnotation(PutMapping.class).value(); }
|
||||
if (verb == null) continue;
|
||||
String path = base + (suffix.length == 0 ? "" : suffix[0]);
|
||||
assertThat(paths.containsKey(path)).as(path).isTrue();
|
||||
Map<?,?> operation = (Map<?,?>)((Map<?,?>)paths.get(path)).get(verb);
|
||||
String expression = method.getAnnotation(PreAuthorize.class).value();
|
||||
String permission = expression.substring(expression.indexOf('\'') + 1, expression.lastIndexOf('\''));
|
||||
assertThat(operation.get("description").toString()).contains(permission);
|
||||
assertThat(permissionSql).contains("'" + permission + "'"); assertThat(initialization).contains("'" + permission + "'"); count++;
|
||||
}
|
||||
assertThat(count).isEqualTo(7);
|
||||
for (String table : List.of("ll_fleet_vehicle_record", "ll_fleet_vehicle_record_history")) {
|
||||
var pattern = Pattern.compile("(?s)CREATE TABLE " + table + " \\(.*?;");
|
||||
var module = pattern.matcher(Files.readString(Path.of("src/main/resources/db/lastleg.sql")));
|
||||
var deployed = pattern.matcher(Files.readString(Path.of("../deploy/sql/海外区域统一增量-MySQL8.sql")));
|
||||
assertThat(module.find()).isTrue(); assertThat(deployed.find()).isTrue();
|
||||
assertThat(module.group().replace("\r\n", "\n")).isEqualTo(deployed.group().replace("\r\n", "\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.baiyue.lastleg.fleet.maintenance;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class VehicleCareAuthorizationTest {
|
||||
@AfterEach void clear() { SecurityContextHolder.clearContext(); }
|
||||
@Test void vehicleListReadsRecordsButDoesNotAuthorizeCreateEditOrPhotoUpload() {
|
||||
try (var context = new AnnotationConfigApplicationContext(Config.class)) {
|
||||
var controller = context.getBean(PlatformVehicleCareController.class);
|
||||
var service = context.getBean(VehicleCareService.class);
|
||||
authenticate("platform:overseas-master-data:vehicle:list");
|
||||
controller.detail(1, "VR-1"); verify(service).detail(1, "VR-1");
|
||||
assertThatThrownBy(() -> controller.create(1, null, null)).isInstanceOf(AccessDeniedException.class);
|
||||
assertThatThrownBy(() -> controller.update(1, "VR-1", null, null)).isInstanceOf(AccessDeniedException.class);
|
||||
assertThatThrownBy(() -> controller.upload(1, "VR-1", null, 0, "key", null)).isInstanceOf(AccessDeniedException.class);
|
||||
authenticate("platform:overseas-master-data:driver:list");
|
||||
assertThatThrownBy(() -> controller.detail(1, "VR-1")).isInstanceOf(AccessDeniedException.class);
|
||||
assertThatThrownBy(() -> controller.download(1, "VR-1", 1)).isInstanceOf(AccessDeniedException.class);
|
||||
verifyNoMoreInteractions(service);
|
||||
}
|
||||
}
|
||||
private void authenticate(String code) { SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "unused", List.of(new SimpleGrantedAuthority(code)))); }
|
||||
@Configuration @EnableMethodSecurity static class Config {
|
||||
@Bean VehicleCareService service() { return mock(VehicleCareService.class); }
|
||||
@Bean PlatformVehicleCareController controller(VehicleCareService service) { return new PlatformVehicleCareController(service); }
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
package com.baiyue.lastleg.fleet.maintenance;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import com.baiyue.lastleg.masterdata.vehicle.adapter.out.persistence.*;
|
||||
import com.baiyue.lastleg.masterdata.vehicle.application.port.out.VehicleRepository;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.*;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.*;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Pattern;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
class VehicleCarePersistenceTest {
|
||||
private JdbcTemplate jdbc;
|
||||
private VehicleCareService service;
|
||||
private VehicleCareFileGateway files;
|
||||
private long vehicleA, vehicleB;
|
||||
private final Instant occurred = Instant.parse("2026-01-01T00:00:00Z");
|
||||
@BeforeEach void setup() throws Exception {
|
||||
var source = new DriverManagerDataSource("jdbc:h2:mem:care-" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
||||
jdbc = new JdbcTemplate(source);
|
||||
String schema = Files.readString(Path.of("src/main/resources/db/lastleg.sql"));
|
||||
for (String table : List.of("ll_vehicle", "ll_fleet_vehicle_record", "ll_fleet_vehicle_record_history")) {
|
||||
var match = Pattern.compile("(?s)CREATE TABLE(?: IF NOT EXISTS)? " + table + " \\(.*?;").matcher(schema);
|
||||
assertThat(match.find()).as(table).isTrue(); jdbc.execute(match.group().replace(" JSON", " LONGTEXT"));
|
||||
}
|
||||
var config = new MybatisConfiguration();
|
||||
config.addMapper(VehicleMapper.class); config.addMapper(VehicleCareMapper.class); config.addMapper(VehicleCareHistoryMapper.class);
|
||||
var interceptor = new com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor(com.baomidou.mybatisplus.annotation.DbType.H2));
|
||||
config.addInterceptor(interceptor);
|
||||
var factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(source); factory.setConfiguration(config);
|
||||
var session = new SqlSessionTemplate(factory.getObject());
|
||||
var vehicles = new VehiclePersistenceAdapter(session.getMapper(VehicleMapper.class));
|
||||
vehicleA = vehicles.create(vehicle("VEH-A")); vehicleB = vehicles.create(vehicle("VEH-B"));
|
||||
files = mock(VehicleCareFileGateway.class);
|
||||
when(files.upload(anyLong(), anyString(), any())).thenReturn(new VehicleCareModels.File("9001", "photo.png", "image/png", 8));
|
||||
var target = new VehicleCareService(session.getMapper(VehicleCareMapper.class), session.getMapper(VehicleCareHistoryMapper.class), vehicles, files,
|
||||
new ObjectMapper().registerModule(new JavaTimeModule()));
|
||||
var proxy = new ProxyFactory(target); proxy.setProxyTargetClass(true);
|
||||
proxy.addAdvice(new TransactionInterceptor(new DataSourceTransactionManager(source), new AnnotationTransactionAttributeSource()));
|
||||
service = (VehicleCareService) proxy.getProxy();
|
||||
}
|
||||
@Test void recordsAreScopedToVehicleAndNeverRewriteMasterOdometerOrCreateAnotherRecordOnRetry() {
|
||||
var request = new VehicleCareModels.Create("key", maintenance());
|
||||
var a = service.create(vehicleA, "1", request);
|
||||
assertThat(service.create(vehicleA, "1", request).recordNo()).isEqualTo(a.recordNo());
|
||||
var b = service.create(vehicleB, "1", request);
|
||||
assertThat(b.recordNo()).isNotEqualTo(a.recordNo());
|
||||
assertThat(service.page(vehicleA, new VehicleCareModels.Query(1, 20, "MAINTENANCE")).records()).extracting(VehicleCareModels.Response::recordNo).containsExactly(a.recordNo());
|
||||
assertThatThrownBy(() -> service.detail(vehicleB, a.recordNo())).hasMessageContaining("不存在");
|
||||
assertThatThrownBy(() -> service.update(vehicleB, a.recordNo(), "1", new VehicleCareModels.Update(0L, "错误车辆", maintenance()))).hasMessageContaining("不存在");
|
||||
assertThatThrownBy(() -> service.download(vehicleB, a.recordNo(), 9001)).hasMessageContaining("不存在");
|
||||
assertThat(jdbc.queryForList("SELECT mileage_km FROM ll_vehicle", Long.class)).containsOnly(1000L);
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_fleet_vehicle_record_history", Integer.class)).isEqualTo(2);
|
||||
}
|
||||
@Test void correctionKeepsImmutableHistoryAndRejectsStaleVersionOrChangedType() {
|
||||
var row = service.create(vehicleA, "1", new VehicleCareModels.Create("key", maintenance()));
|
||||
assertThatThrownBy(() -> service.create(vehicleA, "1", new VehicleCareModels.Create("key", fuel()))).hasMessageContaining("其他运维记录");
|
||||
assertThatThrownBy(() -> service.update(vehicleA, row.recordNo(), "1", new VehicleCareModels.Update(0L, "变更类型", fuel()))).hasMessageContaining("不能改变");
|
||||
service.update(vehicleA, row.recordNo(), "2", new VehicleCareModels.Update(0L, "补充核对", maintenance()));
|
||||
assertThatThrownBy(() -> service.update(vehicleA, row.recordNo(), "1", new VehicleCareModels.Update(0L, "旧页面", maintenance()))).hasMessageContaining("已变化");
|
||||
var history = service.history(vehicleA, row.recordNo(), 1, 20).records();
|
||||
assertThat(history).extracting(VehicleCareModels.History::action).containsExactly("UPDATE", "CREATE");
|
||||
assertThat(history.get(1).snapshot().updatedBy()).isEqualTo("1");
|
||||
}
|
||||
@Test void failedHistoryWriteRollsBackUpdate() {
|
||||
var row = service.create(vehicleA, "1", new VehicleCareModels.Create("key", fuel()));
|
||||
jdbc.execute("ALTER TABLE ll_fleet_vehicle_record_history ADD CONSTRAINT fail_update CHECK(action <> 'UPDATE')");
|
||||
assertThatThrownBy(() -> service.update(vehicleA, row.recordNo(), "2", new VehicleCareModels.Update(0L, "更正", fuel()))).isInstanceOf(RuntimeException.class);
|
||||
assertThat(service.detail(vehicleA, row.recordNo()).recordVersion()).isZero();
|
||||
assertThat(service.detail(vehicleA, row.recordNo()).updatedBy()).isEqualTo("1");
|
||||
}
|
||||
@Test void uploadRetryReturnsOriginalAssociationAndRejectsAnotherImageOrForeignRecord() {
|
||||
var row = service.create(vehicleA, "1", new VehicleCareModels.Create("key", fuel()));
|
||||
var image = new MockMultipartFile("file", "photo.png", "image/png", new byte[]{1,2,3});
|
||||
var uploaded = service.upload(vehicleA, row.recordNo(), 0, "upload-key", "1", image);
|
||||
assertThat(uploaded.files()).hasSize(1);
|
||||
assertThat(service.upload(vehicleA, row.recordNo(), 0, "upload-key", "1", image).recordVersion()).isEqualTo(1);
|
||||
verify(files, times(1)).upload(anyLong(), eq("1"), any());
|
||||
assertThatThrownBy(() -> service.upload(vehicleA, row.recordNo(), 1, "upload-key", "1",
|
||||
new MockMultipartFile("file", "other.png", "image/png", new byte[]{4}))).hasMessageContaining("不同图片");
|
||||
assertThatThrownBy(() -> service.upload(vehicleB, row.recordNo(), 1, "new-key", "1", image)).hasMessageContaining("不存在");
|
||||
assertThatThrownBy(() -> service.download(vehicleA, row.recordNo(), 9999)).hasMessageContaining("不存在");
|
||||
verify(files, never()).metadata(anyLong(), anyLong());
|
||||
}
|
||||
@Test void explicitUnitsAndTypedFieldsAreRequiredButHistoricalOdometersMayBeBelowTheMaster() {
|
||||
var row = service.create(vehicleA, "1", new VehicleCareModels.Create("fuel", fuel()));
|
||||
assertThat(row.details().distanceUnit()).isEqualTo("MI");
|
||||
assertThat(row.details().fuelUnit()).isEqualTo("US_GAL");
|
||||
assertThat(row.details().odometer()).isEqualByComparingTo("800");
|
||||
var bad = new VehicleCareModels.Draft("FUEL", occurred, "MI", new BigDecimal("800"), null, null, new BigDecimal("10"), "GAL", "PENDING", null, null);
|
||||
assertThatThrownBy(() -> service.create(vehicleA, "1", new VehicleCareModels.Create("bad", bad))).hasMessageContaining("明确");
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_fleet_vehicle_record", Integer.class)).isEqualTo(1);
|
||||
}
|
||||
@Test void concurrentDuplicateCreationCreatesOneBusinessRecordAndOneHistory() throws Exception {
|
||||
var request = new VehicleCareModels.Create("concurrent", fuel());
|
||||
var start = new CountDownLatch(1); var executor = Executors.newFixedThreadPool(2);
|
||||
Callable<String> task = () -> { start.await(5, TimeUnit.SECONDS); return service.create(vehicleA, "1", request).recordNo(); };
|
||||
try {
|
||||
var first = executor.submit(task); var second = executor.submit(task); start.countDown();
|
||||
assertThat(first.get(15, TimeUnit.SECONDS)).isEqualTo(second.get(15, TimeUnit.SECONDS));
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_fleet_vehicle_record", Integer.class)).isEqualTo(1);
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_fleet_vehicle_record_history", Integer.class)).isEqualTo(1);
|
||||
} finally { executor.shutdownNow(); }
|
||||
}
|
||||
@Test void incidentTypesKeepProjectsPlacesAndProcessingFactsIsolatedPerVehicle() {
|
||||
for (String type : List.of("REPAIR", "BREAKDOWN", "RESCUE", "EXCEPTION")) {
|
||||
var row = service.create(vehicleA, "1", new VehicleCareModels.Create(type, incident(type, "PENDING", null, null, null)));
|
||||
assertThat(service.detail(vehicleA, row.recordNo()).details().incident()).isEqualTo(row.details().incident());
|
||||
assertThat(service.page(vehicleA, new VehicleCareModels.Query(1, 20, type)).records()).hasSize(1);
|
||||
assertThat(service.page(vehicleB, new VehicleCareModels.Query(1, 20, type)).total()).isZero();
|
||||
assertThatThrownBy(() -> service.update(vehicleB, row.recordNo(), "1", new VehicleCareModels.Update(0L, "更新处理", row.details()))).hasMessageContaining("不存在");
|
||||
if (List.of("REPAIR", "RESCUE").contains(type)) {
|
||||
assertThat(row.details().incident().item()).isEqualTo("更换轮胎");
|
||||
assertThat(row.details().incident().place()).isEqualTo("实际作业地点");
|
||||
assertThat(row.paymentStatus()).isEqualTo("UNLINKED");
|
||||
}
|
||||
}
|
||||
}
|
||||
@Test void completedRepairDoesNotInventPaymentOrReleaseAndChangingCostKeepsHistory() {
|
||||
var created = service.create(vehicleA, "1", new VehicleCareModels.Create("repair", incident("REPAIR", "PENDING", null, null, null)));
|
||||
var started = service.update(vehicleA, created.recordNo(), "2", new VehicleCareModels.Update(0L, "已安排维修", incident("REPAIR", "IN_PROGRESS", "维修人员", new BigDecimal("120.50"), "USD")));
|
||||
var completed = service.update(vehicleA, created.recordNo(), "2", new VehicleCareModels.Update(started.recordVersion(), "现场处理完成", incident("REPAIR", "COMPLETED", "维修人员", BigDecimal.ZERO, "USD")));
|
||||
assertThat(completed.details().incident().reportedCost()).isEqualByComparingTo("0");
|
||||
assertThat(completed.paymentStatus()).isEqualTo("UNLINKED");
|
||||
assertThat(jdbc.queryForObject("SELECT status FROM ll_vehicle WHERE id=?", String.class, vehicleA)).isEqualTo("IN_SERVICE");
|
||||
var history = service.history(vehicleA, created.recordNo(), 1, 20).records();
|
||||
assertThat(history).hasSize(3);
|
||||
assertThat(history.get(1).snapshot().details().incident().reportedCost()).isEqualByComparingTo("120.50");
|
||||
assertThat(history.get(2).snapshot().details().incident().reportedCost()).isNull();
|
||||
assertThatThrownBy(() -> service.update(vehicleA, created.recordNo(), "1", new VehicleCareModels.Update(0L, "旧请求", created.details()))).hasMessageContaining("已变化");
|
||||
}
|
||||
@Test void incidentValidationRejectsMissingHandlersCurrencyAndMixedFuelFields() {
|
||||
assertThatThrownBy(() -> service.create(vehicleA, "1", new VehicleCareModels.Create("missing-handler", incident("RESCUE", "COMPLETED", null, null, null)))).hasMessageContaining("处理人");
|
||||
assertThatThrownBy(() -> service.create(vehicleA, "1", new VehicleCareModels.Create("missing-currency", incident("RESCUE", "PENDING", null, BigDecimal.ZERO, null)))).hasMessageContaining("币种");
|
||||
assertThatThrownBy(() -> service.create(vehicleA, "1", new VehicleCareModels.Create("invalid-currency", incident("RESCUE", "PENDING", null, BigDecimal.ONE, "ZZZ")))).hasMessageContaining("币种无效");
|
||||
var detail = incident("EXCEPTION", "PENDING", null, null, null);
|
||||
var mixed = new VehicleCareModels.Draft(detail.recordType(), occurred, "KM", BigDecimal.ONE, null, null, null, null, null, null, detail.incident());
|
||||
assertThatThrownBy(() -> service.create(vehicleA, "1", new VehicleCareModels.Create("mixed", mixed))).hasMessageContaining("不能混入");
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_fleet_vehicle_record", Integer.class)).isZero();
|
||||
}
|
||||
private VehicleCareModels.Draft incident(String type, String status, String handler, BigDecimal cost, String currency) {
|
||||
boolean priced = List.of("REPAIR", "RESCUE").contains(type);
|
||||
return new VehicleCareModels.Draft(type, occurred, null, null, null, null, null, null, null, null,
|
||||
new VehicleCareModels.Incident("现场轮胎故障及处理情况", priced ? "更换轮胎" : null, priced ? "实际作业地点" : null,
|
||||
handler, status, "EXCEPTION".equals(type) ? "VEHICLE_BREAKDOWN" : null, cost, currency));
|
||||
}
|
||||
private VehicleCareModels.Draft maintenance() { return new VehicleCareModels.Draft("MAINTENANCE", occurred, "KM", new BigDecimal("800"), new BigDecimal("500"), new BigDecimal("700"), null, null, "PENDING", "已超过计划保养里程", null); }
|
||||
private VehicleCareModels.Draft fuel() { return new VehicleCareModels.Draft("FUEL", occurred, "MI", new BigDecimal("800"), null, null, new BigDecimal("28.6"), "US_GAL", "PENDING", null, null); }
|
||||
private VehicleRepository.NewVehicle vehicle(String plate) { return new VehicleRepository.NewVehicle(plate, "Box Truck", new BigDecimal("12.5"), 1000L, null, null, "OVERSEAS", "OWNED", "IN_SERVICE", null, "1", LocalDateTime.now(), 30, new BigDecimal("18000"), new BigDecimal("90")); }
|
||||
}
|
||||
Reference in New Issue
Block a user