/* * Copyright (C) 2011 4th Line GmbH, Switzerland * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.fourthline.konto.client.ledger.entry; import com.google.web.bindery.event.shared.EventBus; import com.google.gwt.user.client.rpc.AsyncCallback; import org.fourthline.konto.client.service.CurrencyServiceAsync; import org.fourthline.konto.client.ledger.entry.view.ExchangeView; import org.seamless.gwt.notify.client.Message; import org.seamless.gwt.notify.client.ServerFailureNotifyEvent; import org.seamless.gwt.notify.client.NotifyEvent; import org.fourthline.konto.shared.entity.CurrencyPair; import org.fourthline.konto.shared.MonetaryAmount; import org.fourthline.konto.shared.entity.MonetaryUnit; import org.fourthline.konto.shared.entity.Split; import org.seamless.gwt.validation.shared.ValidationError; import java.math.BigDecimal; import java.util.Date; import java.util.List; import java.util.logging.Level; /** * @author Christian Bauer */ public class ExchangePresenter implements ExchangeView.Presenter { class ResetRateAmountCallback implements AsyncCallback<CurrencyPair> { @Override public void onFailure(Throwable caught) { bus.fireEvent(new ServerFailureNotifyEvent(caught)); } @Override public void onSuccess(CurrencyPair result) { if (result != null) { currencyPair = result; bus.fireEvent(new NotifyEvent( new Message( Level.INFO, "Retrieved exchange rate from server", "Suggested rate is dated " + currencyPair.getCreatedOn() + "." ) )); } else { currencyPair = new CurrencyPair(fromUnit, toUnit, CurrencyPair.DEFAULT_EXCHANGE_RATE); } MonetaryAmount exchangedAmount = originalAmount != null ? currencyPair.getExchangedAmount(originalAmount) : null; view.reset(currencyPair, exchangedAmount); } } final ExchangeView view; final EventBus bus; final CurrencyServiceAsync currencyService; Date forDay; MonetaryUnit fromUnit; MonetaryUnit toUnit; MonetaryAmount originalAmount; CurrencyPair currencyPair; public ExchangePresenter(ExchangeView view, EventBus bus, CurrencyServiceAsync currencyService) { this.view = view; this.bus = bus; this.currencyService = currencyService; } @Override public void startWith(Date forDay, MonetaryUnit fromUnit, MonetaryUnit toUnit, MonetaryAmount originalAmt, MonetaryAmount exchangedAmt) { this.forDay = forDay; this.fromUnit = fromUnit; this.toUnit = toUnit; this.originalAmount = originalAmt != null ? originalAmt.abs() : originalAmt; view.setPresenter(this); if (exchangedAmt != null && exchangedAmt.signum() != 0) { exchangedAmt = exchangedAmt.abs(); currencyPair = new CurrencyPair(fromUnit, toUnit, originalAmount, exchangedAmt); view.reset(currencyPair, exchangedAmt); } else { currencyService.getCurrencyPair(fromUnit, toUnit, forDay, new ResetRateAmountCallback()); } } @Override public void updateForDay(Date date) { // Not initialized yet if (fromUnit == null || toUnit == null) return; // Valid rate has already been entered, don't retrieve it again and don't overwrite the user value BigDecimal enteredRate = view.getRateProperty().get(); if (enteredRate != null && !enteredRate.equals(CurrencyPair.DEFAULT_EXCHANGE_RATE) && enteredRate.signum() > 0) return; this.forDay = date; currencyService.getCurrencyPair(fromUnit, toUnit, forDay, new ResetRateAmountCallback()); } @Override public void updateOriginalAmount(MonetaryAmount amt) { if (fromUnit == null || toUnit == null) return; originalAmount = amt != null ? amt.abs() : amt; setViewExchangedAmount(); } @Override public void rateUpdated() { // Calculate the target amount using the exchange rate setViewExchangedAmount(); } @Override public void exchangedAmountUpdated() { MonetaryAmount exchangedAmount = view.getAmountProperty().get(); if (exchangedAmount == null) { setViewExchangedAmount(); } else { // If the user entered a "-" symbol, negate that if (exchangedAmount.signum() < 0) { exchangedAmount = exchangedAmount.abs(); view.getAmountProperty().set(exchangedAmount); } if (originalAmount != null && originalAmount.signum() > 0 && exchangedAmount.signum() > 0) { BigDecimal exchangeRate = CurrencyPair.getExchangeRate(originalAmount, exchangedAmount); view.getRateProperty().set(exchangeRate); } } } @Override public MonetaryAmount getExchangedAmount() { return view.getAmountProperty().get(); } @Override public void clearValidationErrors() { view.getRateProperty().clearValidationError(); view.getAmountProperty().clearValidationError(); } @Override public void showValidationErrors(List<ValidationError> errors) { for (ValidationError error : errors) { if (Split.Property.amount.equals(error.getProperty())) { view.getRateProperty().showValidationError(error); view.getAmountProperty().showValidationError(error); } } } protected BigDecimal getViewExchangeRate() { BigDecimal exchangeRate = view.getRateProperty().get(); // Use the default (1.0) exchange rate if there is none entered or invalid if (exchangeRate == null || exchangeRate.signum() < 1) exchangeRate = CurrencyPair.DEFAULT_EXCHANGE_RATE; return exchangeRate; } protected void setViewExchangedAmount() { if (originalAmount != null && originalAmount.signum() > 0) { // Calculcate the exchanged amount based on original amount and visible rate CurrencyPair cp = new CurrencyPair(fromUnit, toUnit, getViewExchangeRate()); MonetaryAmount exchangedAmount = cp.getExchangedAmount(originalAmount); view.getAmountProperty().set(exchangedAmount); } else { // Set to zero view.getAmountProperty().set(new MonetaryAmount(toUnit)); } } }