created dailyReportExport.kt
This commit is contained in:
@@ -0,0 +1,183 @@
|
|||||||
|
package `in`.sminnovations.smiadmin.ui.utils
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.ProgressDialog
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.google.firebase.Firebase
|
||||||
|
import com.google.firebase.firestore.firestore
|
||||||
|
import `in`.sminnovations.smiadmin.data.Constant
|
||||||
|
import `in`.sminnovations.smiadmin.data.Employee
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.tasks.await
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
|
class dailyReportExport(private val fragment: Fragment) {
|
||||||
|
private val db = Firebase.firestore
|
||||||
|
private var currentExcelTask: Job? = null
|
||||||
|
|
||||||
|
// Add permission check
|
||||||
|
private fun checkStoragePermission(): Boolean {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
true // Android 10 and above don't need explicit storage permission for Downloads
|
||||||
|
} else {
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
fragment.requireContext(),
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportAttendance(date : Calendar, source: String) {
|
||||||
|
if (!checkStoragePermission()) {
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
fragment.requireActivity(),
|
||||||
|
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
|
||||||
|
STORAGE_PERMISSION_CODE
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel any existing task
|
||||||
|
currentExcelTask?.cancel()
|
||||||
|
|
||||||
|
val progressDialog = ProgressDialog(fragment.requireContext()).apply {
|
||||||
|
setMessage("Generating attendance report...")
|
||||||
|
setCancelable(false)
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentExcelTask = fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
try {
|
||||||
|
val company = if (source == "SMI"){
|
||||||
|
Constant.COMPANY_NAME
|
||||||
|
}else{
|
||||||
|
"IISc-OMI_LAB"
|
||||||
|
}
|
||||||
|
// First get all employees
|
||||||
|
val employeesSnapshot = withContext(Dispatchers.IO) {
|
||||||
|
db.collection("employees")
|
||||||
|
.whereEqualTo("EmployeeStatus", true)
|
||||||
|
.whereEqualTo("from",source)
|
||||||
|
.get()
|
||||||
|
.await()
|
||||||
|
}
|
||||||
|
|
||||||
|
val employees = employeesSnapshot.documents.map { doc ->
|
||||||
|
Employee(
|
||||||
|
Id = doc.getString("Id") ?: doc.getString("id") ?: "",
|
||||||
|
Name = doc.getString("Name") ?: doc.getString("name") ?: "",
|
||||||
|
)
|
||||||
|
}.sortedBy { it.Name }
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val pdfGenerator = PDFGenerator_daily(fragment.requireContext(), company)
|
||||||
|
pdfGenerator.generateDailyReport(employees, selectedDate = date,source = source)
|
||||||
|
}.also { pdfFile ->
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
// Verify file exists and is readable
|
||||||
|
if (!pdfFile.exists() || !pdfFile.canRead()) {
|
||||||
|
throw IOException("Generated PDF file is not accessible")
|
||||||
|
}
|
||||||
|
|
||||||
|
val downloadsDir = Environment.getExternalStoragePublicDirectory(
|
||||||
|
Environment.DIRECTORY_DOWNLOADS)
|
||||||
|
val pdfFileInDownloads = File(downloadsDir, pdfFile.name)
|
||||||
|
|
||||||
|
// Copy file to Downloads if needed
|
||||||
|
if (!pdfFileInDownloads.exists()) {
|
||||||
|
pdfFile.copyTo(pdfFileInDownloads, overwrite = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the file was copied successfully
|
||||||
|
if (!pdfFileInDownloads.exists() || !pdfFileInDownloads.canRead()) {
|
||||||
|
throw IOException("Failed to copy PDF to Downloads folder")
|
||||||
|
}
|
||||||
|
|
||||||
|
val emailIntent = Intent(Intent.ACTION_SEND).apply {
|
||||||
|
type = "application/pdf"
|
||||||
|
putExtra(Intent.EXTRA_EMAIL, arrayOf("admin@sminnovations.in"))
|
||||||
|
putExtra(Intent.EXTRA_SUBJECT, "Attendance Report - ")
|
||||||
|
putExtra(Intent.EXTRA_TEXT, "Please find attached the attendance report.")
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Convert file URI to content URI for sharing
|
||||||
|
val contentUri = FileProvider.getUriForFile(
|
||||||
|
fragment.requireContext(),
|
||||||
|
"${fragment.requireContext().packageName}.provider",
|
||||||
|
pdfFileInDownloads
|
||||||
|
)
|
||||||
|
putExtra(Intent.EXTRA_STREAM, contentUri)
|
||||||
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw IOException("FileProvider not properly configured: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to Main dispatcher for starting the email activity
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
progressDialog.dismiss()
|
||||||
|
try {
|
||||||
|
fragment.startActivity(Intent.createChooser(emailIntent, "Send Email"))
|
||||||
|
Toast.makeText(
|
||||||
|
fragment.context,
|
||||||
|
"Report saved in Downloads folder: ${pdfFile.name}",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
Toast.makeText(
|
||||||
|
fragment.context,
|
||||||
|
"No email app found",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
progressDialog.dismiss()
|
||||||
|
Toast.makeText(
|
||||||
|
fragment.context,
|
||||||
|
"Error sending email: ${e.message}",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
progressDialog.dismiss()
|
||||||
|
Toast.makeText(
|
||||||
|
fragment.context,
|
||||||
|
"Error: ${e.localizedMessage ?: "Unknown error occurred"}",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cleanup() {
|
||||||
|
currentExcelTask?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val STORAGE_PERMISSION_CODE = 101
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user