| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418 |
- package com.ruoyi.app.flashdelivery.service;
- import com.baomidou.mybatisplus.core.conditions.Wrapper;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryAddressRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryAddressChangeRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryAddressConfirmRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryTipAddRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryQuoteView;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryCreateRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryProofRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryPricingRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryQuoteRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryDeliverRequest;
- import com.ruoyi.app.flashdelivery.dto.FlashDeliveryRiderOrderPageView;
- import com.ruoyi.app.flashdelivery.exception.FlashDeliveryQuoteChangedException;
- import com.ruoyi.app.flashdelivery.route.FlashDeliveryRouteService;
- import com.ruoyi.app.flashdelivery.route.RouteDistance;
- import com.ruoyi.app.order.RiderDeliveryExclusivityService;
- import com.ruoyi.app.order.RiderDeliveryLockService;
- import com.ruoyi.system.domain.InfoUser;
- import com.ruoyi.system.domain.flash.FlashDeliveryOrder;
- import com.ruoyi.system.domain.flash.FlashDeliveryOrderImage;
- import com.ruoyi.system.domain.flash.FlashDeliveryPricing;
- import com.ruoyi.system.mapper.InfoUserMapper;
- import com.ruoyi.system.mapper.flash.FlashDeliveryOrderImageMapper;
- import com.ruoyi.system.mapper.flash.FlashDeliveryOrderLogMapper;
- import com.ruoyi.system.mapper.flash.FlashDeliveryOrderMapper;
- import com.ruoyi.system.mapper.flash.FlashDeliveryPricingMapper;
- import org.junit.jupiter.api.Test;
- import org.junit.jupiter.api.BeforeAll;
- import org.junit.jupiter.api.AfterAll;
- import org.mockito.ArgumentCaptor;
- import org.mockito.InOrder;
- import org.mockito.MockedStatic;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.support.DefaultListableBeanFactory;
- import org.springframework.context.support.StaticMessageSource;
- import com.ruoyi.common.core.domain.entity.SysDictData;
- import com.ruoyi.common.utils.DictUtils;
- import com.ruoyi.common.utils.spring.SpringUtils;
- import org.springframework.test.util.ReflectionTestUtils;
- import java.math.BigDecimal;
- import java.util.List;
- import java.util.Date;
- import java.util.Calendar;
- import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.ACCEPTED;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
- import static org.junit.jupiter.api.Assertions.assertFalse;
- import static org.junit.jupiter.api.Assertions.assertNull;
- import static org.junit.jupiter.api.Assertions.assertThrows;
- import static org.junit.jupiter.api.Assertions.assertTrue;
- import com.ruoyi.common.exception.ServiceException;
- import static org.mockito.ArgumentMatchers.any;
- import static org.mockito.ArgumentMatchers.anyString;
- import static org.mockito.ArgumentMatchers.eq;
- import static org.mockito.ArgumentMatchers.isNull;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.mockStatic;
- import static org.mockito.Mockito.never;
- import static org.mockito.Mockito.times;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- import static org.mockito.Mockito.doAnswer;
- import static org.mockito.Mockito.inOrder;
- import static org.mockito.Mockito.doThrow;
- class FlashDeliveryApplicationServiceTest {
- private static ConfigurableListableBeanFactory originalBeanFactory;
- @BeforeAll
- static void initializeMessages() {
- originalBeanFactory = (ConfigurableListableBeanFactory)
- ReflectionTestUtils.getField(SpringUtils.class, "beanFactory");
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- StaticMessageSource messageSource = new StaticMessageSource();
- messageSource.setUseCodeAsDefaultMessage(true);
- beanFactory.registerSingleton("messageSource", messageSource);
- new SpringUtils().postProcessBeanFactory(beanFactory);
- }
- @AfterAll
- static void restoreMessages() {
- new SpringUtils().postProcessBeanFactory(originalBeanFactory);
- }
- @Test
- void quoteUsesServerRouteAndCurrentTimePricing() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3001, 600, "ROUTE"));
- var quote = fixture.service.quote(request());
- assertEquals(3001, quote.getDistanceMeters());
- assertEquals(90L, quote.getAmount());
- assertEquals(1L, quote.getPricingId());
- assertEquals("00:00", quote.getStartTime());
- assertEquals("24:00", quote.getEndTime());
- assertEquals("ROUTE", quote.getDistanceSource());
- }
- @Test
- void quoteRejectsRoutesLongerThanFortyKilometres() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(40001, 1800, "ROUTE"));
- assertThrows(ServiceException.class, () -> fixture.service.quote(request()));
- }
- @Test
- void wrongDeliveryPinCannotPersistProofOrChangeState() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- FlashDeliveryOrder order = new FlashDeliveryOrder();
- order.setId(10L);
- order.setRiderId(8L);
- order.setStatus("PICKED_UP");
- order.setPinRequired(true);
- order.setDeliveryPinCode("4821");
- when(fixture.orderMapper.selectById(10L)).thenReturn(order);
- FlashDeliveryDeliverRequest request = new FlashDeliveryDeliverRequest();
- request.setPinCode("1234");
- request.setImageUrls(List.of("https://example.com/delivery.jpg"));
- assertThrows(ServiceException.class, () -> fixture.service.deliver(8L, 10L, request));
- verify(fixture.imageMapper, never()).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderImage.class));
- verify(fixture.orderMapper, never()).transitionByRider(any(), any(), any(), any(), any(), any());
- }
- @Test
- void correctDeliveryPinPersistsDeliveryProofAndChangesState() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- FlashDeliveryOrder order = new FlashDeliveryOrder();
- order.setId(10L);
- order.setRiderId(8L);
- order.setStatus("PICKED_UP");
- order.setPinRequired(true);
- order.setDeliveryPinCode("4821");
- when(fixture.orderMapper.selectById(10L)).thenReturn(order);
- when(fixture.orderMapper.transitionByRider(eq(10L), eq(8L), eq("PICKED_UP"),
- eq("DELIVERED"), eq("delivered_at"), any())).thenReturn(1);
- FlashDeliveryDeliverRequest request = new FlashDeliveryDeliverRequest();
- request.setPinCode("4821");
- request.setImageUrls(List.of("https://example.com/delivery.jpg"));
- fixture.service.deliver(8L, 10L, request);
- ArgumentCaptor<com.ruoyi.system.domain.flash.FlashDeliveryOrderImage> image =
- ArgumentCaptor.forClass(com.ruoyi.system.domain.flash.FlashDeliveryOrderImage.class);
- verify(fixture.imageMapper).insert(image.capture());
- assertEquals("DELIVERY", image.getValue().getProofType());
- assertEquals("RIDER", image.getValue().getOperatorType());
- }
- @Test
- void scheduledCreateGeneratesUserOnlyPinAndStoresRelativeSenderProof() {
- Fixture fixture = new Fixture();
- when(fixture.userMapper.selectOrdinaryUserIdsByNormalizedPhone("0922222222"))
- .thenReturn(List.of(88L));
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- doAnswer(invocation -> {
- FlashDeliveryOrder order = invocation.getArgument(0);
- order.setId(99L);
- return 1;
- }).when(fixture.orderMapper).insert(any(FlashDeliveryOrder.class));
- when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- when(fixture.logMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- FlashDeliveryCreateRequest request = createRequest();
- request.setSenderImageUrls(List.of("/profile/upload/2026/09/07/sender.jpg"));
- var result = fixture.service.create(7L, request);
- assertEquals(4, result.getDeliveryPinCode().length());
- ArgumentCaptor<com.ruoyi.system.domain.flash.FlashDeliveryOrderImage> image =
- ArgumentCaptor.forClass(com.ruoyi.system.domain.flash.FlashDeliveryOrderImage.class);
- verify(fixture.imageMapper).insert(image.capture());
- assertEquals("SENDER", image.getValue().getProofType());
- assertEquals("USER", image.getValue().getOperatorType());
- assertEquals("/profile/upload/2026/09/07/sender.jpg", image.getValue().getImageUrl());
- ArgumentCaptor<FlashDeliveryOrder> saved = ArgumentCaptor.forClass(FlashDeliveryOrder.class);
- verify(fixture.orderMapper).insert(saved.capture());
- assertEquals("SCHEDULED", saved.getValue().getDeliveryMode());
- assertEquals("NORMAL", saved.getValue().getDeliveryType());
- assertEquals("DOCUMENT", saved.getValue().getPackageType());
- assertEquals(1, saved.getValue().getQuantity());
- assertEquals("UP_TO_5_KG", saved.getValue().getWeightRange());
- assertEquals("30 x 20 x 10 cm", saved.getValue().getSpecification());
- assertEquals(88L, saved.getValue().getReceiverUserId());
- assertEquals(1L, saved.getValue().getPricingId());
- assertEquals("00:00", saved.getValue().getPricingStartTime());
- assertEquals("24:00", saved.getValue().getPricingEndTime());
- assertEquals(new BigDecimal("3.00"), saved.getValue().getStartingDistance());
- assertEquals(90L, saved.getValue().getStartingFare());
- assertEquals(new BigDecimal("1.00"), saved.getValue().getDistance());
- assertEquals(15L, saved.getValue().getFreight());
- assertEquals(0L, saved.getValue().getDistanceFee());
- assertEquals(90L, saved.getValue().getBaseDeliveryFee());
- assertEquals(new BigDecimal("20.00"), saved.getValue().getUrgentRate());
- assertEquals(10L, saved.getValue().getMinimumUrgentFee());
- assertEquals(0L, saved.getValue().getUrgentFee());
- assertEquals(0L, saved.getValue().getTipAmount());
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void userListOnlyFiltersByOwnerAndReturnsCardFields() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = order(10L, "COMPLETED");
- order.setWeightRange("OVER_5_TO_10_KG");
- Page<FlashDeliveryOrder> source = new Page<>(1, 10, 1);
- source.setRecords(List.of(order));
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(source);
- var result = fixture.service.userOrders(7L, 1, 10, null);
- ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
- ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
- String sql = query.getValue().getSqlSegment().toLowerCase();
- var parameters = query.getValue().getParamNameValuePairs().values();
- assertTrue(sql.contains("user_id"));
- assertFalse(sql.contains("status"));
- assertFalse(sql.contains("service_type"));
- assertTrue(parameters.contains(7L));
- assertEquals("pickup road", result.getRecords().get(0).getPickupAddress());
- assertEquals("OVER_5_TO_10_KG", result.getRecords().get(0).getWeightRange());
- assertEquals(112L, result.getRecords().get(0).getAmount());
- }
- @Test
- void createDoesNotBindReceiverWhenNormalizedPhoneMatchesMultipleUsers() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- when(fixture.userMapper.selectOrdinaryUserIdsByNormalizedPhone("886912345678"))
- .thenReturn(List.of(88L, 99L));
- doAnswer(invocation -> {
- FlashDeliveryOrder order = invocation.getArgument(0);
- order.setId(99L);
- return 1;
- }).when(fixture.orderMapper).insert(any(FlashDeliveryOrder.class));
- FlashDeliveryCreateRequest request = createRequest();
- request.getDelivery().setPhone("+886 912-345-678");
- fixture.service.create(7L, request);
- ArgumentCaptor<FlashDeliveryOrder> saved = ArgumentCaptor.forClass(FlashDeliveryOrder.class);
- verify(fixture.orderMapper).insert(saved.capture());
- assertNull(saved.getValue().getReceiverUserId());
- }
- @Test
- void createLeavesReceiverUnboundWhenPhoneHasNoRegisteredUser() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- when(fixture.userMapper.selectOrdinaryUserIdsByNormalizedPhone("0922222222"))
- .thenReturn(List.of());
- doAnswer(invocation -> {
- FlashDeliveryOrder order = invocation.getArgument(0);
- order.setId(99L);
- return 1;
- }).when(fixture.orderMapper).insert(any(FlashDeliveryOrder.class));
- fixture.service.create(7L, createRequest());
- ArgumentCaptor<FlashDeliveryOrder> saved = ArgumentCaptor.forClass(FlashDeliveryOrder.class);
- verify(fixture.orderMapper).insert(saved.capture());
- assertNull(saved.getValue().getReceiverUserId());
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void receiverListFiltersByCreationTimeReceiverBinding() {
- Fixture fixture = new Fixture();
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
- fixture.service.userOrders(88L, 1, 10, "receiver");
- ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
- ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
- assertTrue(query.getValue().getSqlSegment().toLowerCase().contains("receiver_user_id"));
- assertTrue(query.getValue().getParamNameValuePairs().values().contains(88L));
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void riderNewTaskUsesFoodOrderParametersAndReturnsPrototypeCardSummary() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- FlashDeliveryOrder order = order(10L, "WAITING_ACCEPTANCE");
- order.setWeightRange("OVER_10_TO_15_KG");
- Page<FlashDeliveryOrder> source = new Page<>(1, 10, 1);
- source.setRecords(List.of(order));
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(source);
- when(fixture.orderMapper.selectObjs(any(Wrapper.class))).thenReturn(List.of(168L));
- SysDictData distanceLimit = new SysDictData();
- distanceLimit.setDictValue("5");
- FlashDeliveryRiderOrderPageView result;
- try (MockedStatic<DictUtils> dictionary = mockStatic(DictUtils.class)) {
- dictionary.when(() -> DictUtils.getDictCache("sys_qs_newtask_distance"))
- .thenReturn(List.of(distanceLimit));
- result = fixture.service.riderOrders(8L, 1, 10, "newTask",
- new BigDecimal("121.5000"), new BigDecimal("25.0000"));
- }
- assertEquals(1L, result.getNearbyTaskCount());
- assertEquals(168L, result.getHighestOrderAmount());
- assertEquals("pickup road", result.getRecords().get(0).getPickupAddress());
- assertEquals("delivery road", result.getRecords().get(0).getDeliveryAddress());
- assertEquals("OVER_10_TO_15_KG", result.getRecords().get(0).getWeightRange());
- assertTrue(result.getRecords().get(0).getPickupDistanceMeters() > 0);
- assertTrue(result.getRecords().get(0).getPinRequired());
- ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
- ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
- String sql = query.getValue().getSqlSegment().toLowerCase();
- var parameters = query.getValue().getParamNameValuePairs().values();
- assertTrue(sql.contains("status"));
- assertTrue(sql.contains("rider_id is null"));
- assertTrue(sql.contains("scheduled_pickup_start_at"));
- assertTrue(sql.contains("st_distance_sphere"));
- assertTrue(parameters.contains("WAITING_ACCEPTANCE"));
- assertTrue(parameters.contains("NOW"));
- assertTrue(parameters.stream().anyMatch(Date.class::isInstance));
- ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> summaryQuery =
- ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
- verify(fixture.orderMapper).selectObjs(summaryQuery.capture());
- String summarySql = summaryQuery.getValue().getSqlSegment().toLowerCase();
- var summaryParameters = summaryQuery.getValue().getParamNameValuePairs().values();
- assertTrue(summarySql.contains("rider_id is null"));
- assertTrue(summarySql.contains("scheduled_pickup_start_at"));
- assertTrue(summarySql.contains("st_distance_sphere"));
- assertTrue(summaryParameters.contains("WAITING_ACCEPTANCE"));
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void riderNewTaskWithoutPositionFallsBackToNewestFirst() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
- when(fixture.orderMapper.selectObjs(any(Wrapper.class))).thenReturn(List.of());
- fixture.service.riderOrders(8L, 1, 10, "newTask", null, null);
- ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
- ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
- String sql = query.getValue().getSqlSegment().toLowerCase();
- assertTrue(sql.contains("order by create_time desc"));
- assertFalse(sql.contains("st_distance_sphere"));
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void riderTabsMapStatusesBeforePagingAndRestrictAssignedTabsToRider() {
- assertRiderTab("toPickup", List.of("ACCEPTED"));
- assertRiderTab("delivering", List.of("PICKED_UP"));
- assertRiderTab("completed", List.of("DELIVERED", "COMPLETED"));
- assertRiderTab("cancelled", List.of("CANCELLED"));
- }
- @Test
- void riderListRejectsUnknownTabAndUnpairedOrInvalidCoordinates() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- assertThrows(ServiceException.class,
- () -> fixture.service.riderOrders(8L, 1, 10, "refund", null, null));
- assertThrows(ServiceException.class,
- () -> fixture.service.riderOrders(8L, 1, 10, null, null, null));
- assertThrows(ServiceException.class,
- () -> fixture.service.riderOrders(8L, 1, 10, "newTask", BigDecimal.ONE, null));
- assertThrows(ServiceException.class,
- () -> fixture.service.riderOrders(8L, 1, 10, "newTask",
- new BigDecimal("181"), BigDecimal.ZERO));
- verify(fixture.orderMapper, never()).selectPage(any(), any());
- }
- @Test
- void flashNewTaskListAndAcceptRequireFlashDeliveryType() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- rider.setDeliveryType("FOOD");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- assertThrows(ServiceException.class,
- () -> fixture.service.riderOrders(8L, 1, 10, "newTask", null, null));
- assertThrows(ServiceException.class, () -> fixture.service.accept(8L, 10L));
- verify(fixture.orderMapper, never()).selectPage(any(), any());
- verify(fixture.orderMapper, never()).accept(any(), any(), any());
- }
- @Test
- void riderDetailHidesWaitingFlashOrdersFromNonFlashRiders() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- rider.setDeliveryType("FOOD");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- when(fixture.orderMapper.selectById(10L)).thenReturn(order(10L, "WAITING_ACCEPTANCE"));
- assertThrows(ServiceException.class, () -> fixture.service.riderDetail(8L, 10L));
- verify(fixture.imageMapper, never()).selectList(any());
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void enabledFlashRiderStillListsNewTasks() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- rider.setDeliveryType("FLASH");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
- fixture.service.riderOrders(8L, 1, 10, "newTask", null, null);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class));
- }
- @Test
- @SuppressWarnings({"rawtypes", "unchecked"})
- void ownOrderTabsRemainAccessibleRegardlessOfDeliveryType() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- rider.setDeliveryType("FOOD");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
- fixture.service.riderOrders(8L, 1, 10, "toPickup", null, null);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class));
- }
- @Test
- void assignedRiderTabsIgnoreLocationParameters() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
- fixture.service.riderOrders(8L, 1, 10, "toPickup",
- new BigDecimal("181"), new BigDecimal("91"));
- verify(fixture.orderMapper).selectPage(any(), any());
- }
- @Test
- void preAcceptRiderDetailIsDirectAndShowsTextAddressWithoutSensitiveFields() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- FlashDeliveryOrder order = order(10L, "WAITING_ACCEPTANCE");
- order.setWeightRange("OVER_15_TO_20_KG");
- when(fixture.orderMapper.selectById(10L)).thenReturn(order);
- var result = fixture.service.riderDetail(8L, 10L);
- assertEquals(10L, result.getId());
- assertEquals("pickup road", result.getPickup().getAddress());
- assertEquals("pickup door", result.getPickup().getAddressDetail());
- assertEquals("delivery road", result.getDelivery().getAddress());
- assertEquals("delivery door", result.getDelivery().getAddressDetail());
- assertEquals("OVER_15_TO_20_KG", result.getWeightRange());
- assertNull(result.getPickup().getName());
- assertNull(result.getPickup().getPhone());
- assertNull(result.getPickup().getLongitude());
- assertNull(result.getPickup().getLatitude());
- assertNull(result.getDelivery().getName());
- assertNull(result.getDelivery().getPhone());
- assertNull(result.getDelivery().getLongitude());
- assertNull(result.getDelivery().getLatitude());
- assertNull(result.getDeliveryPinCode());
- assertNull(result.getUserNote());
- assertTrue(result.getSenderImageUrls().isEmpty());
- assertTrue(result.getPickupImageUrls().isEmpty());
- assertTrue(result.getDeliveryImageUrls().isEmpty());
- verify(fixture.imageMapper, never()).selectList(any());
- verify(fixture.logMapper, never()).selectList(any());
- }
- @Test
- void userDetailReturnsDirectOrderAndGroupsImageUrlsWithoutRawLogs() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = order(10L, ACCEPTED);
- order.setRiderId(null);
- order.setWeightRange("OVER_5_TO_10_KG");
- when(fixture.orderMapper.selectById(10L)).thenReturn(order);
- when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of(
- image("SENDER", "https://example.com/sender.jpg"),
- image("PICKUP", "https://example.com/pickup.jpg"),
- image("DELIVERY", "https://example.com/delivery.jpg")));
- var result = fixture.service.userDetail(7L, 10L);
- assertEquals(10L, result.getId());
- assertEquals(List.of("https://example.com/sender.jpg"), result.getSenderImageUrls());
- assertEquals(List.of("https://example.com/pickup.jpg"), result.getPickupImageUrls());
- assertEquals(List.of("https://example.com/delivery.jpg"), result.getDeliveryImageUrls());
- assertEquals("4821", result.getDeliveryPinCode());
- assertEquals("OVER_5_TO_10_KG", result.getWeightRange());
- verify(fixture.logMapper, never()).selectList(any());
- }
- @Test
- void matchedReceiverCanViewAndConfirmButCannotCancelOrder() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = order(10L, "DELIVERED");
- order.setReceiverUserId(88L);
- when(fixture.orderMapper.selectById(10L)).thenReturn(order);
- when(fixture.orderMapper.transitionByParticipant(eq(10L), eq(88L), eq("DELIVERED"),
- eq("COMPLETED"), any(Date.class))).thenReturn(1);
- when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- assertDoesNotThrow(() -> fixture.service.userDetail(88L, 10L));
- assertDoesNotThrow(() -> fixture.service.confirmReceipt(88L, 10L));
- assertThrows(ServiceException.class,
- () -> fixture.service.userCancel(88L, 10L, new com.ruoyi.app.flashdelivery.dto.FlashDeliveryReasonRequest()));
- verify(fixture.orderMapper).transitionByParticipant(eq(10L), eq(88L), eq("DELIVERED"),
- eq("COMPLETED"), any(Date.class));
- }
- @Test
- void orderWithoutCreationTimeReceiverBindingIsNotClaimedLater() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder historicalOrder = order(10L, "DELIVERED");
- historicalOrder.setReceiverUserId(null);
- when(fixture.orderMapper.selectById(10L)).thenReturn(historicalOrder);
- assertThrows(ServiceException.class, () -> fixture.service.userDetail(88L, 10L));
- verify(fixture.userMapper, never()).selectOrdinaryUserIdsByNormalizedPhone(any());
- }
- @Test
- void pickupRejectsMissingProofBeforeChangingState() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- FlashDeliveryProofRequest request = new FlashDeliveryProofRequest();
- request.setImageUrls(List.of());
- assertThrows(RuntimeException.class, () -> fixture.service.pickup(8L, 10L, request));
- verify(fixture.orderMapper, never()).transitionByRider(any(), any(), any(), any(), any(), any());
- }
- @Test
- void atomicAcceptFailureDoesNotBindSecondRider() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- rider.setDeliveryType("FLASH");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- when(fixture.orderMapper.selectById(10L)).thenReturn(order(10L, "WAITING_ACCEPTANCE"));
- when(fixture.orderMapper.accept(eq(10L), eq(8L), any())).thenReturn(0);
- assertThrows(RuntimeException.class, () -> fixture.service.accept(8L, 10L));
- }
- @Test
- void flashAcceptUsesRiderLockAndChecksExclusivityBeforeAtomicUpdate() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- FlashDeliveryOrder waiting = order(10L, "WAITING_ACCEPTANCE");
- FlashDeliveryOrder accepted = order(10L, ACCEPTED);
- accepted.setRiderId(8L);
- when(fixture.orderMapper.selectById(10L)).thenReturn(waiting, accepted);
- when(fixture.orderMapper.accept(eq(10L), eq(8L), any(Date.class))).thenReturn(1);
- fixture.service.accept(8L, 10L);
- InOrder order = inOrder(fixture.lockService, fixture.exclusivityService, fixture.orderMapper);
- order.verify(fixture.lockService).withLock(eq(8L), any(RiderDeliveryLockService.LockedCall.class));
- order.verify(fixture.exclusivityService).assertCanAcceptFlash(8L, "NORMAL");
- order.verify(fixture.orderMapper).accept(eq(10L), eq(8L), any(Date.class));
- }
- @Test
- void flashExclusiveConflictDoesNotUpdateOrder() {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- when(fixture.orderMapper.selectById(10L)).thenReturn(order(10L, "WAITING_ACCEPTANCE"));
- doThrow(new ServiceException("exclusive"))
- .when(fixture.exclusivityService).assertCanAcceptFlash(8L, "NORMAL");
- assertThrows(ServiceException.class, () -> fixture.service.accept(8L, 10L));
- verify(fixture.orderMapper, never()).accept(any(), any(), any());
- }
- @Test
- void oversizedProofUrlIsRejectedBeforeStateTransition() {
- Fixture fixture = new Fixture();
- InfoUser rider = new InfoUser();
- rider.setUserId(8L);
- rider.setUserType("2");
- when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
- FlashDeliveryProofRequest request = new FlashDeliveryProofRequest();
- request.setImageUrls(List.of("https://example.com/" + "a".repeat(1000)));
- assertThrows(RuntimeException.class, () -> fixture.service.pickup(8L, 10L, request));
- verify(fixture.orderMapper, never()).transitionByRider(any(), any(), any(), any(), any(), any());
- }
- @Test
- void missingServiceTypeReturnsBusinessErrorInsteadOfNullPointer() {
- Fixture fixture = new Fixture();
- FlashDeliveryQuoteRequest request = request();
- request.setServiceType(null);
- assertThrows(ServiceException.class, () -> fixture.service.quote(request));
- }
- @Test
- void equalTextAddressesAreRejectedEvenWhenCoordinatesDiffer() {
- Fixture fixture = new Fixture();
- FlashDeliveryQuoteRequest request = request();
- request.getDelivery().setAddress(request.getPickup().getAddress());
- request.getDelivery().setAddressDetail(request.getPickup().getAddressDetail());
- assertThrows(ServiceException.class, () -> fixture.service.quote(request));
- }
- @Test
- void concurrentPricingUpdateIsRejected() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectById(1L)).thenReturn(pricing());
- when(fixture.pricingMapper.countOverlapping("00:00", "12:00", 1L)).thenReturn(0);
- when(fixture.pricingMapper.update(isNull(), any(Wrapper.class))).thenReturn(0);
- FlashDeliveryPricingRequest request = pricingRequest();
- request.setEndTime("12:00");
- request.setConfigVersion(1);
- assertThrows(ServiceException.class,
- () -> fixture.service.updatePricing(1L, 1L, request));
- verify(fixture.pricingMapper, never()).updateById(any(FlashDeliveryPricing.class));
- }
- @Test
- void overlappingPricingPeriodIsRejectedBeforeInsert() {
- Fixture fixture = new Fixture();
- FlashDeliveryPricingRequest request = pricingRequest();
- when(fixture.pricingMapper.countOverlapping("00:00", "24:00", null)).thenReturn(1);
- assertThrows(ServiceException.class, () -> fixture.service.createPricing(1L, request));
- request.setDistance(new BigDecimal("0.004"));
- assertThrows(ServiceException.class, () -> fixture.service.createPricing(1L, request));
- verify(fixture.pricingMapper, never()).insert(any(FlashDeliveryPricing.class));
- }
- @Test
- void pricingDistanceHalfCentimetreNormalizesToDatabaseMinimum() {
- Fixture fixture = new Fixture();
- FlashDeliveryPricingRequest request = pricingRequest();
- request.setDistance(new BigDecimal("0.005"));
- fixture.service.createPricing(1L, request);
- ArgumentCaptor<FlashDeliveryPricing> saved = ArgumentCaptor.forClass(FlashDeliveryPricing.class);
- verify(fixture.pricingMapper).insert(saved.capture());
- assertEquals(new BigDecimal("0.01"), saved.getValue().getDistance());
- }
- @Test
- void pricingDistanceThatRoundsToZeroIsRejectedBeforePersistence() {
- Fixture fixture = new Fixture();
- FlashDeliveryPricingRequest request = pricingRequest();
- request.setDistance(new BigDecimal("0.001"));
- assertThrows(ServiceException.class, () -> fixture.service.createPricing(1L, request));
- verify(fixture.pricingMapper, never()).insert(any(FlashDeliveryPricing.class));
- }
- @Test
- void createPricingPersistsImmediatelyActiveTimePeriod() {
- Fixture fixture = new Fixture();
- FlashDeliveryPricingRequest request = pricingRequest();
- when(fixture.pricingMapper.countOverlapping("00:00", "24:00", null)).thenReturn(0);
- fixture.service.createPricing(7L, request);
- ArgumentCaptor<FlashDeliveryPricing> saved = ArgumentCaptor.forClass(FlashDeliveryPricing.class);
- verify(fixture.pricingMapper).insert(saved.capture());
- assertEquals(1, saved.getValue().getConfigVersion());
- assertEquals(7L, saved.getValue().getUpdatedBy());
- assertEquals(90L, saved.getValue().getStartingFare());
- InOrder writeOrder = inOrder(fixture.pricingMapper);
- writeOrder.verify(fixture.pricingMapper)
- .countOverlapping("00:00", "24:00", null);
- writeOrder.verify(fixture.pricingMapper).insert(any(FlashDeliveryPricing.class));
- }
- @Test
- void homeOmitsServiceWithoutCurrentPricingPeriod() {
- Fixture fixture = new Fixture();
- assertTrue(fixture.service.home().getServices().isEmpty());
- }
- @Test
- void quoteWithoutCurrentPricingPeriodFailsBeforeRouteLookup() {
- Fixture fixture = new Fixture();
- assertThrows(ServiceException.class, () -> fixture.service.quote(request()));
- verify(fixture.routeService, never()).calculate(any(), any());
- }
- @Test
- void multipleCurrentPricingPeriodsFailExplicitlyBeforeRouteLookup() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString()))
- .thenReturn(List.of(pricing(), pricing()));
- assertThrows(ServiceException.class, () -> fixture.service.quote(request()));
- verify(fixture.routeService, never()).calculate(any(), any());
- }
- @Test
- void updatingPricingChecksOverlapBeforeVersionedWrite() {
- Fixture fixture = new Fixture();
- FlashDeliveryPricing existing = pricing();
- when(fixture.pricingMapper.selectById(1L)).thenReturn(existing);
- when(fixture.pricingMapper.update(isNull(), any(Wrapper.class))).thenReturn(1);
- FlashDeliveryPricingRequest request = pricingRequest();
- request.setConfigVersion(1);
- fixture.service.updatePricing(9L, 1L, request);
- InOrder writeOrder = inOrder(fixture.pricingMapper);
- writeOrder.verify(fixture.pricingMapper)
- .countOverlapping("00:00", "24:00", 1L);
- writeOrder.verify(fixture.pricingMapper).update(isNull(), any(Wrapper.class));
- }
- @Test
- void deletePricingRemovesConfigurationImmediately() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectById(18L)).thenReturn(pricing());
- when(fixture.pricingMapper.deleteById(18L)).thenReturn(1);
- fixture.service.deletePricing(18L);
- verify(fixture.pricingMapper).deleteById(18L);
- }
- @Test
- void urgentQuoteReturnsSeparatedFeesAndUsesScheduledPickupTime() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime("16:30")).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(6000, 900, "ROUTE"));
- FlashDeliveryQuoteRequest request = request();
- request.setDeliveryType("URGENT");
- request.setTipAmount(5L);
- request.setDeliveryMode("SCHEDULED");
- Calendar calendar = Calendar.getInstance();
- calendar.add(Calendar.DAY_OF_MONTH, 1);
- calendar.set(Calendar.HOUR_OF_DAY, 16);
- calendar.set(Calendar.MINUTE, 30);
- calendar.set(Calendar.SECOND, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- request.setScheduledPickupStartAt(calendar.getTime());
- request.setScheduledPickupEndAt(new Date(calendar.getTimeInMillis() + 30L * 60L * 1000L));
- var quote = fixture.service.quote(request);
- assertEquals(45L, quote.getDistanceFee());
- assertEquals(135L, quote.getBaseDeliveryFee());
- assertEquals(27L, quote.getUrgentFee());
- assertEquals(5L, quote.getTipAmount());
- assertEquals(167L, quote.getAmount());
- verify(fixture.pricingMapper).selectAtTime("16:30");
- }
- @Test
- void createRejectsChangedQuoteAndReturnsLatestQuoteWithoutInsert() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- FlashDeliveryCreateRequest request = createRequest();
- request.setQuotedAmount(91L);
- FlashDeliveryQuoteChangedException error = assertThrows(FlashDeliveryQuoteChangedException.class,
- () -> fixture.service.create(7L, request));
- assertEquals(90L, error.getLatestQuote().getAmount());
- assertEquals(1L, error.getLatestQuote().getPricingId());
- verify(fixture.orderMapper, never()).insert(any(FlashDeliveryOrder.class));
- }
- @Test
- void createDefaultsPayTypeToCashAndStoresTransferSelection() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- doAnswer(invocation -> {
- FlashDeliveryOrder order = invocation.getArgument(0);
- order.setId(99L);
- return 1;
- }).when(fixture.orderMapper).insert(any(FlashDeliveryOrder.class));
- when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- when(fixture.logMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- var defaultResult = fixture.service.create(7L, createRequest());
- FlashDeliveryCreateRequest transfer = createRequest();
- transfer.setPayType("6");
- var transferResult = fixture.service.create(7L, transfer);
- ArgumentCaptor<FlashDeliveryOrder> saved = ArgumentCaptor.forClass(FlashDeliveryOrder.class);
- verify(fixture.orderMapper, times(2)).insert(saved.capture());
- assertEquals("4", saved.getAllValues().get(0).getPayType());
- assertEquals("6", saved.getAllValues().get(1).getPayType());
- assertEquals("4", defaultResult.getPayType());
- assertEquals("6", transferResult.getPayType());
- }
- @Test
- void createRejectsUnsupportedPayType() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- FlashDeliveryCreateRequest request = createRequest();
- request.setPayType("2");
- assertThrows(ServiceException.class, () -> fixture.service.create(7L, request));
- verify(fixture.orderMapper, never()).insert(any(FlashDeliveryOrder.class));
- }
- @Test
- void quoteValidatesDeliveryLevelAndCompleteItemInformation() {
- Fixture fixture = new Fixture();
- FlashDeliveryQuoteRequest request = request();
- request.setDeliveryType("FAST");
- FlashDeliveryQuoteRequest invalidDeliveryType = request;
- assertThrows(ServiceException.class, () -> fixture.service.quote(invalidDeliveryType));
- request = request();
- request.setQuantity(0);
- FlashDeliveryQuoteRequest invalidQuantity = request;
- assertThrows(ServiceException.class, () -> fixture.service.quote(invalidQuantity));
- request = request();
- request.setWeightRange("SMALL");
- FlashDeliveryQuoteRequest oldWeightRange = request;
- assertThrows(ServiceException.class, () -> fixture.service.quote(oldWeightRange));
- }
- @Test
- void quoteAcceptsAllFourWeightRanges() {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- for (String weightRange : List.of("UP_TO_5_KG", "OVER_5_TO_10_KG",
- "OVER_10_TO_15_KG", "OVER_15_TO_20_KG")) {
- FlashDeliveryQuoteRequest request = request();
- request.setWeightRange(weightRange);
- var quote = assertDoesNotThrow(() -> fixture.service.quote(request), weightRange);
- assertEquals(90L, quote.getAmount(), weightRange);
- }
- }
- @Test
- void createPersistsAndReturnsEveryWeightRange() {
- for (String weightRange : List.of("UP_TO_5_KG", "OVER_5_TO_10_KG",
- "OVER_10_TO_15_KG", "OVER_15_TO_20_KG")) {
- Fixture fixture = new Fixture();
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(3200, 600, "ROUTE"));
- doAnswer(invocation -> {
- FlashDeliveryOrder order = invocation.getArgument(0);
- order.setId(99L);
- return 1;
- }).when(fixture.orderMapper).insert(any(FlashDeliveryOrder.class));
- when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- when(fixture.logMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
- FlashDeliveryCreateRequest request = createRequest();
- request.setWeightRange(weightRange);
- var result = fixture.service.create(7L, request);
- ArgumentCaptor<FlashDeliveryOrder> saved = ArgumentCaptor.forClass(FlashDeliveryOrder.class);
- verify(fixture.orderMapper).insert(saved.capture());
- assertEquals(weightRange, saved.getValue().getWeightRange());
- assertEquals(weightRange, result.getWeightRange());
- }
- }
- @Test
- void quoteRejectsMissingAndUnknownWeightRanges() {
- Fixture fixture = new Fixture();
- for (String weightRange : new String[]{null, "", "SMALL", "OVER_20_KG"}) {
- FlashDeliveryQuoteRequest request = request();
- request.setWeightRange(weightRange);
- assertThrows(ServiceException.class, () -> fixture.service.quote(request), String.valueOf(weightRange));
- }
- }
- private FlashDeliveryQuoteRequest request() {
- FlashDeliveryQuoteRequest request = new FlashDeliveryQuoteRequest();
- request.setServiceType("HELP_SEND");
- request.setDeliveryType("NORMAL");
- request.setPackageType("DOCUMENT");
- request.setQuantity(1);
- request.setWeightRange("UP_TO_5_KG");
- request.setSpecification("30 x 20 x 10 cm");
- request.setTipAmount(0L);
- request.setDeliveryMode("NOW");
- request.setPickup(address("A", "0911111111", "25.0330", "121.5645"));
- request.setDelivery(address("B", "0922222222", "25.0478", "121.5319"));
- request.getDelivery().setAddress("second road");
- return request;
- }
- private FlashDeliveryCreateRequest createRequest() {
- FlashDeliveryCreateRequest request = new FlashDeliveryCreateRequest();
- FlashDeliveryQuoteRequest quote = request();
- request.setServiceType(quote.getServiceType());
- request.setDeliveryType(quote.getDeliveryType());
- request.setPackageType(quote.getPackageType());
- request.setQuantity(quote.getQuantity());
- request.setWeightRange(quote.getWeightRange());
- request.setSpecification(quote.getSpecification());
- request.setTipAmount(quote.getTipAmount());
- request.setPickup(quote.getPickup());
- request.setDelivery(quote.getDelivery());
- request.setClientRequestId("flash-scheduled-001");
- request.setDeliveryMode("SCHEDULED");
- Date start = new Date(System.currentTimeMillis() + 60L * 60L * 1000L);
- request.setScheduledPickupStartAt(start);
- request.setScheduledPickupEndAt(new Date(start.getTime() + 30L * 60L * 1000L));
- request.setPinRequired(true);
- request.setPricingId(1L);
- request.setPricingVersion(1);
- request.setQuotedBaseDeliveryFee(90L);
- request.setQuotedDistanceFee(0L);
- request.setQuotedUrgentFee(0L);
- request.setQuotedAmount(90L);
- request.setSenderImageUrls(List.of("https://example.com/sender.jpg"));
- return request;
- }
- private FlashDeliveryAddressRequest address(String name, String phone, String lat, String lon) {
- FlashDeliveryAddressRequest address = new FlashDeliveryAddressRequest();
- address.setName(name);
- address.setPhone(phone);
- address.setAddress("road");
- address.setAddressDetail("door");
- address.setLatitude(new BigDecimal(lat));
- address.setLongitude(new BigDecimal(lon));
- return address;
- }
- private FlashDeliveryPricing pricing() {
- FlashDeliveryPricing pricing = new FlashDeliveryPricing();
- pricing.setId(1L);
- pricing.setStartTime("00:00");
- pricing.setEndTime("24:00");
- pricing.setStartingDistance(new BigDecimal("3.00"));
- pricing.setStartingFare(90L);
- pricing.setDistance(new BigDecimal("1.00"));
- pricing.setFreight(15L);
- pricing.setUrgentRate(new BigDecimal("20.00"));
- pricing.setMinimumUrgentFee(10L);
- pricing.setConfigVersion(1);
- return pricing;
- }
- private FlashDeliveryPricingRequest pricingRequest() {
- FlashDeliveryPricingRequest request = new FlashDeliveryPricingRequest();
- request.setStartTime("00:00");
- request.setEndTime("24:00");
- request.setStartingDistance(new BigDecimal("3.00"));
- request.setStartingFare(90L);
- request.setDistance(new BigDecimal("1.00"));
- request.setFreight(15L);
- request.setUrgentRate(new BigDecimal("20.00"));
- request.setMinimumUrgentFee(10L);
- return request;
- }
- @SuppressWarnings({"rawtypes", "unchecked"})
- private void assertRiderTab(String tab, List<String> statuses) {
- Fixture fixture = new Fixture();
- rider(fixture, 8L);
- when(fixture.orderMapper.selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class),
- any(Wrapper.class))).thenReturn(new Page<FlashDeliveryOrder>());
- fixture.service.riderOrders(8L, 1, 10, tab, null, null);
- ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.QueryWrapper> query =
- ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper.class);
- verify(fixture.orderMapper).selectPage(any(com.baomidou.mybatisplus.core.metadata.IPage.class), query.capture());
- // MyBatis-Plus 的条件参数在渲染 SQL 段时才写入参数表,必须先取 SQL 再断言参数。
- String sql = query.getValue().getSqlSegment();
- assertTrue(sql.contains("rider_id"), tab);
- var parameters = query.getValue().getParamNameValuePairs().values();
- assertTrue(parameters.contains(8L), tab);
- for (String status : statuses) assertTrue(parameters.contains(status), tab + ":" + status);
- }
- private void rider(Fixture fixture, Long riderId) {
- InfoUser rider = new InfoUser();
- rider.setUserId(riderId);
- rider.setUserType("2");
- rider.setDeliveryType("FLASH");
- when(fixture.userMapper.selectInfoUserByUserId(riderId)).thenReturn(rider);
- }
- private FlashDeliveryOrder order(Long id, String status) {
- FlashDeliveryOrder order = new FlashDeliveryOrder();
- order.setId(id);
- order.setOrderNo("FL-20260813-021");
- order.setUserId(7L);
- order.setServiceType("HELP_SEND");
- order.setDeliveryType("NORMAL");
- order.setStatus(status);
- order.setPackageType("DOCUMENT");
- order.setQuantity(1);
- order.setWeightRange("UP_TO_5_KG");
- order.setDeliveryMode("NOW");
- order.setPinRequired(true);
- order.setDeliveryPinCode("4821");
- order.setPickupName("pickup contact");
- order.setPickupPhone("0911111111");
- order.setPickupAddress("pickup road");
- order.setPickupAddressDetail("pickup door");
- order.setPickupCity("台北市");
- order.setPickupArea("中山區");
- order.setPickupLongitude(new BigDecimal("121.5100"));
- order.setPickupLatitude(new BigDecimal("25.0100"));
- order.setDeliveryName("delivery contact");
- order.setDeliveryPhone("0922222222");
- order.setDeliveryAddress("delivery road");
- order.setDeliveryAddressDetail("delivery door");
- order.setDeliveryCity("台北市");
- order.setDeliveryArea("大安區");
- order.setDeliveryLongitude(new BigDecimal("121.5200"));
- order.setDeliveryLatitude(new BigDecimal("25.0200"));
- order.setDistanceMeters(3200);
- order.setEstimatedDurationSeconds(2100);
- order.setDistanceFee(12L);
- order.setBaseDeliveryFee(102L);
- order.setUrgentRate(new BigDecimal("20.00"));
- order.setMinimumUrgentFee(10L);
- order.setUrgentFee(0L);
- order.setTipAmount(10L);
- order.setAmount(112L);
- order.setCurrency("TWD");
- order.setUserNote("private note");
- order.setCreateTime(new Date());
- return order;
- }
- private FlashDeliveryOrderImage image(String proofType, String url) {
- FlashDeliveryOrderImage image = new FlashDeliveryOrderImage();
- image.setProofType(proofType);
- image.setImageUrl(url);
- return image;
- }
- @Test
- void missingOrInvalidBodyOrderIdIsRejectedBeforeDatabaseAccess() {
- Fixture fixture = new Fixture();
- for (Long orderId : java.util.Arrays.asList(null, 0L, -1L)) {
- ServiceException addressFailure = assertThrows(ServiceException.class,
- () -> fixture.service.updateAddress(7L, orderId, new FlashDeliveryAddressConfirmRequest()));
- ServiceException tipFailure = assertThrows(ServiceException.class,
- () -> fixture.service.addTip(7L, orderId, tipRequest(20L, 2)));
- assertEquals("flash.delivery.order.not.found", addressFailure.getMessage());
- assertEquals("flash.delivery.order.not.found", tipFailure.getMessage());
- }
- org.mockito.Mockito.verifyNoInteractions(fixture.orderMapper);
- }
- @Test
- void addressQuoteUsesLatestPricingForSlotTimeAndDoesNotWrite() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- // 已到预约时间也允许待接单订单改地址;报价读取该时点的最新运价而非订单旧快照。
- order.setDeliveryMode("SCHEDULED");
- order.setScheduledPickupStartAt(new Date(1));
- order.setScheduledPickupEndAt(new Date(1800001));
- FlashDeliveryQuoteView quote = fixture.service.quoteAddress(7L, 10L, addressChange());
- assertEquals(4500, quote.getDistanceMeters());
- assertEquals(900, quote.getEstimatedDurationSeconds());
- assertEquals(23L, quote.getDistanceFee());
- assertEquals(113L, quote.getBaseDeliveryFee());
- assertEquals(10L, quote.getTipAmount());
- assertEquals(123L, quote.getAmount());
- assertEquals(2, quote.getOrderVersion());
- assertEquals(1, quote.getPricingVersion());
- assertEquals("pickup road", order.getPickupAddress());
- // 改址报价必须查询运价表(按定价时点取最新),不再沿用订单快照
- verify(fixture.pricingMapper).selectAtTime(anyString());
- verify(fixture.orderMapper, never()).updateWaitingAddress(any(), any());
- verify(fixture.logMapper, never()).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderLog.class));
- }
- @Test
- void addressSaveUpdatesBothEndsRouteFeesAndReceiverTogether() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- when(fixture.userMapper.selectOrdinaryUserIdsByNormalizedPhone("0922222222"))
- .thenReturn(List.of(88L));
- when(fixture.orderMapper.updateWaitingAddress(any(), eq(2))).thenReturn(1);
- FlashDeliveryAddressConfirmRequest input = confirmAddress(fixture);
- input.getPickup().setName(" new sender ");
- input.getPickup().setAddressDetail(null);
- input.getDelivery().setName("new receiver");
- var view = fixture.service.updateAddress(7L, 10L, input);
- assertEquals("new sender", view.getPickup().getName());
- assertEquals("new receiver", view.getDelivery().getName());
- assertNull(view.getPickup().getAddressDetail());
- assertEquals(4500, view.getDistanceMeters());
- assertEquals(123L, view.getAmount());
- assertEquals(3, view.getOrderVersion());
- assertEquals(88L, order.getReceiverUserId());
- assertEquals(10L, order.getTipAmount());
- assertEquals("WAITING_ACCEPTANCE", order.getStatus());
- verify(fixture.orderMapper).updateWaitingAddress(order, 2);
- verify(fixture.logMapper).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderLog.class));
- }
- @Test
- void addressChangeClearsFormerReceiverWhenNewPhoneDoesNotMatch() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- order.setReceiverUserId(88L);
- when(fixture.orderMapper.updateWaitingAddress(any(), eq(2))).thenReturn(1);
- fixture.service.updateAddress(7L, 10L, confirmAddress(fixture));
- assertNull(order.getReceiverUserId());
- }
- @Test
- void addressQuotePreservesUrgentRulesAndExistingTip() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- order.setDeliveryType("URGENT");
- var quote = fixture.service.quoteAddress(7L, 10L, addressChange());
- assertEquals(23L, quote.getUrgentFee());
- assertEquals(146L, quote.getAmount());
- assertEquals(10L, quote.getTipAmount());
- }
- @Test
- void changedRouteOrUnconfirmedPriceReturnsLatestQuoteWithoutSaving() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- FlashDeliveryAddressConfirmRequest input = confirmAddress(fixture);
- input.setQuotedAmount(1L);
- var exception = assertThrows(FlashDeliveryQuoteChangedException.class,
- () -> fixture.service.updateAddress(7L, 10L, input));
- assertEquals(123L, exception.getLatestQuote().getAmount());
- input.setQuotedAmount(123L);
- input.setQuotedDistanceMeters(4499);
- assertThrows(FlashDeliveryQuoteChangedException.class,
- () -> fixture.service.updateAddress(7L, 10L, input));
- input.setQuotedDistanceMeters(4500);
- input.setQuotedUrgentFee(null);
- assertThrows(FlashDeliveryQuoteChangedException.class,
- () -> fixture.service.updateAddress(7L, 10L, input));
- verify(fixture.orderMapper, never()).updateWaitingAddress(any(), any());
- verify(fixture.logMapper, never()).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderLog.class));
- }
- @Test
- void receiverAndOtherUsersCannotQuoteEditOrAddTip() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- order.setReceiverUserId(88L);
- for (Long user : List.of(88L, 99L)) {
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(user, 10L, addressChange()));
- assertThrows(ServiceException.class, () -> fixture.service.updateAddress(user, 10L, new FlashDeliveryAddressConfirmRequest()));
- assertThrows(ServiceException.class, () -> fixture.service.addTip(user, 10L, tipRequest(5L, 2)));
- }
- verify(fixture.routeService, never()).calculate(any(), any());
- verify(fixture.orderMapper, never()).updateWaitingTip(any(), any());
- }
- @Test
- void everyNonWaitingStateAndAssignedRiderRejectsBothChanges() {
- for (String status : List.of("ACCEPTED", "PICKED_UP", "DELIVERED", "COMPLETED", "CANCELLED")) {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- order.setStatus(status);
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(7L, 10L, addressChange()));
- assertThrows(ServiceException.class, () -> fixture.service.updateAddress(7L, 10L, new FlashDeliveryAddressConfirmRequest()));
- assertThrows(ServiceException.class, () -> fixture.service.addTip(7L, 10L, tipRequest(5L, 2)));
- }
- Fixture fixture = new Fixture();
- editableOrder(fixture).setRiderId(8L);
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(7L, 10L, addressChange()));
- assertThrows(ServiceException.class, () -> fixture.service.addTip(7L, 10L, tipRequest(5L, 2)));
- }
- @Test
- void staleOrMissingVersionCannotOverwriteNewerOrder() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- FlashDeliveryAddressChangeRequest input = addressChange();
- input.setOrderVersion(1);
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(7L, 10L, input));
- for (Integer version : java.util.Arrays.asList(null, -1, 1)) {
- assertThrows(ServiceException.class,
- () -> fixture.service.addTip(7L, 10L, tipRequest(5L, version)));
- }
- verify(fixture.orderMapper, never()).updateWaitingTip(any(), any());
- }
- @Test
- void addressValidationRejectsSameInvalidAndOverDistanceEndpoints() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- FlashDeliveryAddressChangeRequest input = addressChange();
- input.setDelivery(input.getPickup());
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(7L, 10L, input));
- input.setDelivery(request().getDelivery());
- input.getPickup().setPhone("");
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(7L, 10L, input));
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(40001, 1000, "GOOGLE"));
- assertThrows(ServiceException.class, () -> fixture.service.quoteAddress(7L, 10L, addressChange()));
- verify(fixture.orderMapper, never()).updateWaitingAddress(any(), any());
- }
- @Test
- void riderAcceptanceBetweenReadAndAddressSaveRejectsWriteWithoutLog() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- FlashDeliveryAddressConfirmRequest input = confirmAddress(fixture);
- when(fixture.orderMapper.updateWaitingAddress(any(), eq(2))).thenReturn(0);
- ServiceException exception = assertThrows(ServiceException.class,
- () -> fixture.service.updateAddress(7L, 10L, input));
- assertEquals("flash.delivery.state.changed", exception.getMessage());
- verify(fixture.logMapper, never()).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderLog.class));
- }
- @Test
- void addingTipOnlyIncreasesTipAndTotalAndRejectsSameVersionRetry() {
- Fixture fixture = new Fixture();
- FlashDeliveryOrder order = editableOrder(fixture);
- when(fixture.orderMapper.updateWaitingTip(any(), eq(2))).thenReturn(1);
- var view = fixture.service.addTip(7L, 10L, tipRequest(20L, 2));
- assertEquals(30L, view.getTipAmount());
- assertEquals(132L, view.getAmount());
- assertEquals(102L, view.getBaseDeliveryFee());
- assertEquals(3200, view.getDistanceMeters());
- assertEquals(3, view.getOrderVersion());
- assertThrows(ServiceException.class, () -> fixture.service.addTip(7L, 10L, tipRequest(20L, 2)));
- assertEquals(30L, order.getTipAmount());
- verify(fixture.orderMapper).updateWaitingTip(any(), eq(2));
- verify(fixture.routeService, never()).calculate(any(), any());
- verify(fixture.pricingMapper, never()).selectAtTime(anyString());
- }
- @Test
- void tipChangeInvalidatesEarlierAddressConfirmation() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- FlashDeliveryAddressConfirmRequest confirmation = confirmAddress(fixture);
- when(fixture.orderMapper.updateWaitingTip(any(), eq(2))).thenReturn(1);
- fixture.service.addTip(7L, 10L, tipRequest(20L, 2));
- assertThrows(ServiceException.class, () -> fixture.service.updateAddress(7L, 10L, confirmation));
- verify(fixture.orderMapper, never()).updateWaitingAddress(any(), any());
- }
- @Test
- void additionalTipRejectsFractionalJsonBeforeWriting() throws Exception {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- when(fixture.orderMapper.updateWaitingTip(any(), eq(2))).thenReturn(1);
- FlashDeliveryTipAddRequest input = new com.fasterxml.jackson.databind.ObjectMapper().readValue(
- "{\"orderVersion\":2,\"additionalTipAmount\":1.9}", FlashDeliveryTipAddRequest.class);
- ServiceException exception = assertThrows(ServiceException.class,
- () -> fixture.service.addTip(7L, 10L, input));
- assertEquals("flash.delivery.tip.additional.invalid", exception.getMessage());
- verify(fixture.orderMapper, never()).updateWaitingTip(any(), any());
- }
- @Test
- void additionalTipRejectsJsonAmountBeyondLongRange() throws Exception {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- FlashDeliveryTipAddRequest input = new com.fasterxml.jackson.databind.ObjectMapper().readValue(
- "{\"orderVersion\":2,\"additionalTipAmount\":1e100}", FlashDeliveryTipAddRequest.class);
- ServiceException exception = assertThrows(ServiceException.class,
- () -> fixture.service.addTip(7L, 10L, input));
- assertEquals("flash.delivery.tip.additional.invalid", exception.getMessage());
- verify(fixture.orderMapper, never()).updateWaitingTip(any(), any());
- }
- @Test
- void additionalTipRejectsZeroNegativeNullAndOverflow() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- for (Long value : java.util.Arrays.asList(null, 0L, -1L, Long.MAX_VALUE)) {
- assertThrows(ServiceException.class,
- () -> fixture.service.addTip(7L, 10L, tipRequest(value, 2)));
- }
- verify(fixture.orderMapper, never()).updateWaitingTip(any(), any());
- }
- @Test
- void riderAcceptanceBetweenReadAndTipSaveRejectsWriteWithoutLog() {
- Fixture fixture = new Fixture();
- editableOrder(fixture);
- when(fixture.orderMapper.updateWaitingTip(any(), eq(2))).thenReturn(0);
- assertThrows(ServiceException.class, () -> fixture.service.addTip(7L, 10L, tipRequest(20L, 2)));
- verify(fixture.logMapper, never()).insert(any(com.ruoyi.system.domain.flash.FlashDeliveryOrderLog.class));
- }
- private FlashDeliveryOrder editableOrder(Fixture fixture) {
- FlashDeliveryOrder order = order(10L, "WAITING_ACCEPTANCE");
- order.setRiderId(null);
- order.setVersion(2);
- order.setPricingId(1L);
- order.setPricingVersion(1);
- order.setPricingStartTime("00:00");
- order.setPricingEndTime("24:00");
- order.setStartingDistance(new BigDecimal("3.00"));
- order.setStartingFare(90L);
- order.setDistance(new BigDecimal("1.00"));
- order.setFreight(15L);
- when(fixture.orderMapper.selectById(10L)).thenReturn(order);
- when(fixture.routeService.calculate(any(), any())).thenReturn(new RouteDistance(4500, 900, "GOOGLE"));
- // 031 后改址按订单定价时点读最新运价:stub 与订单快照同值,金额断言维持不变
- when(fixture.pricingMapper.selectAtTime(anyString())).thenReturn(List.of(pricing()));
- return order;
- }
- private FlashDeliveryAddressChangeRequest addressChange() {
- FlashDeliveryAddressChangeRequest input = new FlashDeliveryAddressChangeRequest();
- input.setOrderVersion(2);
- input.setPickup(request().getPickup());
- input.setDelivery(request().getDelivery());
- return input;
- }
- private FlashDeliveryAddressConfirmRequest confirmAddress(Fixture fixture) {
- FlashDeliveryAddressChangeRequest change = addressChange();
- FlashDeliveryQuoteView quote = fixture.service.quoteAddress(7L, 10L, change);
- FlashDeliveryAddressConfirmRequest input = new FlashDeliveryAddressConfirmRequest();
- input.setOrderVersion(quote.getOrderVersion());
- input.setPickup(change.getPickup());
- input.setDelivery(change.getDelivery());
- input.setQuotedDistanceMeters(quote.getDistanceMeters());
- input.setQuotedBaseDeliveryFee(quote.getBaseDeliveryFee());
- input.setQuotedDistanceFee(quote.getDistanceFee());
- input.setQuotedUrgentFee(quote.getUrgentFee());
- input.setQuotedAmount(quote.getAmount());
- return input;
- }
- private FlashDeliveryTipAddRequest tipRequest(Long amount, Integer version) {
- FlashDeliveryTipAddRequest input = new FlashDeliveryTipAddRequest();
- input.setAdditionalTipAmount(amount == null ? null : BigDecimal.valueOf(amount));
- input.setOrderVersion(version);
- return input;
- }
- private static class Fixture {
- final FlashDeliveryOrderMapper orderMapper = mock(FlashDeliveryOrderMapper.class);
- final FlashDeliveryPricingMapper pricingMapper = mock(FlashDeliveryPricingMapper.class);
- final FlashDeliveryOrderImageMapper imageMapper = mock(FlashDeliveryOrderImageMapper.class);
- final FlashDeliveryOrderLogMapper logMapper = mock(FlashDeliveryOrderLogMapper.class);
- final InfoUserMapper userMapper = mock(InfoUserMapper.class);
- final FlashDeliveryRouteService routeService = mock(FlashDeliveryRouteService.class);
- final RiderDeliveryLockService lockService = mock(RiderDeliveryLockService.class);
- final RiderDeliveryExclusivityService exclusivityService = mock(RiderDeliveryExclusivityService.class);
- final FlashDeliveryApplicationService service = new FlashDeliveryApplicationService(
- orderMapper, pricingMapper, imageMapper, logMapper, userMapper,
- routeService, new FlashDeliveryPricingCalculator(), lockService, exclusivityService);
- Fixture() {
- when(lockService.withLock(any(), any())).thenAnswer(invocation -> {
- RiderDeliveryLockService.LockedCall<?> call = invocation.getArgument(1);
- return call.call();
- });
- }
- }
- }
|