| | |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.tourguide.common.huifu.properties.HuiFuProperties; |
| | | import com.tourguide.modules.order.domain.OrderStatus; |
| | | import com.tourguide.modules.order.domain.RefundStatus; |
| | | import com.tourguide.modules.order.entity.TourOrder; |
| | | import com.tourguide.modules.order.entity.TourOrderRefund; |
| | | import com.tourguide.modules.order.mapper.TourOrderMapper; |
| | | import com.tourguide.modules.order.mapper.TourOrderRefundMapper; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | |
| | | class HuifuRefundCallbackServiceTest { |
| | | private TourOrderMapper orderMapper; |
| | | private HuifuRefundCallbackService callbackService; |
| | | private GuideSessionTransitionService sessionTransitionService; |
| | | |
| | | @BeforeEach |
| | | void setUp() { |
| | | HuiFuProperties properties = new HuiFuProperties(); |
| | | properties.setHuifuId("merchant-1"); |
| | | orderMapper = mock(TourOrderMapper.class); |
| | | callbackService = new HuifuRefundCallbackService(properties, orderMapper); |
| | | sessionTransitionService = mock(GuideSessionTransitionService.class); |
| | | callbackService = new HuifuRefundCallbackService(properties, orderMapper, null, null, |
| | | sessionTransitionService); |
| | | } |
| | | |
| | | @Test |
| | |
| | | assertThat(first).isTrue(); |
| | | assertThat(duplicate).isFalse(); |
| | | assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUNDED.getCode()); |
| | | assertThat(order.getStatus()).isEqualTo(OrderStatus.REFUNDED.getCode()); |
| | | assertThat(order.getRefundTime()).isNotNull(); |
| | | verify(orderMapper).updateById(order); |
| | | } |
| | |
| | | verify(orderMapper, never()).updateById(order); |
| | | } |
| | | |
| | | @Test |
| | | void nestedSuccessCallbackShouldCompleteOrder() { |
| | | TourOrder order = refundingOrder(); |
| | | when(orderMapper.selectByRefundOrderNoForUpdate("RF001")).thenReturn(order); |
| | | JSONObject data = successBody(); |
| | | JSONObject body = new JSONObject(); |
| | | body.put("data", data); |
| | | |
| | | assertThat(callbackService.handle(body)).isTrue(); |
| | | assertThat(order.getStatus()).isEqualTo(OrderStatus.REFUNDED.getCode()); |
| | | } |
| | | |
| | | @Test |
| | | void partialSuccessCallbackShouldKeepRefundingBalance() { |
| | | TourOrder order = refundingOrder(); |
| | | order.setRefundAmount(new BigDecimal("20.00")); |
| | | when(orderMapper.selectByRefundOrderNoForUpdate("RF001")).thenReturn(order); |
| | | JSONObject body = successBody(); |
| | | body.put("ord_amt", "20.00"); |
| | | |
| | | assertThat(callbackService.handle(body)).isTrue(); |
| | | assertThat(order.getRefundedAmount()).isEqualByComparingTo("20.00"); |
| | | assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.PARTIAL.getCode()); |
| | | assertThat(order.getStatus()).isEqualTo(OrderStatus.CANCELLED.getCode()); |
| | | } |
| | | |
| | | @Test |
| | | void pendingMeetingSuccessCallbackShouldRestoreGuideSession() { |
| | | TourOrder order = refundingOrder(); |
| | | order.setStatus(OrderStatus.PENDING_MEETING.getCode()); |
| | | order.setGuideId(8L); |
| | | order.setReceivingSessionId(18L); |
| | | when(orderMapper.selectByRefundOrderNoForUpdate("RF001")).thenReturn(order); |
| | | |
| | | assertThat(callbackService.handle(successBody())).isTrue(); |
| | | |
| | | verify(sessionTransitionService).restoreAfterOrderCancellation(order); |
| | | } |
| | | |
| | | @Test |
| | | void followUpSuccessCallbackShouldCompleteRemainingRefund() { |
| | | TourOrder order = refundingOrder(); |
| | | order.setRefundAmount(new BigDecimal("16.00")); |
| | | order.setRefundedAmount(new BigDecimal("20.00")); |
| | | when(orderMapper.selectByRefundOrderNoForUpdate("RF001")).thenReturn(order); |
| | | JSONObject body = successBody(); |
| | | body.put("ord_amt", "16.00"); |
| | | |
| | | assertThat(callbackService.handle(body)).isTrue(); |
| | | assertThat(order.getRefundedAmount()).isEqualByComparingTo("36.00"); |
| | | assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUNDED.getCode()); |
| | | assertThat(order.getStatus()).isEqualTo(OrderStatus.REFUNDED.getCode()); |
| | | } |
| | | |
| | | @Test |
| | | void partialSuccessShouldCompleteOnlyTheMatchedRefundRecord() { |
| | | TourOrderRefundMapper refundMapper = mock(TourOrderRefundMapper.class); |
| | | callbackService = new HuifuRefundCallbackService(properties(), orderMapper, refundMapper); |
| | | TourOrder order = refundingOrder(); |
| | | order.setId(99L); |
| | | TourOrderRefund record = new TourOrderRefund(); |
| | | record.setOrderId(99L); |
| | | record.setRefundOrderNo("RF001"); |
| | | record.setRefundAmount(new BigDecimal("20.00")); |
| | | record.setRefundStatus(RefundStatus.REFUNDING.getCode()); |
| | | when(refundMapper.selectByRefundOrderNoForUpdate("RF001")).thenReturn(record); |
| | | when(orderMapper.selectForUpdate(99L)).thenReturn(order); |
| | | JSONObject body = successBody(); |
| | | body.put("ord_amt", "20.00"); |
| | | |
| | | assertThat(callbackService.handle(body)).isTrue(); |
| | | |
| | | assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.PARTIAL.getCode()); |
| | | assertThat(record.getRefundStatus()).isEqualTo(RefundStatus.REFUNDED.getCode()); |
| | | verify(refundMapper).updateById(record); |
| | | } |
| | | |
| | | private HuiFuProperties properties() { |
| | | HuiFuProperties properties = new HuiFuProperties(); |
| | | properties.setHuifuId("merchant-1"); |
| | | return properties; |
| | | } |
| | | |
| | | private TourOrder refundingOrder() { |
| | | TourOrder order = new TourOrder(); |
| | | order.setRefundOrderNo("RF001"); |
| | | order.setRefundStatus(RefundStatus.REFUNDING.getCode()); |
| | | order.setRefundAmount(new BigDecimal("36.00")); |
| | | order.setPaymentAmount(new BigDecimal("36.00")); |
| | | return order; |
| | | } |
| | | |