Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions STATUS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Pinakes Android — Build Status

## 1.12.0 (versionCode 26): loans follow the server calendar, and the same-day handover switch

Pairs with Pinakes 0.9.0 and 0.9.1 (Mobile API 1.10.0 as shipped in the stable release). Works with older servers: the new fields are optional and their absence keeps the 1.11.0 behaviour.

- **Loans show the usable return day** ([#58](https://github.com/fabiodalez-dev/Pinakes-Android/pull/58)): reader and staff loans read `effective_due_at` (the first open day after a due date closed afterwards) and `is_overdue` (lateness in the library timezone and the copy branch calendar). The date shown, the "late" state and the active/overdue grouping follow them, so a loan due on a closure is not shown late while the library is closed; `due_at` keeps the stored date.
- **Same-day handover after a closure**: Library settings → Loans gains the web's *Closures calendar* section with the `same_day_handover_after_closure` switch and its help (when on, another reader can receive the book on the first open day after a closed due day). It is sent only when changed, and only when the server sends it; Staff can change it, as on the web.

## 1.11.0 (versionCode 25): Pinakes 0.9.0, and its whole admin from the staff area

Pairs with Pinakes 0.9.0-rc.2 (Mobile API 1.10.0 for the staff areas, the copy editor's consultation switch and `patron_type` on the profile; Mobile API 1.9.0 for `closed_dates`, `loanable`, `reservations_enabled`, `/me/movements` and the new 409 codes; Mobile API 1.9.1 for the `/health` toggles `fines`, `closures_calendar` and `circulation_rules`). Works with older servers: every field is optional, the three flags default to off, and their absence keeps the 1.10.0 behaviour.
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
minSdk = 26
targetSdk = 35
versionCode = 25
versionName = "1.11.0"
versionCode = 26
versionName = "1.12.0"

vectorDrawables {
useSupportLibrary = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ enum class LoanFieldKind { INT, BOOL, CHOICE, MONEY, TIMEZONE }
/** One field of the loans tab, in the web page's order. */
data class LoanField(val key: String, val kind: LoanFieldKind, val section: LoanSection)

enum class LoanSection { APPROVAL, DURATION, PICKUP, CARD, RENEWALS, LIMITS, RECALLS, FINES }
enum class LoanSection { APPROVAL, DURATION, CLOSURES, PICKUP, CARD, RENEWALS, LIMITS, RECALLS, FINES }

object LoansForm {
/**
Expand All @@ -137,6 +137,7 @@ object LoansForm {
LoanField("loan_duration_days", LoanFieldKind.INT, LoanSection.DURATION),
LoanField("max_loan_duration_days", LoanFieldKind.INT, LoanSection.DURATION),
LoanField("app_timezone", LoanFieldKind.TIMEZONE, LoanSection.DURATION),
LoanField("same_day_handover_after_closure", LoanFieldKind.BOOL, LoanSection.CLOSURES),
LoanField("pickup_expiry_days", LoanFieldKind.INT, LoanSection.PICKUP),
LoanField("pickup_reminder_days", LoanFieldKind.INT, LoanSection.PICKUP),
LoanField("card_expiry_warning_days", LoanFieldKind.INT, LoanSection.CARD),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ internal fun CardsTab(c: Staff090LibraryCards, state: LibrarySettingsUiState, on
private fun loanSectionTitle(s: LoanSection) = when (s) {
LoanSection.APPROVAL -> R.string.staff090_library_loans_approval
LoanSection.DURATION -> R.string.staff090_library_loans_duration
LoanSection.CLOSURES -> R.string.staff090_library_loans_closures
LoanSection.PICKUP -> R.string.staff090_library_loans_pickup
LoanSection.CARD -> R.string.staff090_library_loans_card
LoanSection.RENEWALS -> R.string.staff090_library_loans_renewals
Expand All @@ -477,6 +478,7 @@ internal fun loanFieldLabel(key: String) = when (key) {
"loan_duration_days" -> R.string.staff090_library_loan_duration
"max_loan_duration_days" -> R.string.staff090_library_loan_max_duration
"app_timezone" -> R.string.staff090_library_loan_timezone
"same_day_handover_after_closure" -> R.string.staff090_library_loan_same_day_handover
"pickup_expiry_days" -> R.string.staff090_library_loan_pickup_days
"pickup_reminder_days" -> R.string.staff090_library_loan_pickup_reminder
"card_expiry_warning_days" -> R.string.staff090_library_loan_card_warning
Expand All @@ -501,6 +503,7 @@ private fun loanFieldHelp(key: String): Int? = when (key) {
"loan_duration_days" -> R.string.staff090_library_loan_duration_help
"max_loan_duration_days" -> R.string.staff090_library_loan_max_duration_help
"app_timezone" -> R.string.staff090_library_loan_timezone_help
"same_day_handover_after_closure" -> R.string.staff090_library_loan_same_day_handover_help
"pickup_expiry_days" -> R.string.staff090_library_loan_pickup_days_help
"pickup_reminder_days" -> R.string.staff090_library_loan_pickup_reminder_help
"card_expiry_warning_days" -> R.string.staff090_library_loan_card_warning_help
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import com.pinakes.app.ui.screens.staff.s090.library.CustomForms
import com.pinakes.app.ui.screens.staff.s090.library.IntInput
import com.pinakes.app.ui.screens.staff.s090.library.LibraryMoney
import com.pinakes.app.ui.screens.staff.s090.library.LibrarySettingsUiState
import com.pinakes.app.ui.screens.staff.s090.library.LoanFieldKind
import com.pinakes.app.ui.screens.staff.s090.library.LoanSection
import com.pinakes.app.ui.screens.staff.s090.library.LoansForm
import com.pinakes.app.ui.screens.staff.s090.library.ModulesForm
import com.pinakes.app.ui.screens.staff.s090.library.RuleNumber
Expand Down Expand Up @@ -139,6 +141,26 @@ class Staff090LibraryFormsTest {
assertFalse(LoansForm.editable(l, "fine_grace_mode"))
}

@Test fun theSameDayHandoverSwitchFollowsTheClosuresCalendarAndIsSentWhenChanged() {
// Pinakes 0.9.0+ sends the setting; staff may change it (it is not administrator-only).
val l = data("s090_library_loans_staff_091", Staff090LibraryLoans.serializer())
val field = LoansForm.fields(l).single { it.key == "same_day_handover_after_closure" }
assertEquals(LoanFieldKind.BOOL, field.kind)
assertEquals(LoanSection.CLOSURES, field.section)
val keys = LoansForm.fields(l).map { it.key }
assertTrue(keys.indexOf("app_timezone") < keys.indexOf("same_day_handover_after_closure"))
assertTrue(keys.indexOf("same_day_handover_after_closure") < keys.indexOf("pickup_expiry_days"))
assertTrue(LoansForm.editable(l, "same_day_handover_after_closure"))
val original = LoansForm.initial(l, it)
assertEquals("false", original["same_day_handover_after_closure"])
assertEquals("""{"same_day_handover_after_closure":true}""", LoansForm.body(l, original, original + ("same_day_handover_after_closure" to "true")).toString())
// A server before 0.9.0 does not send it: no switch, and nothing about it in the body.
val old = data("s090_library_loans_staff", Staff090LibraryLoans.serializer())
assertFalse(LoansForm.fields(old).any { it.key == "same_day_handover_after_closure" })
val oldOriginal = LoansForm.initial(old, it)
assertNull(LoansForm.body(old, oldOriginal, oldOriginal + ("same_day_handover_after_closure" to "true")))
}

@Test fun loanValidationUsesTheServerLimits() {
val l = data("s090_library_loans_admin", Staff090LibraryLoans.serializer())
val values = LoansForm.initial(l, it)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"data": {
"can_configure": false,
"currency": "EUR",
"settings": {
"loan_duration_days": 30,
"pickup_expiry_days": 3,
"pickup_reminder_days": 4,
"card_expiry_warning_days": 0,
"max_renewals": 3,
"max_active_loans_per_user": 0,
"max_loan_duration_days": 90,
"recall_interval_days": 7,
"recall_max_count": 3,
"auto_approve_requests": false,
"allow_multiple_loans_same_book": false,
"recall_auto_enabled": false,
"same_day_handover_after_closure": false,
"app_timezone": "Europe/Rome",
"daily_fine_cents": null,
"fine_max_per_loan_cents": null,
"debt_block_threshold_cents": null,
"fine_grace_days": 0,
"fine_grace_mode": "threshold",
"card_renewal_base": "today",
"fine_charged_email": false
},
"editable_fields": [
"loan_duration_days",
"pickup_expiry_days",
"pickup_reminder_days",
"card_expiry_warning_days",
"max_renewals",
"max_active_loans_per_user",
"max_loan_duration_days",
"recall_interval_days",
"recall_max_count",
"auto_approve_requests",
"allow_multiple_loans_same_book",
"recall_auto_enabled",
"same_day_handover_after_closure",
"app_timezone"
],
"admin_only_fields": [
"daily_fine_cents",
"fine_max_per_loan_cents",
"debt_block_threshold_cents",
"fine_grace_days",
"fine_grace_mode",
"card_renewal_base",
"fine_charged_email"
],
"limits": {
"loan_duration_days": {
"min": 1,
"max": 3650
},
"pickup_expiry_days": {
"min": 1,
"max": 30
},
"pickup_reminder_days": {
"min": 0,
"max": 30
},
"card_expiry_warning_days": {
"min": 0,
"max": 365
},
"max_renewals": {
"min": 0,
"max": 100
},
"max_active_loans_per_user": {
"min": 0,
"max": 1000
},
"max_loan_duration_days": {
"min": 1,
"max": 3650
},
"recall_interval_days": {
"min": 1,
"max": 365
},
"recall_max_count": {
"min": 1,
"max": 50
},
"fine_grace_days": {
"min": 0,
"max": 365
},
"money_max_cents": {
"min": 0,
"max": 999999
}
},
"options": {
"fine_grace_mode": [
"threshold",
"deduct"
],
"card_renewal_base": [
"today",
"expiry"
]
}
},
"meta": {},
"error": null
}
3 changes: 3 additions & 0 deletions i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,8 @@
"staff090_library_loan_max_renewals_help": "0 schaltet Verlängerungen ab.",
"staff090_library_loan_multiple_copies": "Mehrere Exemplare desselben Titels",
"staff090_library_loan_multiple_copies_help": "Ein Leser darf dasselbe Buch mehrfach ausleihen, jede Ausleihe auf einem anderen Exemplar.",
"staff090_library_loan_same_day_handover": "Übergabe am selben Tag nach einer Schließung",
"staff090_library_loan_same_day_handover_help": "Wenn eine Ausleihe an einem Schließtag fällig ist, kommt das Buch am ersten Öffnungstag zurück. Wenn aktiv, kann eine andere Person es noch am selben Tag erhalten; wenn inaktiv, bleibt das Buch den ganzen Tag belegt.",
"staff090_library_loan_pickup_days": "Tage zur Abholung einer genehmigten Ausleihe",
"staff090_library_loan_pickup_days_help": "Danach verfällt die genehmigte Ausleihe.",
"staff090_library_loan_pickup_reminder": "Abholerinnerung (Tage vorher)",
Expand All @@ -1812,6 +1814,7 @@
"staff090_library_loans_fines": "Gebühren und Schuldensperre",
"staff090_library_loans_limits": "Grenzen",
"staff090_library_loans_pickup": "Abholung",
"staff090_library_loans_closures": "Schließtage-Kalender",
"staff090_library_loans_recalls": "Mahnungen",
"staff090_library_loans_renewals": "Verlängerungen",
"staff090_library_loans_section": "Ausleihe",
Expand Down
3 changes: 3 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,8 @@
"staff090_library_loan_max_renewals_help": "0 turns renewals off.",
"staff090_library_loan_multiple_copies": "Several copies of the same title",
"staff090_library_loan_multiple_copies_help": "A patron may borrow the same book more than once, each loan on a different copy.",
"staff090_library_loan_same_day_handover": "Same-day handover after a closure",
"staff090_library_loan_same_day_handover_help": "When a loan is due on a closed day, the book comes back on the first open day. When on, another reader can receive it that same day; when off, the book stays taken for that whole day.",
"staff090_library_loan_pickup_days": "Days to pick up an approved loan",
"staff090_library_loan_pickup_days_help": "After that the approved loan expires.",
"staff090_library_loan_pickup_reminder": "Pickup reminder (days before)",
Expand All @@ -1812,6 +1814,7 @@
"staff090_library_loans_fines": "Fines and debt block",
"staff090_library_loans_limits": "Limits",
"staff090_library_loans_pickup": "Pickup",
"staff090_library_loans_closures": "Closures calendar",
"staff090_library_loans_recalls": "Overdue reminders",
"staff090_library_loans_renewals": "Renewals",
"staff090_library_loans_section": "Loans",
Expand Down
3 changes: 3 additions & 0 deletions i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,8 @@
"staff090_library_loan_max_renewals_help": "0 désactive les renouvellements.",
"staff090_library_loan_multiple_copies": "Plusieurs exemplaires du même titre",
"staff090_library_loan_multiple_copies_help": "Un lecteur peut emprunter le même livre plusieurs fois, chaque prêt sur un exemplaire différent.",
"staff090_library_loan_same_day_handover": "Remise le jour même après une fermeture",
"staff090_library_loan_same_day_handover_help": "Lorsqu'un prêt arrive à échéance un jour de fermeture, le livre revient le premier jour d'ouverture. Si activé, un autre lecteur peut le recevoir le jour même ; si désactivé, le livre reste indisponible toute cette journée.",
"staff090_library_loan_pickup_days": "Jours pour retirer un prêt approuvé",
"staff090_library_loan_pickup_days_help": "Passé ce délai le prêt approuvé expire.",
"staff090_library_loan_pickup_reminder": "Rappel de retrait (jours avant)",
Expand All @@ -1812,6 +1814,7 @@
"staff090_library_loans_fines": "Amendes et blocage pour dette",
"staff090_library_loans_limits": "Limites",
"staff090_library_loans_pickup": "Retrait",
"staff090_library_loans_closures": "Calendrier des fermetures",
"staff090_library_loans_recalls": "Relances",
"staff090_library_loans_renewals": "Renouvellements",
"staff090_library_loans_section": "Prêts",
Expand Down
3 changes: 3 additions & 0 deletions i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,8 @@
"staff090_library_loan_max_renewals_help": "0 disattiva i rinnovi.",
"staff090_library_loan_multiple_copies": "Più copie dello stesso titolo",
"staff090_library_loan_multiple_copies_help": "Un lettore può avere più prestiti dello stesso libro, ciascuno su una copia diversa.",
"staff090_library_loan_same_day_handover": "Consegna nello stesso giorno dopo una chiusura",
"staff090_library_loan_same_day_handover_help": "Quando un prestito scade in un giorno di chiusura, il libro torna il primo giorno di apertura. Se attivo, un altro lettore può riceverlo quello stesso giorno; se disattivo, il libro resta occupato per tutto quel giorno.",
"staff090_library_loan_pickup_days": "Giorni per il ritiro del prestito approvato",
"staff090_library_loan_pickup_days_help": "Dopo questo termine il prestito approvato scade.",
"staff090_library_loan_pickup_reminder": "Promemoria di ritiro (giorni prima)",
Expand All @@ -1812,6 +1814,7 @@
"staff090_library_loans_fines": "Multe e blocco per debito",
"staff090_library_loans_limits": "Limiti",
"staff090_library_loans_pickup": "Ritiro",
"staff090_library_loans_closures": "Calendario chiusure",
"staff090_library_loans_recalls": "Solleciti",
"staff090_library_loans_renewals": "Rinnovi",
"staff090_library_loans_section": "Prestiti",
Expand Down
Loading