public void setCurrencies(Integer entityId, CurrencyDTO[] currencies)
      throws NamingException, ParseException {
    EntityBL entity = new EntityBL(entityId);

    // start by wiping out the existing data for this entity
    entity.getEntity().getCurrencies().clear();
    for (CurrencyExchangeDTO exchange : exchangeDas.findByEntity(entityId)) {
      exchangeDas.delete(exchange);
    }

    for (CurrencyDTO currency : currencies) {
      if (currency.getInUse()) {
        set(currency.getId());
        entity.getEntity().getCurrencies().add(new CurrencyDAS().find(this.currency.getId()));

        if (currency.getRate() != null) {
          CurrencyExchangeDTO exchange =
              setOrUpdateExchangeRate(currency.getRateAsDecimal(), entityId, new Date());
          exchangeDas.save(exchange);
        }
      }
    }

    invalidateCache();
    ;
  }
  public CurrencyExchangeDTO setOrUpdateExchangeRate(
      BigDecimal amount, Integer entityId, Date dateFrom) {
    final Date truncatedToDay = com.sapienter.jbilling.common.Util.truncateDate(dateFrom);
    CurrencyExchangeDTO exchangeRate =
        exchangeDas.getExchangeRateForRange(entityId, currency.getId(), truncatedToDay, dateFrom);

    if (amount == null) {
      if (exchangeRate != null) {
        // remove record
        exchangeDas.delete(exchangeRate);
        currency.getCurrencyExchanges().remove(exchangeRate);
      }
      return null;
    }

    if (exchangeRate == null) {
      exchangeRate = new CurrencyExchangeDTO();
      exchangeRate.setEntityId(entityId);
      exchangeRate.setValidSince(truncatedToDay);
      exchangeRate.setCurrency(currency);
      currency.getCurrencyExchanges().add(exchangeRate);
    }

    exchangeRate.setRate(amount);
    invalidateCache();
    ;
    return exchangeRate;
  }
  public void testConvert() throws Exception {
    expect(mockExchangeDas.findExchange(ENTITY_ID, 200))
        .andReturn(_mockCurrencyExchangeDTO("0.98"))
        .once();
    expect(mockExchangeDas.findExchange(ENTITY_ID, 201))
        .andReturn(_mockCurrencyExchangeDTO("1.20"))
        .once();
    replay(mockCurrencyDas, mockExchangeDas);

    // convert $20.00 CAD to AUD - approximated conversion rates ;)
    CurrencyBL bl = new CurrencyBL(mockCurrencyDas, mockExchangeDas);
    BigDecimal amount = bl.convert(200, 201, new BigDecimal("20.00"), ENTITY_ID);

    verify(mockCurrencyDas, mockExchangeDas);

    assertEquals(new BigDecimal("24.48979"), amount);
  }
  /** Removes exchange data for specified date */
  public void removeExchangeRatesForDate(Integer entityId, Date date) {
    final Date dayStart = com.sapienter.jbilling.common.Util.truncateDate(date);

    final CurrencyExchangeDAS exchangeDAS = new CurrencyExchangeDAS();
    final List<CurrencyExchangeDTO> companyExchanges = exchangeDAS.findByEntity(entityId);
    for (CurrencyExchangeDTO exchange : companyExchanges) {
      if (entityId.equals(exchange.getEntityId())) {
        final Date validSince = exchange.getValidSince();
        if (dayStart.equals(com.sapienter.jbilling.common.Util.truncateDate(validSince))) {
          exchangeDAS.delete(exchange);
        }
      }
    }
    /* @todo Konstantin Kulagin this should be in controller	*/
    exchangeDAS.flush();
    invalidateCache();
    ;
  }
  public void testConvertRepeatingDecimal() throws Exception {
    expect(mockExchangeDas.findExchange(ENTITY_ID, 200))
        .andReturn(_mockCurrencyExchangeDTO("3.00"))
        .once();
    expect(mockExchangeDas.findExchange(ENTITY_ID, 201))
        .andReturn(_mockCurrencyExchangeDTO("1.00"))
        .once();
    replay(mockCurrencyDas, mockExchangeDas);

    /*
       Pivot calculation will result in a value of 3.333333~ repeating, which will
       cause an ArithmeticException if not handled correctly.

       10.00 / 3.00 = 3.333333~
    */
    CurrencyBL bl = new CurrencyBL(mockCurrencyDas, mockExchangeDas);
    BigDecimal amount = bl.convert(200, 201, new BigDecimal("10.00"), ENTITY_ID);

    verify(mockCurrencyDas, mockExchangeDas);

    assertEquals(new BigDecimal("3.33"), amount);
  }
  private CurrencyExchangeDTO findExchange(Integer entityId, Integer currencyId, Date toDate)
      throws SessionInternalError {

    // check for system currency exchange
    if (SYSTEM_CURRENCY_ID.equals(currencyId)) {
      return new CurrencyExchangeDTO(
          0, currency, entityId, SYSTEM_CURRENCY_RATE_DEFAULT, new Date());
    }
    LOG.debug("Get exchange rate for %s for entity %s for date %s", currencyId, entityId, toDate);

    CurrencyExchangeDTO exchange = exchangeDas.getExchangeRateForDate(entityId, currencyId, toDate);
    if (exchange == null) {
      // this entity doesn't have this exchange defined
      // 0 is the default, don't try to use null, it won't work
      exchange = exchangeDas.findExchange(SYSTEM_RATE_ENTITY_ID, currencyId);
      if (exchange == null) {
        throw new SessionInternalError(
            "Currency " + currencyId + " doesn't have a default exchange");
      }
    }
    LOG.debug("Exchange found %s", exchange.getId());
    return exchange;
  }
  public List<CurrencyDTO> getCurrenciesToDate(Integer languageId, Integer entityId, Date to)
      throws NamingException, SQLException {

    String cacheKey = getCacheKey(languageId, entityId, to);
    List<CurrencyDTO> cachedCurrencies =
        (List<CurrencyDTO>) cache.getFromCache(cacheKey, cacheModel);

    if (cachedCurrencies != null && !cachedCurrencies.isEmpty()) {
      LOG.debug("Cache hit for %s", cacheKey);
      return cachedCurrencies;
    }

    List<CurrencyDTO> currencies = new CurrencyDAS().findAll();

    for (CurrencyDTO currency : currencies) {
      set(currency.getId());
      currency.setName(this.currency.getDescription(languageId));

      // find system rate
      if (currency.getId() == SYSTEM_CURRENCY_ID.intValue()) {
        currency.setSysRate(SYSTEM_CURRENCY_RATE_DEFAULT);
      } else {
        final CurrencyExchangeDTO exchangeRateForDate =
            findExchange(SYSTEM_RATE_ENTITY_ID, currency.getId(), to);
        currency.setSysRate(exchangeRateForDate.getRate());
      }

      // find entity specific rate
      CurrencyExchangeDTO exchange =
          exchangeDas.getExchangeRateForDate(entityId, currency.getId(), to);
      if (exchange != null) {
        currency.setRate(exchange.getRate().toString());
      }

      // set in-use flag
      currency.setInUse(entityHasCurrency(entityId, currency.getId()));
    }

    cache.putInCache(cacheKey, cacheModel, currencies);

    return currencies;
  }