aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2022-01-14 18:25:26 -0600
committerIván Ávalos <avalos@disroot.org>2022-01-14 18:25:26 -0600
commit7c3e13114fd189c49e86b8d6c200ffb3c27bb498 (patch)
tree9024ba5e810b40c22eeb2065e3d22650aa51d54e
parente10c55888fede23b225dee03044f6953e997c28b (diff)
downloadetbsa-trackermap-mobile-7c3e13114fd189c49e86b8d6c200ffb3c27bb498.tar.gz
etbsa-trackermap-mobile-7c3e13114fd189c49e86b8d6c200ffb3c27bb498.tar.bz2
etbsa-trackermap-mobile-7c3e13114fd189c49e86b8d6c200ffb3c27bb498.zip
Refactored reports code into ReportController.kt and added extra report periods
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt4
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt83
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt179
-rw-r--r--androidApp/src/main/res/menu/report_period_options.xml28
-rw-r--r--androidApp/src/main/res/values-es-rMX/strings.xml12
-rw-r--r--androidApp/src/main/res/values/strings.xml12
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt3
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt134
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Formatter.kt8
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt79
10 files changed, 329 insertions, 213 deletions
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
index 4cbf8e5..d591b0b 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
@@ -10,6 +10,7 @@ import mx.trackermap.TrackerMap.android.session.UserInformationViewModel
import mx.trackermap.TrackerMap.android.units.UnitsViewModel
import mx.trackermap.TrackerMap.client.apis.*
import mx.trackermap.TrackerMap.controllers.GeofencesController
+import mx.trackermap.TrackerMap.controllers.ReportController
import mx.trackermap.TrackerMap.controllers.UnitsController
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
@@ -35,12 +36,13 @@ open class TrackerApp : Application() {
factory { UnitsController(get(), get()) }
factory { GeofencesController(get()) }
+ factory { ReportController(get(), get()) }
viewModel { LoginViewModel(get(), get()) }
viewModel { UnitInformationViewModel(get()) }
viewModel { UnitCommandsViewModel(get()) }
viewModel { UnitsViewModel(get()) }
- viewModel { UnitReportsViewModel(get(), get()) }
+ viewModel { UnitReportsViewModel(get()) }
viewModel { UserInformationViewModel(get()) }
}
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
index b67dd94..957c6a7 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
@@ -26,7 +26,9 @@ import mx.trackermap.TrackerMap.android.map.MarkerTransformations
import mx.trackermap.TrackerMap.client.models.EventInformation
import mx.trackermap.TrackerMap.client.models.Position
import mx.trackermap.TrackerMap.client.models.Stop
+import mx.trackermap.TrackerMap.controllers.ReportController
import mx.trackermap.TrackerMap.utils.Formatter
+import mx.trackermap.TrackerMap.utils.ReportDates
import org.koin.androidx.viewmodel.ext.android.viewModel
import java.lang.Exception
import kotlin.math.max
@@ -76,9 +78,9 @@ class UnitReportsFragment : Fragment() {
binding.reportType.setOnPositionChangedListener { position ->
unitReportsViewModel.setReportType(
when (position) {
- 0 -> UnitReportsViewModel.ReportType.POSITIONS
- 1 -> UnitReportsViewModel.ReportType.EVENTS
- else -> UnitReportsViewModel.ReportType.STOPS
+ 0 -> ReportController.ReportType.POSITIONS
+ 1 -> ReportController.ReportType.EVENTS
+ else -> ReportController.ReportType.STOPS
}
)
}
@@ -88,8 +90,8 @@ class UnitReportsFragment : Fragment() {
binding.exportButton.setOnClickListener {
unitReportsViewModel.fetchReportXlsx()
}
- unitReportsViewModel.setReportPeriod(UnitReportsViewModel.ReportPeriod.DAY)
- unitReportsViewModel.setReportType(UnitReportsViewModel.ReportType.POSITIONS)
+ unitReportsViewModel.setReportPeriod(ReportDates.ReportPeriod.TODAY)
+ unitReportsViewModel.setReportType(ReportController.ReportType.POSITIONS)
}
private fun setupObservers() {
@@ -97,19 +99,22 @@ class UnitReportsFragment : Fragment() {
Log.d("UnitReportsFragment", "Report available: $report")
when (report) {
- is UnitReportsViewModel.Report.PositionsReport -> {
+ is ReportController.Report.PositionsReport -> {
display(report.positions)
showMap(true)
}
- is UnitReportsViewModel.Report.EventsReport -> {
+ is ReportController.Report.EventsReport -> {
display(report.events)
showMap(false)
}
- is UnitReportsViewModel.Report.StopsReport -> {
+ is ReportController.Report.StopsReport -> {
display(report.stops)
showMap(true)
}
- is UnitReportsViewModel.Report.LoadingReport -> loading()
+ is ReportController.Report.XlsxReport -> {
+ downloadFile("report.xlsx")
+ }
+ is ReportController.Report.LoadingReport -> loading()
}
}
@@ -121,21 +126,16 @@ class UnitReportsFragment : Fragment() {
binding.periodButton.text = context?.getString(
when (period) {
- UnitReportsViewModel.ReportPeriod.DAY -> R.string.day_period
- UnitReportsViewModel.ReportPeriod.WEEK -> R.string.week_period
- UnitReportsViewModel.ReportPeriod.MONTH -> R.string.month_period
+ ReportDates.ReportPeriod.TODAY -> R.string.period_today
+ ReportDates.ReportPeriod.LAST_24 -> R.string.period_last_24
+ ReportDates.ReportPeriod.YESTERDAY -> R.string.period_yesterday
+ ReportDates.ReportPeriod.THIS_WEEK -> R.string.period_this_week
+ ReportDates.ReportPeriod.LAST_7 -> R.string.period_last_7
+ ReportDates.ReportPeriod.THIS_MONTH -> R.string.period_this_month
+ ReportDates.ReportPeriod.LAST_30 -> R.string.period_last_30
}
)
}
-
- unitReportsViewModel.reportFile.observe(viewLifecycleOwner) {
- downloadFile("report.xlsx")
- }
-
- unitReportsViewModel.geofences.observe(viewLifecycleOwner) { geofences ->
- Log.d("UnitReportsFragment", "Success $geofences")
- reportsMapFragment.displayGeofences(geofences.values.toTypedArray())
- }
}
private fun showPeriodPopUp(view: View) {
@@ -144,9 +144,14 @@ class UnitReportsFragment : Fragment() {
popOver.setOnMenuItemClickListener { item ->
unitReportsViewModel.setReportPeriod(
when (item.itemId) {
- R.id.dayOption -> UnitReportsViewModel.ReportPeriod.DAY
- R.id.weekOption -> UnitReportsViewModel.ReportPeriod.WEEK
- else -> UnitReportsViewModel.ReportPeriod.MONTH
+ R.id.optionToday -> ReportDates.ReportPeriod.TODAY
+ R.id.optionLast24 -> ReportDates.ReportPeriod.LAST_24
+ R.id.optionYesterday -> ReportDates.ReportPeriod.YESTERDAY
+ R.id.optionWeek -> ReportDates.ReportPeriod.THIS_WEEK
+ R.id.optionLast7 -> ReportDates.ReportPeriod.LAST_7
+ R.id.optionMonth -> ReportDates.ReportPeriod.THIS_MONTH
+ R.id.optionLast30 -> ReportDates.ReportPeriod.LAST_30
+ else -> ReportDates.ReportPeriod.TODAY
}
)
true
@@ -221,10 +226,8 @@ class UnitReportsFragment : Fragment() {
else -> R.string.event_unknown
})
}
- event.event.geofenceId?.let {
- val geofence = unitReportsViewModel.getGeofence(it)
- Log.d("UnitReportsFragment", "Getting geofence $geofence")
- geofenceText.text = geofence?.name
+ event.geofence?.let {
+ geofenceText.text = it.name
}
event.position?.let {
addressText.text = it.address
@@ -286,17 +289,19 @@ class UnitReportsFragment : Fragment() {
private val createDocumentResult =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
- it?.data?.data?.also { uri ->
- Log.d("UnitReportsFragment", "Downloading file into ${uri.path}")
- val outputStream = context?.contentResolver?.openOutputStream(uri)
- outputStream?.let {
- try {
- outputStream.write(unitReportsViewModel.reportFile.value)
- outputStream.flush()
- outputStream.close()
- Log.d("UnitReportsFragment", "Wrote file into ${uri.path}")
- } catch (e: Exception) {
- e.printStackTrace()
+ (unitReportsViewModel.report.value as? ReportController.Report.XlsxReport)?.let { report ->
+ it?.data?.data?.also { uri ->
+ Log.d("UnitReportsFragment", "Downloading file into ${uri.path}")
+ val outputStream = context?.contentResolver?.openOutputStream(uri)
+ outputStream?.let {
+ try {
+ outputStream.write(report.data)
+ outputStream.flush()
+ outputStream.close()
+ Log.d("UnitReportsFragment", "Wrote file into ${uri.path}")
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
}
}
}
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
index fe13ba0..865f096 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
@@ -1,58 +1,31 @@
package mx.trackermap.TrackerMap.android.details.reports
-import android.util.Log
import androidx.lifecycle.*
import kotlinx.coroutines.DelicateCoroutinesApi
-import java.text.SimpleDateFormat
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
-import mx.trackermap.TrackerMap.client.apis.ReportsApi
-import mx.trackermap.TrackerMap.client.models.*
-import mx.trackermap.TrackerMap.controllers.GeofencesController
+import mx.trackermap.TrackerMap.controllers.ReportController
+import mx.trackermap.TrackerMap.utils.ReportDates
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
-import java.util.*
-import java.util.Calendar
@DelicateCoroutinesApi
class UnitReportsViewModel(
- private val reportsApi: ReportsApi,
savedStateHandle: SavedStateHandle
) : ViewModel(), KoinComponent {
- sealed class Report {
- class PositionsReport(val positions: Array<Position>) : Report()
- class EventsReport(val events: Array<EventInformation>) : Report()
- class StopsReport(val stops: Array<Stop>) : Report()
- object LoadingReport: Report()
- }
-
- enum class ReportType {
- POSITIONS, EVENTS, STOPS
- }
-
- enum class ReportPeriod {
- DAY, WEEK, MONTH
- }
-
- private val geofenceController: GeofencesController by inject()
+ private val reportController: ReportController by inject()
private var _deviceId = savedStateHandle.getLiveData("deviceId", 0)
- private val _reportType: MutableLiveData<ReportType> = savedStateHandle.getLiveData("reportType", null)
- private val _reportPeriod: MutableLiveData<ReportPeriod> =
+ private val _reportType: MutableLiveData<ReportController.ReportType> = savedStateHandle.getLiveData("reportType", null)
+ private val _reportPeriod: MutableLiveData<ReportDates.ReportPeriod> =
savedStateHandle.getLiveData("reportPeriod", null)
- private val _report: MutableLiveData<Report> = MutableLiveData()
- private val _reportFile: MutableLiveData<ByteArray> = MutableLiveData()
- private val _geofences: MutableLiveData<Map<Int, Geofence>> = MutableLiveData()
+ private val _report: MutableLiveData<ReportController.Report> = MutableLiveData()
val deviceId: LiveData<Int> get() = _deviceId
- val reportType: LiveData<ReportType> get() = _reportType
- val reportPeriod: LiveData<ReportPeriod> get() = _reportPeriod
- val report: LiveData<Report> get() = _report
- val reportFile: LiveData<ByteArray> get() = _reportFile
- val geofences: LiveData<Map<Int, Geofence>> get() = _geofences
-
- private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())
+ val reportType: LiveData<ReportController.ReportType> get() = _reportType
+ val reportPeriod: LiveData<ReportDates.ReportPeriod> get() = _reportPeriod
+ val report: LiveData<ReportController.Report> get() = _report
init {
viewModelScope.launch {
@@ -62,7 +35,7 @@ class UnitReportsViewModel(
setupPeriodObserver()
}
viewModelScope.launch {
- setupGeofenceObserver()
+ setupReportObserver()
}
}
@@ -78,9 +51,9 @@ class UnitReportsViewModel(
}
}
- private suspend fun setupGeofenceObserver() {
- geofenceController.geofencesFlow.collect {
- _geofences.postValue(it)
+ private suspend fun setupReportObserver() {
+ reportController.reportFlow.collect {
+ _report.value = it
}
}
@@ -88,32 +61,14 @@ class UnitReportsViewModel(
_deviceId.value = id
}
- fun setReportType(reportType: ReportType) {
+ fun setReportType(reportType: ReportController.ReportType) {
_reportType.value = reportType
}
- fun setReportPeriod(reportPeriod: ReportPeriod) {
+ fun setReportPeriod(reportPeriod: ReportDates.ReportPeriod) {
_reportPeriod.value = reportPeriod
}
- fun getGeofence(id: Int): Geofence? = _geofences.value?.get(id)
-
- private fun getDates(): Pair<Date, Date> {
- val calendar = Calendar.getInstance()
- val currentDate = calendar.time
-
- calendar.add(
- Calendar.DATE, when (_reportPeriod.value!!) {
- ReportPeriod.DAY -> -1
- ReportPeriod.WEEK -> -7
- ReportPeriod.MONTH -> -30
- }
- )
- val previousDate = calendar.time
-
- return Pair(currentDate, previousDate)
- }
-
fun fetchReportXlsx() {
fetchReport(true)
}
@@ -123,105 +78,15 @@ class UnitReportsViewModel(
return
}
- val (currentDate, previousDate) = getDates()
- Log.d("UnitReportsVM", "Current report type: ${_reportType.value.toString()}")
- Log.d("UnitReportsVM", "Current report period: ${_reportPeriod.value.toString()}")
- Log.d("UnitReportsVM", "Current date:${dateFormat.format(currentDate)}")
- Log.d("UnitReportsVM", "Previous date:${dateFormat.format(previousDate)}")
-
- if (!xlsx) {
- _report.postValue(Report.LoadingReport)
- }
viewModelScope.launch {
- when (_reportType.value!!) {
- ReportType.POSITIONS -> fetchPositions(previousDate, currentDate, xlsx)
- ReportType.EVENTS -> fetchEvents(previousDate, currentDate, xlsx)
- ReportType.STOPS -> fetchStops(previousDate, currentDate, xlsx)
- }
- }
- }
-
- private suspend fun fetchPositions(from: Date, to: Date, xlsx: Boolean) {
- Log.d("UnitReportsVM", "Fetching positions")
-
- if (!xlsx) {
- val result = reportsApi.reportsRouteGet(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
- Log.d("UnitReportsVM", "Positions report: $result")
- _report.postValue(Report.PositionsReport(result))
- } else {
- val result = reportsApi.reportsRouteGetXlsx(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
- Log.d("UnitReportsVM", "Positions report: $result")
- _reportFile.postValue(result)
- }
-
- }
-
- private suspend fun fetchEvents(from: Date, to: Date, xlsx: Boolean) {
- Log.d("UnitReportsVM", "Fetching events")
-
- if (!xlsx) {
- val positionsResult = reportsApi.reportsRouteGet(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
-
- val eventsResult = reportsApi.reportsEventsGet(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
-
- val result = mutableListOf<EventInformation>()
-
- eventsResult.forEach { event ->
- result.add(EventInformation(
- event = event,
- position = positionsResult.find { it.id == event.positionId }
- ))
+ _deviceId.value?.let { id ->
+ reportController.fetchReport(
+ deviceId = id,
+ reportType = _reportType.value,
+ reportPeriod = _reportPeriod.value,
+ xlsx = xlsx
+ )
}
-
- Log.d("UnitReportsVM", "Events report: $result")
- _report.postValue(Report.EventsReport(result.toTypedArray()))
- } else {
- val result = reportsApi.reportsEventsGetXlsx(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
- Log.d("UnitReportsVM", "Events report: $result")
- _reportFile.postValue(result)
- }
- }
-
- private suspend fun fetchStops(from: Date, to: Date, xlsx: Boolean) {
- Log.d("UnitReportsVM", "Fetching stops")
-
- if (!xlsx) {
- val result = reportsApi.reportsStopsGet(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
- Log.d("UnitReportsVM", "Stops report: $result")
- _report.postValue(Report.StopsReport(result))
- } else {
- val result = reportsApi.reportsStopsGetXlsx(
- dateFormat.format(from),
- dateFormat.format(to),
- _deviceId.value!!
- )
- Log.d("UnitReportsVM", "Stops report: $result")
- _reportFile.postValue(result)
}
-
}
} \ No newline at end of file
diff --git a/androidApp/src/main/res/menu/report_period_options.xml b/androidApp/src/main/res/menu/report_period_options.xml
index cf54ec3..60fb58c 100644
--- a/androidApp/src/main/res/menu/report_period_options.xml
+++ b/androidApp/src/main/res/menu/report_period_options.xml
@@ -3,15 +3,31 @@
xmlns:android="http://schemas.android.com/apk/res/android">
<item
- android:id="@+id/dayOption"
- android:title="@string/day_period" />
+ android:id="@+id/optionToday"
+ android:title="@string/period_today" />
<item
- android:id="@+id/weekOption"
- android:title="@string/week_period" />
+ android:id="@+id/optionLast24"
+ android:title="@string/period_last_24" />
<item
- android:id="@+id/monthOption"
- android:title="@string/month_period" />
+ android:id="@+id/optionYesterday"
+ android:title="@string/period_yesterday" />
+
+ <item
+ android:id="@+id/optionWeek"
+ android:title="@string/period_this_week" />
+
+ <item
+ android:id="@+id/optionLast7"
+ android:title="@string/period_last_7" />
+
+ <item
+ android:id="@+id/optionMonth"
+ android:title="@string/period_this_month" />
+
+ <item
+ android:id="@+id/optionLast30"
+ android:title="@string/period_last_30" />
</menu> \ No newline at end of file
diff --git a/androidApp/src/main/res/values-es-rMX/strings.xml b/androidApp/src/main/res/values-es-rMX/strings.xml
index 1916f26..7ebf7d2 100644
--- a/androidApp/src/main/res/values-es-rMX/strings.xml
+++ b/androidApp/src/main/res/values-es-rMX/strings.xml
@@ -81,13 +81,19 @@
<string name="positions">Posiciones</string>
<string name="events">Eventos</string>
<string name="stops">Paradas</string>
- <string name="day_period">Día</string>
- <string name="week_period">Semana</string>
- <string name="month_period">Mes</string>
<string name="period">Periodo</string>
<string name="select_period">Seleccionar</string>
<string name="export_report">Exportar</string>
+ <!-- Report periods -->
+ <string name="period_today">Hoy</string>
+ <string name="period_last_24">Últimas 24H</string>
+ <string name="period_yesterday">Ayer</string>
+ <string name="period_this_week">Semana</string>
+ <string name="period_last_7">Últimos 7d</string>
+ <string name="period_this_month">Mes</string>
+ <string name="period_last_30">Últimos 30d</string>
+
<string name="table_event">Evento</string>
<string name="table_datetime">Fecha y hora</string>
<string name="table_geofence">Geocerca</string>
diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml
index e3a31e0..5f9714e 100644
--- a/androidApp/src/main/res/values/strings.xml
+++ b/androidApp/src/main/res/values/strings.xml
@@ -104,13 +104,19 @@
<string name="positions">Positions</string>
<string name="events">Events</string>
<string name="stops">Stops</string>
- <string name="day_period">Day</string>
- <string name="week_period">Week</string>
- <string name="month_period">Month</string>
<string name="period">Period</string>
<string name="select_period">Select</string>
<string name="export_report">Export</string>
+ <!-- Report periods -->
+ <string name="period_today">Today</string>
+ <string name="period_last_24">Last 24H</string>
+ <string name="period_yesterday">Yesterday</string>
+ <string name="period_this_week">Week</string>
+ <string name="period_last_7">Last 7d</string>
+ <string name="period_this_month">Month</string>
+ <string name="period_last_30">Last 30d</string>
+
<string name="table_event">Event</string>
<string name="table_datetime">Datetime</string>
<string name="table_geofence">Geofence</string>
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt
index 1256b8c..c4f91fe 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt
@@ -2,5 +2,6 @@ package mx.trackermap.TrackerMap.client.models
data class EventInformation(
val event: Event,
- val position: Position?
+ val position: Position?,
+ val geofence: Geofence?
)
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt
new file mode 100644
index 0000000..2151331
--- /dev/null
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt
@@ -0,0 +1,134 @@
+package mx.trackermap.TrackerMap.controllers
+
+import android.util.Log
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+import mx.trackermap.TrackerMap.client.apis.GeofencesApi
+import mx.trackermap.TrackerMap.client.apis.ReportsApi
+import mx.trackermap.TrackerMap.client.models.EventInformation
+import mx.trackermap.TrackerMap.client.models.Position
+import mx.trackermap.TrackerMap.client.models.Stop
+import mx.trackermap.TrackerMap.utils.ReportDates
+
+@DelicateCoroutinesApi
+class ReportController(
+ private val reportsApi: ReportsApi,
+ private val geofencesApi: GeofencesApi
+) {
+
+ sealed class Report {
+ class PositionsReport(val positions: Array<Position>) : Report()
+ class EventsReport(val events: Array<EventInformation>) : Report()
+ class StopsReport(val stops: Array<Stop>) : Report()
+ class XlsxReport(val data: ByteArray) : Report()
+ object LoadingReport: Report()
+ }
+
+ enum class ReportType {
+ POSITIONS, EVENTS, STOPS
+ }
+
+ val reportFlow: MutableStateFlow<Report> = MutableStateFlow(Report.LoadingReport)
+
+ fun fetchReport(
+ deviceId: Int,
+ reportType: ReportType?,
+ reportPeriod: ReportDates.ReportPeriod?,
+ xlsx: Boolean = false
+ ) {
+ if (reportType == null || reportPeriod == null) {
+ return
+ }
+
+ val (currentDate, previousDate) = ReportDates.getDates(reportPeriod)
+ Log.d("UnitReportsVM", "Current report type: $reportType")
+ Log.d("UnitReportsVM", "Current report period: $reportType")
+ Log.d("UnitReportsVM", "Current date:${currentDate}")
+ Log.d("UnitReportsVM", "Previous date:${previousDate}")
+
+ if (!xlsx) {
+ reportFlow.value = Report.LoadingReport
+ }
+ GlobalScope.launch {
+ when (reportType) {
+ ReportType.POSITIONS -> fetchPositions(deviceId, previousDate, currentDate, xlsx)
+ ReportType.EVENTS -> fetchEvents(deviceId, previousDate, currentDate, xlsx)
+ ReportType.STOPS -> fetchStops(deviceId, previousDate, currentDate, xlsx)
+ }
+ }
+ }
+
+ private suspend fun fetchPositions(
+ deviceId: Int,
+ from: String,
+ to: String,
+ xlsx: Boolean
+ ) {
+ Log.d("UnitReportsVM", "Fetching positions")
+
+ if (!xlsx) {
+ val result = reportsApi.reportsRouteGet(from, to, deviceId)
+ Log.d("UnitReportsVM", "Positions report: $result")
+ reportFlow.value = Report.PositionsReport(result)
+ } else {
+ val result = reportsApi.reportsRouteGetXlsx(from, to, deviceId)
+ Log.d("UnitReportsVM", "Positions report: $result")
+ reportFlow.value = Report.XlsxReport(result)
+ }
+
+ }
+
+ private suspend fun fetchEvents(
+ deviceId: Int,
+ from: String,
+ to: String,
+ xlsx: Boolean
+ ) {
+ Log.d("UnitReportsVM", "Fetching events")
+
+ if (!xlsx) {
+ val positionsResult = reportsApi.reportsRouteGet(from, to, deviceId)
+ val eventsResult = reportsApi.reportsEventsGet(from, to, deviceId)
+ val geofencesResult = geofencesApi.geofencesGet(all = true)
+
+ val result = mutableListOf<EventInformation>()
+ eventsResult.forEach { event ->
+ result.add(EventInformation(
+ event = event,
+ position = positionsResult.find { it.id == event.positionId },
+ geofence = geofencesResult.find { it.id == event.geofenceId }
+ ))
+ }
+
+ Log.d("UnitReportsVM", "Events report: $result")
+ reportFlow.value = Report.EventsReport(result.toTypedArray())
+ } else {
+ val result = reportsApi.reportsEventsGetXlsx(from, to, deviceId)
+
+ Log.d("UnitReportsVM", "Events report: $result")
+ reportFlow.value = Report.XlsxReport(result)
+ }
+ }
+
+ private suspend fun fetchStops(
+ deviceId: Int,
+ from: String,
+ to: String,
+ xlsx: Boolean
+ ) {
+ Log.d("UnitReportsVM", "Fetching stops")
+
+ if (!xlsx) {
+ val result = reportsApi.reportsStopsGet(from, to, deviceId)
+ Log.d("UnitReportsVM", "Stops report: $result")
+ reportFlow.value = Report.StopsReport(result)
+ } else {
+ val result = reportsApi.reportsStopsGetXlsx(from, to, deviceId)
+ Log.d("UnitReportsVM", "Stops report: $result")
+ reportFlow.value = Report.XlsxReport(result)
+ }
+
+ }
+} \ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Formatter.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Formatter.kt
index af4e14d..878418e 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Formatter.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Formatter.kt
@@ -5,9 +5,11 @@ import kotlin.math.round
class Formatter {
companion object {
- fun formatDate(date: String): String {
- return date.substring(0 until date.indexOf('+'))
- .toLocalDateTime().toString().replace('T', ' ')
+ fun formatDate(str: String): String {
+ val timezone = TimeZone.currentSystemDefault()
+ val date = str.toInstant().toLocalDateTime(timezone).toString()
+ return date
+ .replace('T', ' ').trim('Z')
}
fun formatSpeed(speed: Double, unit: SpeedUnit): String {
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt
new file mode 100644
index 0000000..360cce8
--- /dev/null
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt
@@ -0,0 +1,79 @@
+package mx.trackermap.TrackerMap.utils
+
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.datetime.*
+
+@DelicateCoroutinesApi
+class ReportDates {
+ enum class ReportPeriod {
+ TODAY, LAST_24, YESTERDAY, THIS_WEEK, LAST_7, THIS_MONTH, LAST_30
+ }
+
+ companion object {
+ private fun formatDateTime(dateTime: LocalDateTime, timezone: TimeZone) =
+ dateTime.toInstant(timezone).toString()
+
+ fun getDates(period: ReportPeriod): Pair<String, String> {
+ val timezone = TimeZone.currentSystemDefault()
+ val clock = Clock.System
+ val instant = clock.now()
+ val dateTime = instant.toLocalDateTime(timezone)
+ val date = dateTime.date
+
+ var currentDate: LocalDateTime? = null
+ var previousDate: LocalDateTime? = null
+ when (period) {
+ ReportPeriod.TODAY -> {
+ previousDate = date.atTime(0, 0)
+ currentDate = dateTime
+ }
+ ReportPeriod.LAST_24 -> {
+ previousDate = instant
+ .minus(1, DateTimeUnit.DAY, timezone)
+ .toLocalDateTime(timezone)
+ currentDate = dateTime
+ }
+ ReportPeriod.YESTERDAY -> {
+ val yesterday = instant
+ .minus(1, DateTimeUnit.DAY, timezone)
+ .toLocalDateTime(timezone).date
+ previousDate = yesterday.atTime(0, 0)
+ currentDate = yesterday.atTime(23, 59)
+ }
+ ReportPeriod.THIS_WEEK -> {
+ previousDate = instant
+ .minus(date.dayOfWeek.isoDayNumber - 1, DateTimeUnit.DAY, timezone)
+ .toLocalDateTime(timezone).date
+ .atTime(0, 0)
+ currentDate = dateTime
+ }
+ ReportPeriod.LAST_7 -> {
+ previousDate = instant
+ .minus(1, DateTimeUnit.WEEK, timezone)
+ .toLocalDateTime(timezone).date
+ .atTime(0, 0)
+ currentDate = dateTime
+ }
+ ReportPeriod.THIS_MONTH -> {
+ previousDate = instant
+ .minus(date.dayOfMonth - 1, DateTimeUnit.DAY, timezone)
+ .toLocalDateTime(timezone).date
+ .atTime(0, 0)
+ currentDate = dateTime
+ }
+ ReportPeriod.LAST_30 -> {
+ previousDate = instant
+ .minus(1, DateTimeUnit.MONTH, timezone)
+ .toLocalDateTime(timezone).date
+ .atTime(0, 0)
+ currentDate = dateTime
+ }
+ }
+
+ return Pair(
+ formatDateTime(currentDate, timezone),
+ formatDateTime(previousDate, timezone)
+ )
+ }
+ }
+} \ No newline at end of file