Season end nudge: post once per close, not daily for the lead window
SupplyCheckReceiver re-posted the auto-cancel "Forleng" card on every daily check for the whole 5-day window, so a dismissed nudge came back each morning. Remember the season-end epoch day nudged per med (plaintext pref) and skip re-posting for the same close; a new end date (next year, or after Forleng) still earns one fresh nudge.
This commit is contained in:
parent
041f9e2cf6
commit
4bbb06d5d0
2 changed files with 26 additions and 9 deletions
|
|
@ -12,6 +12,7 @@ import no.naiv.meddetsamme.data.MedDatabase
|
||||||
import no.naiv.meddetsamme.domain.ScheduleEngine
|
import no.naiv.meddetsamme.domain.ScheduleEngine
|
||||||
import no.naiv.meddetsamme.domain.ScheduleText
|
import no.naiv.meddetsamme.domain.ScheduleText
|
||||||
import no.naiv.meddetsamme.notify.Notifications
|
import no.naiv.meddetsamme.notify.Notifications
|
||||||
|
import no.naiv.meddetsamme.settings.SettingsStore
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Daily derived-state check: low stock (inventory ÷ scheduled rate) and
|
* Daily derived-state check: low stock (inventory ÷ scheduled rate) and
|
||||||
|
|
@ -96,7 +97,7 @@ class SupplyCheckReceiver : BroadcastReceiver() {
|
||||||
/**
|
/**
|
||||||
* Per-med seasonal nudge, post-or-cancel like the digests above:
|
* Per-med seasonal nudge, post-or-cancel like the digests above:
|
||||||
* - resting and within [SEASON_START_LEAD_DAYS] of the next window → "Start nå";
|
* - resting and within [SEASON_START_LEAD_DAYS] of the next window → "Start nå";
|
||||||
* - in season and within [SEASON_END_LEAD_DAYS] of its close → "Forleng".
|
* - in season and within [SEASON_END_LEAD_DAYS] of its close → "Forleng" (once per close).
|
||||||
* Acting on either (or the season simply passing) clears it the next day.
|
* Acting on either (or the season simply passing) clears it the next day.
|
||||||
*/
|
*/
|
||||||
private fun checkSeason(
|
private fun checkSeason(
|
||||||
|
|
@ -130,14 +131,20 @@ class SupplyCheckReceiver : BroadcastReceiver() {
|
||||||
val end = ScheduleEngine.currentSeasonEnd(doseTimes, today)
|
val end = ScheduleEngine.currentSeasonEnd(doseTimes, today)
|
||||||
val days = end?.let { ChronoUnit.DAYS.between(today, it) }
|
val days = end?.let { ChronoUnit.DAYS.between(today, it) }
|
||||||
if (end != null && days != null && days in 0..SEASON_END_LEAD_DAYS) {
|
if (end != null && days != null && days in 0..SEASON_END_LEAD_DAYS) {
|
||||||
Notifications.post(
|
// Once per season close, not daily: a dismissed card stays dismissed.
|
||||||
context, notifId,
|
// Keyed on the end date, so "Forleng" (new end) earns one fresh nudge.
|
||||||
Notifications.buildSeasonNotification(
|
val settings = SettingsStore(context)
|
||||||
context, medId, name,
|
if (settings.seasonEndNudgedEpochDay(medId) != end.toEpochDay()) {
|
||||||
"Sesongen er snart over (${ScheduleText.dateLabel(end)}). Fortsatt plaget? Forleng to uker.",
|
Notifications.post(
|
||||||
starting = false,
|
context, notifId,
|
||||||
),
|
Notifications.buildSeasonNotification(
|
||||||
)
|
context, medId, name,
|
||||||
|
"Sesongen er snart over (${ScheduleText.dateLabel(end)}). Fortsatt plaget? Forleng to uker.",
|
||||||
|
starting = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
settings.setSeasonEndNudgedEpochDay(medId, end.toEpochDay())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Notifications.cancel(context, notifId)
|
Notifications.cancel(context, notifId)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,16 @@ class SettingsStore(context: Context) {
|
||||||
get() = prefs.getBoolean("repeat_reminders", true)
|
get() = prefs.getBoolean("repeat_reminders", true)
|
||||||
set(v) = prefs.edit { putBoolean("repeat_reminders", v) }
|
set(v) = prefs.edit { putBoolean("repeat_reminders", v) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Epoch day of the season close a med was last nudged "Forleng" for. The
|
||||||
|
* end-of-season card posts once per close, not daily for the whole lead
|
||||||
|
* window: keyed on the end date so next year's (or an extended) season
|
||||||
|
* gets a fresh nudge. -1 = never.
|
||||||
|
*/
|
||||||
|
fun seasonEndNudgedEpochDay(medId: Long): Long = prefs.getLong("season_end_nudged_$medId", -1)
|
||||||
|
fun setSeasonEndNudgedEpochDay(medId: Long, endEpochDay: Long) =
|
||||||
|
prefs.edit { putLong("season_end_nudged_$medId", endEpochDay) }
|
||||||
|
|
||||||
/** S3/Garage credentials complete — gates the S3 upload path only. */
|
/** S3/Garage credentials complete — gates the S3 upload path only. */
|
||||||
val isS3Configured: Boolean
|
val isS3Configured: Boolean
|
||||||
get() = !s3Endpoint.isNullOrBlank() && !s3Bucket.isNullOrBlank() &&
|
get() = !s3Endpoint.isNullOrBlank() && !s3Bucket.isNullOrBlank() &&
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue