diff --git a/app/src/main/java/in/sminnovations/smiadmin/ui/utils/dailyReportExport.kt b/app/src/main/java/in/sminnovations/smiadmin/ui/utils/dailyReportExport.kt new file mode 100644 index 0000000..ee585e6 --- /dev/null +++ b/app/src/main/java/in/sminnovations/smiadmin/ui/utils/dailyReportExport.kt @@ -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 + } +}