test(procurement): verify pending commands and late successful receipts
This commit is contained in:
+61
@@ -120,6 +120,67 @@ class ProcurementFinancePersistenceTest {
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_procurement_wallet_attempt WHERE fee_id=?",Integer.class,fee.getId())).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test void pendingOriginalRejectsReplacementAndLateSuccessKeepsOriginalAmountAndLedger() {
|
||||
var original=confirm(ProcurementFeePurpose.DUTY,"POSITIVE","10");
|
||||
var originalFreeze=result(original,"FREEZE","SUCCEEDED","FROZEN","10");
|
||||
assertPendingVersionCannotBeReplaced(original);
|
||||
// Replaying a timed-out confirmation returns the original command, never a new attempt.
|
||||
assertThat(confirm(ProcurementFeePurpose.DUTY,"POSITIVE","10").getWalletCommandEventId())
|
||||
.isEqualTo(originalFreeze.commandEventId());
|
||||
handle(originalFreeze);
|
||||
var settling=fees.selectById(original.getId());
|
||||
assertPendingVersionCannotBeReplaced(settling);
|
||||
assertThat(confirm(ProcurementFeePurpose.DUTY,"POSITIVE","10").getWalletCommandEventId())
|
||||
.isEqualTo(settling.getWalletCommandEventId());
|
||||
var lateSuccess=result(settling,"SETTLE","SUCCEEDED","SETTLED","10");
|
||||
handle(lateSuccess);
|
||||
// A delayed freeze receipt after settlement must not regress the settled projection.
|
||||
handle(originalFreeze);
|
||||
handle(lateSuccess);
|
||||
var saved=fees.selectById(original.getId());
|
||||
assertThat(saved.getFeeVersion()).isEqualTo(1);
|
||||
assertThat(saved.getOriginalAmount()).isEqualByComparingTo("10");
|
||||
assertThat(saved.getAmount()).isEqualByComparingTo("10");
|
||||
assertThat(saved.getWalletStatus()).isEqualTo("SETTLED");
|
||||
assertThat(saved.getSettledCommandEventId()).isEqualTo(lateSuccess.commandEventId());
|
||||
assertThat(saved.getWalletLedgerId()).isEqualTo(lateSuccess.walletLedgerId());
|
||||
assertThat(saved.getSourceFeeId()).isEqualTo(901L);
|
||||
assertThat(service.all(11)).hasSize(1);
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_procurement_wallet_attempt WHERE fee_id=? AND status='SUCCEEDED'",Integer.class,original.getId())).isEqualTo(2);
|
||||
assertThat(jdbc.queryForObject("SELECT fee_id FROM ll_procurement_wallet_attempt WHERE command_event_id=?",Long.class,lateSuccess.commandEventId())).isEqualTo(original.getId());
|
||||
verify(commands,times(2)).publish(anyString(),anyLong(),anyString(),anyString(),any(),anyString(),anyLong());
|
||||
verify(commands,never()).publishRefund(anyLong(),anyString(),anyString(),any(),anyString(),anyString(),anyLong());
|
||||
verify(sources).publishSettled(anyString(),anyString(),argThat(r -> r.amount().compareTo(new BigDecimal("10"))==0),any(),
|
||||
argThat(ref -> ref.commandEventId().equals(lateSuccess.commandEventId())));
|
||||
}
|
||||
|
||||
private void assertPendingVersionCannotBeReplaced(OverseasProcurementFee original) {
|
||||
assertThatThrownBy(() -> confirm(ProcurementFeePurpose.DUTY,"POSITIVE","20")).hasMessageContaining("已确认");
|
||||
assertThatThrownBy(() -> tx.execute(s -> service.replaceFailed("9","PO-1","7",original.getId(),new BigDecimal("20"),1,"corrected target")))
|
||||
.hasMessageContaining("须先终止");
|
||||
assertThatThrownBy(() -> tx.execute(s -> service.retry("9","PO-1",original.getId()))).hasMessageContaining("未明确失败");
|
||||
assertThatThrownBy(() -> tx.executeWithoutResult(s -> service.terminateFailed("9","PO-1",original.getId()))).hasMessageContaining("明确失败");
|
||||
assertThatThrownBy(() -> tx.execute(s -> service.refund("9","PO-1","7",original.getId(),BigDecimal.ONE,1,"corrected target","pending-refund")))
|
||||
.hasMessageContaining("已成功实扣");
|
||||
assertThat(fees.selectById(original.getId()).getWalletCommandEventId()).isEqualTo(original.getWalletCommandEventId());
|
||||
}
|
||||
|
||||
@Test void pendingEstimateCannotBeReleasedOrReplacedBeforeLateFreezeResult() {
|
||||
var estimate=confirm(ProcurementFeePurpose.INTERNATIONAL_ESTIMATE,"POSITIVE","10");
|
||||
assertThatThrownBy(() -> tx.executeWithoutResult(s -> service.releaseEstimate("9","PO-1",estimate.getId())))
|
||||
.hasMessageContaining("未决");
|
||||
assertThatThrownBy(() -> confirm(ProcurementFeePurpose.INTERNATIONAL_ESTIMATE,"POSITIVE","20")).hasMessageContaining("已确认");
|
||||
assertThat(confirm(ProcurementFeePurpose.INTERNATIONAL_ESTIMATE,"POSITIVE","10").getId()).isEqualTo(estimate.getId());
|
||||
var lateFreeze=result(estimate,"FREEZE","SUCCEEDED","FROZEN","10");
|
||||
handle(lateFreeze);handle(lateFreeze);
|
||||
assertThat(fees.selectById(estimate.getId()).getWalletStatus()).isEqualTo("FROZEN");
|
||||
assertThat(fees.selectById(estimate.getId()).getAmount()).isEqualByComparingTo("10");
|
||||
assertThat(jdbc.queryForObject("SELECT COUNT(*) FROM ll_procurement_wallet_attempt",Integer.class)).isEqualTo(1);
|
||||
verify(commands).publish(eq("FREEZE"),anyLong(),anyString(),eq(estimate.getFeeNo()),eq(new BigDecimal("10")),anyString(),anyLong());
|
||||
verifyNoMoreInteractions(commands);
|
||||
verifyNoInteractions(sources);
|
||||
}
|
||||
|
||||
@Test void sourceFailureRollsBackResultProjectionAndRetriesWithoutAnotherDebit() {
|
||||
var fee=confirm(ProcurementFeePurpose.DUTY,"POSITIVE","10");
|
||||
handle(result(fee,"FREEZE","SUCCEEDED","FROZEN","10"));
|
||||
|
||||
Reference in New Issue
Block a user