package org.openbankdata.bank.americanexpress.service;
import org.openbankdata.bank.americanexpress.client.AmericanExpressBankClient;
import org.openbankdata.bank.americanexpress.client.AmericanExpressTransactionPaginationStrategy;
import org.openbankdata.core.Account;
import org.openbankdata.core.Transaction;
import org.openbankdata.core.client.BankClient;
import org.openbankdata.core.client.BankResponse;
import org.openbankdata.core.client.PageIterator;
import org.openbankdata.core.client.PagedBankRequest;
import org.openbankdata.core.service.AbstractTransactionService;
import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.Locale;
/**
* Service class for accessing transaction data at AmericanExpress.
*/
public class AmericanExpressTransactionService extends AbstractTransactionService
{
private static final String TRANSACTIONS_URL =
"https://global.americanexpress.com/myca/intl/estatement/emea/statement.do";
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("d MMM yyyy").withLocale(
new Locale("sv-SE"));
private BankClient mBankClient;
public AmericanExpressTransactionService(
AmericanExpressBankClient pBankClient) {
mBankClient = pBankClient;
}
@Override
public List<Transaction> getTransactions(Account pAccount, LocalDate pFromDateTime,
LocalDate pToDateTime) {
List<Transaction> transactions = new ArrayList<Transaction>();
PageIterator it =
new PageIterator(getBankRequest(pAccount, pFromDateTime, pToDateTime), mBankClient);
for (BankResponse response : it) {
transactions.addAll(parseTransactions(response));
}
return filterTransactions(transactions, pFromDateTime, pToDateTime);
}
private List<Transaction> parseTransactions(BankResponse pResponse) {
List<Transaction> transactions = new ArrayList<Transaction>();
Document doc = Jsoup.parse(pResponse.body());
Element transactionTable = doc.getElementById("table-txnsCard0");
if (transactionTable != null) {
for (Element transaction : transactionTable.select("tbody tr")) {
transactions.add(parseTransaction(transaction));
}
}
return transactions;
}
private Transaction parseTransaction(Element elem) {
Transaction transaction = new Transaction();
String date = elem.child(0).html();
transaction.setTransactionDate(DATE_FORMATTER.parseLocalDate(date));
transaction.setDescription(elem.child(1).ownText().trim());
transaction.setAmount(parseAmount(elem.child(2), elem.child(3)));
transaction.setCurrency(Currency.getInstance("SEK"));
return transaction;
}
private BigDecimal parseAmount(Element pIncoming, Element pOutgoing) {
String nonNumeric = "[^\\d]";
String amount = pIncoming.ownText().replaceAll(nonNumeric, "").trim();
if (amount.isEmpty()) {
amount = "-"
+ pOutgoing.ownText().replaceAll(nonNumeric, "").trim();
}
return new BigDecimal(amount).divide(new BigDecimal(100));
}
private PagedBankRequest getBankRequest(Account pAccount, LocalDate pFromDateTime,
LocalDate pToDateTime) {
return (PagedBankRequest) new PagedBankRequest(calculateFirstPage(pFromDateTime))
.setPaginationStrategy(
new AmericanExpressTransactionPaginationStrategy(pFromDateTime, pToDateTime))
.setUri(TRANSACTIONS_URL)
.addParam("sorted_index", pAccount.getId())
.addParam("Face", "sv_SE");
}
private int calculateFirstPage(LocalDate pFromDateTime) {
if (pFromDateTime == null) {
return 0;
}
return Months.monthsBetween(pFromDateTime, LocalDate.now()).getMonths();
}
}