Add excuse function to "not excusable" account (#1429)

This commit is contained in:
Mateusz Idziejczak 2021-08-29 19:47:14 +02:00 committed by GitHub
parent ea0fb00bde
commit 98dcc62bb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 7 deletions

View File

@ -10,6 +10,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.enums.SentExcuseStatus import io.github.wulkanowy.data.enums.SentExcuseStatus
import io.github.wulkanowy.databinding.ItemAttendanceBinding import io.github.wulkanowy.databinding.ItemAttendanceBinding
import io.github.wulkanowy.utils.description import io.github.wulkanowy.utils.description
import io.github.wulkanowy.utils.isExcusableOrNotExcused
import javax.inject.Inject import javax.inject.Inject
class AttendanceAdapter @Inject constructor() : class AttendanceAdapter @Inject constructor() :
@ -56,7 +57,7 @@ class AttendanceAdapter @Inject constructor() :
attendanceItemExcuseInfo.visibility = View.VISIBLE attendanceItemExcuseInfo.visibility = View.VISIBLE
} }
else -> { else -> {
if (item.excusable && excuseActionMode) { if (item.isExcusableOrNotExcused && excuseActionMode) {
attendanceItemNumber.visibility = View.GONE attendanceItemNumber.visibility = View.GONE
attendanceItemExcuseCheckbox.visibility = View.VISIBLE attendanceItemExcuseCheckbox.visibility = View.VISIBLE
} else { } else {

View File

@ -24,6 +24,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
import io.github.wulkanowy.ui.widgets.DividerItemDecoration import io.github.wulkanowy.ui.widgets.DividerItemDecoration
import io.github.wulkanowy.utils.SchoolDaysValidator import io.github.wulkanowy.utils.SchoolDaysValidator
import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.dpToPx
@ -120,7 +121,9 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh) attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
attendanceSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary)) attendanceSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
attendanceSwipe.setProgressBackgroundColorSchemeColor( attendanceSwipe.setProgressBackgroundColorSchemeColor(
requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh) requireContext().getThemeAttrColor(
R.attr.colorSwipeRefresh
)
) )
attendanceErrorRetry.setOnClickListener { presenter.onRetry() } attendanceErrorRetry.setOnClickListener { presenter.onRetry() }
attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() } attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
@ -253,8 +256,13 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
.setNegativeButton(android.R.string.cancel) { _, _ -> } .setNegativeButton(android.R.string.cancel) { _, _ -> }
.create() .create()
.apply { .apply {
setButton(BUTTON_POSITIVE, getString(R.string.attendance_excuse_dialog_submit)) { _, _ -> setButton(
presenter.onExcuseDialogSubmit(dialogBinding.excuseReason.text?.toString().orEmpty()) BUTTON_POSITIVE,
getString(R.string.attendance_excuse_dialog_submit)
) { _, _ ->
presenter.onExcuseDialogSubmit(
dialogBinding.excuseReason.text?.toString().orEmpty()
)
} }
}.show() }.show()
} }
@ -267,6 +275,17 @@ 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) {
val reasonFullText = getString(
R.string.attendance_excuse_formula,
date,
numbers,
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
reason.ifBlank { "" }
)
startActivity(SendMessageActivity.getStartIntent(requireContext(), reasonFullText))
}
override fun showExcuseCheckboxes(show: Boolean) { override fun showExcuseCheckboxes(show: Boolean) {
attendanceAdapter.apply { attendanceAdapter.apply {
excuseActionMode = show excuseActionMode = show

View File

@ -15,6 +15,7 @@ import io.github.wulkanowy.utils.capitalise
import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
import io.github.wulkanowy.utils.isExcusableOrNotExcused
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nextSchoolDay
import io.github.wulkanowy.utils.previousOrSameSchoolDay import io.github.wulkanowy.utils.previousOrSameSchoolDay
@ -47,6 +48,8 @@ class AttendancePresenter @Inject constructor(
private val attendanceToExcuseList = mutableListOf<Attendance>() private val attendanceToExcuseList = mutableListOf<Attendance>()
private var isVulcanExcusedFunctionEnabled = false
fun onAttachView(view: AttendanceView, date: Long?) { fun onAttachView(view: AttendanceView, date: Long?) {
super.onAttachView(view) super.onAttachView(view)
view.initView() view.initView()
@ -148,7 +151,21 @@ class AttendancePresenter @Inject constructor(
fun onExcuseDialogSubmit(reason: String) { fun onExcuseDialogSubmit(reason: String) {
view?.finishActionMode() view?.finishActionMode()
excuseAbsence(if (reason != "") reason else null, attendanceToExcuseList.toList())
if (isVulcanExcusedFunctionEnabled) {
excuseAbsence(
reason = reason.takeIf { it.isNotBlank() },
toExcuseList = attendanceToExcuseList.toList()
)
} else {
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
view?.startSendMessageIntent(
date = attendanceToExcuseList[0].date,
numbers = attendanceToExcuseNumbers.joinToString(", "),
reason = reason
)
}
} }
fun onPrepareActionMode(): Boolean { fun onPrepareActionMode(): Boolean {
@ -188,8 +205,12 @@ class AttendancePresenter @Inject constructor(
private fun loadData(forceRefresh: Boolean = false) { private fun loadData(forceRefresh: Boolean = false) {
Timber.i("Loading attendance data started") Timber.i("Loading attendance data started")
var isParent = false
flowWithResourceIn { flowWithResourceIn {
val student = studentRepository.getCurrentStudent() val student = studentRepository.getCurrentStudent()
isParent = student.isParent
val semester = semesterRepository.getCurrentSemester(student) val semester = semesterRepository.getCurrentSemester(student)
attendanceRepository.getAttendance( attendanceRepository.getAttendance(
student, student,
@ -227,12 +248,17 @@ class AttendancePresenter @Inject constructor(
it.data?.filter { item -> !item.presence }.orEmpty() it.data?.filter { item -> !item.presence }.orEmpty()
} }
isVulcanExcusedFunctionEnabled =
filteredAttendance.any { item -> item.excusable }
view?.apply { view?.apply {
updateData(filteredAttendance.sortedBy { item -> item.number }) updateData(filteredAttendance.sortedBy { item -> item.number })
showEmpty(filteredAttendance.isEmpty()) showEmpty(filteredAttendance.isEmpty())
showErrorView(false) showErrorView(false)
showContent(filteredAttendance.isNotEmpty()) showContent(filteredAttendance.isNotEmpty())
showExcuseButton(filteredAttendance.any { item -> item.excusable }) showExcuseButton(filteredAttendance.any { item ->
(!isParent && isVulcanExcusedFunctionEnabled) || (isParent && item.isExcusableOrNotExcused)
})
} }
analytics.logEvent( analytics.logEvent(
"load_data", "load_data",

View File

@ -54,6 +54,8 @@ interface AttendanceView : BaseView {
fun openSummaryView() fun openSummaryView()
fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String)
fun startActionMode() fun startActionMode()
fun showExcuseCheckboxes(show: Boolean) fun showExcuseCheckboxes(show: Boolean)

View File

@ -35,6 +35,8 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
companion object { companion object {
private const val EXTRA_MESSAGE = "EXTRA_MESSAGE" private const val EXTRA_MESSAGE = "EXTRA_MESSAGE"
private const val EXTRA_REASON = "EXTRA_REASON"
private const val EXTRA_REPLY = "EXTRA_REPLY" private const val EXTRA_REPLY = "EXTRA_REPLY"
fun getStartIntent(context: Context) = Intent(context, SendMessageActivity::class.java) fun getStartIntent(context: Context) = Intent(context, SendMessageActivity::class.java)
@ -44,6 +46,11 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
.putExtra(EXTRA_MESSAGE, message) .putExtra(EXTRA_MESSAGE, message)
.putExtra(EXTRA_REPLY, reply) .putExtra(EXTRA_REPLY, reply)
} }
fun getStartIntent(context: Context, reason: String): Intent {
return getStartIntent(context)
.putExtra(EXTRA_REASON, reason)
}
} }
override val isDropdownListVisible: Boolean override val isDropdownListVisible: Boolean
@ -79,6 +86,7 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
presenter.onAttachView( presenter.onAttachView(
view = this, view = this,
reason = intent.getSerializableExtra(EXTRA_REASON) as? String,
message = intent.getSerializableExtra(EXTRA_MESSAGE) as? Message, message = intent.getSerializableExtra(EXTRA_MESSAGE) as? Message,
reply = intent.getSerializableExtra(EXTRA_REPLY) as? Boolean reply = intent.getSerializableExtra(EXTRA_REPLY) as? Boolean
) )

View File

@ -40,7 +40,7 @@ class SendMessagePresenter @Inject constructor(
private val messageUpdateChannel = Channel<Unit>() private val messageUpdateChannel = Channel<Unit>()
fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) { fun onAttachView(view: SendMessageView, reason: String?, message: Message?, reply: Boolean?) {
super.onAttachView(view) super.onAttachView(view)
view.initView() view.initView()
initializeSubjectStream() initializeSubjectStream()
@ -50,6 +50,10 @@ class SendMessagePresenter @Inject constructor(
if (messageRepository.draftMessage != null && reply == null) { if (messageRepository.draftMessage != null && reply == null) {
view.showMessageBackupDialog() view.showMessageBackupDialog()
} }
reason?.let {
setSubject("Usprawiedliwenie")
setContent(it)
}
message?.let { message?.let {
setSubject(when (reply) { setSubject(when (reply) {
true -> "RE: " true -> "RE: "

View File

@ -16,6 +16,9 @@ private inline val AttendanceSummary.allPresences: Double
private inline val AttendanceSummary.allAbsences: Double private inline val AttendanceSummary.allAbsences: Double
get() = absence.toDouble() + absenceExcused get() = absence.toDouble() + absenceExcused
inline val Attendance.isExcusableOrNotExcused: Boolean
get() = excusable || ((absence || lateness) && !excused)
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences) fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
fun List<AttendanceSummary>.calculatePercentage(): Double { fun List<AttendanceSummary>.calculatePercentage(): Double {

View File

@ -192,6 +192,8 @@
<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_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>
<!--Attendance summary--> <!--Attendance summary-->