From 672704ab67fc485baa686ea9a01fca556608cf34 Mon Sep 17 00:00:00 2001 From: Eranga Date: Sun, 6 Dec 2015 16:21:55 +0530 Subject: [PATCH 1/2] Finalized project --- .idea/encodings.xml | 6 + .idea/gradle.xml | 18 ++ .idea/libraries/appcompat_v7_23_1_1.xml | 15 ++ .idea/libraries/design_23_1_1.xml | 15 ++ .idea/libraries/recyclerview_v7_23_1_1.xml | 15 ++ .../libraries/support_annotations_23_1_1.xml | 11 + .idea/libraries/support_v4_23_1_1.xml | 16 ++ SimpleExpenseManager.iml | 19 ++ app/src/main/AndroidManifest.xml | 1 + .../dbs/simpleexpensemanager/AppContext.java | 23 ++ .../control/PersistentExpenseManager.java | 36 +++ .../data/impl/PersistentAccountDAO.java | 206 ++++++++++++++++++ .../data/impl/PersistentTransactionDAO.java | 118 ++++++++++ .../database/DBHandler.java | 64 ++++++ .../simpleexpensemanager/database/Fields.java | 22 ++ .../simpleexpensemanager/ui/MainActivity.java | 8 +- 16 files changed, 591 insertions(+), 2 deletions(-) create mode 100644 .idea/encodings.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/libraries/appcompat_v7_23_1_1.xml create mode 100644 .idea/libraries/design_23_1_1.xml create mode 100644 .idea/libraries/recyclerview_v7_23_1_1.xml create mode 100644 .idea/libraries/support_annotations_23_1_1.xml create mode 100644 .idea/libraries/support_v4_23_1_1.xml create mode 100644 SimpleExpenseManager.iml create mode 100644 app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/AppContext.java create mode 100644 app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/control/PersistentExpenseManager.java create mode 100644 app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentAccountDAO.java create mode 100644 app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java create mode 100644 app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java create mode 100644 app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000000..97626ba454 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000000..8d2df476e5 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/appcompat_v7_23_1_1.xml b/.idea/libraries/appcompat_v7_23_1_1.xml new file mode 100644 index 0000000000..ba79709059 --- /dev/null +++ b/.idea/libraries/appcompat_v7_23_1_1.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/design_23_1_1.xml b/.idea/libraries/design_23_1_1.xml new file mode 100644 index 0000000000..da1aaa46da --- /dev/null +++ b/.idea/libraries/design_23_1_1.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/recyclerview_v7_23_1_1.xml b/.idea/libraries/recyclerview_v7_23_1_1.xml new file mode 100644 index 0000000000..dabc8b7b84 --- /dev/null +++ b/.idea/libraries/recyclerview_v7_23_1_1.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/support_annotations_23_1_1.xml b/.idea/libraries/support_annotations_23_1_1.xml new file mode 100644 index 0000000000..00e0e70313 --- /dev/null +++ b/.idea/libraries/support_annotations_23_1_1.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/support_v4_23_1_1.xml b/.idea/libraries/support_v4_23_1_1.xml new file mode 100644 index 0000000000..3eee20cfc7 --- /dev/null +++ b/.idea/libraries/support_v4_23_1_1.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SimpleExpenseManager.iml b/SimpleExpenseManager.iml new file mode 100644 index 0000000000..79b88c864d --- /dev/null +++ b/SimpleExpenseManager.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7a80be4194..a019d8d57c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,6 +19,7 @@ package="lk.ac.mrt.cse.dbs.simpleexpensemanager"> getAccountNumbersList() { + + //Open the database connection + DBHandler handler = DBHandler.getInstance(context); + if( handler == null){ + System.out.print("Damn"); + } + SQLiteDatabase db = handler.getReadableDatabase(); + + //Query to select all account numbers from the account table + String query = "SELECT "+ Fields.COLUMN_ACCOUNT_NO+" FROM " + Fields.TABLE_ACCOUNT+" ORDER BY " + Fields.COLUMN_ACCOUNT_NO + " ASC"; + + Cursor cursor = db.rawQuery(query, null); + + ArrayList resultSet = new ArrayList<>(); + + //Add account numbers to a list + while (cursor.moveToNext()) + { + resultSet.add(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO))); + } + + cursor.close(); + + //Return the list of account numbers + return resultSet; + + } + + @Override + public List getAccountsList() { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getReadableDatabase(); + + //Query to select all the details about all the accounts in the account table + String query = "SELECT * FROM " + Fields.TABLE_ACCOUNT+" ORDER BY "+Fields.COLUMN_ACCOUNT_NO+" ASC"; + + Cursor cursor = db.rawQuery(query, null); + + ArrayList resultSet = new ArrayList<>(); + + //Add account details to a list + while (cursor.moveToNext()) + { + Account account = new Account(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)), + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_BANK_NAME)), + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_HOLDER_NAME)), + cursor.getDouble(cursor.getColumnIndex(Fields.COLUMN_BALANCE))); + + resultSet.add(account); + } + + cursor.close(); + + //Return list of account objects + return resultSet; + + } + + @Override + public Account getAccount(String accountNo) throws InvalidAccountException { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getReadableDatabase(); + + //Query to get details of the account specifiec by the account number + String query = "SELECT * FROM " + Fields.TABLE_ACCOUNT + " WHERE " + Fields.COLUMN_ACCOUNT_NO + " = '" + accountNo + "'"; + + Cursor cursor = db.rawQuery(query, null); + + Account account = null; + + //add the details to an account object + if (cursor.moveToFirst()) { + account = new Account(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)), + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_BANK_NAME)), + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_HOLDER_NAME)), + cursor.getDouble(cursor.getColumnIndex(Fields.COLUMN_BALANCE))); + } + //If account is not found throw an exception + else { + throw new InvalidAccountException("You have selected an invalid account number...!"); + } + + cursor.close(); + + //Return the account object + return account; + } + + @Override + public void addAccount(Account account) { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getWritableDatabase(); + + //Save account details to the account table + ContentValues values = new ContentValues(); + values.put(Fields.COLUMN_ACCOUNT_NO, account.getAccountNo()); + values.put(Fields.COLUMN_BANK_NAME, account.getBankName()); + values.put(Fields.COLUMN_ACCOUNT_HOLDER_NAME, account.getAccountHolderName()); + values.put(Fields.COLUMN_BALANCE, account.getBalance()); + + db.insert(Fields.TABLE_ACCOUNT, null, values); + + } + + @Override + public void removeAccount(String accountNo) throws InvalidAccountException { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getWritableDatabase(); + + //Query to delete a particular account from the account table + String query = "SELECT * FROM " + Fields.TABLE_ACCOUNT + " WHERE " + Fields.COLUMN_ACCOUNT_NO + " = '" + accountNo + "'"; + + Cursor cursor = db.rawQuery(query, null); + + Account account = null; + + //Delete the account if found in the table + if (cursor.moveToFirst()) { + account = new Account(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)), + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_BANK_NAME)), + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_HOLDER_NAME)), + cursor.getFloat(cursor.getColumnIndex(Fields.COLUMN_BALANCE))); + db.delete(Fields.TABLE_ACCOUNT, Fields.COLUMN_ACCOUNT_NO + " = ?", new String[] { accountNo }); + cursor.close(); + + } + //If account is not found throw an exception + else { + throw new InvalidAccountException("No such account found...!"); + } + + } + + @Override + public void updateBalance(String accountNo, ExpenseType expenseType, double amount) throws InvalidAccountException { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getWritableDatabase(); + + ContentValues values = new ContentValues(); + + //Retrieve the account details of the selected account + Account account = getAccount(accountNo); + + //Update the balance if the account is found in the table + if (account!=null) { + + double new_amount=0; + + //Deduct the amount is it is an expense + if (expenseType.equals(ExpenseType.EXPENSE)) { + new_amount = account.getBalance() - amount; + } + //Add the amount if it is an income + else if (expenseType.equals(ExpenseType.INCOME)) { + new_amount = account.getBalance() + amount; + } + + //Query to update balance in the account table + String strSQL = "UPDATE "+Fields.TABLE_ACCOUNT+" SET "+Fields.COLUMN_BALANCE+" = "+new_amount+" WHERE "+Fields.COLUMN_ACCOUNT_NO+" = '"+ accountNo+"'"; + + db.execSQL(strSQL); + + } + //If account is not found throw an exception + else { + throw new InvalidAccountException("No such account found...!"); + } + + } +} diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java new file mode 100644 index 0000000000..f87c62f901 --- /dev/null +++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java @@ -0,0 +1,118 @@ +package lk.ac.mrt.cse.dbs.simpleexpensemanager.data.impl; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import lk.ac.mrt.cse.dbs.simpleexpensemanager.data.TransactionDAO; +import lk.ac.mrt.cse.dbs.simpleexpensemanager.data.model.ExpenseType; +import lk.ac.mrt.cse.dbs.simpleexpensemanager.data.model.Transaction; +import lk.ac.mrt.cse.dbs.simpleexpensemanager.database.DBHandler; +import lk.ac.mrt.cse.dbs.simpleexpensemanager.database.Fields; + +/** + * Created by Eranga on 12/6/2015. + */ +public class PersistentTransactionDAO implements TransactionDAO { + + private Context context; + + //Constructor + public PersistentTransactionDAO(Context context) { + this.context = context; + } + + @Override + public void logTransaction(Date date, String accountNo, ExpenseType expenseType, double amount) { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getReadableDatabase(); + + //Save transaction details to the transaction_log table + ContentValues values = new ContentValues(); + values.put(Fields.COLUMN_ACCOUNT_NO, accountNo); + values.put(Fields.COLUMN_TRANSACTION_DATE, convertDateToString(date)); + values.put(Fields.COLUMN_TRANSACTION_AMOUNT, amount); + values.put(Fields.COLUMN_EXPENSE_TYPE, expenseType.toString()); + + db.insert(Fields.TABLE_TRANSACTION_LOG,null,values); + } + + @Override + public List getAllTransactionLogs() { + return getPaginatedTransactionLogs(0); + } + + @Override + public List getPaginatedTransactionLogs(int limit) { + + DBHandler handler = DBHandler.getInstance(context); + SQLiteDatabase db = handler.getReadableDatabase(); + + //Query to get details of all the transactions + String query = "SELECT "+ Fields.COLUMN_ACCOUNT_NO + ", " + + Fields.COLUMN_TRANSACTION_DATE + ", " + + Fields.COLUMN_EXPENSE_TYPE+", " + + Fields.COLUMN_TRANSACTION_AMOUNT + + " FROM " + Fields.TABLE_TRANSACTION_LOG + " ORDER BY " + Fields.COLUMN_TRANSACTION_ID + " DESC"; + + Cursor cursor = db.rawQuery(query, null); + + ArrayList transactionLogs = new ArrayList<>(); + + //Add the transaction details to a list + while (cursor.moveToNext()) + { + try { + + ExpenseType expenseType = null; + if (cursor.getString(cursor.getColumnIndex(Fields.COLUMN_EXPENSE_TYPE)).equals(ExpenseType.INCOME.toString())) { + expenseType = ExpenseType.INCOME; + } + else{ + expenseType = ExpenseType.EXPENSE; + } + + String dateString = cursor.getString(cursor.getColumnIndex(Fields.COLUMN_TRANSACTION_DATE)); + Date date = convertStringToDate(dateString); + + Transaction tans = new Transaction( + date, + cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)), + expenseType, + cursor.getDouble(cursor.getColumnIndex(Fields.COLUMN_TRANSACTION_AMOUNT))); + + transactionLogs.add(tans); + + } catch (ParseException e) { + e.printStackTrace(); + } + + } + + //Return the list of transactions + return transactionLogs; + } + + //Method to convert a date object to a string + public static String convertDateToString(Date date){ + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); + String dateString = dateFormat.format(date); + return dateString; + + } + + //Method to convert a string to a date object + public static Date convertStringToDate(String date) throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); + Date strDate = dateFormat.parse(date); + return strDate; + } +} diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java new file mode 100644 index 0000000000..d63478e3f5 --- /dev/null +++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java @@ -0,0 +1,64 @@ +package lk.ac.mrt.cse.dbs.simpleexpensemanager.database; + +import android.content.ContentValues; +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +/** + * Created by Eranga on 12/6/2015. + */ +public class DBHandler extends SQLiteOpenHelper { + private static DBHandler handler = null; + + //private static final + private static final String DATABASE_NAME = "130401J.db"; + private static final int DATABASE_VERSION = 1; + + + public DBHandler(Context context) { + super(context,DATABASE_NAME,null,DATABASE_VERSION); + } + + public static DBHandler getInstance(Context context) + { + if(handler == null) + handler = new DBHandler(context); + return handler; + } + + //private static final + + @Override + public void onCreate(SQLiteDatabase sqLiteDatabase) { + + String accountTable = "CREATE TABLE " + + Fields.TABLE_ACCOUNT + "(" + + Fields.COLUMN_ACCOUNT_NO + " VARCHAR(20) NOT NULL PRIMARY KEY," + + Fields.COLUMN_BANK_NAME + " VARCHAR(100) NULL," + + Fields.COLUMN_ACCOUNT_HOLDER_NAME + " VARCHAR(100) NULL," + + Fields.COLUMN_BALANCE + " DECIMAL(10,2) NULL )"; + + String transactionTable = "CREATE TABLE " + + Fields.TABLE_TRANSACTION_LOG + "(" + + Fields.COLUMN_TRANSACTION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + + Fields.COLUMN_ACCOUNT_NO + " VARCHAR(100) NOT NULL," + + Fields.COLUMN_TRANSACTION_DATE + " DATE NULL," + + Fields.COLUMN_TRANSACTION_AMOUNT + " DECIMAL(10,2) NULL," + + Fields.COLUMN_EXPENSE_TYPE + " VARCHAR(100) NULL, " + + "FOREIGN KEY("+Fields.COLUMN_ACCOUNT_NO+") REFERENCES "+Fields.TABLE_ACCOUNT+"("+Fields.COLUMN_ACCOUNT_NO+"))"; + + sqLiteDatabase.execSQL(accountTable); + sqLiteDatabase.execSQL(transactionTable); + + } + + @Override + public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int j) { + + sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Fields.TABLE_ACCOUNT); + sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Fields.TABLE_TRANSACTION_LOG); + onCreate(sqLiteDatabase); + + } +} diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java new file mode 100644 index 0000000000..fd989b415f --- /dev/null +++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java @@ -0,0 +1,22 @@ +package lk.ac.mrt.cse.dbs.simpleexpensemanager.database; + +/** + * Created by Eranga on 12/6/2015. + */ +public class Fields { + + //account table + public static final String TABLE_ACCOUNT = "account"; + public static final String COLUMN_ACCOUNT_NO = "accountNo"; + public static final String COLUMN_BANK_NAME = "bankName"; + public static final String COLUMN_ACCOUNT_HOLDER_NAME = "accountHolderName"; + public static final String COLUMN_BALANCE = "balance"; + + //transaction_log table + public static final String TABLE_TRANSACTION_LOG = "transaction_log"; + public static final String COLUMN_TRANSACTION_ID = "transaction_id"; + public static final String COLUMN_TRANSACTION_AMOUNT = "amount"; + public static final String COLUMN_TRANSACTION_DATE = "date"; + public static final String COLUMN_EXPENSE_TYPE = "expense_type"; + +} diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java index 46c5f78299..c6fa3267ee 100644 --- a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java +++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java @@ -16,6 +16,7 @@ package lk.ac.mrt.cse.dbs.simpleexpensemanager.ui; +import android.content.Context; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; @@ -25,9 +26,10 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import lk.ac.mrt.cse.dbs.simpleexpensemanager.AppContext; import lk.ac.mrt.cse.dbs.simpleexpensemanager.R; import lk.ac.mrt.cse.dbs.simpleexpensemanager.control.ExpenseManager; -import lk.ac.mrt.cse.dbs.simpleexpensemanager.control.InMemoryDemoExpenseManager; +import lk.ac.mrt.cse.dbs.simpleexpensemanager.control.PersistentExpenseManager; public class MainActivity extends AppCompatActivity { private ExpenseManager expenseManager; @@ -45,6 +47,7 @@ public class MainActivity extends AppCompatActivity { * The {@link ViewPager} that will host the section contents. */ private ViewPager mViewPager; + private Context context; @Override protected void onCreate(Bundle savedInstanceState) { @@ -65,7 +68,8 @@ protected void onCreate(Bundle savedInstanceState) { tabLayout.setupWithViewPager(mViewPager); /*** Begin generating dummy data for In-Memory implementation ***/ - expenseManager = new InMemoryDemoExpenseManager(); + context = AppContext.getContext(); + expenseManager = new PersistentExpenseManager(context); /*** END ***/ } From 71a4af3df49e5691e758f9766040596b48dea3d9 Mon Sep 17 00:00:00 2001 From: Eranga Heshan Date: Mon, 29 Oct 2018 00:27:09 +0530 Subject: [PATCH 2/2] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebf306d1d7..efcd8bfa9a 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ You can make improvements to the project as you require. However this project is * [`AccountDAO`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/AccountDAO.java) * [`TransactionDAO`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/TransactionDAO.java) 4. Extend and implement the `setup()` method of the abstract class [`ExpenseManager`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/control/ExpenseManager.java). -5. Change current implementation to your implementation in the [`MainActivity`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java) ui class. +5. Change current implementation to your implementation in the [`MainActivity`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java) UI class. Current implementation ```Java