feat(fleet): read attributable trip receivables and receipts from finance
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
package com.baiyue.finance.controller;
|
||||
import com.baiyue.finance.dto.TripFinanceModels;
|
||||
import com.baiyue.finance.service.TripFinanceQueryService;
|
||||
import com.baiyue.finance.service.FinanceEventException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
class InternalTripFinanceControllerTest {
|
||||
@Test void rejectsAbsentOrWrongInternalTokenBeforeReadingFinance() {
|
||||
var service=mock(TripFinanceQueryService.class);var controller=new InternalTripFinanceController(service,"synthetic-token");
|
||||
var query=new TripFinanceModels.Query(List.of(),false);
|
||||
assertThatThrownBy(()->controller.query(null,query)).isInstanceOf(FinanceEventException.class);
|
||||
assertThatThrownBy(()->controller.query("wrong",query)).isInstanceOf(FinanceEventException.class);
|
||||
verifyNoInteractions(service);
|
||||
}
|
||||
@Test void validInternalTokenReturnsOnlyTheProviderResult() {
|
||||
var service=mock(TripFinanceQueryService.class);var query=new TripFinanceModels.Query(List.of(),false);
|
||||
var result=new TripFinanceModels.Result("PENDING_ALLOCATION",List.of(),List.of(),List.of(),"pending");
|
||||
when(service.query(query)).thenReturn(result);
|
||||
assertThat(new InternalTripFinanceController(service,"synthetic-token").query("synthetic-token",query).data()).isSameAs(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.baiyue.finance.service;
|
||||
import com.baiyue.finance.dto.TripFinanceModels;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import java.util.*;
|
||||
import java.math.BigDecimal;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
class TripFinanceQueryServiceTest {
|
||||
JdbcTemplate jdbc;TripFinanceQueryService service;
|
||||
@BeforeEach void setup() {
|
||||
jdbc=new JdbcTemplate(new DriverManagerDataSource("jdbc:h2:mem:"+UUID.randomUUID()+";MODE=MySQL;DB_CLOSE_DELAY=-1","sa",""));
|
||||
jdbc.execute("CREATE TABLE fin_fee_source(id BIGINT,customer_id BIGINT,business_no VARCHAR(64),business_type VARCHAR(32),source_no VARCHAR(64),fee_item_name VARCHAR(64),source_fee_id BIGINT,source_fee_version INT,source_system VARCHAR(32),source_type VARCHAR(32),direction VARCHAR(32),review_status VARCHAR(32),status VARCHAR(32),currency_code VARCHAR(3),amount DECIMAL(20,6))");
|
||||
jdbc.execute("CREATE TABLE fin_bill(id BIGINT,tenant_id BIGINT,bill_no VARCHAR(64),currency_code VARCHAR(3),status VARCHAR(16))");
|
||||
jdbc.execute("CREATE TABLE fin_bill_line(tenant_id BIGINT,bill_id BIGINT,source_id BIGINT,source_version INT,currency_code VARCHAR(3))");
|
||||
jdbc.execute("CREATE TABLE fin_receipt(id BIGINT,tenant_id BIGINT,status VARCHAR(16),currency_code VARCHAR(3))");
|
||||
jdbc.execute("CREATE TABLE fin_receipt_bill(tenant_id BIGINT,receipt_id BIGINT,bill_id BIGINT,applied_amount DECIMAL(20,6))");
|
||||
service=new TripFinanceQueryService(jdbc);
|
||||
}
|
||||
void fee(long id,long customer,String business,int version,String currency,String amount,String status) {
|
||||
jdbc.update("INSERT INTO fin_fee_source VALUES(?,?,?,'DELIVERY_ORDER',?,'Delivery',99,?,'LASTLEG','OVERSEAS_DELIVERY_FEE','RECEIVABLE','APPROVED',?,?,?)",id,customer,business,business,version,status,currency,new BigDecimal(amount));
|
||||
}
|
||||
TripFinanceModels.Query request(boolean receipts) {return new TripFinanceModels.Query(List.of(new TripFinanceModels.Business(1,"DL-A")),receipts);}
|
||||
void bill(long source,int version) {
|
||||
jdbc.update("INSERT INTO fin_bill VALUES(1,1,'BILL-A','CNY','ISSUED')");
|
||||
jdbc.update("INSERT INTO fin_bill_line VALUES(1,1,?,?,'CNY')",source,version);
|
||||
}
|
||||
void receipt(String amount) {
|
||||
jdbc.update("INSERT INTO fin_receipt VALUES(1,1,'CONFIRMED','CNY')");
|
||||
jdbc.update("INSERT INTO fin_receipt_bill VALUES(1,1,1,?)",new BigDecimal(amount));
|
||||
}
|
||||
@Test void exactWholeBillUsesRecordedAllocationAmount() {
|
||||
fee(1,1,"DL-A",1,"CNY","20","AVAILABLE");bill(1,1);receipt("3.5");
|
||||
var result=service.query(request(true));assertThat(result.totals().get(0).receivedAmount()).isEqualByComparingTo("3.5");
|
||||
assertThat(result.totals().get(0).receivableAmount()).isEqualByComparingTo("20");
|
||||
assertThat(result.documents().get(0).allocationStatus()).isEqualTo("ATTRIBUTED");
|
||||
}
|
||||
@Test void mixedBillNeverProratesReceipt() {
|
||||
fee(1,1,"DL-A",1,"CNY","20","AVAILABLE");bill(1,1);receipt("30");
|
||||
jdbc.update("INSERT INTO fin_bill_line VALUES(1,1,999,1,'CNY')");
|
||||
var result=service.query(request(true));assertThat(result.totals().get(0).receivedAmount()).isNull();
|
||||
assertThat(result.documents().get(0).billNo()).isEqualTo("BILL-A");
|
||||
assertThat(result.documents().get(0).allocationStatus()).isEqualTo("PENDING_ALLOCATION");
|
||||
}
|
||||
@Test void unbilledOrNoConfirmedReceiptIsUnknownNotZero() {
|
||||
fee(1,1,"DL-A",1,"CNY","0","AVAILABLE");
|
||||
assertThat(service.query(request(true)).totals().get(0).receivedAmount()).isNull();
|
||||
bill(1,1);assertThat(service.query(request(true)).totals().get(0).receivedAmount()).isNull();
|
||||
assertThat(service.query(request(true)).totals().get(0).receivableAmount()).isEqualByComparingTo("0");
|
||||
}
|
||||
@Test void latestVoidedDoesNotFallBackAndOtherCustomerExcluded() {
|
||||
fee(1,1,"DL-A",1,"CNY","20","AVAILABLE");fee(2,1,"DL-A",2,"CNY","20","VOIDED");
|
||||
fee(3,2,"DL-A",1,"CNY","999","AVAILABLE");
|
||||
var result=service.query(request(true));assertThat(result.sources()).isEmpty();assertThat(result.status()).isEqualTo("PENDING_ALLOCATION");
|
||||
}
|
||||
@Test void currenciesSeparateAndNoReceiptPermissionMasksDocuments() {
|
||||
fee(1,1,"DL-A",1,"CNY","20","AVAILABLE");
|
||||
jdbc.update("UPDATE fin_fee_source SET source_fee_id=1 WHERE id=1");
|
||||
fee(2,1,"DL-A",1,"USD","5","AVAILABLE");
|
||||
var result=service.query(request(false));assertThat(result.totals()).extracting(TripFinanceModels.Money::currency).containsExactly("CNY","USD");
|
||||
assertThat(result.totals()).allSatisfy(m->assertThat(m.receivedAmount()).isNull());assertThat(result.documents()).isEmpty();
|
||||
}
|
||||
@Test void wholeTripBillIsCountedOnceAcrossTwoFeeLines() {
|
||||
fee(1,1,"DL-A",1,"CNY","20","AVAILABLE");jdbc.update("UPDATE fin_fee_source SET source_fee_id=1 WHERE id=1");
|
||||
fee(2,1,"DL-A",1,"CNY","10","AVAILABLE");bill(1,1);jdbc.update("INSERT INTO fin_bill_line VALUES(1,1,2,1,'CNY')");receipt("7");
|
||||
var result=service.query(request(true));assertThat(result.documents()).hasSize(1);assertThat(result.totals().get(0).receivedAmount()).isEqualByComparingTo("7");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user