Bug 10190: (QA follow-up) Fix six issues reported during QA

1. Letter context: setFilteredLetters() was reading library_id from
   currentRuleSet (which has no top-level library_id property) instead
   of this.context.library_id, causing library-specific letter templates
   to never match.

2. False conflict on edit: conflict check fetched rule set from DB with
   effective=false (raw), but the in-memory snapshot was fetched with
   effective=true (with fallbacks). Comparing raw vs effective always
   triggered a conflict when a context inherited any value from a more
   general rule. Fixed by using effective=true for the DB fetch too.

3. Incomplete deletion: updateCircRuleSets() inside deleteRuleSet() was
   called without await, creating a race condition where the page refresh
   could complete before the deletion API call, leaving stale data visible.
   Also added a guard to skip rule sets with no explicit rules for the
   trigger being deleted, and simplified rulesForDeletion construction.

4. No rules displayed on initial load: the route watcher in
   CirculationTriggersList fired immediately before init() had loaded
   patron categories and item types, causing setAllExhaustiveEffectiveRuleSets()
   to produce an empty result. Fixed with a metaInitialized flag that the
   watcher waits for before proceeding.

5. DefaultToLoggedInLibraryOverdueTriggers syspref not respected: the
   default_view template variable was computed but never applied to the
   store's currentLibraryId. Fixed by passing it to init().

6. UI colors: info box background changed from #84c1f3 to #DAECFB (lighter,
   matching the circulation rules page). Error alert messages changed from
   alert-info (blue) to alert-warning (yellow) to match Koha conventions.

Signed-off-by: Michaela <michaela.sieber@kit.edu>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Martin Renvoize 2026-02-27 05:49:34 +00:00 committed by Pedro Amorim
parent 8f6cee51ea
commit 14fe8cb2f5
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
6 changed files with 44 additions and 22 deletions

View File

@ -126,7 +126,7 @@
<p>{{ $__("Loading context...") }}</p>
</div>
<fieldset class="rows" v-if="alertMessage">
<div class="alert alert-info">{{ alertMessage }}</div>
<div class="alert alert-warning">{{ alertMessage }}</div>
</fieldset>
<fieldset
class="rows"
@ -601,7 +601,10 @@ export default {
// in edit mode, check for changes from elsewhere to the rule set being edited
if (this.editMode === "edit") {
const ruleSetInDb = await this.getSelectedRuleSet(this.context);
const ruleSetInDb = await this.getSelectedRuleSet(
this.context,
true
);
if (
this.hasConflict(
ruleSetInDb,
@ -756,7 +759,7 @@ export default {
: Infinity;
},
setFilteredLetters() {
const library = this.currentRuleSet.library_id;
const library = this.context.library_id;
const byCode = new Map();
for (const letter of this.letters) {

View File

@ -259,7 +259,7 @@
</fieldset>
<fieldset class="rows" v-if="alertMessage">
<div class="alert alert-info">{{ alertMessage }}</div>
<div class="alert alert-warning">{{ alertMessage }}</div>
</fieldset>
</CirculationTriggersForm>
</template>

View File

@ -33,7 +33,7 @@
}}
</p>
</div>
<div class="alert alert-info" v-if="alertMessage">
<div class="alert alert-warning" v-if="alertMessage">
{{ alertMessage }}
</div>
</fieldset>

View File

@ -352,6 +352,7 @@ export default {
allEffectiveRuleSets,
librariesWithRules,
storeInitialized,
metaInitialized,
} = storeToRefs(circRulesStore);
return {
@ -372,6 +373,7 @@ export default {
isLastTrigger,
getLibrariesWithRules,
storeInitialized,
metaInitialized,
from_branch,
};
},
@ -483,6 +485,19 @@ export default {
this.$route.fullPath.includes("refresh") ||
this.$route.path.endsWith("circulation_triggers")
) {
if (!this.metaInitialized) {
await new Promise(resolve => {
const stop = this.$watch(
"metaInitialized",
val => {
if (val) {
stop();
resolve();
}
}
);
});
}
await this.$nextTick();
await this.filterRuleSetsbySearchParam();
}

View File

@ -29,7 +29,7 @@ import { inject } from "vue";
export default {
setup() {
const circRulesStore = inject("circRulesStore");
circRulesStore.init();
circRulesStore.init(default_view);
letters.unshift({
name: "No letter",
code: "",
@ -51,6 +51,10 @@ export default {
</script>
<style>
.page-section.bg-info {
background-color: #DAECFB !important;
}
form .v-select {
display: inline-block;
background-color: white;

View File

@ -20,6 +20,7 @@ export const useCircRulesStore = defineStore("circRules", () => {
currentPatronCategoryId: null,
currentItemTypeId: null,
triggerCounts: { "*": 0 },
metaInitialized: false,
// references
itemTypes: [],
libraries: [],
@ -44,10 +45,12 @@ export const useCircRulesStore = defineStore("circRules", () => {
const actions = {
// controllers
async init() {
async init(defaultLibraryId = "*") {
await this.getItemTypes();
await this.getLibraries();
await this.getPatronCategories();
this.currentLibraryId = defaultLibraryId;
this.metaInitialized = true;
},
async loadUserPermissions() {
if (this.userPermissions !== null) {
@ -390,27 +393,24 @@ export const useCircRulesStore = defineStore("circRules", () => {
},
// repositories
async deleteRuleSet(ruleSet, triggerNumber) {
if (!this.hasExplicitRulesForTrigger(ruleSet, triggerNumber)) {
return;
}
const ruleSetInDb = await this.getSelectedRuleSet(ruleSet.context);
if (this.hasConflict(ruleSet, ruleSetInDb, triggerNumber)) {
throw "The rule set for the selected trigger context could not be reset as it was updated elsewhere. Please see the updated trigger above.";
}
const rulesForDeletion = { context: ruleSet.context };
if (ruleSet[`overdue_${triggerNumber}_delay`] !== null) {
rulesForDeletion[`overdue_${triggerNumber}_delay`] = null;
}
if (ruleSet[`overdue_${triggerNumber}_notice`] !== null) {
rulesForDeletion[`overdue_${triggerNumber}_notice`] = null;
}
if (ruleSet[`overdue_${triggerNumber}_restrict`] !== null) {
rulesForDeletion[`overdue_${triggerNumber}_restrict`] = null;
}
if (ruleSet[`overdue_${triggerNumber}_mtt`] !== null) {
rulesForDeletion[`overdue_${triggerNumber}_mtt`] = null;
}
this.updateCircRuleSets(rulesForDeletion, triggerNumber);
const rulesForDeletion = {
context: ruleSet.context,
[`overdue_${triggerNumber}_delay`]: null,
[`overdue_${triggerNumber}_notice`]: null,
[`overdue_${triggerNumber}_restrict`]: null,
[`overdue_${triggerNumber}_mtt`]: null,
};
await this.updateCircRuleSets(rulesForDeletion, triggerNumber);
},
async getLibrariesWithRules() {
const client = APIClient.circRule;