forked from github/wulkanowy-mirror
Compare commits
5 Commits
develop
...
feature/at
Author | SHA1 | Date | |
---|---|---|---|
|
1591d494ab | ||
|
1af44cf60a | ||
|
28c234a8fd | ||
|
f8c9122686 | ||
|
7effb7aca2 |
@ -88,9 +88,12 @@ class AttendanceRepository @Inject constructor(
|
|||||||
return attendanceDb.updateAll(timetable)
|
return attendanceDb.updateAll(timetable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmName("excuseForAbsenceLessons")
|
||||||
suspend fun excuseForAbsence(
|
suspend fun excuseForAbsence(
|
||||||
student: Student, semester: Semester,
|
student: Student,
|
||||||
absenceList: List<Attendance>, reason: String? = null
|
semester: Semester,
|
||||||
|
absenceList: List<Attendance>,
|
||||||
|
reason: String? = null
|
||||||
) {
|
) {
|
||||||
val items = absenceList.map { attendance ->
|
val items = absenceList.map { attendance ->
|
||||||
Absent(
|
Absent(
|
||||||
@ -102,4 +105,22 @@ class AttendanceRepository @Inject constructor(
|
|||||||
.switchSemester(semester)
|
.switchSemester(semester)
|
||||||
.excuseForAbsence(items, reason)
|
.excuseForAbsence(items, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmName("excuseForAbsenceDays")
|
||||||
|
suspend fun excuseForAbsence(
|
||||||
|
student: Student,
|
||||||
|
semester: Semester,
|
||||||
|
days: List<LocalDate>,
|
||||||
|
reason: String? = null
|
||||||
|
) {
|
||||||
|
val items = days.map { day ->
|
||||||
|
Absent(
|
||||||
|
date = LocalDateTime.of(day, LocalTime.of(0, 0)),
|
||||||
|
timeId = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
sdk.init(student)
|
||||||
|
.switchSemester(semester)
|
||||||
|
.excuseForAbsence(items, reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,14 @@ package io.github.wulkanowy.ui.modules.attendance
|
|||||||
|
|
||||||
import android.content.DialogInterface.BUTTON_POSITIVE
|
import android.content.DialogInterface.BUTTON_POSITIVE
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.view.View.*
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
import android.view.View.INVISIBLE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -63,6 +69,8 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
val inflater = mode.menuInflater
|
val inflater = mode.menuInflater
|
||||||
inflater.inflate(R.menu.context_menu_attendance, menu)
|
inflater.inflate(R.menu.context_menu_attendance, menu)
|
||||||
|
menu.findItem(R.id.excuseMenuDaySubmit).setVisible(presenter.isWholeDayExcusable)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +86,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, menu: MenuItem): Boolean {
|
override fun onActionItemClicked(mode: ActionMode, menu: MenuItem): Boolean {
|
||||||
return when (menu.itemId) {
|
return when (menu.itemId) {
|
||||||
|
R.id.excuseMenuDaySubmit -> presenter.onExcuseDayButtonClick()
|
||||||
R.id.excuseMenuSubmit -> presenter.onExcuseSubmitButtonClick()
|
R.id.excuseMenuSubmit -> presenter.onExcuseSubmitButtonClick()
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
@ -257,11 +266,18 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
|
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String) {
|
override fun startSendMessageIntent(date: LocalDate, lessons: String, reason: String) {
|
||||||
val reasonFullText = getString(
|
val reasonFullText = if (lessons.isEmpty()) {
|
||||||
R.string.attendance_excuse_formula,
|
getString(
|
||||||
|
R.string.attendance_excuse_day_formula,
|
||||||
|
date,
|
||||||
|
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
||||||
|
reason.ifBlank { "" }
|
||||||
|
)
|
||||||
|
} else getString(
|
||||||
|
R.string.attendance_excuse_lessons_formula,
|
||||||
date,
|
date,
|
||||||
numbers,
|
lessons,
|
||||||
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
||||||
reason.ifBlank { "" }
|
reason.ifBlank { "" }
|
||||||
)
|
)
|
||||||
|
@ -38,6 +38,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
private lateinit var lastError: Throwable
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
||||||
|
var isWholeDayExcusable = false
|
||||||
|
|
||||||
private var isVulcanExcusedFunctionEnabled = false
|
private var isVulcanExcusedFunctionEnabled = false
|
||||||
|
|
||||||
@ -131,6 +132,12 @@ class AttendancePresenter @Inject constructor(
|
|||||||
view?.startActionMode()
|
view?.startActionMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onExcuseDayButtonClick(): Boolean {
|
||||||
|
view?.showExcuseDialog()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) {
|
fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) {
|
||||||
if (checked) attendanceToExcuseList.add(attendanceItem)
|
if (checked) attendanceToExcuseList.add(attendanceItem)
|
||||||
else attendanceToExcuseList.remove(attendanceItem)
|
else attendanceToExcuseList.remove(attendanceItem)
|
||||||
@ -152,7 +159,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
fun onExcuseDialogSubmit(reason: String) {
|
fun onExcuseDialogSubmit(reason: String) {
|
||||||
view?.finishActionMode()
|
view?.finishActionMode()
|
||||||
|
|
||||||
if (attendanceToExcuseList.isEmpty()) return
|
if (attendanceToExcuseList.isEmpty() && !isWholeDayExcusable) return
|
||||||
|
|
||||||
if (isVulcanExcusedFunctionEnabled) {
|
if (isVulcanExcusedFunctionEnabled) {
|
||||||
excuseAbsence(
|
excuseAbsence(
|
||||||
@ -163,8 +170,8 @@ class AttendancePresenter @Inject constructor(
|
|||||||
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
|
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
|
||||||
|
|
||||||
view?.startSendMessageIntent(
|
view?.startSendMessageIntent(
|
||||||
date = attendanceToExcuseList[0].date,
|
date = currentDate ?: attendanceToExcuseList[0].date,
|
||||||
numbers = attendanceToExcuseNumbers.joinToString(", "),
|
lessons = attendanceToExcuseNumbers.joinToString(", "),
|
||||||
reason = reason
|
reason = reason
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -217,7 +224,9 @@ class AttendancePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
.logResourceStatus("load attendance")
|
.logResourceStatus("load attendance")
|
||||||
.onResourceLoading {
|
.onResourceLoading {
|
||||||
view?.showExcuseButton(false)
|
view?.apply {
|
||||||
|
showExcuseButton(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.mapResourceData {
|
.mapResourceData {
|
||||||
if (prefRepository.isShowPresent) {
|
if (prefRepository.isShowPresent) {
|
||||||
@ -240,15 +249,16 @@ class AttendancePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onResourceIntermediate { view?.showRefresh(true) }
|
.onResourceIntermediate { view?.showRefresh(true) }
|
||||||
.onResourceSuccess {
|
.onResourceSuccess { items ->
|
||||||
isVulcanExcusedFunctionEnabled = it.any { item -> item.excusable }
|
isVulcanExcusedFunctionEnabled = items.any { item -> item.excusable }
|
||||||
val anyExcusables = it.any { it.isExcusableOrNotExcused }
|
isWholeDayExcusable = items.all { it.isAbsenceExcusable }
|
||||||
|
val anyExcusables = items.any { it.isExcusableOrNotExcused }
|
||||||
view?.showExcuseButton(anyExcusables && (isParent || isVulcanExcusedFunctionEnabled))
|
view?.showExcuseButton(anyExcusables && (isParent || isVulcanExcusedFunctionEnabled))
|
||||||
|
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"load_data",
|
"load_data",
|
||||||
"type" to "attendance",
|
"type" to "attendance",
|
||||||
"items" to it.size
|
"items" to items.size
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.onResourceNotLoading {
|
.onResourceNotLoading {
|
||||||
@ -301,7 +311,19 @@ class AttendancePresenter @Inject constructor(
|
|||||||
resourceFlow {
|
resourceFlow {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
attendanceRepository.excuseForAbsence(student, semester, toExcuseList, reason)
|
if (toExcuseList.isEmpty()) {
|
||||||
|
attendanceRepository.excuseForAbsence(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
days = listOfNotNull(currentDate),
|
||||||
|
reason = reason
|
||||||
|
)
|
||||||
|
} else attendanceRepository.excuseForAbsence(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
absenceList = toExcuseList,
|
||||||
|
reason = reason
|
||||||
|
)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Resource.Loading -> view?.run {
|
is Resource.Loading -> view?.run {
|
||||||
|
@ -56,7 +56,7 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun openSummaryView()
|
fun openSummaryView()
|
||||||
|
|
||||||
fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String)
|
fun startSendMessageIntent(date: LocalDate, lessons: String, reason: String)
|
||||||
|
|
||||||
fun startActionMode()
|
fun startActionMode()
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ private inline val AttendanceSummary.allAbsences: Double
|
|||||||
inline val Attendance.isExcusableOrNotExcused: Boolean
|
inline val Attendance.isExcusableOrNotExcused: Boolean
|
||||||
get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null
|
get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null
|
||||||
|
|
||||||
|
inline val Attendance.isAbsenceExcusable: Boolean
|
||||||
|
get() = (excusable && absence && !excused) && excuseStatus == null
|
||||||
|
|
||||||
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
|
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
|
||||||
|
|
||||||
fun List<AttendanceSummary>.calculatePercentage(): Double {
|
fun List<AttendanceSummary>.calculatePercentage(): Double {
|
||||||
|
@ -2,6 +2,13 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/excuseMenuDaySubmit"
|
||||||
|
android:icon="@drawable/ic_all_done_all"
|
||||||
|
android:title="@string/attendance_excuse_day_title"
|
||||||
|
app:iconTint="@color/material_on_surface_emphasis_medium"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/excuseMenuSubmit"
|
android:id="@+id/excuseMenuSubmit"
|
||||||
android:icon="@drawable/ic_all_done"
|
android:icon="@drawable/ic_all_done"
|
||||||
|
@ -274,8 +274,10 @@
|
|||||||
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
||||||
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
||||||
<string name="attendance_excuse_title">Excuse</string>
|
<string name="attendance_excuse_title">Excuse</string>
|
||||||
|
<string name="attendance_excuse_day_title">Excuse entire day</string>
|
||||||
<string name="attendance_excuse_reason" translatable="false">z powodu</string>
|
<string name="attendance_excuse_reason" translatable="false">z powodu</string>
|
||||||
<string name="attendance_excuse_formula" translatable="false">Dzień dobry,\nProszę o usprawiedliwienie mojego dziecka w dniu %s z lekcji %s%s%s.\n\nPozdrawiam.</string>
|
<string name="attendance_excuse_lessons_formula" translatable="false">Dzień dobry,\nProszę o usprawiedliwienie mojego dziecka w dniu %s z lekcji %s%s%s.\n\nPozdrawiam.</string>
|
||||||
|
<string name="attendance_excuse_day_formula" translatable="false">Dzień dobry,\nProszę o usprawiedliwienie mojego dziecka w dniu %s%s%s.\n\nPozdrawiam.</string>
|
||||||
<plurals name="attendance_notify_new_items_title">
|
<plurals name="attendance_notify_new_items_title">
|
||||||
<item quantity="one">New attendance</item>
|
<item quantity="one">New attendance</item>
|
||||||
<item quantity="other">New attendance</item>
|
<item quantity="other">New attendance</item>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user