package rewards.internal;
import rewards.AccountContribution;
import rewards.Dining;
import rewards.RewardConfirmation;
import rewards.RewardNetwork;
import rewards.internal.account.Account;
import rewards.internal.account.AccountMapper;
import rewards.internal.account.Beneficiary;
import rewards.internal.restaurant.Restaurant;
import rewards.internal.restaurant.RestaurantMapper;
import rewards.internal.reward.RewardRepository;
import common.money.MonetaryAmount;
/**
* Rewards an Account for Dining at a Restaurant.
*
* The sole Reward Network implementation. This object is an application-layer service responsible for coordinating with
* the domain-layer to carry out the process of rewarding benefits to accounts for dining.
*
* Said in other words, this class implements the "reward account for dining" use case.
*/
public class RewardNetworkImpl implements RewardNetwork {
private AccountMapper accountMapper;
private RestaurantMapper restaurantMapper;
private RewardRepository rewardRepository;
/**
* Creates a new reward network.
* @param accountMapper the repository for loading accounts to reward
* @param restaurantMapper the repository for loading restaurants that determine how much to reward
* @param rewardRepository the repository for recording a record of successful reward transactions
*/
public RewardNetworkImpl(AccountMapper accountMapper,
RestaurantMapper restaurantMapper, RewardRepository rewardRepository) {
this.accountMapper = accountMapper;
this.restaurantMapper = restaurantMapper;
this.rewardRepository = rewardRepository;
}
public RewardConfirmation rewardAccountFor(Dining dining) {
Account account = accountMapper.findByCreditCard(dining.getCreditCardNumber());
Restaurant restaurant = restaurantMapper.findByMerchantNumber(dining.getMerchantNumber());
MonetaryAmount amount = restaurant.calculateBenefitFor(account, dining);
AccountContribution contribution = account.makeContribution(amount);
updateBeneficiaries(account);
return rewardRepository.confirmReward(contribution, dining);
}
public void updateBeneficiaries(Account account){
for (Beneficiary beneficiary : account.getBeneficiaries()) {
accountMapper.updateBeneficiary(beneficiary);
}
}
}