synchronizing
This commit is contained in:
parent
94d309c491
commit
cd299477d4
|
@ -5,7 +5,11 @@ import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.RequestBody.Companion.asRequestBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||||
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||||
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Product
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class Net {
|
class Net {
|
||||||
|
@ -383,4 +387,190 @@ class Net {
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun uploadCategory(groupId: Int, category: Category): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("localId", category.id.toString())
|
||||||
|
.add("categoryName", category.name)
|
||||||
|
.add("groupId", groupId.toString())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/category/create")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateCategory(groupId: Int, category: Category): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("localId", category.id.toString())
|
||||||
|
.add("categoryName", category.name)
|
||||||
|
.add("groupId", groupId.toString())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/category/update")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uploadProduct(groupId: Int, product: Product): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("localId", product.id.toString())
|
||||||
|
.add("groupId", groupId.toString())
|
||||||
|
.add("abstract_product_id", product.abstractProductId.toString())
|
||||||
|
.add("amount", product.amount.toString())
|
||||||
|
.add("date_of_production", product.dateOfProduction.toString())
|
||||||
|
.add("expiry_date", product.dateOfExpiry.toString())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/product/create")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateProduct(groupId: Int, product: Product): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("localId", product.id.toString())
|
||||||
|
.add("groupId", groupId.toString())
|
||||||
|
.add("abstract_product_id", product.abstractProductId.toString())
|
||||||
|
.add("amount", product.amount.toString())
|
||||||
|
.add("date_of_production", product.dateOfProduction.toString())
|
||||||
|
.add("expiry_date", product.dateOfExpiry.toString())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/product/update")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun synchronize(groupId: Int): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/user/synchronize/$groupId")
|
||||||
|
.get()
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProduct(groupId: Int, localId: Int): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/product/$groupId/$localId")
|
||||||
|
.get()
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAbstractProduct(groupId: Int, localId: Int): Response {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/abstractproduct/$groupId/$localId")
|
||||||
|
.get()
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
fun downloadImage(url: String, file: File) {
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
client.newCall(request).execute().use { response ->
|
||||||
|
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||||
|
|
||||||
|
val fos = FileOutputStream(file)
|
||||||
|
|
||||||
|
response.body?.byteStream()?.use { inputStream ->
|
||||||
|
fos.use {
|
||||||
|
inputStream.copyTo(fos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.join()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,11 +12,19 @@ import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import com.google.firebase.components.BuildConfig
|
import com.google.firebase.components.BuildConfig
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.net.URLEncoder
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
fun convertToUnixEpochTimestamp(dateString: String): Long {
|
||||||
|
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||||
|
format.timeZone = TimeZone.getTimeZone("UTC")
|
||||||
|
val date = format.parse(dateString)
|
||||||
|
return date!!.time / 1000
|
||||||
|
}
|
||||||
|
|
||||||
fun getImageUri(activity: Activity, imageFile: File): Uri? {
|
fun getImageUri(activity: Activity, imageFile: File): Uri? {
|
||||||
return FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + "." + activity.localClassName + ".provider", imageFile)
|
return FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + "." + activity.localClassName + ".provider", imageFile)
|
||||||
}
|
}
|
||||||
|
@ -60,8 +68,6 @@ fun removeSubstringsFromString(text: String, toRemove: Array<String>): String {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.utf8(): String = URLEncoder.encode(this, "UTF-8")
|
|
||||||
|
|
||||||
fun getActivity(context: Context?): Activity? {
|
fun getActivity(context: Context?): Activity? {
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
return null
|
return null
|
||||||
|
@ -98,4 +104,29 @@ fun getUnitNameById (context: Context, id: Int): String {
|
||||||
|
|
||||||
fun parseArray(input: String): IntArray {
|
fun parseArray(input: String): IntArray {
|
||||||
return input.trim('[', ']').split(",").map { it.trim().toInt() }.toIntArray()
|
return input.trim('[', ']').split(",").map { it.trim().toInt() }.toIntArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateMd5Hash(file: File): String {
|
||||||
|
val digest = MessageDigest.getInstance("MD5")
|
||||||
|
val fis = FileInputStream(file)
|
||||||
|
val buffer = ByteArray(1024)
|
||||||
|
var bytesRead = fis.read(buffer)
|
||||||
|
while (bytesRead != -1) {
|
||||||
|
digest.update(buffer, 0, bytesRead)
|
||||||
|
bytesRead = fis.read(buffer)
|
||||||
|
}
|
||||||
|
fis.close()
|
||||||
|
return bytesToHex(digest.digest())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bytesToHex(bytes: ByteArray): String {
|
||||||
|
val hexString = StringBuilder()
|
||||||
|
for (byte in bytes) {
|
||||||
|
val hex = Integer.toHexString(0xff and byte.toInt())
|
||||||
|
if (hex.length == 1) {
|
||||||
|
hexString.append('0')
|
||||||
|
}
|
||||||
|
hexString.append(hex)
|
||||||
|
}
|
||||||
|
return hexString.toString()
|
||||||
}
|
}
|
|
@ -154,7 +154,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
|
||||||
val currentGroup = sharedPreferences.getString("currentGroup", "")!!
|
val currentGroup = sharedPreferences.getString("currentGroup", "offline")!!
|
||||||
|
|
||||||
lateinit var response: Response
|
lateinit var response: Response
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
productName,
|
productName,
|
||||||
netWeight.toString().toDouble(),
|
netWeight.toString().toDouble(),
|
||||||
pictureFile.nameWithoutExtension,
|
pictureFile.nameWithoutExtension,
|
||||||
categorySpinner.selectedItemPosition,
|
categorySpinner.selectedItemPosition + 1,
|
||||||
unitTypeSpinner.selectedItemPosition
|
unitTypeSpinner.selectedItemPosition
|
||||||
)
|
)
|
||||||
val pictureFile = File(File(filesDir, "pictures"), "${abstractProduct!!.imageHash}.png")
|
val pictureFile = File(File(filesDir, "pictures"), "${abstractProduct!!.imageHash}.png")
|
||||||
|
@ -269,8 +269,9 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
if (success) {
|
if (success) {
|
||||||
//Move picture to a proper directory according to its calculated hash
|
//Move picture to a proper directory according to its calculated hash
|
||||||
val tempfile = File(filesDir, "image.png")
|
val tempfile = File(filesDir, "image.png")
|
||||||
val imageContent = tempfile.inputStream().readBytes()
|
val imageHash = calculateMd5Hash(tempfile)
|
||||||
val imageHash = imageContent.toString(Charsets.UTF_8).md5()
|
// val imageContent = tempfile.inputStream().readBytes()
|
||||||
|
// val imageHash = imageContent.toString(Charsets.UTF_8).md5()
|
||||||
|
|
||||||
pictureFile = File(picturesPath, "$imageHash.png")
|
pictureFile = File(picturesPath, "$imageHash.png")
|
||||||
Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.widget.EditText
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
import androidx.security.crypto.MasterKeys
|
import androidx.security.crypto.MasterKeys
|
||||||
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
|
@ -31,7 +32,7 @@ class AddCategoryActivity : Activity() {
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
)
|
)
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
DAO = CategoryDAO(dbHelper)
|
DAO = CategoryDAO(dbHelper)
|
||||||
|
|
||||||
val extras = intent.extras
|
val extras = intent.extras
|
||||||
|
@ -41,6 +42,14 @@ class AddCategoryActivity : Activity() {
|
||||||
|
|
||||||
categoryNameTextEdit.setText(category!!.name)
|
categoryNameTextEdit.setText(category!!.name)
|
||||||
|
|
||||||
|
val net = Net()
|
||||||
|
|
||||||
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
|
net.language = sharedPreferences.getString("language", "")!!
|
||||||
|
|
||||||
|
val currentGroup = sharedPreferences.getString("currentGroup", "offline")!!.toInt()
|
||||||
|
|
||||||
findViewById<Button>(R.id.saveButton).setOnClickListener {
|
findViewById<Button>(R.id.saveButton).setOnClickListener {
|
||||||
if (categoryNameTextEdit.text.toString() == "") {
|
if (categoryNameTextEdit.text.toString() == "") {
|
||||||
Toast.makeText(this, getString(R.string.category_name_required), Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.category_name_required), Toast.LENGTH_SHORT).show()
|
||||||
|
@ -48,9 +57,13 @@ class AddCategoryActivity : Activity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (category.id == 0) { // Inserting new category
|
if (category.id == 0) { // Inserting new category
|
||||||
DAO.addCategory(Category(0, categoryNameTextEdit.text.toString()))
|
val newCategory = Category(0, categoryNameTextEdit.text.toString())
|
||||||
|
newCategory.id = DAO.addCategory(newCategory).toInt()
|
||||||
|
net.uploadCategory(currentGroup, newCategory)
|
||||||
} else { // Updating existing category
|
} else { // Updating existing category
|
||||||
|
category.name = categoryNameTextEdit.text.toString()
|
||||||
DAO.updateCategory(category)
|
DAO.updateCategory(category)
|
||||||
|
net.updateCategory(currentGroup, category)
|
||||||
}
|
}
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
|
|
|
@ -18,6 +18,8 @@ import androidx.security.crypto.MasterKeys
|
||||||
import com.journeyapps.barcodescanner.ScanContract
|
import com.journeyapps.barcodescanner.ScanContract
|
||||||
import com.journeyapps.barcodescanner.ScanIntentResult
|
import com.journeyapps.barcodescanner.ScanIntentResult
|
||||||
import com.journeyapps.barcodescanner.ScanOptions
|
import com.journeyapps.barcodescanner.ScanOptions
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
|
@ -67,10 +69,11 @@ class AddProductActivity : AppCompatActivity() {
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
)
|
)
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
productDAO = ProductDAO(dbHelper)
|
productDAO = ProductDAO(dbHelper)
|
||||||
abstractProductDAO = AbstractProductDAO(dbHelper)
|
abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
|
|
||||||
|
|
||||||
scanButton = findViewById(R.id.scanButton)
|
scanButton = findViewById(R.id.scanButton)
|
||||||
noBarcodeButton = findViewById(R.id.noBarcodeButton)
|
noBarcodeButton = findViewById(R.id.noBarcodeButton)
|
||||||
abstractProductView = findViewById(R.id.abstractProductView)
|
abstractProductView = findViewById(R.id.abstractProductView)
|
||||||
|
@ -137,6 +140,12 @@ class AddProductActivity : AppCompatActivity() {
|
||||||
product!!.amount = text.toInt()
|
product!!.amount = text.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val net = Net()
|
||||||
|
|
||||||
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
|
||||||
saveProductButton.setOnClickListener {
|
saveProductButton.setOnClickListener {
|
||||||
if (abstractProduct == null) {
|
if (abstractProduct == null) {
|
||||||
Toast.makeText(this, getString(R.string.abstract_product_request), Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.abstract_product_request), Toast.LENGTH_SHORT).show()
|
||||||
|
@ -168,12 +177,22 @@ class AddProductActivity : AppCompatActivity() {
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "")!! == "") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
|
var response: Response? = null
|
||||||
|
|
||||||
if (updatingExistentProduct) {
|
if (updatingExistentProduct) {
|
||||||
productDAO.updateProduct(product!!)
|
productDAO.updateProduct(product!!)
|
||||||
|
if (currentGroup > 0) response = net.updateProduct(currentGroup, product!!)
|
||||||
} else {
|
} else {
|
||||||
productDAO.insertNewProduct(product!!)
|
product!!.id = productDAO.insertNewProduct(product!!).toInt()
|
||||||
|
if (currentGroup > 0) response = net.uploadProduct(currentGroup, product!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response != null) {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
update()
|
update()
|
||||||
|
|
|
@ -57,9 +57,11 @@ class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
|
||||||
val r = n.getMyGroups().body!!.string()
|
val r = n.getMyGroups().body!!.string()
|
||||||
val myGroups = parseArray(r)
|
val myGroups = parseArray(r).map { a -> a.toString()}
|
||||||
|
|
||||||
|
sharedPreferences.edit().putStringSet("groups", myGroups.toSet()).apply()
|
||||||
|
sharedPreferences.edit().putString("currentGroup", myGroups[0]).apply()
|
||||||
|
|
||||||
sharedPreferences.edit().putStringSet("groups", myGroups.map { a -> a.toString()}.toSet())
|
|
||||||
val intent = Intent(this, MainActivity::class.java)
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
finish()
|
finish()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
//import android.R
|
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -11,15 +10,28 @@ import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
|
import androidx.security.crypto.MasterKeys
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.google.android.material.navigation.NavigationView
|
import com.google.android.material.navigation.NavigationView
|
||||||
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.ViewPagerAdapter
|
import org.foxarmy.barcodescannerforemployees.ViewPagerAdapter
|
||||||
|
import org.foxarmy.barcodescannerforemployees.convertToUnixEpochTimestamp
|
||||||
|
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
||||||
|
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
||||||
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
|
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityMainBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityMainBinding
|
||||||
|
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||||
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Product
|
||||||
import org.foxarmy.barcodescannerforemployees.fragments.CategoriesFragment
|
import org.foxarmy.barcodescannerforemployees.fragments.CategoriesFragment
|
||||||
import org.foxarmy.barcodescannerforemployees.fragments.ShelfFragment
|
import org.foxarmy.barcodescannerforemployees.fragments.ShelfFragment
|
||||||
import org.foxarmy.barcodescannerforemployees.fragments.StorageFragment
|
import org.foxarmy.barcodescannerforemployees.fragments.StorageFragment
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||||
|
@ -90,6 +102,234 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
synchronize()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun synchronize() {
|
||||||
|
|
||||||
|
val sharedPreferences = EncryptedSharedPreferences.create(
|
||||||
|
"sensitive",
|
||||||
|
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
||||||
|
applicationContext,
|
||||||
|
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||||
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
|
)
|
||||||
|
|
||||||
|
if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") return
|
||||||
|
|
||||||
|
val net = Net()
|
||||||
|
|
||||||
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
|
||||||
|
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
|
val data = JSONObject(net.synchronize(currentGroup).body!!.string())
|
||||||
|
|
||||||
|
val remoteAbstractProducts = data["abstract_products"] as JSONArray
|
||||||
|
val remoteProducts = data["products"] as JSONArray
|
||||||
|
val remoteCategories = data["categories"] as JSONArray
|
||||||
|
|
||||||
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "")!!)
|
||||||
|
|
||||||
|
val abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
|
val productDAO = ProductDAO(dbHelper)
|
||||||
|
val categoryDAO = CategoryDAO(dbHelper)
|
||||||
|
|
||||||
|
val localAbstractProducts = abstractProductDAO.getSortedListOfAbstractProducts(0, "", arrayOf(""))
|
||||||
|
val localProducts = productDAO.getSortedListOfProducts(0, "", "")
|
||||||
|
val localCategories = categoryDAO.getAllCategories()
|
||||||
|
|
||||||
|
syncAbstractProducts(net, currentGroup, abstractProductDAO, remoteAbstractProducts, localAbstractProducts)
|
||||||
|
syncProducts(productDAO, remoteProducts, localProducts)
|
||||||
|
syncCategories(categoryDAO, remoteCategories, localCategories)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun syncCategories(
|
||||||
|
categoryDAO: CategoryDAO,
|
||||||
|
remoteCategories: JSONArray,
|
||||||
|
localCategories: List<Category>
|
||||||
|
) {
|
||||||
|
for (i in 0 until remoteCategories.length()) {
|
||||||
|
var categoryInRemoteDB: JSONObject? = null
|
||||||
|
var categoryInLocalDB: Category? = null
|
||||||
|
|
||||||
|
val remoteCategory = remoteCategories.getJSONObject(i)
|
||||||
|
|
||||||
|
for (localCategory in localCategories) {
|
||||||
|
if (remoteCategory["local_id"] == localCategory.id) {
|
||||||
|
categoryInRemoteDB = remoteCategory
|
||||||
|
categoryInLocalDB = localCategory
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categoryInLocalDB == null && remoteCategory != null) {
|
||||||
|
var newCategory: Category
|
||||||
|
|
||||||
|
with (remoteCategory) {
|
||||||
|
newCategory = Category(
|
||||||
|
this["local_id"].toString().toInt(),
|
||||||
|
this["name"].toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryDAO.addCategory(newCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categoryInRemoteDB != null && categoryInLocalDB != null) {
|
||||||
|
if (categoryInRemoteDB["hash"] != categoryInLocalDB.calculateHash()) {
|
||||||
|
|
||||||
|
var updatedData: Category
|
||||||
|
|
||||||
|
with(categoryInRemoteDB) {
|
||||||
|
updatedData = Category(
|
||||||
|
this["local_id"].toString().toInt(),
|
||||||
|
this["name"].toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryDAO.updateCategory(updatedData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun syncProducts(
|
||||||
|
productDAO: ProductDAO,
|
||||||
|
remoteProducts: JSONArray,
|
||||||
|
localProducts: List<Product>
|
||||||
|
) {
|
||||||
|
for (i in 0 until remoteProducts.length()) {
|
||||||
|
var productInRemoteDB: JSONObject? = null
|
||||||
|
var productInLocalDB: Product? = null
|
||||||
|
|
||||||
|
val remoteProduct = remoteProducts.getJSONObject(i)
|
||||||
|
|
||||||
|
for (localProduct in localProducts) {
|
||||||
|
if (remoteProduct["local_id"] == localProduct.id) {
|
||||||
|
productInRemoteDB = remoteProduct
|
||||||
|
productInLocalDB = localProduct
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (productInLocalDB == null && remoteProduct != null) {
|
||||||
|
var newProduct: Product
|
||||||
|
|
||||||
|
with(remoteProduct) {
|
||||||
|
newProduct = Product(
|
||||||
|
this["local_id"].toString().toInt(),
|
||||||
|
this["abstract_product_id"].toString().toInt(),
|
||||||
|
this["amount"].toString().toInt(),
|
||||||
|
convertToUnixEpochTimestamp(this["date_of_production"].toString()),
|
||||||
|
convertToUnixEpochTimestamp(this["expiry_date"].toString())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
productDAO.insertNewProduct(newProduct)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (productInRemoteDB != null && productInLocalDB != null) {
|
||||||
|
if (productInRemoteDB["hash"] != productInLocalDB.calculateHash()) {
|
||||||
|
|
||||||
|
var updatedData: Product
|
||||||
|
|
||||||
|
with(productInRemoteDB) {
|
||||||
|
updatedData = Product(
|
||||||
|
this["local_id"].toString().toInt(),
|
||||||
|
this["abstract_product_id"].toString().toInt(),
|
||||||
|
this["amount"].toString().toInt(),
|
||||||
|
convertToUnixEpochTimestamp(this["date_of_production"].toString()),
|
||||||
|
convertToUnixEpochTimestamp(this["expiry_date"].toString())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
productDAO.updateProduct(updatedData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun syncAbstractProducts(
|
||||||
|
net: Net,
|
||||||
|
currentGroup: Int,
|
||||||
|
abstractProductDAO: AbstractProductDAO,
|
||||||
|
remoteAbstractProducts: JSONArray,
|
||||||
|
localAbstractProducts: List<AbstractProduct>
|
||||||
|
) {
|
||||||
|
for (i in 0 until remoteAbstractProducts.length()) {
|
||||||
|
var abstractProductInRemoteDB: JSONObject? = null
|
||||||
|
var abstractProductInLocalDB: AbstractProduct? = null
|
||||||
|
|
||||||
|
val remoteAbstractProduct = remoteAbstractProducts.getJSONObject(i)
|
||||||
|
|
||||||
|
for (localAbstractProduct in localAbstractProducts) {
|
||||||
|
if (remoteAbstractProduct["local_id"] == localAbstractProduct.id) {
|
||||||
|
abstractProductInRemoteDB = remoteAbstractProduct
|
||||||
|
abstractProductInLocalDB = localAbstractProduct
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abstractProductInLocalDB == null && remoteAbstractProduct != null) {
|
||||||
|
val localId = remoteAbstractProduct["local_id"].toString().toInt()
|
||||||
|
|
||||||
|
val picturesDir = File(filesDir, "pictures")
|
||||||
|
picturesDir.mkdirs()
|
||||||
|
|
||||||
|
val pictureFile =
|
||||||
|
File(picturesDir, "${remoteAbstractProduct["image_filename"]}.png")
|
||||||
|
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${localId}"
|
||||||
|
net.downloadImage(url, pictureFile)
|
||||||
|
|
||||||
|
var newAbstractProduct: AbstractProduct
|
||||||
|
|
||||||
|
with(remoteAbstractProduct) {
|
||||||
|
newAbstractProduct = AbstractProduct(
|
||||||
|
this["local_id"].toString().toInt(),
|
||||||
|
this["barcode"].toString(),
|
||||||
|
this["name"].toString(),
|
||||||
|
this["net_weight"].toString().toDouble(),
|
||||||
|
this["image_filename"].toString(),
|
||||||
|
this["category"].toString().toInt(),
|
||||||
|
this["unit"].toString().toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstractProductDAO.addAbstractProduct(newAbstractProduct)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abstractProductInRemoteDB != null && abstractProductInLocalDB != null) {
|
||||||
|
if (abstractProductInRemoteDB["hash"] != abstractProductInLocalDB.calculateHash()) {
|
||||||
|
val localId = abstractProductInRemoteDB["local_id"].toString().toInt()
|
||||||
|
|
||||||
|
val pictureFile =
|
||||||
|
File(File(filesDir, "pictures"), "${abstractProductInRemoteDB["image_filename"]}.png")
|
||||||
|
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${localId}"
|
||||||
|
net.downloadImage(url, pictureFile)
|
||||||
|
|
||||||
|
var updatedData: AbstractProduct
|
||||||
|
|
||||||
|
with(abstractProductInRemoteDB) {
|
||||||
|
updatedData = AbstractProduct(
|
||||||
|
this["local_id"].toString().toInt(),
|
||||||
|
this["barcode"].toString(),
|
||||||
|
this["name"].toString(),
|
||||||
|
this["net_weight"].toString().toDouble(),
|
||||||
|
this["image_filename"].toString(),
|
||||||
|
this["category"].toString().toInt(),
|
||||||
|
this["unit"].toString().toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abstractProductDAO.updateAbstractProduct(updatedData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViewPager(viewpager: ViewPager) {
|
private fun setupViewPager(viewpager: ViewPager) {
|
||||||
|
@ -117,9 +357,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
R.id.nav_account -> {
|
R.id.nav_account -> {
|
||||||
intent = Intent(this, AccountSettingsActivity::class.java)
|
intent = Intent(this, AccountSettingsActivity::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_groups -> {
|
R.id.nav_groups -> {
|
||||||
intent = Intent(this, MyGroupsActivity::class.java)
|
intent = Intent(this, MyGroupsActivity::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_settings -> {
|
R.id.nav_settings -> {
|
||||||
//TODO: Settings
|
//TODO: Settings
|
||||||
return false
|
return false
|
||||||
|
@ -169,6 +411,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
|
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
"ShelfFragment" -> {
|
"ShelfFragment" -> {
|
||||||
val shelfFragment = fragment as ShelfFragment
|
val shelfFragment = fragment as ShelfFragment
|
||||||
shelfFragment.removeSelected()
|
shelfFragment.removeSelected()
|
||||||
|
|
|
@ -232,6 +232,7 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
val db = dbHelper.writableDatabase
|
val db = dbHelper.writableDatabase
|
||||||
|
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
|
if (abstractProduct.id > 0) put(BaseColumns._ID, abstractProduct.id)
|
||||||
put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode)
|
put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode)
|
||||||
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name)
|
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name)
|
||||||
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, abstractProduct.netWeight.toString())
|
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, abstractProduct.netWeight.toString())
|
||||||
|
@ -249,6 +250,7 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
val db = dbHelper.writableDatabase
|
val db = dbHelper.writableDatabase
|
||||||
|
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
|
put(BaseColumns._ID, abstractProduct.id)
|
||||||
put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode)
|
put(AbstractProductContract.AbstractProductEntry.BARCODE, abstractProduct.barcode)
|
||||||
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name)
|
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, abstractProduct.name)
|
||||||
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, abstractProduct.netWeight.toString())
|
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, abstractProduct.netWeight.toString())
|
||||||
|
@ -265,7 +267,11 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSortedListOfAbstractProducts(selectedSort: Int, filterBy: String, filter: Array<String>): List<AbstractProduct> {
|
fun getSortedListOfAbstractProducts(
|
||||||
|
selectedSort: Int,
|
||||||
|
filterBy: String,
|
||||||
|
filter: Array<String>
|
||||||
|
): List<AbstractProduct> {
|
||||||
|
|
||||||
val db = dbHelper.readableDatabase
|
val db = dbHelper.readableDatabase
|
||||||
|
|
||||||
|
@ -282,10 +288,11 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
)
|
)
|
||||||
|
|
||||||
var orderBy: String = ""
|
var orderBy: String = ""
|
||||||
when(selectedSort) {
|
when (selectedSort) {
|
||||||
0 -> {
|
0 -> {
|
||||||
orderBy = "${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} ASC"
|
orderBy = "${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} ASC"
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
orderBy = "${AbstractProductContract.AbstractProductEntry.CATEGORY} ASC"
|
orderBy = "${AbstractProductContract.AbstractProductEntry.CATEGORY} ASC"
|
||||||
}
|
}
|
||||||
|
@ -299,6 +306,7 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
selection = "${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?"
|
selection = "${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?"
|
||||||
selectionArgs = filter
|
selectionArgs = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
"barcodeless" -> {
|
"barcodeless" -> {
|
||||||
selection = "${AbstractProductContract.AbstractProductEntry.BARCODE} = '' "
|
selection = "${AbstractProductContract.AbstractProductEntry.BARCODE} = '' "
|
||||||
selectionArgs = null
|
selectionArgs = null
|
||||||
|
@ -306,24 +314,35 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, orderBy)
|
val cursor = db.query(
|
||||||
|
AbstractProductContract.AbstractProductEntry.TABLE_NAME,
|
||||||
|
projection,
|
||||||
|
selection,
|
||||||
|
selectionArgs,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
orderBy
|
||||||
|
)
|
||||||
|
|
||||||
with (cursor) {
|
with(cursor) {
|
||||||
while(moveToNext()) {
|
while (moveToNext()) {
|
||||||
val productId = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID))
|
val productId = getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID))
|
||||||
val barcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE))
|
val barcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE))
|
||||||
val productName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME))
|
val productName =
|
||||||
val netWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT))
|
getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME))
|
||||||
val productImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME))
|
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 category = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.CATEGORY))
|
||||||
val unit = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT))
|
val unit = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.UNIT))
|
||||||
|
|
||||||
val product = AbstractProduct(productId, barcode, productName, netWeight, productImageHash, category, unit)
|
val product =
|
||||||
|
AbstractProduct(productId, barcode, productName, netWeight, productImageHash, category, unit)
|
||||||
|
|
||||||
abstractProducts.add(product)
|
abstractProducts.add(product)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return abstractProducts
|
return abstractProducts
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ import android.content.Context
|
||||||
import android.provider.BaseColumns
|
import android.provider.BaseColumns
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||||
|
|
||||||
class CategoryDAO (private val dbHelper: DBStorageController) {
|
class CategoryDAO(private val dbHelper: DBStorageController) {
|
||||||
fun eraseCategory(id: Int, context: Context) {
|
fun eraseCategory(id: Int, context: Context) {
|
||||||
|
|
||||||
val abstractProductDAO = AbstractProductDAO(dbHelper)
|
val abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
|
@ -56,6 +56,7 @@ class CategoryDAO (private val dbHelper: DBStorageController) {
|
||||||
val categories = mutableListOf<Category>()
|
val categories = mutableListOf<Category>()
|
||||||
|
|
||||||
val projection = arrayOf(
|
val projection = arrayOf(
|
||||||
|
BaseColumns._ID,
|
||||||
CategoriesContract.CategoryEntry.CATEGORY_NAME
|
CategoriesContract.CategoryEntry.CATEGORY_NAME
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ class CategoryDAO (private val dbHelper: DBStorageController) {
|
||||||
with(cursor) {
|
with(cursor) {
|
||||||
while (moveToNext()) {
|
while (moveToNext()) {
|
||||||
val category = Category(
|
val category = Category(
|
||||||
getInt(getColumnIndexOrThrow(android.provider.BaseColumns._ID)),
|
getInt(getColumnIndexOrThrow(BaseColumns._ID)),
|
||||||
getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME))
|
getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME))
|
||||||
)
|
)
|
||||||
categories.add(category)
|
categories.add(category)
|
||||||
|
@ -82,15 +83,18 @@ class CategoryDAO (private val dbHelper: DBStorageController) {
|
||||||
return categories
|
return categories
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCategory(category: Category) {
|
fun addCategory(category: Category): Long {
|
||||||
|
|
||||||
val db = dbHelper.writableDatabase
|
val db = dbHelper.writableDatabase
|
||||||
|
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
|
if (category.id > 0) put(BaseColumns._ID, category.id)
|
||||||
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name)
|
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.insert(CategoriesContract.CategoryEntry.TABLE_NAME, null, values)
|
val id = db.insert(CategoriesContract.CategoryEntry.TABLE_NAME, null, values)
|
||||||
|
|
||||||
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCategory(category: Category) {
|
fun updateCategory(category: Category) {
|
||||||
|
@ -100,6 +104,11 @@ class CategoryDAO (private val dbHelper: DBStorageController) {
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name)
|
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, category.name)
|
||||||
}
|
}
|
||||||
db.update(CategoriesContract.CategoryEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(category.id.toString()))
|
db.update(
|
||||||
|
CategoriesContract.CategoryEntry.TABLE_NAME,
|
||||||
|
values,
|
||||||
|
"${BaseColumns._ID} = ?",
|
||||||
|
arrayOf(category.id.toString())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,18 +13,20 @@ class ProductDAO (private val dbHelper: DBStorageController) {
|
||||||
db.delete(ProductContract.ProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null)
|
db.delete(ProductContract.ProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun insertNewProduct(product: Product) {
|
fun insertNewProduct(product: Product) : Long{
|
||||||
|
|
||||||
val db = dbHelper.writableDatabase
|
val db = dbHelper.writableDatabase
|
||||||
|
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
|
if (product.id > 0) put(BaseColumns._ID, product.id)
|
||||||
put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId)
|
put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId)
|
||||||
put(ProductContract.ProductEntry.AMOUNT, product.amount)
|
put(ProductContract.ProductEntry.AMOUNT, product.amount)
|
||||||
put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction)
|
put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction)
|
||||||
put(ProductContract.ProductEntry.EXPIRY_DATE, product.dateOfExpiry)
|
put(ProductContract.ProductEntry.EXPIRY_DATE, product.dateOfExpiry)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values)
|
val id = db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values)
|
||||||
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findAmountOfProductsWithExpiryDate(date: Long): Int {
|
fun findAmountOfProductsWithExpiryDate(date: Long): Int {
|
||||||
|
@ -82,6 +84,7 @@ class ProductDAO (private val dbHelper: DBStorageController) {
|
||||||
val db = dbHelper.writableDatabase
|
val db = dbHelper.writableDatabase
|
||||||
|
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
|
put(BaseColumns._ID, product.id)
|
||||||
put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId)
|
put(ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID, product.abstractProductId)
|
||||||
put(ProductContract.ProductEntry.AMOUNT, product.amount)
|
put(ProductContract.ProductEntry.AMOUNT, product.amount)
|
||||||
put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction)
|
put(ProductContract.ProductEntry.DATE_OF_PRODUCTION, product.dateOfProduction)
|
||||||
|
@ -157,9 +160,7 @@ class ProductDAO (private val dbHelper: DBStorageController) {
|
||||||
|
|
||||||
val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry)
|
val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry)
|
||||||
|
|
||||||
if (selectedSort == 2) { //freshness
|
products.add(product)
|
||||||
products.add(product)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.foxarmy.barcodescannerforemployees.dataclasses
|
||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import org.foxarmy.barcodescannerforemployees.md5
|
||||||
|
|
||||||
class AbstractProduct() : Parcelable {
|
class AbstractProduct() : Parcelable {
|
||||||
var id: Int = 0
|
var id: Int = 0
|
||||||
|
@ -32,6 +33,10 @@ class AbstractProduct() : Parcelable {
|
||||||
unit = parcel.readInt()
|
unit = parcel.readInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun calculateHash(): String {
|
||||||
|
return "$id:$barcode:$name:${if (netWeight % 1 == 0.0) netWeight.toInt() else netWeight}:$imageHash:$category:$unit".md5()
|
||||||
|
}
|
||||||
|
|
||||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
parcel.writeInt(id)
|
parcel.writeInt(id)
|
||||||
parcel.writeString(barcode)
|
parcel.writeString(barcode)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.foxarmy.barcodescannerforemployees.dataclasses
|
||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import org.foxarmy.barcodescannerforemployees.md5
|
||||||
|
|
||||||
class Category() : Parcelable {
|
class Category() : Parcelable {
|
||||||
var id = 0
|
var id = 0
|
||||||
|
@ -27,6 +28,10 @@ class Category() : Parcelable {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun calculateHash(): String {
|
||||||
|
return "$id:$name".md5()
|
||||||
|
}
|
||||||
|
|
||||||
companion object CREATOR : Parcelable.Creator<Category> {
|
companion object CREATOR : Parcelable.Creator<Category> {
|
||||||
override fun createFromParcel(parcel: Parcel): Category {
|
override fun createFromParcel(parcel: Parcel): Category {
|
||||||
return Category(parcel)
|
return Category(parcel)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import org.foxarmy.barcodescannerforemployees.calculateProductFreshness
|
import org.foxarmy.barcodescannerforemployees.calculateProductFreshness
|
||||||
|
import org.foxarmy.barcodescannerforemployees.md5
|
||||||
|
|
||||||
class Product() : Parcelable {
|
class Product() : Parcelable {
|
||||||
var id = 0
|
var id = 0
|
||||||
|
@ -46,6 +47,10 @@ class Product() : Parcelable {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun calculateHash(): String {
|
||||||
|
return "$id:$abstractProductId:$amount:$dateOfProduction:$dateOfExpiry".md5()
|
||||||
|
}
|
||||||
|
|
||||||
companion object CREATOR : Parcelable.Creator<Product> {
|
companion object CREATOR : Parcelable.Creator<Product> {
|
||||||
override fun createFromParcel(parcel: Parcel): Product {
|
override fun createFromParcel(parcel: Parcel): Product {
|
||||||
return Product(parcel)
|
return Product(parcel)
|
||||||
|
|
|
@ -37,13 +37,24 @@ class AbstractProductView: LinearLayout {
|
||||||
var isProductSelected = false
|
var isProductSelected = false
|
||||||
private var activity: Activity
|
private var activity: Activity
|
||||||
|
|
||||||
private lateinit var categoryDAO: CategoryDAO
|
private var categoryDAO: CategoryDAO
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
||||||
activity = getActivity(context)!!
|
activity = getActivity(context)!!
|
||||||
val inflater:LayoutInflater = activity.layoutInflater
|
val inflater:LayoutInflater = activity.layoutInflater
|
||||||
inflater.inflate(R.layout.abstract_product_view, this)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(activity: Activity, context: Context, abstractProduct: AbstractProduct) : super(context) {
|
constructor(activity: Activity, context: Context, abstractProduct: AbstractProduct) : super(context) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ import kotlin.concurrent.thread
|
||||||
class ProductView: LinearLayout {
|
class ProductView: LinearLayout {
|
||||||
var product: Product = Product()
|
var product: Product = Product()
|
||||||
var isProductSelected = false
|
var isProductSelected = false
|
||||||
private lateinit var activity: Activity
|
private var activity: Activity
|
||||||
|
|
||||||
private lateinit var productImageView: ImageView
|
private lateinit var productImageView: ImageView
|
||||||
private lateinit var productNameTextView: TextView
|
private lateinit var productNameTextView: TextView
|
||||||
|
@ -56,9 +56,9 @@ class ProductView: LinearLayout {
|
||||||
private var strokeColor: Int = 0x000000
|
private var strokeColor: Int = 0x000000
|
||||||
private lateinit var outline: GradientDrawable
|
private lateinit var outline: GradientDrawable
|
||||||
|
|
||||||
private lateinit var categoryDAO: CategoryDAO
|
private var categoryDAO: CategoryDAO
|
||||||
private lateinit var abstractProductDAO: AbstractProductDAO
|
private var abstractProductDAO: AbstractProductDAO
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
||||||
activity = getActivity(context)!!
|
activity = getActivity(context)!!
|
||||||
|
@ -71,7 +71,7 @@ class ProductView: LinearLayout {
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
)
|
)
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
abstractProductDAO = AbstractProductDAO(dbHelper)
|
abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
categoryDAO = CategoryDAO(dbHelper)
|
categoryDAO = CategoryDAO(dbHelper)
|
||||||
|
|
||||||
|
@ -86,6 +86,18 @@ class ProductView: LinearLayout {
|
||||||
val inflater: LayoutInflater = activity.layoutInflater
|
val inflater: LayoutInflater = activity.layoutInflater
|
||||||
inflater.inflate(R.layout.product_view, this)
|
inflater.inflate(R.layout.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", "offline")!!)
|
||||||
|
abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
|
categoryDAO = CategoryDAO(dbHelper)
|
||||||
|
|
||||||
productImageView = findViewById(R.id.productPicture)
|
productImageView = findViewById(R.id.productPicture)
|
||||||
productNameTextView = findViewById(R.id.productNameView)
|
productNameTextView = findViewById(R.id.productNameView)
|
||||||
productNetWeightTextView = findViewById(R.id.productNetWeightView)
|
productNetWeightTextView = findViewById(R.id.productNetWeightView)
|
||||||
|
|
Loading…
Reference in New Issue