PortofolioEntity extends AuditableEntity { public Order buy(SymbolEntity fromSymbol, double quantity, RateService rateService) throws OrderException { Objects.requireNonNull(fromSymbol, "fromSymbol must be not null"); Preconditions.checkArgument(quantity > 0, "quantity must be positive: %s", getBaseCurrency()); Preconditions.checkArgument(!getBaseCurrency().equals(fromSymbol), "Cannot buy baseCurrency: %s", getBaseCurrency()); final SymbolEntity currency = getCurrencyFor(fromSymbol); Rate q = rateService.getLatest(fromSymbol.getCode(), currency.getCode()); final BigDecimal currencyAmount; if (currency.equals(getBaseCurrency())) { currencyAmount = getAmount(); } else if (getAsset(currency.getCode()) != null) { currencyAmount = getAsset(currency.getCode()).getQuantity(); } else { currencyAmount = ZERO; } BigDecimal amountNeeded = q.getValue().multiply(BigDecimal.valueOf(quantity)); if (currencyAmount.compareTo(amountNeeded) < 0) { throw OrderException.NOT_ENOUGH_FUND(fromSymbol.getCode(), quantity, currency.getCode(), currencyAmount.doubleValue(), amountNeeded.doubleValue()); } AssetEntity ownedAsset = getAsset(fromSymbol.getCode()); if (ownedAsset == null) { ownedAsset = new AssetEntity(this, fromSymbol, ZERO, currency, ZERO); assets.add(ownedAsset); } BigDecimal fundAfterPurchase = currencyAmount.subtract(amountNeeded); if (currency.equals(getBaseCurrency())) { this.amount = fundAfterPurchase; } else { AssetEntity currencyAsset = getAsset(currency.getCode()); currencyAsset.withdraw(amountNeeded); } ownedAsset.makeDeposit(BigDecimal.valueOf(quantity), amountNeeded); return new Order(currency, amountNeeded.doubleValue(), fromSymbol, quantity); }  List<AssetEntity> getAssets(); AssetEntity getAsset(String symbolCode); SymbolEntity getCurrencyFor(SymbolEntity symbol); List<SymbolEntity> getCurrencies(); Order buy(SymbolEntity fromSymbol, double quantity, RateService rateService); Order sell(SymbolEntity fromSymbol, double quantity, RateService rateService);  }
@Test public void testBuy_NoFund() throws Exception { String login = "seller"; String assetCode = "BRE"; double quantity = 1; PortofolioEntity portofolio = portofolioRepo.findByUserUsername(login); assertThatExceptionOfType(OrderException.class) .isThrownBy(() -> portofolio.buy(symbolRepo.findById(assetCode).get(), quantity, rateService)) .withMessageContaining("not_enough_fund"); }
@Test public void testBuy_NotEnoughFund() throws Exception { String login = "seller"; String assetCode = "UBI"; double quantity = 1; PortofolioEntity portofolio = portofolioRepo.findByUserUsername(login); assertThatExceptionOfType(OrderException.class) .isThrownBy(() -> portofolio.buy(symbolRepo.findById(assetCode).get(), quantity, rateService)) .withMessageContaining("not_enough_fund"); }