package sample.model.asset; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.math.BigDecimal; import java.time.LocalDate; import org.junit.Test; import sample.*; import sample.ValidationException.ErrorKeys; import sample.model.DomainErrorKeys; import sample.model.account.*; import sample.model.asset.CashInOut.*; import sample.model.asset.type.CashflowType; import sample.model.master.SelfFiAccount; //low: 簡易な正常系検証が中心。依存するCashflow/CashBalanceの単体検証パスを前提。 public class CashInOutTest extends EntityTestSupport { private static final String ccy = "JPY"; private static final String accId = "test"; @Override protected void setupPreset() { targetEntities(Account.class, FiAccount.class, SelfFiAccount.class, CashInOut.class, Cashflow.class, CashBalance.class); } @Override public void before() { // 残高1000円の口座(test)を用意 LocalDate baseDay = businessDay.day(); tx(() -> { fixtures.selfFiAcc(Remarks.CashOut, ccy).save(rep); fixtures.acc(accId).save(rep); fixtures.fiAcc(accId, Remarks.CashOut, ccy).save(rep); fixtures.cb(accId, baseDay, ccy, "1000").save(rep); }); } @Test public void 振込入出金を検索する() { LocalDate baseDay = businessDay.day(); LocalDate basePlus1Day = businessDay.day(1); LocalDate basePlus2Day = businessDay.day(2); tx(() -> { fixtures.cio(accId, "300", true).save(rep); //low: ちゃんとやると大変なので最低限の検証 assertThat( CashInOut.find(rep, findParam(baseDay, basePlus1Day)), hasSize(1)); assertThat( CashInOut.find(rep, findParam(baseDay, basePlus1Day, ActionStatusType.Unprocessed)), hasSize(1)); assertThat( CashInOut.find(rep, findParam(baseDay, basePlus1Day, ActionStatusType.Processed)), empty()); assertThat( CashInOut.find(rep, findParam(basePlus1Day, basePlus2Day, ActionStatusType.Unprocessed)), empty()); }); } private FindCashInOut findParam(LocalDate fromDay, LocalDate toDay, ActionStatusType... statusTypes) { return new FindCashInOut(ccy, statusTypes, fromDay, toDay); } @Test @SuppressWarnings("unchecked") public void 振込出金依頼をする() { LocalDate baseDay = businessDay.day(); LocalDate basePlus3Day = businessDay.day(3); tx(() -> { // 超過の出金依頼 [例外] try { CashInOut.withdraw(rep, businessDay, new RegCashOut(accId, ccy, new BigDecimal("1001"))); fail(); } catch (ValidationException e) { assertThat(e.getMessage(), is(AssetErrorKeys.CashInOutWithdrawAmount)); } // 0円出金の出金依頼 [例外] try { CashInOut.withdraw(rep, businessDay, new RegCashOut(accId, ccy, BigDecimal.ZERO)); fail(); } catch (ValidationException e) { assertThat(e.getMessage(), is(DomainErrorKeys.AbsAmountZero)); } // 通常の出金依頼 CashInOut normal = CashInOut.withdraw(rep, businessDay, new RegCashOut(accId, ccy, new BigDecimal("300"))); assertThat(normal, allOf( hasProperty("accountId", is(accId)), hasProperty("currency", is(ccy)), hasProperty("absAmount", is(new BigDecimal(300))), hasProperty("withdrawal", is(true)), hasProperty("requestDay", is(baseDay)), hasProperty("eventDay", is(baseDay)), hasProperty("valueDay", is(basePlus3Day)), hasProperty("targetFiCode", is(Remarks.CashOut + "-" + ccy)), hasProperty("targetFiAccountId", is("FI" + accId)), hasProperty("selfFiCode", is(Remarks.CashOut + "-" + ccy)), hasProperty("selfFiAccountId", is("xxxxxx")), hasProperty("statusType", is(ActionStatusType.Unprocessed)), hasProperty("cashflowId", is(nullValue())))); // 拘束額を考慮した出金依頼 [例外] try { CashInOut.withdraw(rep, businessDay, new RegCashOut(accId, ccy, new BigDecimal("701"))); fail(); } catch (ValidationException e) { assertThat(e.getMessage(), is(AssetErrorKeys.CashInOutWithdrawAmount)); } }); } @Test public void 振込出金依頼を取消する() { LocalDate baseDay = businessDay.day(); tx(() -> { // CF未発生の依頼を取消 CashInOut normal = fixtures.cio(accId, "300", true).save(rep); assertThat(normal.cancel(rep), hasProperty("statusType", is(ActionStatusType.Cancelled))); // 発生日を迎えた場合は取消できない [例外] CashInOut today = fixtures.cio(accId, "300", true); today.setEventDay(baseDay); today.save(rep); try { today.cancel(rep); fail(); } catch (ValidationException e) { assertThat(e.getMessage(), is(AssetErrorKeys.CashInOutBeforeEqualsDay)); } }); } @Test public void 振込出金依頼を例外状態とする() { LocalDate baseDay = businessDay.day(); tx(() -> { CashInOut normal = fixtures.cio(accId, "300", true).save(rep); assertThat(normal.error(rep), hasProperty("statusType", is(ActionStatusType.Error))); // 処理済の時はエラーにできない [例外] CashInOut today = fixtures.cio(accId, "300", true); today.setEventDay(baseDay); today.setStatusType(ActionStatusType.Processed); today.save(rep); try { today.error(rep); fail(); } catch (ValidationException e) { assertThat(e.getMessage(), is(ErrorKeys.ActionUnprocessing)); } }); } @Test @SuppressWarnings("unchecked") public void 発生日を迎えた振込入出金をキャッシュフロー登録する() { LocalDate baseDay = businessDay.day(); LocalDate basePlus3Day = businessDay.day(3); tx(() -> { // 発生日未到来の処理 [例外] CashInOut future = fixtures.cio(accId, "300", true).save(rep); try { future.process(rep); fail(); } catch (ValidationException e) { assertThat(e.getMessage(), is(AssetErrorKeys.CashInOutAfterEqualsDay)); } // 発生日到来処理 CashInOut normal = fixtures.cio(accId, "300", true); normal.setEventDay(baseDay); normal.save(rep); assertThat(normal.process(rep), allOf( hasProperty("statusType", is(ActionStatusType.Processed)), hasProperty("cashflowId", not(nullValue())))); // 発生させたキャッシュフローの検証 assertThat(Cashflow.load(rep, normal.getCashflowId()), allOf( hasProperty("accountId", is(accId)), hasProperty("currency", is(ccy)), hasProperty("amount", is(new BigDecimal("-300"))), hasProperty("cashflowType", is(CashflowType.CashOut)), hasProperty("remark", is(Remarks.CashOut)), hasProperty("eventDay", is(baseDay)), hasProperty("valueDay", is(basePlus3Day)), hasProperty("statusType", is(ActionStatusType.Unprocessed)))); }); } }