package sample.usecase;
import java.util.List;
import org.springframework.stereotype.Service;
import sample.context.actor.Actor;
import sample.context.lock.IdLockHandler.LockType;
import sample.model.asset.CashInOut;
import sample.model.asset.CashInOut.RegCashOut;
/**
* 資産ドメインに対する顧客ユースケース処理。
*/
@Service
public class AssetService extends ServiceSupport {
/** 匿名を除くActorを返します。 */
@Override
protected Actor actor() {
return ServiceUtils.actorUser(super.actor());
}
/**
* 未処理の振込依頼情報を検索します。
* low: 参照系は口座ロックが必要無いケースであれば@Transactionalでも十分
* low: CashInOutは情報過多ですがアプリケーション層では公開対象を特定しにくい事もあり、
* UI層に最終判断を委ねています。
*/
public List<CashInOut> findUnprocessedCashOut() {
final String accId = actor().getId();
return tx(accId, LockType.Read, () -> {
return CashInOut.findUnprocessed(rep(), accId);
});
}
/**
* 振込出金依頼をします。
* low: 公開リスクがあるためUI層には必要以上の情報を返さない事を意識します。
* low: 監査ログの記録は状態を変えうる更新系ユースケースでのみ行います。
* low: ロールバック発生時にメールが飛ばないようにトランザクション境界線を明確に分離します。
* @return 振込出金依頼ID
*/
public Long withdraw(final RegCashOut p) {
return audit().audit("振込出金依頼をします", () -> {
p.setAccountId(actor().getId()); // 顧客側はログイン利用者で強制上書き
// low: 口座IDロック(WRITE)とトランザクションをかけて振込処理
CashInOut cio = tx(actor().getId(), LockType.Write, () -> {
return CashInOut.withdraw(rep(), businessDay(), p);
});
// low: トランザクション確定後に出金依頼を受付した事をメール通知します。
mail().sendWithdrawal(cio);
return cio.getId();
});
}
}