From 3e5150754af99add0719332addeced55c7d9325b Mon Sep 17 00:00:00 2001 From: leca Date: Wed, 6 Nov 2024 03:29:06 +0300 Subject: [PATCH] first working upload: abstract product --- .../foxarmy/barcodescannerforemployees/Net.kt | 4 +- .../activities/AddAbstractProductActivity.kt | 52 ++- .../activities/AddCategoryActivity.kt | 18 +- .../activities/AddProductActivity.kt | 25 +- .../activities/ExpiryCalendarActivity.kt | 10 +- .../activities/GroupActivity.kt | 4 +- .../AbstractProductDAO.kt} | 361 ++---------------- .../database/CategoryDAO.kt | 105 +++++ .../database/DBStorageController.kt | 82 ++++ .../database/ProductDAO.kt | 171 +++++++++ .../fragments/CategoriesFragment.kt | 18 +- .../fragments/ShelfFragment.kt | 18 +- .../fragments/StorageFragment.kt | 29 +- .../views/AbstractProductView.kt | 27 +- .../views/CategoryView.kt | 22 +- .../views/ExpiryGroupView.kt | 23 +- .../views/ProductView.kt | 38 +- 17 files changed, 576 insertions(+), 431 deletions(-) rename app/src/main/java/org/foxarmy/barcodescannerforemployees/{DBStorageController.kt => database/AbstractProductDAO.kt} (50%) create mode 100644 app/src/main/java/org/foxarmy/barcodescannerforemployees/database/CategoryDAO.kt create mode 100644 app/src/main/java/org/foxarmy/barcodescannerforemployees/database/DBStorageController.kt create mode 100644 app/src/main/java/org/foxarmy/barcodescannerforemployees/database/ProductDAO.kt diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt index b50e117..3fc7d85 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt @@ -184,7 +184,9 @@ class Net { }.join() - return changeGroupPassword(name, password) + changeGroupPassword(name, password) + + return response } fun joinGroup(id: Int, password: String): Response { diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt index 90baf5a..bf44ae3 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt @@ -18,7 +18,11 @@ import androidx.security.crypto.MasterKeys import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanOptions +import okhttp3.Response import org.foxarmy.barcodescannerforemployees.* +import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO +import org.foxarmy.barcodescannerforemployees.database.CategoryDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import java.io.File import java.nio.file.Files @@ -48,7 +52,7 @@ class AddAbstractProductActivity : AppCompatActivity() { private var scanningBarcode = false - private lateinit var db: DBStorageController + private lateinit var DAO: AbstractProductDAO private lateinit var sharedPreferences: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { @@ -64,7 +68,8 @@ class AddAbstractProductActivity : AppCompatActivity() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + DAO = AbstractProductDAO(dbHelper) picturesPath = File(filesDir, "pictures") val thumbnailsDir = File(cacheDir, "thumbnails") @@ -143,11 +148,35 @@ class AddAbstractProductActivity : AppCompatActivity() { Toast.makeText(this, getString(R.string.product_net_weight_request), Toast.LENGTH_SHORT).show() } + val net = Net() + + net.token = sharedPreferences.getString("token", "")!! + net.server = sharedPreferences.getString("server", "")!! + net.language = sharedPreferences.getString("language", "en-US")!! + + val currentGroup = sharedPreferences.getString("currentGroup", "")!! + + lateinit var response: Response if (action == "update") { - db.updateAbstractProduct(abstractProduct!!, this) + DAO.updateAbstractProduct(abstractProduct!!, this) } else if (action == "new" || action == "new_from_barcode") { - db.addAbstractProduct(abstractProduct!!, this) + + abstractProduct = AbstractProduct( + 0, + barcode, + productName, + netWeight.toString().toDouble(), + pictureFile.nameWithoutExtension, + categorySpinner.selectedItemPosition, + unitTypeSpinner.selectedItemPosition + ) + + abstractProduct!!.id = DAO.addAbstractProduct(abstractProduct!!).toInt() + val pictureFile = File(File(filesDir, "pictures"), "${abstractProduct!!.imageHash}.png") + response = net.uploadAbstractProduct(currentGroup.toInt(), abstractProduct!!, pictureFile); } + Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show() + finish() } @@ -169,7 +198,7 @@ class AddAbstractProductActivity : AppCompatActivity() { var abstractProduct: AbstractProduct - if (db.findAbstractProductByBarcode(this.barcode) != null) { + if (DAO.findAbstractProductByBarcode(this.barcode) != null) { AlertDialog.Builder(this) .setMessage(getString(R.string.abstract_product_already_exists)) .setPositiveButton(getString(R.string.quit)) { _: DialogInterface, _: Int -> @@ -178,7 +207,7 @@ class AddAbstractProductActivity : AppCompatActivity() { .setNegativeButton(getString(R.string.edit_existing)) { _: DialogInterface, _: Int -> val addProductIntent = Intent(this, AddAbstractProductActivity::class.java) val extras = Bundle() - val existingAbstractProduct = db.findAbstractProductByBarcode(this.barcode) + val existingAbstractProduct = DAO.findAbstractProductByBarcode(this.barcode) extras.putParcelable("abstractProduct", existingAbstractProduct) addProductIntent.putExtras(extras) @@ -223,7 +252,10 @@ class AddAbstractProductActivity : AppCompatActivity() { } fun fillupCategorySpinner() { - val categories = db.getAllCategories().map { category -> category.name } + + val categoriesDAO = CategoryDAO(DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!)) + + val categories = categoriesDAO.getAllCategories().map { category -> category.name } val arrayAdapter = ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, categories) @@ -290,12 +322,6 @@ class AddAbstractProductActivity : AppCompatActivity() { } } - override fun onDestroy() { - super.onDestroy() - - db.close() - } - private fun prepareBarcodeScanner() { val options = ScanOptions() options.setDesiredBarcodeFormats(ScanOptions.EAN_13) diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt index 5926b2a..caf954d 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt @@ -8,13 +8,14 @@ import android.widget.EditText import android.widget.Toast import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys -import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.R +import org.foxarmy.barcodescannerforemployees.database.CategoryDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.dataclasses.Category class AddCategoryActivity : Activity() { - private lateinit var db: DBStorageController + private lateinit var DAO: CategoryDAO private lateinit var sharedPreferences: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { @@ -30,7 +31,8 @@ class AddCategoryActivity : Activity() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + DAO = CategoryDAO(dbHelper) val extras = intent.extras val category = extras!!.get("category") as Category? @@ -46,18 +48,12 @@ class AddCategoryActivity : Activity() { } if (category.id == 0) { // Inserting new category - db.addCategory(Category(0, categoryNameTextEdit.text.toString())) + DAO.addCategory(Category(0, categoryNameTextEdit.text.toString())) } else { // Updating existing category - db.updateCategory(category) + DAO.updateCategory(category) } finish() } } - - override fun onDestroy() { - super.onDestroy() - - db.close() - } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddProductActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddProductActivity.kt index 4cb2d8b..aa1168e 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddProductActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddProductActivity.kt @@ -18,8 +18,10 @@ import androidx.security.crypto.MasterKeys import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanOptions -import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.R +import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController +import org.foxarmy.barcodescannerforemployees.database.ProductDAO import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.dataclasses.Product import org.foxarmy.barcodescannerforemployees.views.AbstractProductView @@ -48,7 +50,8 @@ class AddProductActivity : AppCompatActivity() { private var product: Product? = null private var abstractProduct: AbstractProduct? = null - private lateinit var db: DBStorageController + private lateinit var productDAO: ProductDAO + private lateinit var abstractProductDAO: AbstractProductDAO private lateinit var sharedPreferences: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { @@ -64,7 +67,9 @@ class AddProductActivity : AppCompatActivity() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + productDAO = ProductDAO(dbHelper) + abstractProductDAO = AbstractProductDAO(dbHelper) scanButton = findViewById(R.id.scanButton) noBarcodeButton = findViewById(R.id.noBarcodeButton) @@ -86,7 +91,7 @@ class AddProductActivity : AppCompatActivity() { product = extras!!.get("product") as Product? if (product != null) { - abstractProduct = db.findAbstractProductById(product!!.abstractProductId) + abstractProduct = abstractProductDAO.findAbstractProductById(product!!.abstractProductId) abstractProductView.abstractProduct = abstractProduct!! expiryDateRadioButton.isSelected = true shelfLifeRadioButton.isSelected = false @@ -164,9 +169,9 @@ class AddProductActivity : AppCompatActivity() { } if (updatingExistentProduct) { - db.updateProduct(product!!) + productDAO.updateProduct(product!!) } else { - db.insertNewProduct(product!!) + productDAO.insertNewProduct(product!!) } finish() @@ -261,7 +266,7 @@ class AddProductActivity : AppCompatActivity() { Toast.makeText(this, getString(R.string.cancelled), Toast.LENGTH_SHORT).show() } else { val scannedBarcode = result.contents - abstractProduct = db.findAbstractProductByBarcode(scannedBarcode) + abstractProduct = abstractProductDAO.findAbstractProductByBarcode(scannedBarcode) displayAbstractProduct(abstractProduct, scannedBarcode) if (abstractProduct != null) { @@ -282,10 +287,4 @@ class AddProductActivity : AppCompatActivity() { scanLauncher.launch(options) } - - override fun onDestroy() { - super.onDestroy() - - db.close() - } } diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/ExpiryCalendarActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/ExpiryCalendarActivity.kt index 8689be6..aaaba71 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/ExpiryCalendarActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/ExpiryCalendarActivity.kt @@ -9,15 +9,16 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys -import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.R +import org.foxarmy.barcodescannerforemployees.database.DBStorageController +import org.foxarmy.barcodescannerforemployees.database.ProductDAO import org.foxarmy.barcodescannerforemployees.databinding.ActivityExpiryCalendarBinding import org.foxarmy.barcodescannerforemployees.views.ExpiryGroupView class ExpiryCalendarActivity : AppCompatActivity() { private lateinit var binding: ActivityExpiryCalendarBinding - private lateinit var db: DBStorageController + private lateinit var productDAO: ProductDAO private lateinit var sharedPreferences: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { @@ -33,7 +34,8 @@ class ExpiryCalendarActivity : AppCompatActivity() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + productDAO = ProductDAO(dbHelper) fillUp() } @@ -47,7 +49,7 @@ class ExpiryCalendarActivity : AppCompatActivity() { } private fun fillUp() { - val dates = db.findAllExpiryDates() + val dates = productDAO.findAllExpiryDates() val container = findViewById(R.id.datesLinearLayout) diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/GroupActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/GroupActivity.kt index 087577b..39c152a 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/GroupActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/GroupActivity.kt @@ -30,7 +30,7 @@ class GroupActivity : AppCompatActivity() { binding.createGroupButton.setOnClickListener { val groupName = binding.groupNameTextEdit.text.toString() val groupPassword = binding.groupPasswordTextEdit.text.toString() - + // group is set to "successful" val n = Net() n.language = sharedPreferences.getString("language", "en-US")!! n.server = sharedPreferences.getString("server", "")!! @@ -69,7 +69,7 @@ class GroupActivity : AppCompatActivity() { val currentGroups = sharedPreferences.getStringSet("groups", mutableSetOf()) currentGroups!!.add(groupId.toString()) sharedPreferences.edit().putStringSet("groups", currentGroups).apply() - sharedPreferences.edit().putString("currentGroup", responseText).apply() + sharedPreferences.edit().putString("currentGroup", groupId.toString()).apply() val intent = Intent(this, MainActivity::class.java) startActivity(intent) finish() diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/AbstractProductDAO.kt similarity index 50% rename from app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt rename to app/src/main/java/org/foxarmy/barcodescannerforemployees/database/AbstractProductDAO.kt index ae59d0a..e7463b1 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/AbstractProductDAO.kt @@ -1,129 +1,20 @@ -package org.foxarmy.barcodescannerforemployees +package org.foxarmy.barcodescannerforemployees.database import android.content.ContentValues import android.content.Context import android.database.DatabaseUtils -import android.database.sqlite.SQLiteDatabase -import android.database.sqlite.SQLiteOpenHelper import android.provider.BaseColumns -import android.widget.Toast -import androidx.security.crypto.EncryptedSharedPreferences -import androidx.security.crypto.MasterKeys import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct -import org.foxarmy.barcodescannerforemployees.dataclasses.Category -import org.foxarmy.barcodescannerforemployees.dataclasses.Product import java.io.File -object AbstractProductContract { - object AbstractProductEntry : BaseColumns { - const val TABLE_NAME = "abstract_products" - const val BARCODE = "barcode" - const val PRODUCT_NAME = "name" - const val PRODUCT_NET_WEIGHT = "net_weight" - const val IMAGE_FILENAME = "image_filename" - const val CATEGORY = "category" - const val UNIT = "unit" - } -} - -object CategoriesContract { - object CategoryEntry : BaseColumns { - const val TABLE_NAME = "categories" - const val CATEGORY_NAME = "category_name" - } -} - -object ProductContract { - object ProductEntry : BaseColumns { - const val TABLE_NAME = "products" - const val ABSTRACT_PRODUCT_ID = "abstract_product_id" - const val AMOUNT = "amount" - const val DATE_OF_PRODUCTION = "date_of_production" - const val EXPIRY_DATE = "expiry_date" - } -} - -const val SQL_CREATE_ABSTRACT_PRODUCTS_TABLE = - "CREATE TABLE ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} (" + - "${BaseColumns._ID} INTEGER PRIMARY KEY," + - "${AbstractProductContract.AbstractProductEntry.BARCODE} TEXT," + - "${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} TEXT," + - "${AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT} REAL," + - "${AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME} TEXT," + - "${AbstractProductContract.AbstractProductEntry.CATEGORY} INTEGER," + - "${AbstractProductContract.AbstractProductEntry.UNIT} INTEGER)" - -const val SQL_CREATE_PRODUCTS_TABLE = - "CREATE TABLE ${ProductContract.ProductEntry.TABLE_NAME} (" + - "${BaseColumns._ID} INTEGER PRIMARY KEY," + - "${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID} INTEGER," + - "${ProductContract.ProductEntry.AMOUNT} INTEGER," + - "${ProductContract.ProductEntry.DATE_OF_PRODUCTION} INTEGER," + - "${ProductContract.ProductEntry.EXPIRY_DATE} INTGER)" - -const val SQL_CREATE_CATEGORIES_TABLE = - "CREATE TABLE ${CategoriesContract.CategoryEntry.TABLE_NAME} (" + - "${BaseColumns._ID} INTEGER PRIMARY KEY," + - "${CategoriesContract.CategoryEntry.CATEGORY_NAME} TEXT)" - -class DBStorageController(context: Context, dbname: String) : - SQLiteOpenHelper(context, dbname, null, DATABASE_VERSION) { - - private lateinit var dbname: String - private lateinit var db: SQLiteDatabase - - override fun onCreate(db: SQLiteDatabase) { - this.db = db - DATABASE_NAME = "$dbname.db" - - db.execSQL(SQL_CREATE_ABSTRACT_PRODUCTS_TABLE) - db.execSQL(SQL_CREATE_PRODUCTS_TABLE) - db.execSQL(SQL_CREATE_CATEGORIES_TABLE) - } - - override fun onUpgrade(db: SQLiteDatabase?, oldV: Int, newV: Int) { - TODO("Not yet implemented") - } - - fun eraseCategory(id: Int, context: Context) { - val productsInCategory = getAllAbstractProductInCategory(id) - - for (product in productsInCategory.iterator()) { - eraseAbstractProduct(product.id, context) - } - - db.delete(CategoriesContract.CategoryEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) - } - - fun getCategoryNameById(id: Int): String { - var result = "" - - val projection = arrayOf(CategoriesContract.CategoryEntry.CATEGORY_NAME) - val selection = "${BaseColumns._ID} = ?" - val selectionArgs = arrayOf(id.toString()) - - val cursor = db.query( - CategoriesContract.CategoryEntry.TABLE_NAME, - projection, - selection, - selectionArgs, - null, - null, - null - ) - - with(cursor) { - while (moveToNext()) { - result = getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME)) - } - } - - return result - } +class AbstractProductDAO(private val dbHelper: DBStorageController) { fun getAllAbstractProductInCategory(id: Int): List { - var result = mutableListOf() + val db = dbHelper.readableDatabase + + val result = mutableListOf() + val projection = arrayOf( BaseColumns._ID, AbstractProductContract.AbstractProductEntry.BARCODE, @@ -148,7 +39,7 @@ class DBStorageController(context: Context, dbname: String) : with(cursor) { while (moveToNext()) { - val abstractProductId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) + val abstractProductId = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)) val abstractProductBarcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) val abstractProductName = @@ -178,6 +69,7 @@ class DBStorageController(context: Context, dbname: String) : } fun getAmountOfAbstractProductsInCategory(id: Int): Int { + val db = dbHelper.readableDatabase return DatabaseUtils.longForQuery( db, "SELECT COUNT(*) FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?", @@ -186,6 +78,9 @@ class DBStorageController(context: Context, dbname: String) : } fun eraseAbstractProduct(id: Int, context: Context) { + + val db = dbHelper.writableDatabase + val projectionForAbstractProduct = arrayOf( AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME ) @@ -232,73 +127,17 @@ class DBStorageController(context: Context, dbname: String) : with(cursorForProducts) { while (moveToNext()) { - eraseProduct(getInt(getColumnIndexOrThrow(BaseColumns._ID))) + ProductDAO(dbHelper).eraseProduct(getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID))) } } db.delete(AbstractProductContract.AbstractProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) } - fun eraseProduct(id: Int) { - db.delete(ProductContract.ProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) - } - - fun insertNewProduct(product: Product) { - val values = ContentValues().apply { - put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId) - put(ProductContract.ProductEntry.AMOUNT, product.amount) - put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction) - put(ProductContract.ProductEntry.EXPIRY_DATE, product.dateOfExpiry) - } - - db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values) - } - - fun findAmountOfProductsWithExpiryDate(date: Long): Int { - var amount = 0 - - val projection = arrayOf( - ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, - ProductContract.ProductEntry.AMOUNT, - ProductContract.ProductEntry.DATE_OF_PRODUCTION, - ) - - val selection = "${ProductContract.ProductEntry.EXPIRY_DATE} = ?" - val selectionArgs = arrayOf(date.toString()) - - val cursor = - db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) - - with(cursor) { - while (moveToNext()) { - amount++ - } - } - - return amount - } - - fun findAllExpiryDates(): Set { - val dates: MutableSet = mutableSetOf() - - val projection = arrayOf( - ProductContract.ProductEntry.EXPIRY_DATE - ) - - val orderBy = "${ProductContract.ProductEntry.EXPIRY_DATE} ASC" - - val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, null, null, null, null, orderBy) - - with(cursor) { - while (moveToNext()) { - dates.add(getLong(getColumnIndexOrThrow(ProductContract.ProductEntry.EXPIRY_DATE))) - } - } - - return dates - } - fun findAbstractProductByBarcode(barcode: String): AbstractProduct? { + + val db = dbHelper.readableDatabase + var abstractProduct: AbstractProduct? = null val projection = arrayOf( BaseColumns._ID, @@ -324,7 +163,7 @@ class DBStorageController(context: Context, dbname: String) : with(cursor) { while (moveToNext()) { - val id = getInt(getColumnIndexOrThrow(BaseColumns._ID)) + val id = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)) val productName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) val imageFilename = @@ -342,6 +181,9 @@ class DBStorageController(context: Context, dbname: String) : } fun findAbstractProductById(id: Int): AbstractProduct? { + + val db = dbHelper.readableDatabase + var abstractProduct: AbstractProduct? = null val projection = arrayOf( BaseColumns._ID, @@ -368,7 +210,7 @@ class DBStorageController(context: Context, dbname: String) : with(cursor) { while (moveToNext()) { - val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) + val productId = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)) val barcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) val name = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) val netWeight = @@ -385,22 +227,10 @@ class DBStorageController(context: Context, dbname: String) : return abstractProduct } - fun updateProduct(product: Product) { - val values = ContentValues().apply { - put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId) - put(ProductContract.ProductEntry.AMOUNT, product.amount) - put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction) - put(ProductContract.ProductEntry.EXPIRY_DATE, product.dateOfExpiry) - } - db.update( - ProductContract.ProductEntry.TABLE_NAME, - values, - "${BaseColumns._ID} = ?", - arrayOf(product.id.toString()) - ) - } + fun addAbstractProduct(abstractProduct: AbstractProduct): Long { + + val db = dbHelper.writableDatabase - fun addAbstractProduct(abstractProduct: AbstractProduct, context: Context) { val values = ContentValues().apply { put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode) put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name) @@ -411,27 +241,13 @@ class DBStorageController(context: Context, dbname: String) : } val id = db.insert(AbstractProductContract.AbstractProductEntry.TABLE_NAME, null, values) - val n = Net() - val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) - - val sharedPreferences = EncryptedSharedPreferences.create( - "sensitive", - masterKeyAlias, - context, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM - ) - - n.language = sharedPreferences.getString("language", "en-US")!! - n.server = sharedPreferences.getString("server", "")!! - n.token = sharedPreferences.getString("token", "")!! - val pictureFile = File(File(context.filesDir, "pictures"), "${abstractProduct.imageHash}.png") - val response = n.uploadAbstractProduct(1, abstractProduct, pictureFile); - - Toast.makeText(context, response.body!!.string(), Toast.LENGTH_LONG).show() + return id } fun updateAbstractProduct(abstractProduct: AbstractProduct, context: Context) { + + val db = dbHelper.writableDatabase + val values = ContentValues().apply { put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode) put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name) @@ -449,123 +265,10 @@ class DBStorageController(context: Context, dbname: String) : ) } - fun getAllCategories(): List { - val categories = mutableListOf() - - val projection = arrayOf( - CategoriesContract.CategoryEntry.CATEGORY_NAME - ) - - val cursor = db.query( - CategoriesContract.CategoryEntry.TABLE_NAME, - projection, - null, - null, - null, - null, - BaseColumns._ID + " ASC" - ) - - with(cursor) { - while (moveToNext()) { - val category = Category( - getInt(getColumnIndexOrThrow(BaseColumns._ID)), - getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME)) - ) - categories.add(category) - } - } - - return categories - } - - fun addCategory(category: Category) { - val values = ContentValues().apply { - put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name) - } - - db.insert(CategoriesContract.CategoryEntry.TABLE_NAME, null, values) - } - - fun updateCategory(category: Category) { - val values = ContentValues().apply { - put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name) - } - db.update(CategoriesContract.CategoryEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(category.id.toString())) - } - - fun getSortedListOfProducts(selectedSort: Int, filterBy: String, filter: String): List { - val products = mutableListOf() - - val projection = arrayOf( - BaseColumns._ID, - ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, - ProductContract.ProductEntry.AMOUNT, - ProductContract.ProductEntry.DATE_OF_PRODUCTION, - ProductContract.ProductEntry.EXPIRY_DATE, - ) - - var orderBy: String = "" - - when (selectedSort) { - 0 -> { - orderBy = - "(SELECT ${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID} = ${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID}) ASC" - } - - 1 -> { - orderBy = - "(SELECT ${AbstractProductContract.AbstractProductEntry.CATEGORY} FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID} = ${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID}) ASC" - } - - 3 -> { - orderBy = "${ProductContract.ProductEntry.DATE_OF_PRODUCTION} ASC" - } - - 4 -> { - orderBy = "${ProductContract.ProductEntry.EXPIRY_DATE} ASC" - } - } - - var selection: String? = null - var selectionArgs: Array? = null - - when (filterBy) { - "expiryDate" -> { - selection = "${ProductContract.ProductEntry.EXPIRY_DATE} = ?" - selectionArgs = arrayOf(filter) - } - - "" -> {} - } - - val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, orderBy) - - with(cursor) { - while (moveToNext()) { - val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) - val abstractProductId = - getInt(getColumnIndexOrThrow(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID)) - val amount = getInt(getColumnIndexOrThrow(ProductContract.ProductEntry.AMOUNT)) - val dateOfProduction = - getLong(getColumnIndexOrThrow(ProductContract.ProductEntry.DATE_OF_PRODUCTION)) - val dateOfExpiry = getLong(getColumnIndexOrThrow(ProductContract.ProductEntry.EXPIRY_DATE)) - - val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry) - - if (selectedSort == 2) { //freshness - products.add(product) - } - } - } - - products.sortWith(compareByDescending { it.freshness }) - - return products - } - fun getSortedListOfAbstractProducts(selectedSort: Int, filterBy: String, filter: Array): List { + val db = dbHelper.readableDatabase + val abstractProducts = mutableListOf() val projection = arrayOf( @@ -607,7 +310,7 @@ class DBStorageController(context: Context, dbname: String) : with (cursor) { while(moveToNext()) { - val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) + val productId = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)) val barcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) val productName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) val netWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) @@ -623,8 +326,4 @@ class DBStorageController(context: Context, dbname: String) : return abstractProducts } - companion object { - const val DATABASE_VERSION = 1 - var DATABASE_NAME = "database.db" - } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/CategoryDAO.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/CategoryDAO.kt new file mode 100644 index 0000000..bab30cc --- /dev/null +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/CategoryDAO.kt @@ -0,0 +1,105 @@ +package org.foxarmy.barcodescannerforemployees.database + +import android.content.ContentValues +import android.content.Context +import android.provider.BaseColumns +import org.foxarmy.barcodescannerforemployees.dataclasses.Category + +class CategoryDAO (private val dbHelper: DBStorageController) { + fun eraseCategory(id: Int, context: Context) { + + val abstractProductDAO = AbstractProductDAO(dbHelper) + val db = dbHelper.writableDatabase + + val productsInCategory = abstractProductDAO.getAllAbstractProductInCategory(id) + + for (product in productsInCategory.iterator()) { + abstractProductDAO.eraseAbstractProduct(product.id, context) + } + + db.delete(CategoriesContract.CategoryEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) + } + + fun getCategoryNameById(id: Int): String { + + val db = dbHelper.readableDatabase + + var result = "" + + val projection = arrayOf(CategoriesContract.CategoryEntry.CATEGORY_NAME) + val selection = "${BaseColumns._ID} = ?" + val selectionArgs = arrayOf(id.toString()) + + val cursor = db.query( + CategoriesContract.CategoryEntry.TABLE_NAME, + projection, + selection, + selectionArgs, + null, + null, + null + ) + + with(cursor) { + while (moveToNext()) { + result = getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME)) + } + } + + return result + } + + fun getAllCategories(): List { + + val db = dbHelper.readableDatabase + + val categories = mutableListOf() + + val projection = arrayOf( + CategoriesContract.CategoryEntry.CATEGORY_NAME + ) + + val cursor = db.query( + CategoriesContract.CategoryEntry.TABLE_NAME, + projection, + null, + null, + null, + null, + BaseColumns._ID + " ASC" + ) + + with(cursor) { + while (moveToNext()) { + val category = Category( + getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)), + getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME)) + ) + categories.add(category) + } + } + + return categories + } + + fun addCategory(category: Category) { + + val db = dbHelper.writableDatabase + + val values = ContentValues().apply { + put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name) + } + + db.insert(CategoriesContract.CategoryEntry.TABLE_NAME, null, values) + } + + fun updateCategory(category: Category) { + + val db = dbHelper.writableDatabase + + val values = ContentValues().apply { + put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name) + } + db.update(CategoriesContract.CategoryEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(category.id.toString())) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/DBStorageController.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/DBStorageController.kt new file mode 100644 index 0000000..01a9ef1 --- /dev/null +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/DBStorageController.kt @@ -0,0 +1,82 @@ +package org.foxarmy.barcodescannerforemployees.database + +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper +import android.provider.BaseColumns + +object AbstractProductContract { + object AbstractProductEntry : BaseColumns { + const val TABLE_NAME = "abstract_products" + const val BARCODE = "barcode" + const val PRODUCT_NAME = "name" + const val PRODUCT_NET_WEIGHT = "net_weight" + const val IMAGE_FILENAME = "image_filename" + const val CATEGORY = "category" + const val UNIT = "unit" + } +} + +object CategoriesContract { + object CategoryEntry : BaseColumns { + const val TABLE_NAME = "categories" + const val CATEGORY_NAME = "category_name" + } +} + +object ProductContract { + object ProductEntry : BaseColumns { + const val TABLE_NAME = "products" + const val ABSTRACT_PRODUCT_ID = "abstract_product_id" + const val AMOUNT = "amount" + const val DATE_OF_PRODUCTION = "date_of_production" + const val EXPIRY_DATE = "expiry_date" + } +} + +const val SQL_CREATE_ABSTRACT_PRODUCTS_TABLE = + "CREATE TABLE ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} (" + + "${BaseColumns._ID} INTEGER PRIMARY KEY," + + "${AbstractProductContract.AbstractProductEntry.BARCODE} TEXT," + + "${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} TEXT," + + "${AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT} REAL," + + "${AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME} TEXT," + + "${AbstractProductContract.AbstractProductEntry.CATEGORY} INTEGER," + + "${AbstractProductContract.AbstractProductEntry.UNIT} INTEGER)" + +const val SQL_CREATE_PRODUCTS_TABLE = + "CREATE TABLE ${ProductContract.ProductEntry.TABLE_NAME} (" + + "${BaseColumns._ID} INTEGER PRIMARY KEY," + + "${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID} INTEGER," + + "${ProductContract.ProductEntry.AMOUNT} INTEGER," + + "${ProductContract.ProductEntry.DATE_OF_PRODUCTION} INTEGER," + + "${ProductContract.ProductEntry.EXPIRY_DATE} INTGER)" + +const val SQL_CREATE_CATEGORIES_TABLE = + "CREATE TABLE ${CategoriesContract.CategoryEntry.TABLE_NAME} (" + + "${BaseColumns._ID} INTEGER PRIMARY KEY," + + "${CategoriesContract.CategoryEntry.CATEGORY_NAME} TEXT)" + +class DBStorageController(context: Context, dbname: String) : + SQLiteOpenHelper(context, dbname, null, DATABASE_VERSION) { + + init { + DATABASE_NAME = "$dbname.db" + } + + override fun onCreate(db: SQLiteDatabase) { + + db.execSQL(SQL_CREATE_ABSTRACT_PRODUCTS_TABLE) + db.execSQL(SQL_CREATE_PRODUCTS_TABLE) + db.execSQL(SQL_CREATE_CATEGORIES_TABLE) + } + + override fun onUpgrade(db: SQLiteDatabase?, oldV: Int, newV: Int) { + TODO("Not yet implemented") + } + + companion object { + const val DATABASE_VERSION = 1 + var DATABASE_NAME = "database.db" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/ProductDAO.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/ProductDAO.kt new file mode 100644 index 0000000..58e2548 --- /dev/null +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/database/ProductDAO.kt @@ -0,0 +1,171 @@ +package org.foxarmy.barcodescannerforemployees.database + +import android.content.ContentValues +import android.provider.BaseColumns +import org.foxarmy.barcodescannerforemployees.dataclasses.Product + +class ProductDAO (private val dbHelper: DBStorageController) { + + fun eraseProduct(id: Int) { + + val db = dbHelper.writableDatabase + + db.delete(ProductContract.ProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) + } + + fun insertNewProduct(product: Product) { + + val db = dbHelper.writableDatabase + + val values = ContentValues().apply { + put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId) + put(ProductContract.ProductEntry.AMOUNT, product.amount) + put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction) + put(ProductContract.ProductEntry.EXPIRY_DATE, product.dateOfExpiry) + } + + db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values) + } + + fun findAmountOfProductsWithExpiryDate(date: Long): Int { + + val db = dbHelper.readableDatabase + + var amount = 0 + + val projection = arrayOf( + ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, + ProductContract.ProductEntry.AMOUNT, + ProductContract.ProductEntry.DATE_OF_PRODUCTION, + ) + + val selection = "${ProductContract.ProductEntry.EXPIRY_DATE} = ?" + val selectionArgs = arrayOf(date.toString()) + + val cursor = + db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) + + with(cursor) { + while (moveToNext()) { + amount++ + } + } + + return amount + } + + fun findAllExpiryDates(): Set { + + val db = dbHelper.readableDatabase + + val dates: MutableSet = mutableSetOf() + + val projection = arrayOf( + ProductContract.ProductEntry.EXPIRY_DATE + ) + + val orderBy = "${ProductContract.ProductEntry.EXPIRY_DATE} ASC" + + val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, null, null, null, null, orderBy) + + with(cursor) { + while (moveToNext()) { + dates.add(getLong(getColumnIndexOrThrow(ProductContract.ProductEntry.EXPIRY_DATE))) + } + } + + return dates + } + + fun updateProduct(product: Product) { + + val db = dbHelper.writableDatabase + + val values = ContentValues().apply { + put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId) + put(ProductContract.ProductEntry.AMOUNT, product.amount) + put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction) + put(ProductContract.ProductEntry.EXPIRY_DATE, product.dateOfExpiry) + } + db.update( + ProductContract.ProductEntry.TABLE_NAME, + values, + "${BaseColumns._ID} = ?", + arrayOf(product.id.toString()) + ) + } + + fun getSortedListOfProducts(selectedSort: Int, filterBy: String, filter: String): List { + + val db = dbHelper.readableDatabase + + val products = mutableListOf() + + val projection = arrayOf( + BaseColumns._ID, + ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, + ProductContract.ProductEntry.AMOUNT, + ProductContract.ProductEntry.DATE_OF_PRODUCTION, + ProductContract.ProductEntry.EXPIRY_DATE, + ) + + var orderBy: String = "" + + when (selectedSort) { + 0 -> { + orderBy = + "(SELECT ${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID} = ${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID}) ASC" + } + + 1 -> { + orderBy = + "(SELECT ${AbstractProductContract.AbstractProductEntry.CATEGORY} FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID} = ${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID}) ASC" + } + + 3 -> { + orderBy = "${ProductContract.ProductEntry.DATE_OF_PRODUCTION} ASC" + } + + 4 -> { + orderBy = "${ProductContract.ProductEntry.EXPIRY_DATE} ASC" + } + } + + var selection: String? = null + var selectionArgs: Array? = null + + when (filterBy) { + "expiryDate" -> { + selection = "${ProductContract.ProductEntry.EXPIRY_DATE} = ?" + selectionArgs = arrayOf(filter) + } + + "" -> {} + } + + val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, orderBy) + + with(cursor) { + while (moveToNext()) { + val productId = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)) + val abstractProductId = + getInt(getColumnIndexOrThrow(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID)) + val amount = getInt(getColumnIndexOrThrow(ProductContract.ProductEntry.AMOUNT)) + val dateOfProduction = + getLong(getColumnIndexOrThrow(ProductContract.ProductEntry.DATE_OF_PRODUCTION)) + val dateOfExpiry = getLong(getColumnIndexOrThrow(ProductContract.ProductEntry.EXPIRY_DATE)) + + val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry) + + if (selectedSort == 2) { //freshness + products.add(product) + } + } + } + + products.sortWith(compareByDescending { it.freshness }) + + return products + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/CategoriesFragment.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/CategoriesFragment.kt index a020206..687550d 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/CategoriesFragment.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/CategoriesFragment.kt @@ -13,15 +13,16 @@ import androidx.core.view.children import androidx.fragment.app.Fragment import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys -import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity +import org.foxarmy.barcodescannerforemployees.database.CategoryDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.views.CategoryView class CategoriesFragment : Fragment() { private lateinit var sharedPreferences: SharedPreferences - private lateinit var db: DBStorageController + private lateinit var categoryDAO: CategoryDAO override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -34,7 +35,8 @@ class CategoriesFragment : Fragment() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!) + categoryDAO = CategoryDAO(dbHelper) } override fun onCreateView( @@ -56,7 +58,7 @@ class CategoriesFragment : Fragment() { var deleted = false for (view: CategoryView in layout?.children!!.iterator() as Iterator) { if (view.isCategorySelected) { - db.eraseCategory(view.category.id, requireContext()) + categoryDAO.eraseCategory(view.category.id, requireContext()) deleted = true } } @@ -84,7 +86,7 @@ class CategoriesFragment : Fragment() { val layout = view?.findViewById(R.id.categoriesLayout) layout?.removeAllViews() - val categories = db.getAllCategories() + val categories = categoryDAO.getAllCategories() for (category in categories) { val categoryView = CategoryView(requireActivity(), requireContext(), category) @@ -97,10 +99,4 @@ class CategoriesFragment : Fragment() { updateContent() } - - override fun onDestroy() { - super.onDestroy() - - db.close() - } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/ShelfFragment.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/ShelfFragment.kt index f3a1127..5aab4fc 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/ShelfFragment.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/ShelfFragment.kt @@ -16,9 +16,10 @@ import androidx.fragment.app.Fragment import androidx.gridlayout.widget.GridLayout import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys -import org.foxarmy.barcodescannerforemployees.DBStorageController +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.AddProductActivity +import org.foxarmy.barcodescannerforemployees.database.ProductDAO import org.foxarmy.barcodescannerforemployees.databinding.FragmentShelfBinding import org.foxarmy.barcodescannerforemployees.views.ProductView import kotlin.concurrent.thread @@ -30,7 +31,7 @@ class ShelfFragment : Fragment() { private var filterBy = "" private var filter = "" - private lateinit var db: DBStorageController + private lateinit var productDAO: ProductDAO private lateinit var sharedPreferences: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { @@ -44,7 +45,8 @@ class ShelfFragment : Fragment() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!) + productDAO = ProductDAO(dbHelper) } override fun onCreateView( @@ -122,7 +124,7 @@ class ShelfFragment : Fragment() { grv?.removeAllViews() } - val products = db.getSortedListOfProducts(binding.spinner.selectedItemPosition, filterBy, filter) + val products = productDAO.getSortedListOfProducts(binding.spinner.selectedItemPosition, filterBy, filter) for (product in products.iterator()) { val productView = ProductView( @@ -149,7 +151,7 @@ class ShelfFragment : Fragment() { view.findViewById(R.id.productPicture).setImageURI(null) } if (view.isProductSelected) { - db.eraseProduct(view.product.id) + productDAO.eraseProduct(view.product.id) deleted = true } } @@ -163,12 +165,6 @@ class ShelfFragment : Fragment() { } } - override fun onDestroy() { - super.onDestroy() - - db.close() - } - companion object { fun newInstance(date: Long):ShelfFragment = ShelfFragment().apply { diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt index 0abb658..cdae2ec 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt @@ -12,10 +12,11 @@ import androidx.core.view.children import androidx.fragment.app.Fragment import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys -import org.foxarmy.barcodescannerforemployees.DBStorageController +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.AddAbstractProductActivity import org.foxarmy.barcodescannerforemployees.activities.FindBarcodelessAbstractProduct +import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO import org.foxarmy.barcodescannerforemployees.databinding.FragmentStorageBinding import org.foxarmy.barcodescannerforemployees.generateThumbnailForImage import org.foxarmy.barcodescannerforemployees.views.AbstractProductView @@ -28,11 +29,13 @@ class StorageFragment : Fragment() { private lateinit var filter: Array private lateinit var sharedPreferences: SharedPreferences - private lateinit var db: DBStorageController + private lateinit var abstractProductDAO: AbstractProductDAO - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { sharedPreferences = EncryptedSharedPreferences.create( "sensitive", MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), @@ -41,13 +44,9 @@ class StorageFragment : Fragment() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - db = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!) - } + val dbHelper = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!) + abstractProductDAO = AbstractProductDAO(dbHelper) - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { binding = FragmentStorageBinding.inflate(inflater) fillUpSortBySpinner() @@ -96,7 +95,7 @@ class StorageFragment : Fragment() { view.findViewById(R.id.productPicture).setImageURI(null) } if (view.isProductSelected) { - db.eraseAbstractProduct(view.abstractProduct.id, requireContext()) + abstractProductDAO.eraseAbstractProduct(view.abstractProduct.id, requireContext()) deleted = true } } @@ -132,7 +131,7 @@ class StorageFragment : Fragment() { grv.removeAllViews() } - val abstractProducts = db.getSortedListOfAbstractProducts(binding.spinner.selectedItemPosition, filterBy, filter) + val abstractProducts = abstractProductDAO.getSortedListOfAbstractProducts(binding.spinner.selectedItemPosition, filterBy, filter) for (abstractProduct in abstractProducts) { generateThumbnailForImage(context!!, abstractProduct.imageHash) @@ -172,12 +171,6 @@ class StorageFragment : Fragment() { updateContent() } - override fun onDestroy() { - super.onDestroy() - - db.close() - } - companion object { fun newInstance(filterBy: String, filter: Array):StorageFragment = StorageFragment().apply { diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt index 800a2a4..68e9606 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt @@ -3,6 +3,7 @@ package org.foxarmy.barcodescannerforemployees.views import android.app.Activity import android.content.Context import android.content.Intent +import android.content.SharedPreferences import android.os.Bundle import android.util.AttributeSet import android.view.LayoutInflater @@ -13,9 +14,16 @@ import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat.startActivity -import org.foxarmy.barcodescannerforemployees.* +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys +import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity +import org.foxarmy.barcodescannerforemployees.database.CategoryDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct +import org.foxarmy.barcodescannerforemployees.getActivity +import org.foxarmy.barcodescannerforemployees.getImageUri +import org.foxarmy.barcodescannerforemployees.getUnitNameById import java.io.File class AbstractProductView: LinearLayout { @@ -27,7 +35,10 @@ class AbstractProductView: LinearLayout { private var unitField: TextView? = null var abstractProduct: AbstractProduct = AbstractProduct() var isProductSelected = false - private lateinit var activity: Activity + private var activity: Activity + + private lateinit var categoryDAO: CategoryDAO + private lateinit var sharedPreferences: SharedPreferences constructor(context: Context, a: AttributeSet) : super(context, a) { activity = getActivity(context)!! @@ -41,6 +52,16 @@ class AbstractProductView: LinearLayout { val inflater:LayoutInflater = activity.layoutInflater inflater.inflate(R.layout.abstract_product_view, this) + sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + context, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!) + categoryDAO = CategoryDAO(dbHelper) update() } @@ -89,6 +110,6 @@ class AbstractProductView: LinearLayout { productNameField!!.text = abstractProduct.name netWeightField!!.text = abstractProduct.netWeight.toString() - categoryField!!.text = DBStorageController(context).getCategoryNameById(DBStorageController(context).readableDatabase, abstractProduct.category) + categoryField!!.text = categoryDAO.getCategoryNameById(abstractProduct.category) } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/CategoryView.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/CategoryView.kt index c5e961e..e9b5927 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/CategoryView.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/CategoryView.kt @@ -2,13 +2,17 @@ package org.foxarmy.barcodescannerforemployees.views import android.app.Activity import android.content.Context +import android.content.SharedPreferences import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.TextView import androidx.core.content.ContextCompat -import org.foxarmy.barcodescannerforemployees.DBStorageController +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.MainActivity +import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.dataclasses.Category class CategoryView : LinearLayout { @@ -17,9 +21,23 @@ class CategoryView : LinearLayout { val amountOfProducts: TextView var isCategorySelected = false + private var abstractProductDAO: AbstractProductDAO + private var sharedPreferences: SharedPreferences + constructor(activity: Activity, context: Context, category: Category) : super(context) { this.category = category + sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + context, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!) + abstractProductDAO = AbstractProductDAO(dbHelper) + val inflater: LayoutInflater = activity.layoutInflater inflater.inflate(R.layout.category_view, this) @@ -29,7 +47,7 @@ class CategoryView : LinearLayout { amountOfProducts = findViewById(R.id.amountOfProducts) categoryName.text = category.name - amountOfProducts.text = DBStorageController(context).getAmountOfAbstractProductsInCategory(DBStorageController(context).readableDatabase, category.id).toString() + amountOfProducts.text = abstractProductDAO.getAmountOfAbstractProductsInCategory(category.id).toString() setOnLongClickListener { isCategorySelected = !isCategorySelected diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ExpiryGroupView.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ExpiryGroupView.kt index 8cb3f53..7a68f37 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ExpiryGroupView.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ExpiryGroupView.kt @@ -2,21 +2,39 @@ package org.foxarmy.barcodescannerforemployees.views import android.app.Activity import android.content.Context +import android.content.SharedPreferences import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.TextView import androidx.core.content.ContextCompat -import org.foxarmy.barcodescannerforemployees.DBStorageController +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.ExpiryCalendarActivity +import org.foxarmy.barcodescannerforemployees.database.DBStorageController +import org.foxarmy.barcodescannerforemployees.database.ProductDAO import java.text.SimpleDateFormat class ExpiryGroupView : LinearLayout { private var representingDate: Long? = null + private var sharedPreferences: SharedPreferences + private var productDAO: ProductDAO + constructor(activity: Activity, context: Context, representingDate: Long) : super(context) { + sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + context, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!) + productDAO = ProductDAO(dbHelper) + val inflater: LayoutInflater = activity.layoutInflater inflater.inflate(R.layout.expiry_group_view, this) @@ -24,14 +42,13 @@ class ExpiryGroupView : LinearLayout { this.background = ContextCompat.getDrawable(context,R.drawable.outline) - var amount = DBStorageController(context).findAmountOfProductsWithExpiryDate(DBStorageController(context).readableDatabase, representingDate) + val amount = productDAO.findAmountOfProductsWithExpiryDate(representingDate) findViewById(R.id.representingDateTextView).text = SimpleDateFormat("dd.MM.yyyy").format(representingDate * 1000) findViewById(R.id.amountTextView).text = amount.toString() setOnClickListener { (activity as ExpiryCalendarActivity).displayDate(representingDate) -// (activity as MainActivity).filterAbstractProductsByCategory(category.id) } } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ProductView.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ProductView.kt index 93d5cdd..a721ed1 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ProductView.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/ProductView.kt @@ -3,6 +3,7 @@ package org.foxarmy.barcodescannerforemployees.views import android.app.Activity import android.content.Context import android.content.Intent +import android.content.SharedPreferences import android.graphics.Color import android.graphics.drawable.GradientDrawable import android.os.Build @@ -20,10 +21,18 @@ import androidx.core.graphics.blue import androidx.core.graphics.green import androidx.core.graphics.red import androidx.core.math.MathUtils.clamp -import org.foxarmy.barcodescannerforemployees.* +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys +import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity +import org.foxarmy.barcodescannerforemployees.calculateProductFreshness +import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO +import org.foxarmy.barcodescannerforemployees.database.CategoryDAO +import org.foxarmy.barcodescannerforemployees.database.DBStorageController import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.dataclasses.Product +import org.foxarmy.barcodescannerforemployees.getActivity +import org.foxarmy.barcodescannerforemployees.getImageUri import java.io.File import java.text.DecimalFormat import java.text.SimpleDateFormat @@ -47,8 +56,25 @@ class ProductView: LinearLayout { private var strokeColor: Int = 0x000000 private lateinit var outline: GradientDrawable + private lateinit var categoryDAO: CategoryDAO + private lateinit var abstractProductDAO: AbstractProductDAO + private lateinit var sharedPreferences: SharedPreferences + constructor(context: Context, a: AttributeSet) : super(context, a) { activity = getActivity(context)!! + + sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + context, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!) + abstractProductDAO = AbstractProductDAO(dbHelper) + categoryDAO = CategoryDAO(dbHelper) + val inflater: LayoutInflater = activity.layoutInflater inflater.inflate(R.layout.product_view, this) } @@ -77,7 +103,7 @@ class ProductView: LinearLayout { productImageView.setOnClickListener { val fullscreenIntent = Intent(activity, FullscreenActivity::class.java) val extras = Bundle() - val abstractProduct = DBStorageController(context).findAbstractProductById(DBStorageController(context).readableDatabase, product.abstractProductId) + val abstractProduct = abstractProductDAO.findAbstractProductById(product.abstractProductId) extras.putString("imagehash", abstractProduct!!.imageHash) fullscreenIntent.putExtras(extras) startActivity(context, fullscreenIntent, extras) @@ -88,11 +114,7 @@ class ProductView: LinearLayout { @RequiresApi(Build.VERSION_CODES.O) fun update () { - val linkedAbstractProduct: AbstractProduct? = DBStorageController(activity).findAbstractProductById(DBStorageController(activity).readableDatabase, product.abstractProductId) - - if(linkedAbstractProduct == null) { - return - } + val linkedAbstractProduct: AbstractProduct = abstractProductDAO.findAbstractProductById(product.abstractProductId) ?: return val thumbnailsDir = File(activity.cacheDir, "thumbnails") thumbnailsDir.mkdirs() @@ -104,7 +126,7 @@ class ProductView: LinearLayout { productNameTextView.text = linkedAbstractProduct.name productNetWeightTextView.text = linkedAbstractProduct.netWeight.toString() productAmountTextView.text = product.amount.toString() - productCategoryView.text = DBStorageController(activity).getCategoryNameById(DBStorageController(activity).readableDatabase, linkedAbstractProduct.category) + productCategoryView.text = categoryDAO.getCategoryNameById(linkedAbstractProduct.category) productLifeSpan.text = "${SimpleDateFormat("dd.MM.yyyy").format(Date(product.dateOfProduction*1000))}-${SimpleDateFormat("dd.MM.yyyy").format(Date(product.dateOfExpiry*1000))}" productFreshnessTextView.text = if (product.freshness == Double.NEGATIVE_INFINITY || product.freshness == Double.POSITIVE_INFINITY || product.freshness < 0) {