package org.internna.ossmoney.mvc;
import java.util.Set;
import java.util.Date;
import java.util.Locale;
import java.util.TreeSet;
import java.util.Currency;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import org.internna.ossmoney.model.Account;
import org.internna.ossmoney.util.DateUtils;
import org.internna.ossmoney.model.Investment;
import org.internna.ossmoney.cache.CacheStore;
import org.internna.ossmoney.model.Subcategory;
import org.internna.ossmoney.model.InvestmentPrice;
import org.internna.ossmoney.model.AccountTransaction;
import org.internna.ossmoney.model.security.UserDetails;
import org.internna.ossmoney.services.InvestmentService;
import org.internna.ossmoney.model.InvestmentTransaction;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
@Controller
@RequestMapping("/financial/investments")
public class InvestmentController {
@Autowired private CacheStore cache;
@Autowired private InvestmentService investmentService;
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
@RequestMapping("/{id}")
public String investments(@PathVariable Long id, ModelMap modelMap) {
modelMap.addAttribute("id", id);
Account account = Account.findAccount(id);
UserDetails user = UserDetails.findCurrentUser();
if (account.belongsTo(user)) {
modelMap.addAttribute("investments", account.getCurrentInvestments());
}
return "investment/performance";
}
@RequestMapping("/create")
public String create(ModelMap modelMap) {
return "investment/create";
}
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String create(String type, String name, String symbol, String locale, ModelMap modelMap) {
String[] parts = locale.split("_");
Investment investment = new Investment();
investment.setName(name);
investment.setSymbol(symbol);
investment.setProductType(type);
investment.setOwner(UserDetails.findCurrentUser());
investment.setLocale(new Locale(parts[0], parts[1], ""));
investment.persist();
return "redirect:/financial/accounts";
}
@RequestMapping("/add")
public String add(ModelMap modelMap) {
return add(null, modelMap);
}
@RequestMapping("/add/{id}")
public String add(@PathVariable Long id, ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
Collection<Account> accounts = user.getInvestmentAccounts();
if (id != null) {
Account account = Account.findAccount(id);
if (account.belongsTo(user)) {
modelMap.addAttribute("account", account);
modelMap.addAttribute("currency", account.getCurrency());
} else {
modelMap.addAttribute("currency", CollectionUtils.isEmpty(accounts) ? "EUR" : accounts.iterator().next().getCurrency());
}
}
modelMap.addAttribute("accounts", accounts);
modelMap.addAttribute("investments", Investment.findInvestmentsByOwner(user));
return "investment/add";
}
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String add(InvestmentTransaction transaction, double commision, ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
Account account = Account.findAccount(transaction.getAccountTransaction().getAccount().getId());
if (account.belongsTo(user)) {
cache.invalidate(user);
investmentService.addInvestment(user, account, transaction, commision);
}
return "redirect:/financial/accounts/" + transaction.getAccountTransaction().getAccount().getId();
}
@RequestMapping("/view/{id}")
public String view(@PathVariable Long id, ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
InvestmentTransaction transaction = InvestmentTransaction.findInvestmentTransaction(id);
Account account = transaction.getAccountTransaction().getAccount();
if (account.belongsTo(user)) {
modelMap.addAttribute("account", account);
modelMap.addAttribute("transaction", transaction);
modelMap.addAttribute("investments", Investment.findInvestmentsByOwner(user));
}
return "investment/view";
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public String edit(InvestmentTransaction transaction, ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
InvestmentTransaction loaded = InvestmentTransaction.findInvestmentTransaction(transaction.getId());
Account account = loaded.getAccountTransaction().getAccount();
if (account.belongsTo(user)) {
cache.invalidate(user);
AccountTransaction accountTransaction = loaded.getAccountTransaction();
if (transaction.getPrice() != null) {
loaded.setQuantity(transaction.getQuantity());
loaded.getPrice().setPrice(transaction.getPrice().getPrice());
accountTransaction.setAmount(new BigDecimal(transaction.getQuantity() * transaction.getPrice().getPrice()));
} else {
loaded.setPrice(null);
accountTransaction.setAmount(transaction.getAccountTransaction().getAmount());
}
Investment investment = Investment.findInvestment(transaction.getInvestment().getId());
loaded.setInvestment(investment);
loaded.getAccountTransaction().setPayee(investment);
accountTransaction.setOperationDate(transaction.getAccountTransaction().getOperationDate());
accountTransaction.setReferenceNumber(transaction.getAccountTransaction().getReferenceNumber());
accountTransaction.setSubcategory(Subcategory.findBySubcategory(transaction.getAccountTransaction().getSubcategory().getCategory(), user));
loaded.merge();
}
return "redirect:/financial/accounts/" + account.getId();
}
@RequestMapping("/remove/{id}")
public String remove(@PathVariable Long id, ModelMap modelMap) {
Long accountId = null;
UserDetails user = UserDetails.findCurrentUser();
InvestmentTransaction transaction = InvestmentTransaction.findInvestmentTransaction(id);
if (transaction != null) {
AccountTransaction accountTransaction = transaction.getAccountTransaction();
Account account = accountTransaction.getAccount();
if (account.belongsTo(user)) {
cache.invalidate(user);
accountId = account.getId();
accountTransaction.remove();
}
}
return "redirect:/financial/accounts/" + (accountId != null ? accountId : "");
}
@RequestMapping("/update-prices")
public String investments(ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
modelMap.addAttribute("investments", Investment.findInvestmentsByOwner(user));
return "investment/prices";
}
@RequestMapping("/prices/{id}")
public String getPrices(@PathVariable Long id, ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
String currency = "EUR";
Investment investment = Investment.findInvestment(id);
Set<InvestmentPrice> prices = new TreeSet<InvestmentPrice>();
Set<InvestmentPrice> datedPrices = new TreeSet<InvestmentPrice>();
if (investment.belongsTo(user)) {
if (investment.getLocale() != null) {
Locale locale = investment.getLocale();
Currency investmentCurrency = Currency.getInstance(locale);
currency = investmentCurrency.getCurrencyCode();
}
modelMap.addAttribute("investment", investment.getName());
prices.addAll(InvestmentPrice.findInvestmentPricesByInvestment(investment));
datedPrices.addAll(prices);
fill(datedPrices);
}
modelMap.addAttribute("id", id);
modelMap.addAttribute("prices", prices);
modelMap.addAttribute("currency", currency);
modelMap.addAttribute("datedPrices", datedPrices);
return "investment/list-prices";
}
protected void fill(Set<InvestmentPrice> prices) {
if ((prices != null) && (prices.size() > 1)) {
Collection<InvestmentPrice> dated = new ArrayList<InvestmentPrice>();
Iterator<InvestmentPrice> it = prices.iterator();
InvestmentPrice target, origin = it.next();
while (it.hasNext()) {
target = it.next();
fill(dated, origin, target);
origin = target;
}
prices.addAll(dated);
}
}
protected void fill(Collection<InvestmentPrice> prices, InvestmentPrice origin, InvestmentPrice target) {
Date[] dates = DateUtils.interval(origin.getUpdateTime(), target.getUpdateTime());
for (Date date : dates) {
InvestmentPrice price = new InvestmentPrice();
price.setUpdateTime(date);
price.setPrice(origin.getPrice());
prices.add(price);
}
}
@RequestMapping(value = "/prices", method = RequestMethod.POST)
public String setPrice(Long investmentId, Long priceId, Date operationDate, Double amount, ModelMap modelMap) {
UserDetails user = UserDetails.findCurrentUser();
Investment investment = Investment.findInvestment(investmentId);
InvestmentPrice price = InvestmentPrice.findInvestmentPrice(priceId);
if (price == null) {
price = new InvestmentPrice();
investment.addPrice(price);
}
if ((investment != null) && investment.belongsTo(user) && price.belongsTo(investment)) {
price.setPrice(amount);
price.setUpdateTime(operationDate);
if (price.getId() != null) {
price.merge();
} else {
price.persist();
}
}
return getPrices(investmentId, modelMap);
}
}