/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.setup.migrations.version3_5; import static nl.strohalm.cyclos.utils.JDBCWrapper.closeQuietly; import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import nl.strohalm.cyclos.entities.settings.LocalSettings; import nl.strohalm.cyclos.entities.settings.LocalSettings.Precision; import nl.strohalm.cyclos.setup.UntraceableMigration; import nl.strohalm.cyclos.utils.JDBCWrapper; import nl.strohalm.cyclos.utils.conversion.CoercionHelper; /** * Populates the account_status and account_fee_charges tables * @author luis */ @SuppressWarnings("deprecation") public class FixedAccountStatusRecreationMigration implements UntraceableMigration { public void execute(final JDBCWrapper jdbc) throws SQLException { final String accountQuery = "select id, subclass, credit_limit, upper_credit_limit from accounts"; final String transferQuery = "select id, ifnull(process_date, date) as date, amount, status, from_account_id, to_account_id, parent_id, account_fee_log_id, chargeback_of_id from transfers where status in ('O', 'P') and (from_account_id = ? or to_account_id = ?) order by ifnull(process_date, date), id"; final String initialStatusInsert = "insert into account_status (subclass, account_id, date, credit_limit, upper_credit_limit) select subclass, id, creation_date, credit_limit, upper_credit_limit from accounts"; final String statusInsert = "insert into account_status (subclass, account_id, date, root_credits_count, root_credits_amount, root_debits_count, root_debits_amount, nested_credits_count, nested_credits_amount, nested_debits_count, nested_debits_amount, pending_credits_amount, pending_credits_count, pending_debits_amount, pending_debits_count, credit_limit, upper_credit_limit, transfer_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; final ResultSet rsAccounts = jdbc.query(accountQuery); // Ensure the account status table is empty jdbc.execute("delete from account_status"); // Read the local settings final LocalSettings settings = new LocalSettings(); final Precision precision = CoercionHelper.coerce(Precision.class, jdbc.readScalarAsString("select value from settings where name=?", "precision")); if (precision != null) { settings.setPrecision(precision); } // Insert an account status for every account creation jdbc.execute(initialStatusInsert); // Get each account while (rsAccounts.next()) { final long accountId = rsAccounts.getLong("id"); final String subclass = rsAccounts.getString("subclass"); final BigDecimal creditLimit = settings.round(rsAccounts.getBigDecimal("credit_limit")); final BigDecimal upperCreditLimit = settings.round(rsAccounts.getBigDecimal("upper_credit_limit")); BigDecimal rootCreditsAmount = BigDecimal.ZERO; int rootCreditsCount = 0; BigDecimal rootDebitsAmount = BigDecimal.ZERO; int rootDebitsCount = 0; BigDecimal nestedCreditsAmount = BigDecimal.ZERO; int nestedCreditsCount = 0; BigDecimal nestedDebitsAmount = BigDecimal.ZERO; int nestedDebitsCount = 0; // BigDecimal pendingCreditsAmount = BigDecimal.ZERO; int pendingCreditsCount = 0; BigDecimal pendingDebitsAmount = BigDecimal.ZERO; int pendingDebitsCount = 0; // Insert a new status for every transfer from or to that account final ResultSet rsTransfers = jdbc.query(transferQuery, accountId, accountId); while (rsTransfers.next()) { final long transferId = rsTransfers.getLong("id"); final Timestamp date = rsTransfers.getTimestamp("date"); final BigDecimal amount = settings.round(rsTransfers.getBigDecimal("amount")).abs(); final long fromAccountId = rsTransfers.getLong("from_account_id"); Long chargebackOfId = rsTransfers.getLong("chargeback_of_id"); if (rsTransfers.wasNull()) { chargebackOfId = null; } final boolean isRoot = rsTransfers.getString("parent_id") == null && rsTransfers.getString("account_fee_log_id") == null; final String status = rsTransfers.getString("status"); // Check if is a credit or a debit final boolean isDebit = chargebackOfId == null ? accountId == fromAccountId : accountId != fromAccountId; final boolean isProcessed = status.equals("O"); final boolean isPending = status.equals("P"); if (isDebit) { if (isRoot) { if (isProcessed) { rootDebitsAmount = rootDebitsAmount.add(amount); rootDebitsCount++; } else if (isPending) { pendingDebitsAmount = pendingDebitsAmount.add(amount); pendingDebitsCount++; } } else { if (isProcessed) { nestedDebitsAmount = nestedDebitsAmount.add(amount); nestedDebitsCount++; } else if (isPending) { pendingDebitsAmount = pendingDebitsAmount.add(amount); pendingDebitsCount++; } } } else { if (isRoot) { if (isProcessed) { rootCreditsAmount = rootCreditsAmount.add(amount); rootCreditsCount++; } else if (isPending) { pendingCreditsAmount = pendingCreditsAmount.add(amount); pendingCreditsCount++; } } else { if (isProcessed) { nestedCreditsAmount = nestedCreditsAmount.add(amount); nestedCreditsCount++; } else if (isPending) { pendingCreditsAmount = pendingCreditsAmount.add(amount); pendingCreditsCount++; } } } // Insert the account status jdbc.execute(statusInsert, subclass, accountId, date, rootCreditsCount, rootCreditsAmount, rootDebitsCount, rootDebitsAmount, nestedCreditsCount, nestedCreditsAmount, nestedDebitsCount, nestedDebitsAmount, pendingCreditsAmount, pendingCreditsCount, pendingDebitsAmount, pendingDebitsCount, creditLimit, upperCreditLimit, transferId); } closeQuietly(rsTransfers); } closeQuietly(rsAccounts); } }