Created
July 3, 2015 13:27
-
-
Save gordonbyron/30e3caac68e4d8c56163 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package novofront.service.business; | |
import com.barcapint.schemas.cerberus.association.account.x2015.x06.x01.AccountDto; | |
import novofront.api.command.GetLiquidityCommand; | |
import novofront.api.command.GetLiquidityCommandResponse; | |
import novofront.api.command.account.IndividualBalanceCommand; | |
import novofront.api.command.account.IndividualBalanceCommandResponse; | |
import novofront.api.view.AccountBalance; | |
import novofront.api.view.*; | |
import novofront.api.view.balance.ConsolidatedBalanceItem; | |
import novofront.api.view.balance.ConsolidatedCurrentBalanceItem; | |
import novofront.core.Constants; | |
import novofront.dto.ClientLiquidity; | |
import novofront.dto.ClientLiquidityKey; | |
import novofront.dto.LiquidityPosition; | |
import novofront.model.jpa.*; | |
import novofront.repository.filter.LiquidityFilter; | |
import novofront.service.orient.OrientDbService; | |
import org.joda.time.DateTime; | |
import org.joda.time.LocalDateTime; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.stereotype.Service; | |
import java.math.BigDecimal; | |
import java.util.*; | |
/** | |
* Provides services for building up a liquidity model | |
* | |
* @author Werner Weber | |
*/ | |
@Service | |
public class LiquidityService implements ILiquidityService { | |
private final Logger logger = LoggerFactory.getLogger(LiquidityService.class); | |
@Autowired | |
OrientDbService orientDbService; | |
@Autowired | |
ClientService clientService; | |
@Autowired | |
AccountService accountService; | |
@Autowired | |
UserService userService; | |
@Autowired | |
ExchangeRateService exhangeRateService; | |
public GetLiquidityCommandResponse GetLiquidity(GetLiquidityCommand command) { | |
logger.debug("LiquidityService.GetLiquidity(GetLiquidityCommand {0}) - start", command); | |
GetLiquidityCommandResponse response = new GetLiquidityCommandResponse(command); | |
//a list that contains all the client ids that we need to fetch account data for | |
//this list is resolved either via resolving all the children for the root element | |
//or we use the list given in the entityFilter list for the command. | |
ArrayList<String> clientIds = new ArrayList<String>(); | |
LegalEntity rootEntity = null; | |
try { | |
rootEntity = orientDbService.getEntityHierarchy(command.getClientId(), 3); //TODO: Decide on the default depth at which to query for the client hierarchy | |
if (rootEntity == null) { | |
response.addError(String.format("Could not load client with id: %s", command.getClientId()), Constants.ERROR_CODE_ENTITY_NOT_FOUND, "Please check input parameters for client id filter"); | |
response.setSuccess(false); | |
response.setMessage(String.format("Could not load client with id: %s", command.getClientId())); | |
response.setLiquidity(null); | |
response.setCompletedTime(DateTime.now()); | |
return response; | |
} | |
//we know our entity is not null so we can add it to the list of client ids | |
clientIds.add(rootEntity.getClientID()); | |
if (command.getEntityFilter().size() > 0) { | |
//if we are given the entity filter we just use it as is. This is the easiest route.//we are using the parent company in the inclu | |
clientIds.addAll(command.getEntityFilter()); | |
} else { | |
//if we are not given the entity filter we use the root entity and resolve all the client id's contained in the hierarchy | |
clientIds.addAll(getChildrenIds(rootEntity)); | |
} | |
} catch (Exception e) { | |
logger.error("Could not retrieve data due to an excpetion thrown from Orient error", e); | |
response.addError("Could not retrieve data due to a system error", Constants.ERROR_CODE_SYSTEM_ERROR_ORIENT, "Please try again later, or contact support should this be resolved."); | |
} | |
//build a list of accounts that we need to fetch balances for | |
List<Account> accounts = new ArrayList<Account>(); | |
for (String clientId : clientIds) { | |
accounts.addAll(accountService.listAllAccountsForClient(clientId)); | |
} | |
WorkingCapital workingCapital = new WorkingCapital(); | |
CashBalance cashBalance = new CashBalance(); | |
Liquidity liquidity = new Liquidity(); | |
liquidity.setWorkingCapital(workingCapital); | |
liquidity.setCashBalance(cashBalance); | |
LiquidityFilter filter = new LiquidityFilter(); | |
List<AccountBalance> cashBalances = new ArrayList<AccountBalance>(); | |
List<AccountBalance> workingCapitalBalances = new ArrayList<AccountBalance>(); | |
for (Account account : accounts) { | |
//get the account balances for the account and the period defined | |
account.setBalanceEntries(accountService.getAccountBalanceForAccountAndDateRange(account.getAccountId(), command.getStartDateFilter(), command.getEndDateFilter())); | |
//iterate through account balances | |
for (novofront.model.jpa.AccountBalance balance : account.getBalanceEntries()) { | |
//whatever logic applies to put them in either bucket | |
boolean isCashbalance = false; | |
AccountBalance vbalance = new AccountBalance(); | |
vbalance.setPreferredCurrencyCode(command.getPreferredCurrencyCode()); | |
vbalance.setAccountId(balance.getAccount().getAccountId()); | |
vbalance.setBalance(balance.getBalance()); | |
vbalance.setFacility(balance.getFacility()); | |
vbalance.setBalanceDate(balance.getBalanceDate()); | |
if (vbalance.getCategory().toLowerCase() == novofront.treasurydashboard.Constants.ACCOUNT_BALANCE_CATEGORY_CASH.toLowerCase()) { | |
isCashbalance = true; | |
} else { | |
//some additional logic may apply here to decide if it is a cash balance | |
} | |
vbalance.setCountryCode(balance.getAccount().getCountryCode()); | |
vbalance.setCategory(balance.getCategory()); | |
vbalance.setClientId(balance.getAccount().getClient().getClientId()); | |
vbalance.setCurrencyCode(balance.getAccount().getCurrency().getCurrencyCode()); | |
if (vbalance.requiresMultiplier())//set the multiplier for the currency conversion | |
vbalance.setMultiplier(exhangeRateService.getMultiplier(vbalance.getCurrencyCode(), vbalance.getPreferredCurrencyCode(), DateTime.now())); | |
if (isCashbalance) { | |
cashBalances.add(vbalance); | |
} else { | |
workingCapitalBalances.add(vbalance); | |
} | |
} | |
} | |
for (AccountBalance balance : cashBalances) { | |
//do whatever work is required | |
CashBalanceItem cbItem = new CashBalanceItem(); | |
} | |
Map<String, WorkingCapitalItem> workingCapitalMap = new HashMap<String, WorkingCapitalItem>(); | |
for (AccountBalance balance : workingCapitalBalances) { | |
//do whatever work is required | |
WorkingCapitalItem wcItem = null; | |
if (workingCapitalMap.containsKey(balance.getCurrencyCode())) { | |
wcItem = (WorkingCapitalItem) workingCapitalMap.get(balance.getCurrencyCode()); | |
} else { | |
wcItem = new WorkingCapitalItem(); | |
wcItem.setCurrencyCode(balance.getCurrencyCode()); | |
wcItem.setBalance(BigDecimal.ZERO); | |
wcItem.setFacility(BigDecimal.ZERO); | |
} | |
ContributingCountryItem contributingCountryItem = null; | |
contributingCountryItem = wcItem.getContributingCountryItemForCountry(balance.getCountryCode()); | |
if (contributingCountryItem == null) { | |
contributingCountryItem = new ContributingCountryItem(); | |
contributingCountryItem.setFacility(BigDecimal.ZERO); | |
contributingCountryItem.setBalance(BigDecimal.ZERO); | |
contributingCountryItem.setCurrencyCode(balance.getCurrencyCode()); | |
contributingCountryItem.setBalanceDate(DateTime.now()); | |
contributingCountryItem.setCountryCode(balance.getCountryCode()); | |
contributingCountryItem.setPreferredCurrencyCode(command.getPreferredCurrencyCode()); | |
contributingCountryItem.setMultiplier(exhangeRateService.getMultiplier(balance.getCurrencyCode(), command.getPreferredCurrencyCode(), DateTime.now())); | |
} | |
contributingCountryItem.addAccountBalance(balance); | |
workingCapitalMap.put(balance.getCurrencyCode(), wcItem); | |
} | |
for (WorkingCapitalItem wcItem : workingCapitalMap.values()) { | |
liquidity.getWorkingCapital().addWorkingCapitalItem(wcItem); | |
} | |
response.setLiquidity(liquidity); | |
return response; | |
} | |
private List<String> getChildrenIds(LegalEntity entity) { | |
ArrayList<String> ids = new ArrayList<String>(); | |
for (LegalEntity child : entity.getSubsidiaries()) { | |
//check if the command filters allows us to add the legal entity to the list of clients we | |
//are looking for | |
ids.add(child.getClientID()); | |
ids.addAll(getChildrenIds(child)); | |
} | |
return ids; | |
} | |
public List<ConsolidatedCurrentBalanceItem> getConsolidatedBalancesCurrent(List<String> clientIds, List<String> currencyCodes, List<String> countryCodes, String convertToCurrency) { | |
List<ConsolidatedBalanceItem> items = getConsolidatedBalances(clientIds, currencyCodes, countryCodes, null, null, false); | |
logger.info("Convert to Currency is ::-- {}", convertToCurrency); | |
List<ConsolidatedCurrentBalanceItem> currentItems = new ArrayList<ConsolidatedCurrentBalanceItem>(); | |
for (ConsolidatedBalanceItem item : items) { | |
currentItems.add(ConsolidatedCurrentBalanceItem.from(item)); | |
} | |
if (convertToCurrency != null) { | |
DateTime now = DateTime.now(); | |
DateTime start = DateTime.parse(String.format(novofront.core.Constants.DATE_FORMAT_STRING_MIDNIGHT, now.getYear(), now.getMonthOfYear(), now.getDayOfMonth())); | |
DateTime end = DateTime.parse(String.format(novofront.core.Constants.DATE_FORMAT_STRING_MIDNIGHT, now.getYear(), now.getMonthOfYear(), now.getDayOfMonth() + 1)); | |
logger.info("The start is ::-- {}", start); | |
logger.info("The end is ::-- {}", end); | |
for (ConsolidatedCurrentBalanceItem item : currentItems) { | |
//List<ExchangeRate> exchangeRates = exhangeRateService.getByBaseCurrencyCodeInAndTargetCurrencyCodeInAndExchangeDateBetween(item.getCurrencyCode(), convertToCurrency, start, end); | |
List<ExchangeRate> exchangeRates = exhangeRateService.findByBaseCurrencyCodeAndTargetCurrencyCodeAndExchangeDateBetween(item.getCurrencyCode(), convertToCurrency, start, end); | |
if (exchangeRates != null && !exchangeRates.isEmpty()) { | |
logger.info("The Currency is ::-- {}", item.getCurrencyCode()); | |
logger.info("The Exchange rate is ::-- {}", exchangeRates.get(0).getFactor()); | |
item.setCash(item.getCash().multiply(BigDecimal.valueOf(exchangeRates.get(0).getFactor())).setScale(0, BigDecimal.ROUND_DOWN)); | |
item.setLiquidity(item.getLiquidity().multiply(BigDecimal.valueOf(exchangeRates.get(0).getFactor())).setScale(0, BigDecimal.ROUND_DOWN)); | |
item.setAvailableFacilities(item.getAvailableFacilities().multiply(BigDecimal.valueOf(exchangeRates.get(0).getFactor())).setScale(0, BigDecimal.ROUND_DOWN)); | |
item.setTotalFacilities(item.getTotalFacilities().multiply(BigDecimal.valueOf(exchangeRates.get(0).getFactor())).setScale(0, BigDecimal.ROUND_DOWN)); | |
item.setUsedFacilities(item.getUsedFacilities().multiply(BigDecimal.valueOf(exchangeRates.get(0).getFactor())).setScale(0, BigDecimal.ROUND_DOWN)); | |
} | |
} | |
} | |
return currentItems; | |
} | |
public List<ConsolidatedBalanceItem> getConsolidatedBalances(List<String> clientIds, List<String> currencyCodes, List<String> countryCodes, DateTime startDate, DateTime endDate, boolean useDefaults) { | |
User user = userService.getCurrentUser(); | |
List<String> clientIdsToItterate = new ArrayList<String>(); | |
clientIdsToItterate.addAll(clientIds); | |
if (clientIdsToItterate.isEmpty()) { | |
for (Client client : user.getClients()) { | |
clientIdsToItterate.add(client.getClientId()); | |
} | |
} | |
List<String> countryCodesToUse; | |
List<String> currencyCodesToUse; | |
if (useDefaults) { | |
countryCodesToUse = userService.getCountryCodesForCurrentUser(countryCodes); | |
currencyCodesToUse = userService.getCurrencyCodesForCurrentUser(currencyCodes); | |
} else { | |
currencyCodesToUse = currencyCodes; | |
countryCodesToUse = countryCodes; | |
} | |
HashMap<ClientLiquidityKey, ConsolidatedBalanceItem> map = new HashMap<ClientLiquidityKey, ConsolidatedBalanceItem>(); | |
final List<ClientLiquidity> liquidityPositionPerClient = getLiquidityPositionPerClient(clientIdsToItterate, currencyCodesToUse, countryCodesToUse, startDate, endDate); | |
for (ClientLiquidity clientLiquidity : liquidityPositionPerClient) { | |
final Iterator<LiquidityPosition> iterator = clientLiquidity.iterator(); | |
while (iterator.hasNext()) { | |
final LiquidityPosition liquidityPosition = iterator.next(); | |
//day without time | |
Date balanceDate = liquidityPosition.getDate(); | |
final String currencyCode = liquidityPosition.getCurrencyCode(); | |
final ClientLiquidityKey key = new ClientLiquidityKey(balanceDate, currencyCode); | |
ConsolidatedBalanceItem item = null; | |
item = map.get(key); | |
if (item == null) { | |
item = new ConsolidatedBalanceItem(); | |
item.setBalanceDate(new LocalDateTime(balanceDate).toDateTime()); | |
item.setCurrencyCode(currencyCode); | |
} | |
item.setTotalFacilities(liquidityPosition.getTotalFacilities()); | |
item.setCash(item.getCash().add(liquidityPosition.getCash())); | |
item.setUsedFacilities(item.getUsedFacilities().add(liquidityPosition.getUsedFacilities())); | |
map.put(key, item); | |
} | |
} | |
List<ConsolidatedBalanceItem> consolidatedBalances = new ArrayList<ConsolidatedBalanceItem>(); | |
for (ConsolidatedBalanceItem item : map.values()) { | |
item.setNetCash(item.getUsedFacilities().add(item.getCash())); | |
item.setAvailableFacilities(item.getUsedFacilities().add(item.getTotalFacilities())); | |
if (item.getAvailableFacilities().compareTo(BigDecimal.ZERO) < 0) | |
item.setAvailableFacilities(BigDecimal.ZERO); | |
item.setLiquidity(item.getCash().add(item.getAvailableFacilities())); | |
consolidatedBalances.add(item); | |
} | |
Collections.sort(consolidatedBalances); | |
return consolidatedBalances; | |
} | |
private BigDecimal getTotalFacilities(Client client) { | |
BigDecimal totalFacilities = BigDecimal.ZERO; | |
for (ClientLimit limit : client.getClientLimits()) { | |
switch (limit.getProductSet()) { | |
case novofront.treasurydashboard.Constants.CLIENT_LIMIT_CATEGORY_CFC_FACILITY: { | |
} | |
case novofront.treasurydashboard.Constants.CLIENT_LIMIT_CATEGORY_OVERDRAFT_FACILITY: { | |
} | |
case novofront.treasurydashboard.Constants.CLIENT_LIMIT_CATEGORY_PRIMARY_LENDING_FACILITY: { | |
totalFacilities = totalFacilities.add(new BigDecimal(limit.getAmount())); | |
break; | |
} | |
} | |
} | |
return totalFacilities; | |
} | |
public IndividualBalanceCommandResponse getIndividualBalances(IndividualBalanceCommand command) { | |
IndividualBalanceCommandResponse commandResponse = new IndividualBalanceCommandResponse(); | |
List<String> countryCodesToUse = userService.getCountryCodesForCurrentUser(command.getCountryCodes()); | |
List<String> currencyCodesToUse = userService.getCurrencyCodesForCurrentUser(command.getCurrencies()); | |
List<String> clientIds = userService.getClientIdsForCurrentUser(command.getClientIds()); | |
final List<ClientLiquidity> liquidityPositionPerClient = getLiquidityPositionPerClient(clientIds, currencyCodesToUse, countryCodesToUse, null, null); | |
logger.info("The number of clients retrieved is {}", clientIds.size()); | |
for (ClientLiquidity client : liquidityPositionPerClient) { | |
final Iterator<LiquidityPosition> iterator = client.iterator(); | |
while (iterator.hasNext()) { | |
final LiquidityPosition liquidityPosition = iterator.next(); | |
final IndividualBalance individualBalance = new IndividualBalance(); | |
individualBalance.setCurrencyCode(liquidityPosition.getCurrencyCode()); | |
individualBalance.setClientID(client.getClient().getClientId()); | |
individualBalance.setClientName(client.getClient().getLegalName()); | |
individualBalance.setCountryCode(liquidityPosition.getCountryCode()); | |
final Financials financials = new Financials(); | |
financials.setAvailableFacilities(liquidityPosition.getAvailableFacilities()); | |
financials.setCash(liquidityPosition.getCash()); | |
financials.setLiquidity(liquidityPosition.getLiquidity()); | |
financials.setUsedFacilities(liquidityPosition.getUsedFacilities()); | |
financials.setCurrency(liquidityPosition.getCurrencyCode()); | |
//TODO fix this | |
BigDecimal limitUtilised = BigDecimal.ZERO; | |
for (ClientLimit clientLimit : client.getClient().getClientLimits()) { | |
limitUtilised = limitUtilised.add(new BigDecimal(clientLimit.getUtilised())); | |
} | |
financials.setCreditLimitUtilisation(limitUtilised); | |
financials.setUsedLimit(BigDecimal.ZERO); | |
individualBalance.getFinancials().add(financials); | |
commandResponse.getIndividualBalancesResponse().add(individualBalance); | |
} | |
} | |
return commandResponse; | |
} | |
public List<ClientLiquidity> getLiquidityPositionPerClient(List<String> clientIds, List<String> currencyCodes, List<String> countryCodes, DateTime startDate, DateTime endDate) { | |
HashMap<String, ClientLiquidity> map = new HashMap<String, ClientLiquidity>(); | |
for (String clientId : clientIds) { | |
Client client = clientService.getByClientId(clientId); | |
BigDecimal totalFacilities = getTotalFacilities(client); | |
List<Account> accounts = accountService.listAllAccountsForClient(clientId, currencyCodes, countryCodes); | |
boolean latest = false; | |
if (startDate == null || endDate == null) | |
latest = true; | |
List<novofront.model.jpa.AccountBalance> balances = accountService.listAccountBalances(accounts, latest, startDate, endDate); | |
ClientLiquidity clientLiquidity = map.get(clientId); | |
if (clientLiquidity == null) { | |
clientLiquidity = new ClientLiquidity(); | |
clientLiquidity.setClient(client); | |
map.put(clientId, clientLiquidity); | |
} | |
for (novofront.model.jpa.AccountBalance balance : balances) { | |
//day without time | |
Date balanceDate = balance.getBalanceDate().toLocalDate().toDate(); | |
String currency = balance.getAccount().getCurrencyCode(); | |
final ClientLiquidityKey key = new ClientLiquidityKey(balanceDate, currency); | |
LiquidityPosition liquidityPosition = clientLiquidity.getLiquidityAt(key); | |
if (liquidityPosition == null) { | |
liquidityPosition = new LiquidityPosition(); | |
liquidityPosition.setDate(balanceDate); | |
liquidityPosition.setTotalFacilities(totalFacilities); | |
liquidityPosition.setCurrencyCode(balance.getAccount().getCurrencyCode()); | |
} | |
switch (balance.getAccount().getCategory()) { | |
case novofront.treasurydashboard.Constants.ACCOUNT_CATEGORY_CASH_AND_WORKING_CAPITAL: { | |
if (balance.getBalance().compareTo(BigDecimal.ZERO) > 0) { | |
liquidityPosition.setCash(liquidityPosition.getCash().add(balance.getBalance())); | |
} else { | |
liquidityPosition.setUsedFacilities(liquidityPosition.getUsedFacilities().add(balance.getBalance())); | |
} | |
break; | |
} | |
} | |
clientLiquidity.addLiquidityAt(key, liquidityPosition); | |
} | |
List<LiquidityPosition> consolidatedBalances = new ArrayList<LiquidityPosition>(); | |
final Iterator<LiquidityPosition> iterator = clientLiquidity.iterator(); | |
while (iterator.hasNext()) { | |
LiquidityPosition item = iterator.next(); | |
item.setNetCash(item.getUsedFacilities().add(item.getCash())); | |
item.setAvailableFacilities(item.getUsedFacilities().add(item.getTotalFacilities())); | |
if (item.getAvailableFacilities().compareTo(BigDecimal.ZERO) < 0) | |
item.setAvailableFacilities(BigDecimal.ZERO); | |
item.setLiquidity(item.getCash().add(item.getAvailableFacilities())); | |
} | |
} | |
return new ArrayList<ClientLiquidity>(map.values()); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment