package sample.model.asset; import java.math.BigDecimal; import java.time.LocalDate; import lombok.Getter; import sample.context.orm.OrmRepository; import sample.util.Calculator; /** * 口座の資産概念を表現します。 * asset配下のEntityを横断的に取り扱います。 * low: 実際の開発では多通貨や執行中/拘束中のキャッシュフローアクションに対する考慮で、サービスによってはかなり複雑になります。 */ @Getter public class Asset { /** 口座ID */ private final String id; private Asset(String id) { this.id = id; } /** 口座IDに紐付く資産概念を返します。 */ public static Asset by(String accountId) { return new Asset(accountId); } /** * 振込出金可能か判定します。 * <p>0 <= 口座残高 + 未実現キャッシュフロー - (出金依頼拘束額 + 出金依頼額) * low: 判定のみなのでscale指定は省略。余力金額を返す時はきちんと指定する */ public boolean canWithdraw(final OrmRepository rep, String currency, BigDecimal absAmount, LocalDate valueDay) { Calculator calc = Calculator.of(CashBalance.getOrNew(rep, id, currency).getAmount()); Cashflow.findUnrealize(rep, id, currency, valueDay).stream().forEach((cf) -> calc.add(cf.getAmount())); CashInOut.findUnprocessed(rep, id, currency, true).stream() .forEach((withdrawal) -> calc.add(withdrawal.getAbsAmount().negate())); calc.add(absAmount.negate()); return 0 <= calc.decimal().signum(); } }