/* * Copyright (C) 2012-2016 The Android Money Manager Ex Project Team * * This program 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 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.money.manager.ex.budget; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteQueryBuilder; import android.support.v4.widget.SimpleCursorAdapter; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CursorAdapter; import android.widget.TextView; import com.money.manager.ex.Constants; import com.money.manager.ex.MoneyManagerApplication; import com.money.manager.ex.R; import com.money.manager.ex.datalayer.Select; import com.money.manager.ex.log.ExceptionHandler; import com.money.manager.ex.currency.CurrencyService; import com.money.manager.ex.database.SQLDataSet; import com.money.manager.ex.database.ViewMobileData; import com.squareup.sqlbrite.BriteDatabase; import javax.inject.Inject; import butterknife.ButterKnife; import dagger.Lazy; import info.javaperformance.money.MoneyFactory; import timber.log.Timber; /** * Adapter for budgets. */ public class BudgetAdapter extends SimpleCursorAdapter { /** * Standard constructor. * * @param context The context where the ListView associated with this * SimpleListItemFactory is running * @param from A list of column names representing the data to bind to the UI. Can be null * if the cursor is not available yet. * @param to The views that should display column in the "from" parameter. * These should all be TextViews. The first N views in this list * are given the values of the first N columns in the from * parameter. Can be null if the cursor is not available yet. * @param flags Flags used to determine the behavior of the adapter, * as per {@link CursorAdapter#CursorAdapter(Context, Cursor, int)}. */ public BudgetAdapter(Context context, Cursor cursor, String[] from, int[] to, int flags) { super(context, R.layout.item_budget, cursor, from, to, flags); mContext = context; mLayout = R.layout.item_budget; MoneyManagerApplication.getApp().iocComponent.inject(this); } @Inject Lazy<BriteDatabase> databaseLazy; private int mLayout; private String mBudgetName; @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final LayoutInflater inflater = LayoutInflater.from(context); return inflater.inflate(mLayout, parent, false); } @Override public void bindView(View view, Context context, Cursor cursor) { // Category boolean hasSubcategory = false; TextView categoryTextView = (TextView) view.findViewById(R.id.categoryTextView); if (categoryTextView != null) { int categoryCol = cursor.getColumnIndex(BudgetQuery.CATEGNAME); String category = cursor.getString(categoryCol); // Subcategory String subCategory = cursor.getString(cursor.getColumnIndex(BudgetQuery.SUBCATEGNAME)); if (!TextUtils.isEmpty(subCategory)) { category += ":" + subCategory; hasSubcategory = true; } categoryTextView.setText(category); } // Frequency TextView frequencyTextView = (TextView) view.findViewById(R.id.frequencyTextView); if (frequencyTextView != null) { String text = cursor.getString(cursor.getColumnIndex(BudgetQuery.PERIOD)); frequencyTextView.setText(text); } CurrencyService currencyService = new CurrencyService(mContext); // Amount TextView amountTextView = (TextView) view.findViewById(R.id.amountTextView); if (amountTextView != null) { double amount = cursor.getDouble(cursor.getColumnIndex(BudgetQuery.AMOUNT)); String text = currencyService.getBaseCurrencyFormatted(MoneyFactory.fromDouble(amount)); amountTextView.setText(text); } // Estimated // Actual // todo: colour the amount depending on whether it is above/below the budgeted amount. TextView actualTextView = (TextView) view.findViewById(R.id.actualTextView); if (actualTextView != null) { double actual; if (!hasSubcategory) { int categoryId = cursor.getInt(cursor.getColumnIndex(BudgetQuery.CATEGID)); actual = getAmountForCategory(categoryId); } else { int subCategoryId = cursor.getInt(cursor.getColumnIndex(BudgetQuery.SUBCATEGID)); actual = getAmountForSubCategory(subCategoryId); } String actualString = currencyService.getBaseCurrencyFormatted(MoneyFactory.fromDouble(actual)); actualTextView.setText(actualString); } } public Context getContext() { return mContext; } public void setBudgetName(String budgetName) { mBudgetName = budgetName; } private double getAmountForCategory(int categoryId) { double total = loadTotalFor(ViewMobileData.CATEGID + "=" + Integer.toString(categoryId)); return total; } private double getAmountForSubCategory(int subCategoryId) { double total = loadTotalFor(ViewMobileData.SubcategID + "=" + Integer.toString(subCategoryId)); return total; } private double loadTotalFor(String where) { double total = 0; int year = getYearFromBudgetName(mBudgetName); where += " AND " + ViewMobileData.Year + "=" + Integer.toString(year); int month = getMonthFromBudgetName(mBudgetName); if (month != Constants.NOT_SET) { where += " AND " + ViewMobileData.Month + "=" + Integer.toString(month); } try { String query = prepareQuery(where); Cursor cursor = databaseLazy.get().query(query); if (cursor == null) return 0; // add all the categories and subcategories together. while (cursor.moveToNext()) { total += cursor.getDouble(cursor.getColumnIndex("TOTAL")); } cursor.close(); } catch (IllegalStateException ise) { Timber.e(ise, "loading category total"); } return total; } private String prepareQuery(String whereClause) { SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); ViewMobileData mobileData = new ViewMobileData(getContext()); //data to compose builder String[] projectionIn = new String[]{ "ROWID AS _id", ViewMobileData.CATEGID, ViewMobileData.Category, ViewMobileData.SubcategID, ViewMobileData.Subcategory, "SUM(" + ViewMobileData.AmountBaseConvRate + ") AS TOTAL" }; String selection = ViewMobileData.Status + "<>'V' AND " + ViewMobileData.TransactionType + " IN ('Withdrawal', 'Deposit')"; if (!TextUtils.isEmpty(whereClause)) { selection += " AND " + whereClause; } String groupBy = ViewMobileData.CATEGID + ", " + ViewMobileData.Category + ", " + ViewMobileData.SubcategID + ", " + ViewMobileData.Subcategory; String having = null; // if (!TextUtils.isEmpty(((CategoriesReportActivity) context).mFilter)) { // String filter = ((CategoriesReportActivity) context).mFilter; // if (TransactionTypes.valueOf(filter).equals(TransactionTypes.Withdrawal)) { // having = "SUM(" + ViewMobileData.AmountBaseConvRate + ") < 0"; // } else { // having = "SUM(" + ViewMobileData.AmountBaseConvRate + ") > 0"; // } // } String sortOrder = ViewMobileData.Category + ", " + ViewMobileData.Subcategory; String limit = null; builder.setTables(mobileData.getSource()); return builder.buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit); } private int getYearFromBudgetName(String budgetName) { String yearString = budgetName.substring(0, 4); int year = Integer.parseInt(yearString); return year; } private int getMonthFromBudgetName(String budgetName) { int result = Constants.NOT_SET; if (!budgetName.contains("-")) return result; int separatorLocation = budgetName.indexOf("-"); String monthString = budgetName.substring(separatorLocation + 1, separatorLocation + 3); result = Integer.parseInt(monthString); return result; } }