diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt index baa6664..ae59d0a 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt @@ -6,7 +6,11 @@ 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 @@ -51,20 +55,27 @@ const val SQL_CREATE_ABSTRACT_PRODUCTS_TABLE = 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)" + "${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) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { +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) @@ -74,26 +85,34 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE TODO("Not yet implemented") } - fun eraseCategory (db: SQLiteDatabase, id: Int, context: Context) { - val productsInCategory = getAllAbstractProductInCategory(db, id) + fun eraseCategory(id: Int, context: Context) { + val productsInCategory = getAllAbstractProductInCategory(id) for (product in productsInCategory.iterator()) { - eraseAbstractProduct(db, product.id, context) + eraseAbstractProduct(product.id, context) } db.delete(CategoriesContract.CategoryEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) } - fun getCategoryNameById(db: SQLiteDatabase, id: Int) : String { + 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) + val cursor = db.query( + CategoriesContract.CategoryEntry.TABLE_NAME, + projection, + selection, + selectionArgs, + null, + null, + null + ) - with (cursor) { + with(cursor) { while (moveToNext()) { result = getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME)) } @@ -102,7 +121,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE return result } - fun getAllAbstractProductInCategory(db: SQLiteDatabase, id: Int) : List { + fun getAllAbstractProductInCategory(id: Int): List { var result = mutableListOf() val projection = arrayOf( @@ -117,18 +136,39 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE val selection = "${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?" val selectionArgs = arrayOf(id.toString()) - val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) + val cursor = db.query( + AbstractProductContract.AbstractProductEntry.TABLE_NAME, + projection, + selection, + selectionArgs, + null, + null, + null + ) with(cursor) { while (moveToNext()) { val abstractProductId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) - val abstractProductBarcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) - val abstractProductName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) - val abstractProductNetWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) - val abstractProductImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) - val abstractProductUnit = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT)) + val abstractProductBarcode = + getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) + val abstractProductName = + getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) + val abstractProductNetWeight = + getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) + val abstractProductImageHash = + getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) + val abstractProductUnit = + getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT)) - val abstractProduct = AbstractProduct(abstractProductId, abstractProductBarcode, abstractProductName, abstractProductNetWeight, abstractProductImageHash, category = id, abstractProductUnit) + val abstractProduct = AbstractProduct( + abstractProductId, + abstractProductBarcode, + abstractProductName, + abstractProductNetWeight, + abstractProductImageHash, + category = id, + abstractProductUnit + ) result.add(abstractProduct) } @@ -137,10 +177,15 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE return result } - fun getAmountOfAbstractProductsInCategory(db:SQLiteDatabase, id: Int) : Int { - return DatabaseUtils.longForQuery(db, "SELECT COUNT(*) FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?", arrayOf(id.toString())).toInt() + fun getAmountOfAbstractProductsInCategory(id: Int): Int { + return DatabaseUtils.longForQuery( + db, + "SELECT COUNT(*) FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?", + arrayOf(id.toString()) + ).toInt() } - fun eraseAbstractProduct(db: SQLiteDatabase, id: Int, context: Context) { + + fun eraseAbstractProduct(id: Int, context: Context) { val projectionForAbstractProduct = arrayOf( AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME ) @@ -158,9 +203,10 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE ) var imageHash: String = "" - with (cursorForAbstractProduct) { - while(moveToNext()) { - val productImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) + with(cursorForAbstractProduct) { + while (moveToNext()) { + val productImageHash = + getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) imageHash = productImageHash } } @@ -174,22 +220,30 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE val selectionForProducts = "${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID} = ?" val selectionArgsForProducts = arrayOf(id.toString()) - val cursorForProducts = db.query(ProductContract.ProductEntry.TABLE_NAME, projectionForProducts, selectionForProducts, selectionArgsForProducts, null, null, null) + val cursorForProducts = db.query( + ProductContract.ProductEntry.TABLE_NAME, + projectionForProducts, + selectionForProducts, + selectionArgsForProducts, + null, + null, + null + ) - with (cursorForProducts) { - while(moveToNext()) { - eraseProduct(db, getInt(getColumnIndexOrThrow(BaseColumns._ID))) + with(cursorForProducts) { + while (moveToNext()) { + eraseProduct(getInt(getColumnIndexOrThrow(BaseColumns._ID))) } } db.delete(AbstractProductContract.AbstractProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) } - fun eraseProduct(db:SQLiteDatabase, id: Int) { + fun eraseProduct(id: Int) { db.delete(ProductContract.ProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null) } - fun insertNewProduct(db: SQLiteDatabase, product: Product) { + fun insertNewProduct(product: Product) { val values = ContentValues().apply { put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId) put(ProductContract.ProductEntry.AMOUNT, product.amount) @@ -200,7 +254,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values) } - fun findAmountOfProductsWithExpiryDate(db: SQLiteDatabase, date: Long): Int { + fun findAmountOfProductsWithExpiryDate(date: Long): Int { var amount = 0 val projection = arrayOf( @@ -212,7 +266,8 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE 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) + val cursor = + db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) with(cursor) { while (moveToNext()) { @@ -223,7 +278,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE return amount } - fun findAllExpiryDates(db:SQLiteDatabase): Set { + fun findAllExpiryDates(): Set { val dates: MutableSet = mutableSetOf() val projection = arrayOf( @@ -243,7 +298,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE return dates } - fun findAbstractProductByBarcode (db: SQLiteDatabase, barcode: String) : AbstractProduct? { + fun findAbstractProductByBarcode(barcode: String): AbstractProduct? { var abstractProduct: AbstractProduct? = null val projection = arrayOf( BaseColumns._ID, @@ -257,14 +312,25 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE val selection = "${AbstractProductContract.AbstractProductEntry.BARCODE} = ?" val selectionArgs = arrayOf(barcode) - val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) + val cursor = db.query( + AbstractProductContract.AbstractProductEntry.TABLE_NAME, + projection, + selection, + selectionArgs, + null, + null, + null + ) with(cursor) { - while(moveToNext()) { + while (moveToNext()) { val id = getInt(getColumnIndexOrThrow(BaseColumns._ID)) - val productName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) - val imageFilename = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) - val netWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) + val productName = + getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) + val imageFilename = + getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) + val netWeight = + getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) val category = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.CATEGORY)) val unit = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT)) @@ -275,7 +341,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE return abstractProduct } - fun findAbstractProductById(db: SQLiteDatabase, id: Int): AbstractProduct? { + fun findAbstractProductById(id: Int): AbstractProduct? { var abstractProduct: AbstractProduct? = null val projection = arrayOf( BaseColumns._ID, @@ -290,15 +356,25 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE val selection = "${BaseColumns._ID} = ?" val selectionArgs = arrayOf(id.toString()) - val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) + val cursor = db.query( + AbstractProductContract.AbstractProductEntry.TABLE_NAME, + projection, + selection, + selectionArgs, + null, + null, + null + ) - with (cursor) { + with(cursor) { while (moveToNext()) { val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) val barcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) val name = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) - val netWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) - val imageHash = getString((getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME))) + val netWeight = + getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) + val imageHash = + getString((getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME))) val category = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.CATEGORY)) val unit = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT)) @@ -309,18 +385,246 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE return abstractProduct } - fun updateProduct(db: SQLiteDatabase, product: Product) { + 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())) + db.update( + ProductContract.ProductEntry.TABLE_NAME, + values, + "${BaseColumns._ID} = ?", + arrayOf(product.id.toString()) + ) + } + + fun addAbstractProduct(abstractProduct: AbstractProduct, context: Context) { + val values = ContentValues().apply { + put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode) + put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name) + put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, abstractProduct.netWeight.toString()) + put(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, abstractProduct.imageHash) + put(AbstractProductContract.AbstractProductEntry.CATEGORY, abstractProduct.category) + put(AbstractProductContract.AbstractProductEntry.UNIT, abstractProduct.unit) + } + + 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() + } + + fun updateAbstractProduct(abstractProduct: AbstractProduct, context: Context) { + val values = ContentValues().apply { + put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode) + put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name) + put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, abstractProduct.netWeight.toString()) + put(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, abstractProduct.imageHash) + put(AbstractProductContract.AbstractProductEntry.CATEGORY, abstractProduct.category) + put(AbstractProductContract.AbstractProductEntry.UNIT, abstractProduct.unit) + } + + db.update( + AbstractProductContract.AbstractProductEntry.TABLE_NAME, + values, + "${BaseColumns._ID} = ?", + arrayOf(abstractProduct.id.toString()) + ) + } + + 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 abstractProducts = mutableListOf() + + val projection = arrayOf( + BaseColumns._ID, + AbstractProductContract.AbstractProductEntry.BARCODE, + AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, + AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, + AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, + AbstractProductContract.AbstractProductEntry.CATEGORY, + AbstractProductContract.AbstractProductEntry.UNIT + ) + + var orderBy: String = "" + when(selectedSort) { + 0 -> { + orderBy = "${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} ASC" + } + 1 -> { + orderBy = "${AbstractProductContract.AbstractProductEntry.CATEGORY} ASC" + } + } + + var selection = "" + var selectionArgs: Array? = null + + when (filterBy) { + "category" -> { + selection = "${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?" + selectionArgs = filter + } + "barcodeless" -> { + selection = "${AbstractProductContract.AbstractProductEntry.BARCODE} = '' " + selectionArgs = null + } + } + + + val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, orderBy) + + with (cursor) { + while(moveToNext()) { + val productId = getInt(getColumnIndexOrThrow(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)) + val productImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) + val category = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.CATEGORY)) + val unit = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT)) + + val product = AbstractProduct(productId, barcode, productName, netWeight, productImageHash, category, unit) + + abstractProducts.add(product) + } + } + return abstractProducts } companion object { const val DATABASE_VERSION = 1 - const val DATABASE_NAME = "database.db" + var DATABASE_NAME = "database.db" } } \ No newline at end of file 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 8008cf1..90baf5a 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt @@ -1,11 +1,10 @@ package org.foxarmy.barcodescannerforemployees.activities -import android.content.ContentValues import android.content.DialogInterface import android.content.Intent +import android.content.SharedPreferences import android.os.Build import android.os.Bundle -import android.provider.BaseColumns import android.util.Log import android.widget.* import androidx.activity.result.contract.ActivityResultContracts @@ -49,11 +48,23 @@ class AddAbstractProductActivity : AppCompatActivity() { private var scanningBarcode = false + private lateinit var db: DBStorageController + private lateinit var sharedPreferences: SharedPreferences + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.fragment_add_abstract_product) + sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + applicationContext, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + db = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) picturesPath = File(filesDir, "pictures") val thumbnailsDir = File(cacheDir, "thumbnails") @@ -92,6 +103,7 @@ class AddAbstractProductActivity : AppCompatActivity() { "update" -> { abstractProduct = extras.get("abstractProduct") as AbstractProduct? } + "new_from_barcode" -> { abstractProduct = extras.get("abstractProduct") as AbstractProduct? barcode = abstractProduct!!.barcode @@ -131,43 +143,10 @@ class AddAbstractProductActivity : AppCompatActivity() { Toast.makeText(this, getString(R.string.product_net_weight_request), Toast.LENGTH_SHORT).show() } - val db = DBStorageController(this).writableDatabase - val values = ContentValues().apply { - put(AbstractProductContract.AbstractProductEntry.BARCODE, barcode) - put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, productName) - put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString()) - put(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, pictureFile.nameWithoutExtension) - put(AbstractProductContract.AbstractProductEntry.CATEGORY, categorySpinner.selectedItemPosition) - put(AbstractProductContract.AbstractProductEntry.UNIT, unitTypeSpinner.selectedItemPosition) - } - if (action == "update") { - db.update( - AbstractProductContract.AbstractProductEntry.TABLE_NAME, - values, - "${BaseColumns._ID} = ?", - arrayOf(abstractProduct!!.id.toString()) - ) - } else if (action == "new" || action == "new_from_barcode"){ - val id = db.insert(AbstractProductContract.AbstractProductEntry.TABLE_NAME, null, values) - val n = Net() - val abstractProduct = AbstractProduct(id.toInt(), barcode, productName, netWeight.toString().toDouble(), pictureFile.nameWithoutExtension, categorySpinner.selectedItemPosition, unitTypeSpinner.selectedItemPosition) - val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) - - val sharedPreferences = EncryptedSharedPreferences.create( - "sensitive", - masterKeyAlias, - applicationContext, - 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 response = n.uploadAbstractProduct(1, abstractProduct, File(pictureFile.absolutePath)); - - Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show() + db.updateAbstractProduct(abstractProduct!!, this) + } else if (action == "new" || action == "new_from_barcode") { + db.addAbstractProduct(abstractProduct!!, this) } finish() } @@ -190,11 +169,7 @@ class AddAbstractProductActivity : AppCompatActivity() { var abstractProduct: AbstractProduct - if (DBStorageController(this).findAbstractProductByBarcode( - DBStorageController(this).readableDatabase, - this.barcode - ) != null - ) { + if (db.findAbstractProductByBarcode(this.barcode) != null) { AlertDialog.Builder(this) .setMessage(getString(R.string.abstract_product_already_exists)) .setPositiveButton(getString(R.string.quit)) { _: DialogInterface, _: Int -> @@ -203,10 +178,8 @@ class AddAbstractProductActivity : AppCompatActivity() { .setNegativeButton(getString(R.string.edit_existing)) { _: DialogInterface, _: Int -> val addProductIntent = Intent(this, AddAbstractProductActivity::class.java) val extras = Bundle() - val existingAbstractProduct = DBStorageController(this).findAbstractProductByBarcode( - DBStorageController(this).readableDatabase, - this.barcode - ) + val existingAbstractProduct = db.findAbstractProductByBarcode(this.barcode) + extras.putParcelable("abstractProduct", existingAbstractProduct) addProductIntent.putExtras(extras) ContextCompat.startActivity(this, addProductIntent, extras) @@ -243,40 +216,17 @@ class AddAbstractProductActivity : AppCompatActivity() { getString(R.string.pieces) ) - val arrayAdapter = - ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, units) + ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, units) arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item) unitTypeSpinner.adapter = arrayAdapter } fun fillupCategorySpinner() { - val db = DBStorageController(this).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()) { - categories.add(getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME))) - } - } + val categories = db.getAllCategories().map { category -> category.name } val arrayAdapter = - ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, categories) + ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, categories) arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item) categorySpinner.adapter = arrayAdapter } @@ -322,7 +272,8 @@ class AddAbstractProductActivity : AppCompatActivity() { getPicture() } } else { - Toast.makeText(this, getString(R.string.camera_permission_for_picture_request), Toast.LENGTH_LONG).show() + Toast.makeText(this, getString(R.string.camera_permission_for_picture_request), Toast.LENGTH_LONG) + .show() } } @@ -339,6 +290,12 @@ 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 c2d4c01..5926b2a 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt @@ -1,23 +1,37 @@ package org.foxarmy.barcodescannerforemployees.activities import android.app.Activity -import android.content.ContentValues +import android.content.SharedPreferences import android.os.Bundle -import android.provider.BaseColumns import android.widget.Button import android.widget.EditText import android.widget.Toast -import org.foxarmy.barcodescannerforemployees.CategoriesContract +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.dataclasses.Category class AddCategoryActivity : Activity() { + + private lateinit var db: DBStorageController + private lateinit var sharedPreferences: SharedPreferences + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_add_category) + sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + applicationContext, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + db = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + val extras = intent.extras val category = extras!!.get("category") as Category? @@ -26,27 +40,24 @@ class AddCategoryActivity : Activity() { categoryNameTextEdit.setText(category!!.name) findViewById