diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ba17d99cdc9f0e00611e02631089e70ea24e131f..01f1d0c94c72e6caa3bc12a7f937daa45a5cfd68 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,6 +40,16 @@ </activity> <service android:name=".services.services.ExpiryService" /> + <provider + android:name="androidx.core.content.FileProvider" + android:authorities="${applicationId}.provider" + android:exported="false" + android:grantUriPermissions="true"> + <meta-data + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/file_paths" /> + </provider> </application> + </manifest> diff --git a/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SendTransactionReport.kt b/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SendTransactionReport.kt new file mode 100644 index 0000000000000000000000000000000000000000..ee46b060fc5070d3ba569ce0434f919d45ffb7a8 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SendTransactionReport.kt @@ -0,0 +1,8 @@ +package com.example.bondoman.data.viewmodels.settings + +import org.apache.poi.ss.usermodel.Workbook + +data class SendTransactionResponse( + val workbook: Workbook, + val nim: String? +) diff --git a/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SettingViewModel.kt b/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SettingViewModel.kt index eb8e9c9a2c9b222fe619832d7a7062631e090dfd..1624451327d9e74b879fe04102d49aa713461252 100644 --- a/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SettingViewModel.kt +++ b/app/src/main/java/com/example/bondoman/data/viewmodels/settings/SettingViewModel.kt @@ -25,8 +25,10 @@ import java.util.Locale class SettingViewModel(applicationContext: Application) : AndroidViewModel(applicationContext) { private val _exportReportResponse = MutableLiveData<ExportTransactionResponseContainer>() val exportReportResponse = _exportReportResponse + private val _sendTransactionReport = MutableLiveData<SendTransactionResponse>() + val sendTransactionReport = _sendTransactionReport - fun exportTransactionReport(bearerToken: String) { + fun exportTransactionReport(bearerToken: String, save: Boolean = true) { viewModelScope.launch { val userRepository = UserRepository( @@ -49,24 +51,29 @@ class SettingViewModel(applicationContext: Application) : AndroidViewModel(appli val transactionDB = TransactionDatabase.getInstance(getApplication()) val transactionRepository = TransactionRepository(transactionDB.transactionDao()) - val transactions = transactionRepository.getAll(response.body()!!.nim!!) + val workbook = transactionToExcel(transactions) - try { - createExcel(workbook) - _exportReportResponse.value = - ExportTransactionResponseContainer( - ExportTransactionStatus.SUCCESS, - "Export Report Success", - ) - } catch (e: Exception) { - Log.e("SettingViewModel", e.message ?: "Unknown error") - _exportReportResponse.value = - ExportTransactionResponseContainer( - ExportTransactionStatus.FAILED, - e.message ?: "Unknown error", - ) + if (save) { + try { + createExcel(workbook) + _exportReportResponse.value = + ExportTransactionResponseContainer( + ExportTransactionStatus.SUCCESS, + "Export Report Success", + ) + } catch (e: Exception) { + Log.e("SettingViewModel", e.message ?: "Unknown error") + _exportReportResponse.value = + ExportTransactionResponseContainer( + ExportTransactionStatus.FAILED, + e.message ?: "Unknown error", + ) + } + } else { + val nim = response.body()?.nim + _sendTransactionReport.value = SendTransactionResponse(workbook, nim) } } } @@ -84,11 +91,20 @@ class SettingViewModel(applicationContext: Application) : AndroidViewModel(appli val contentValues = ContentValues().apply { put(MediaStore.MediaColumns.DISPLAY_NAME, "$filename.xlsx") - put(MediaStore.MediaColumns.MIME_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/Bondoman") + put( + MediaStore.MediaColumns.MIME_TYPE, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ) + put( + MediaStore.MediaColumns.RELATIVE_PATH, + Environment.DIRECTORY_DOWNLOADS + "/Bondoman" + ) } - val uri = getApplication<Application>().contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues) + val uri = getApplication<Application>().contentResolver.insert( + MediaStore.Downloads.EXTERNAL_CONTENT_URI, + contentValues + ) val outputStream = getApplication<Application>().contentResolver.openOutputStream(uri!!) workbook.write(outputStream) outputStream?.close() @@ -96,7 +112,7 @@ class SettingViewModel(applicationContext: Application) : AndroidViewModel(appli workbook.close() } - private fun transactionToExcel(transactions: List<Transaction>): Workbook { + fun transactionToExcel(transactions: List<Transaction>): Workbook { // Write transactions to XLSX File val workbook = XSSFWorkbook() val sheet: Sheet = workbook.createSheet("Transaction Report") diff --git a/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt b/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt index 2f61bb3a0f89aea1e4afebf6f6fea085cb3fc91e..2341bf8e541e46ad42acef391a083c40f5bc15d4 100644 --- a/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt +++ b/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt @@ -56,7 +56,7 @@ class TransactionViewModel( Transaction( title = title, owner = currentUserNim, - amount = Long.MAX_VALUE, + amount = amount, category = category, location = location, ) diff --git a/app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt b/app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt index 25cee9d2da3e3b80be271cebab49d38ca9fc6082..8c0b93a42aaf394a513d15d99c9e544b3a5daded 100644 --- a/app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt +++ b/app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt @@ -235,14 +235,14 @@ class MainActivity : AppCompatActivity(), ParentActivityService { // Set the action to go back to TransactionListFragment navController.popBackStack(R.id.transactionListFragment, false) currentFragmentId = R.id.transactionAddFragment - } - + } + // handle scan fragment navigation else if (currentFragmentId != R.id.scanReceiptFragment && destination.id == R.id.scanReceiptResultFragment) { navController.popBackStack(R.id.scanReceiptFragment, false) currentFragmentId = R.id.scanReceiptFragment - } - + } + // handle default behaviour else { if (destination.id in MAIN_FRAGMENT_IDS) { diff --git a/app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt index 24a41ef4ae2b58e7e30be4d87b9cf3d507fd49bb..88dce1e5c4d1e760310f384b6f23dc8a85abb3d1 100644 --- a/app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt @@ -2,10 +2,12 @@ package com.example.bondoman.views.fragments import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.core.content.FileProvider import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider @@ -14,10 +16,13 @@ import com.example.bondoman.R import com.example.bondoman.data.utils.PreferencesManager import com.example.bondoman.data.viewmodels.settings.ExportTransactionResponseContainer import com.example.bondoman.data.viewmodels.settings.ExportTransactionStatus +import com.example.bondoman.data.viewmodels.settings.SendTransactionResponse import com.example.bondoman.data.viewmodels.settings.SettingViewModel import com.example.bondoman.services.services.ExpiryService import com.example.bondoman.views.activities.LoginActivity import com.example.bondoman.views.components.SettingButtonComponent +import java.io.File +import java.io.FileOutputStream class SettingsFragment : Fragment() { private lateinit var settingViewModel: SettingViewModel @@ -59,10 +64,19 @@ class SettingsFragment : Fragment() { Observer<ExportTransactionResponseContainer> { when (it.status) { ExportTransactionStatus.SUCCESS -> { - Toast.makeText(requireActivity(), "Export Report Success", Toast.LENGTH_SHORT).show() + Toast.makeText( + requireActivity(), + "Export Report Success", + Toast.LENGTH_SHORT + ).show() } + ExportTransactionStatus.FAILED -> { - Toast.makeText(requireActivity(), "Export Report Failed", Toast.LENGTH_SHORT).show() + Toast.makeText( + requireActivity(), + "Export Report Failed", + Toast.LENGTH_SHORT + ).show() } } } @@ -72,7 +86,57 @@ class SettingsFragment : Fragment() { } private fun onSendReportButtonClick() { - Toast.makeText(requireActivity(), "Send Report", Toast.LENGTH_SHORT).show() + val token = PreferencesManager.getString(requireActivity(), "token", true) + + if (token != null) { + Toast.makeText(requireActivity(), "Processing report...", Toast.LENGTH_SHORT).show() + + settingViewModel.exportTransactionReport(token, false) + + val observer = Observer<SendTransactionResponse> { response -> + val tempFile = File.createTempFile( + "TransactionReport", + ".xlsx", + this.requireContext().cacheDir + ) + FileOutputStream(tempFile).use { + response.workbook.write(it) + } + val reportUri = FileProvider.getUriForFile( + this.requireContext(), + this.requireContext().applicationContext.packageName + ".provider", tempFile + ) + + val emailIntent = Intent(Intent.ACTION_SEND) + emailIntent.type = + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + emailIntent.putExtra( + Intent.EXTRA_EMAIL, + arrayOf("${response.nim}@std.stei.itb.ac.id") + ) + emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Your Transaction Report") + emailIntent.putExtra( + Intent.EXTRA_TEXT, + "Your transaction reports is attached with this email. Don't be surprised 😎" + ) + emailIntent.putExtra(Intent.EXTRA_STREAM, reportUri) + emailIntent.setPackage("com.google.android.gm") + + try { + this.requireContext() + .startActivity(emailIntent) + } catch (ex: android.content.ActivityNotFoundException) { + Log.e(TAG, "${ex.message}") + } + + Log.d(TAG, "Workbook: ${response.workbook}") + } + + settingViewModel.sendTransactionReport.observe(this.requireActivity(), observer) + } else { + Toast.makeText(requireActivity(), "Failed to processing report", Toast.LENGTH_SHORT) + .show() + } } private fun onRandomizeTransactionButtonClick() { @@ -93,6 +157,8 @@ class SettingsFragment : Fragment() { } companion object { + private const val TAG = "SettingsFragment" + @JvmStatic fun newInstance() = SettingsFragment().apply { diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000000000000000000000000000000000000..c782c28367916ea755be7875a055e154307d3976 --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<paths> + <cache-path + name="cache" + path="/" /> +</paths>