|
Lines 12-24
Link Here
|
| 12 |
<div class="page-section bg-info" v-if="circRules.length"> |
12 |
<div class="page-section bg-info" v-if="circRules.length"> |
| 13 |
<h2>{{ $__("Trigger context") }}</h2> |
13 |
<h2>{{ $__("Trigger context") }}</h2> |
| 14 |
<TriggerContext :ruleInfo="ruleInfo" /> |
14 |
<TriggerContext :ruleInfo="ruleInfo" /> |
| 15 |
<h2>{{ $__("Existing rules") }}</h2> |
15 |
<h2 v-if="ruleInfo.numberOfTriggers > 0"> |
| 16 |
<p>{{ $__("Notice") }} {{ " " + newTriggerNumber - 1 }}</p> |
16 |
{{ $__("Existing rules") }} |
|
|
17 |
</h2> |
| 18 |
<p v-if="ruleInfo.numberOfTriggers > 0"> |
| 19 |
{{ $__("Notice") }} {{ " " + newTriggerNumber - 1 }} |
| 20 |
</p> |
| 17 |
<TriggersTable |
21 |
<TriggersTable |
|
|
22 |
v-if="ruleInfo.numberOfTriggers > 0" |
| 18 |
:circRules="circRules" |
23 |
:circRules="circRules" |
| 19 |
:triggerNumber="newTriggerNumber - 1" |
24 |
:triggerNumber="newTriggerNumber - 1" |
| 20 |
:modal="true" |
25 |
:modal="true" |
| 21 |
:ruleBeingEdited="ruleBeingEdited" |
26 |
:ruleBeingEdited="ruleBeingEdited" |
|
|
27 |
:triggerBeingEdited="triggerBeingEdited" |
| 22 |
:letters="letters" |
28 |
:letters="letters" |
| 23 |
/> |
29 |
/> |
| 24 |
</div> |
30 |
</div> |
|
Lines 30-36
Link Here
|
| 30 |
> |
36 |
> |
| 31 |
<v-select |
37 |
<v-select |
| 32 |
id="library_id" |
38 |
id="library_id" |
| 33 |
v-model="circRuleTrigger.library_id" |
39 |
v-model="newRule.library_id" |
| 34 |
label="name" |
40 |
label="name" |
| 35 |
:reduce="lib => lib.library_id" |
41 |
:reduce="lib => lib.library_id" |
| 36 |
:options="libraries" |
42 |
:options="libraries" |
|
Lines 39-45
Link Here
|
| 39 |
> |
45 |
> |
| 40 |
<template #search="{ attributes, events }"> |
46 |
<template #search="{ attributes, events }"> |
| 41 |
<input |
47 |
<input |
| 42 |
:required="!circRuleTrigger.library_id" |
48 |
:required="!newRule.library_id" |
| 43 |
class="vs__search" |
49 |
class="vs__search" |
| 44 |
v-bind="attributes" |
50 |
v-bind="attributes" |
| 45 |
v-on="events" |
51 |
v-on="events" |
|
Lines 54-60
Link Here
|
| 54 |
> |
60 |
> |
| 55 |
<v-select |
61 |
<v-select |
| 56 |
id="patron_category_id" |
62 |
id="patron_category_id" |
| 57 |
v-model="circRuleTrigger.patron_category_id" |
63 |
v-model="newRule.patron_category_id" |
| 58 |
label="name" |
64 |
label="name" |
| 59 |
:reduce="cat => cat.patron_category_id" |
65 |
:reduce="cat => cat.patron_category_id" |
| 60 |
:options="categories" |
66 |
:options="categories" |
|
Lines 63-71
Link Here
|
| 63 |
> |
69 |
> |
| 64 |
<template #search="{ attributes, events }"> |
70 |
<template #search="{ attributes, events }"> |
| 65 |
<input |
71 |
<input |
| 66 |
:required=" |
72 |
:required="!newRule.patron_category_id" |
| 67 |
!circRuleTrigger.patron_category_id |
|
|
| 68 |
" |
| 69 |
class="vs__search" |
73 |
class="vs__search" |
| 70 |
v-bind="attributes" |
74 |
v-bind="attributes" |
| 71 |
v-on="events" |
75 |
v-on="events" |
|
Lines 80-86
Link Here
|
| 80 |
> |
84 |
> |
| 81 |
<v-select |
85 |
<v-select |
| 82 |
id="item_type_id" |
86 |
id="item_type_id" |
| 83 |
v-model="circRuleTrigger.item_type_id" |
87 |
v-model="newRule.item_type_id" |
| 84 |
label="description" |
88 |
label="description" |
| 85 |
:reduce="type => type.item_type_id" |
89 |
:reduce="type => type.item_type_id" |
| 86 |
:options="itemTypes" |
90 |
:options="itemTypes" |
|
Lines 89-97
Link Here
|
| 89 |
> |
93 |
> |
| 90 |
<template #search="{ attributes, events }"> |
94 |
<template #search="{ attributes, events }"> |
| 91 |
<input |
95 |
<input |
| 92 |
:required=" |
96 |
:required="!newRule.item_type_id" |
| 93 |
!circRuleTrigger.item_type_id |
|
|
| 94 |
" |
| 95 |
class="vs__search" |
97 |
class="vs__search" |
| 96 |
v-bind="attributes" |
98 |
v-bind="attributes" |
| 97 |
v-on="events" |
99 |
v-on="events" |
|
Lines 106-113
Link Here
|
| 106 |
</label> |
108 |
</label> |
| 107 |
<input |
109 |
<input |
| 108 |
id="overdue_delay" |
110 |
id="overdue_delay" |
| 109 |
v-model="circRuleTrigger.delay" |
111 |
v-model="newRule.delay" |
| 110 |
type="number" |
112 |
type="number" |
|
|
113 |
:placeholder="fallbackRule.delay" |
| 114 |
:min="minDelay" |
| 111 |
/> |
115 |
/> |
| 112 |
</li> |
116 |
</li> |
| 113 |
<li> |
117 |
<li> |
|
Lines 116-122
Link Here
|
| 116 |
> |
120 |
> |
| 117 |
<v-select |
121 |
<v-select |
| 118 |
id="letter_code" |
122 |
id="letter_code" |
| 119 |
v-model="circRuleTrigger.notice" |
123 |
v-model="newRule.notice" |
| 120 |
label="name" |
124 |
label="name" |
| 121 |
:reduce="type => type.code" |
125 |
:reduce="type => type.code" |
| 122 |
:options="letters" |
126 |
:options="letters" |
|
Lines 126-142
Link Here
|
| 126 |
class="vs__search" |
130 |
class="vs__search" |
| 127 |
v-bind="attributes" |
131 |
v-bind="attributes" |
| 128 |
v-on="events" |
132 |
v-on="events" |
|
|
133 |
:placeholder=" |
| 134 |
letters.find( |
| 135 |
letter => |
| 136 |
letter.code === |
| 137 |
fallbackRule.notice |
| 138 |
)?.name || fallbackRule.notice |
| 139 |
" |
| 129 |
/> |
140 |
/> |
| 130 |
</template> |
141 |
</template> |
| 131 |
</v-select> |
142 |
</v-select> |
| 132 |
</li> |
143 |
</li> |
| 133 |
<li> |
144 |
<li |
|
|
145 |
v-if=" |
| 146 |
newRule.notice !== '' || |
| 147 |
((newRule.notice === null || |
| 148 |
newRule.notice === undefined) && |
| 149 |
fallbackRule.notice !== '') |
| 150 |
" |
| 151 |
> |
| 134 |
<label for="mtt" |
152 |
<label for="mtt" |
| 135 |
>{{ $__("Transport type(s)") }}:</label |
153 |
>{{ $__("Transport type(s)") }}:</label |
| 136 |
> |
154 |
> |
| 137 |
<v-select |
155 |
<v-select |
| 138 |
id="mtt" |
156 |
id="mtt" |
| 139 |
v-model="circRuleTrigger.mtt" |
157 |
v-model="newRule.mtt" |
| 140 |
label="name" |
158 |
label="name" |
| 141 |
:reduce="type => type.code" |
159 |
:reduce="type => type.code" |
| 142 |
:options="mtts" |
160 |
:options="mtts" |
|
Lines 147-152
Link Here
|
| 147 |
class="vs__search" |
165 |
class="vs__search" |
| 148 |
v-bind="attributes" |
166 |
v-bind="attributes" |
| 149 |
v-on="events" |
167 |
v-on="events" |
|
|
168 |
:placeholder=" |
| 169 |
newRule.mtt === null || |
| 170 |
newRule.mtt === undefined || |
| 171 |
newRule.mtt.length === 0 |
| 172 |
? fallbackRule.mtt |
| 173 |
: '' |
| 174 |
" |
| 150 |
/> |
175 |
/> |
| 151 |
</template> |
176 |
</template> |
| 152 |
</v-select> |
177 |
</v-select> |
|
Lines 155-168
Link Here
|
| 155 |
<label for="restricts" |
180 |
<label for="restricts" |
| 156 |
>{{ $__("Restricts checkouts") }}:</label |
181 |
>{{ $__("Restricts checkouts") }}:</label |
| 157 |
> |
182 |
> |
| 158 |
<input |
183 |
<div> |
| 159 |
type="checkbox" |
184 |
<input |
| 160 |
id="restricts" |
185 |
type="radio" |
| 161 |
:checked="false" |
186 |
id="restricts-yes" |
| 162 |
true-value="1" |
187 |
v-model="newRule.restrict" |
| 163 |
false-value="0" |
188 |
:value="1" |
| 164 |
v-model="circRuleTrigger.restrict" |
189 |
/> |
| 165 |
/> |
190 |
{{ $__("Yes") }} |
|
|
191 |
|
| 192 |
<input |
| 193 |
type="radio" |
| 194 |
id="restricts-no" |
| 195 |
v-model="newRule.restrict" |
| 196 |
:value="0" |
| 197 |
/> |
| 198 |
{{ $__("No") }} |
| 199 |
|
| 200 |
<input |
| 201 |
type="radio" |
| 202 |
id="restricts-fallback" |
| 203 |
v-model="newRule.restrict" |
| 204 |
:value="null" |
| 205 |
/> |
| 206 |
{{ $__("Fallback to default") }} |
| 207 |
<span v-if="fallbackRule.restricts !== null"> |
| 208 |
({{ |
| 209 |
fallbackRule.restricts === 1 |
| 210 |
? $__("Yes") |
| 211 |
: $__("No") |
| 212 |
}}) |
| 213 |
</span> |
| 214 |
</div> |
| 166 |
</li> |
215 |
</li> |
| 167 |
</ol> |
216 |
</ol> |
| 168 |
</fieldset> |
217 |
</fieldset> |
|
Lines 209-231
export default {
Link Here
|
| 209 |
categories: null, |
258 |
categories: null, |
| 210 |
itemTypes: null, |
259 |
itemTypes: null, |
| 211 |
circRules: [], |
260 |
circRules: [], |
| 212 |
circRuleTrigger: { |
261 |
newRule: { |
| 213 |
item_type_id: "*", |
262 |
item_type_id: "*", |
| 214 |
library_id: "*", |
263 |
library_id: "*", |
| 215 |
patron_category_id: "*", |
264 |
patron_category_id: "*", |
| 216 |
delay: null, |
265 |
delay: null, |
| 217 |
notice: null, |
266 |
notice: null, |
| 218 |
mtt: null, |
267 |
mtt: null, |
| 219 |
restrict: "0", |
268 |
restrict: null, |
| 220 |
}, |
269 |
}, |
| 221 |
effectiveRule: { |
270 |
fallbackRule: { |
| 222 |
item_type_id: "*", |
271 |
item_type_id: "*", |
| 223 |
library_id: "*", |
272 |
library_id: "*", |
| 224 |
patron_category_id: "*", |
273 |
patron_category_id: "*", |
| 225 |
delay: null, |
274 |
delay: null, |
| 226 |
notice: null, |
275 |
notice: null, |
| 227 |
mtt: null, |
276 |
mtt: null, |
| 228 |
restrict: "0", |
277 |
restrict: null, |
| 229 |
}, |
278 |
}, |
| 230 |
newTriggerNumber: 1, |
279 |
newTriggerNumber: 1, |
| 231 |
mtts: [ |
280 |
mtts: [ |
|
Lines 239-306
export default {
Link Here
|
| 239 |
fine: null, |
288 |
fine: null, |
| 240 |
chargeperiod: null, |
289 |
chargeperiod: null, |
| 241 |
lengthunit: null, |
290 |
lengthunit: null, |
|
|
291 |
numberOfTriggers: null, |
| 242 |
}, |
292 |
}, |
| 243 |
editMode: false, |
293 |
editMode: false, |
| 244 |
ruleBeingEdited: null, |
294 |
ruleBeingEdited: null, |
|
|
295 |
triggerBeingEdited: null, |
| 245 |
}; |
296 |
}; |
| 246 |
}, |
297 |
}, |
| 247 |
beforeRouteEnter(to, from, next) { |
298 |
beforeRouteEnter(to, from, next) { |
| 248 |
next(vm => { |
299 |
next(vm => { |
| 249 |
vm.getLibraries().then(() => |
300 |
vm.getLibraries().then(() => |
| 250 |
vm.getCategories().then(() => |
301 |
vm.getCategories().then(() => |
| 251 |
vm.getItemTypes().then(() => { |
302 |
vm.getItemTypes().then(() => |
| 252 |
const { query } = to; |
303 |
vm.getCircRules().then(() => { |
| 253 |
vm.checkForExistingRules(query).then( |
304 |
const { query } = to; |
| 254 |
() => (vm.initialized = true) |
305 |
vm.checkForExistingRules(query).then( |
| 255 |
); |
306 |
() => (vm.initialized = true) |
| 256 |
}) |
307 |
); |
|
|
308 |
}) |
| 309 |
) |
| 257 |
) |
310 |
) |
| 258 |
); |
311 |
); |
| 259 |
}); |
312 |
}); |
| 260 |
}, |
313 |
}, |
|
|
314 |
computed: { |
| 315 |
minDelay() { |
| 316 |
const lastRule = this.circRules[this.newTriggerNumber - 2]; |
| 317 |
return lastRule |
| 318 |
? parseInt( |
| 319 |
lastRule[`overdue_${this.newTriggerNumber - 1}_delay`] |
| 320 |
) + 1 |
| 321 |
: 0; |
| 322 |
}, |
| 323 |
}, |
| 261 |
methods: { |
324 |
methods: { |
| 262 |
async addCircRule(e) { |
325 |
async addCircRule(e) { |
| 263 |
e.preventDefault(); |
326 |
e.preventDefault(); |
| 264 |
|
327 |
|
| 265 |
const context = { |
328 |
const context = { |
| 266 |
library_id: this.circRuleTrigger.library_id || "*", |
329 |
library_id: this.newRule.library_id || "*", |
| 267 |
item_type_id: this.circRuleTrigger.item_type_id || "*", |
330 |
item_type_id: this.newRule.item_type_id || "*", |
| 268 |
patron_category_id: |
331 |
patron_category_id: this.newRule.patron_category_id || "*", |
| 269 |
this.circRuleTrigger.patron_category_id || "*", |
|
|
| 270 |
}; |
332 |
}; |
| 271 |
|
333 |
|
| 272 |
const delay = |
|
|
| 273 |
this.circRuleTrigger.delay === this.effectiveRule.delay |
| 274 |
? null |
| 275 |
: this.circRuleTrigger.delay; |
| 276 |
const notice = |
| 277 |
this.circRuleTrigger.notice === this.effectiveRule.notice |
| 278 |
? null |
| 279 |
: this.circRuleTrigger.notice; |
| 280 |
const restrict = |
| 281 |
this.circRuleTrigger.restrict === this.effectiveRule.restrict |
| 282 |
? null |
| 283 |
: this.circRuleTrigger.restrict; |
| 284 |
const mtt = |
| 285 |
this.circRuleTrigger.mtt.join(",") === |
| 286 |
this.effectiveRule.mtt.join(",") |
| 287 |
? null |
| 288 |
: this.circRuleTrigger.mtt.join(","); |
| 289 |
|
| 290 |
const circRule = { |
334 |
const circRule = { |
| 291 |
context, |
335 |
context, |
| 292 |
}; |
336 |
}; |
| 293 |
circRule[`overdue_${this.newTriggerNumber}_delay`] = delay; |
337 |
circRule[`overdue_${this.newTriggerNumber}_delay`] = |
| 294 |
circRule[`overdue_${this.newTriggerNumber}_notice`] = notice; |
338 |
this.newRule.delay; |
| 295 |
circRule[`overdue_${this.newTriggerNumber}_restrict`] = restrict; |
339 |
circRule[`overdue_${this.newTriggerNumber}_notice`] = |
| 296 |
circRule[`overdue_${this.newTriggerNumber}_mtt`] = mtt; |
340 |
this.newRule.notice; |
| 297 |
|
341 |
circRule[`overdue_${this.newTriggerNumber}_restrict`] = |
| 298 |
if (this.editMode) { |
342 |
this.newRule.restrict; |
| 299 |
Object.keys(circRule).forEach(key => { |
343 |
circRule[`overdue_${this.newTriggerNumber}_mtt`] = |
| 300 |
if (key === "context") return; |
344 |
this.newRule.mtt && this.newRule.mtt.length |
| 301 |
if (!circRule[key]) delete circRule[key]; |
345 |
? this.newRule.mtt.join(",") |
| 302 |
}); |
346 |
: null; |
| 303 |
} |
|
|
| 304 |
|
347 |
|
| 305 |
const client = APIClient.circRule; |
348 |
const client = APIClient.circRule; |
| 306 |
await client.circRules.update(circRule).then( |
349 |
await client.circRules.update(circRule).then( |
|
Lines 354-359
export default {
Link Here
|
| 354 |
error => {} |
397 |
error => {} |
| 355 |
); |
398 |
); |
| 356 |
}, |
399 |
}, |
|
|
400 |
async getCircRules() { |
| 401 |
const client = APIClient.circRule; |
| 402 |
await client.circRules.getAll({}, { effective: false }).then( |
| 403 |
rules => { |
| 404 |
const { rulesPerTrigger } = |
| 405 |
this.splitCircRulesByTriggerNumber(rules); |
| 406 |
this.circRules = rulesPerTrigger.length |
| 407 |
? rulesPerTrigger |
| 408 |
: rules; |
| 409 |
}, |
| 410 |
error => {} |
| 411 |
); |
| 412 |
}, |
| 357 |
async handleContextChange() { |
413 |
async handleContextChange() { |
| 358 |
await this.checkForExistingRules(); |
414 |
await this.checkForExistingRules(); |
| 359 |
}, |
415 |
}, |
|
Lines 362-456
export default {
Link Here
|
| 362 |
const editMode = routeParams && routeParams.triggerNumber; |
418 |
const editMode = routeParams && routeParams.triggerNumber; |
| 363 |
if (editMode) { |
419 |
if (editMode) { |
| 364 |
this.editMode = editMode; |
420 |
this.editMode = editMode; |
| 365 |
this.ruleBeingEdited = routeParams.triggerNumber; |
421 |
this.triggerBeingEdited = routeParams.triggerNumber; |
| 366 |
} |
422 |
} |
| 367 |
const library_id = |
423 |
const library_id = |
| 368 |
routeParams && routeParams.library_id |
424 |
routeParams && routeParams.library_id |
| 369 |
? routeParams.library_id |
425 |
? routeParams.library_id |
| 370 |
: this.circRuleTrigger.library_id || "*"; |
426 |
: this.newRule.library_id || "*"; |
| 371 |
const item_type_id = |
427 |
const item_type_id = |
| 372 |
routeParams && routeParams.item_type_id |
428 |
routeParams && routeParams.item_type_id |
| 373 |
? routeParams.item_type_id |
429 |
? routeParams.item_type_id |
| 374 |
: this.circRuleTrigger.item_type_id || "*"; |
430 |
: this.newRule.item_type_id || "*"; |
| 375 |
const patron_category_id = |
431 |
const patron_category_id = |
| 376 |
routeParams && routeParams.patron_category_id |
432 |
routeParams && routeParams.patron_category_id |
| 377 |
? routeParams.patron_category_id |
433 |
? routeParams.patron_category_id |
| 378 |
: this.circRuleTrigger.patron_category_id || "*"; |
434 |
: this.newRule.patron_category_id || "*"; |
| 379 |
const params = { |
435 |
const params = { |
| 380 |
library_id, |
436 |
library_id, |
| 381 |
item_type_id, |
437 |
item_type_id, |
| 382 |
patron_category_id, |
438 |
patron_category_id, |
| 383 |
}; |
439 |
}; |
| 384 |
|
440 |
|
|
|
441 |
// Fetch effective ruleset for context |
| 385 |
const client = APIClient.circRule; |
442 |
const client = APIClient.circRule; |
| 386 |
await client.circRules.getAll({}, params).then( |
443 |
await client.circRules.getAll({}, params).then( |
| 387 |
rules => { |
444 |
rules => { |
| 388 |
if (rules.length === 0) { |
445 |
this.ruleBeingEdited = rules[0]; |
| 389 |
this.newTriggerNumber = 1; |
446 |
this.ruleBeingEdited.context = params; |
| 390 |
} else { |
447 |
const regex = /overdue_(\d+)_delay/g; |
| 391 |
const { rulesPerTrigger } = |
448 |
const numberOfTriggers = Object.keys(rules[0]).filter( |
| 392 |
this.splitCircRulesByTriggerNumber(rules); |
449 |
key => regex.test(key) && rules[0][key] !== null |
| 393 |
this.circRules = rulesPerTrigger; |
450 |
).length; |
| 394 |
this.ruleInfo = { |
451 |
const splitRules = this.filterCircRulesByContext( |
| 395 |
issuelength: rules[0].issuelength, |
452 |
this.ruleBeingEdited |
| 396 |
decreaseloanholds: rules[0].decreaseloanholds, |
453 |
); |
| 397 |
fine: rules[0].fine, |
454 |
this.newTriggerNumber = editMode |
| 398 |
chargeperiod: rules[0].chargeperiod, |
455 |
? routeParams.triggerNumber |
| 399 |
lengthunit: rules[0].lengthunit, |
456 |
: numberOfTriggers + 1; |
| 400 |
}; |
457 |
this.assignTriggerValues( |
| 401 |
} |
458 |
splitRules, |
|
|
459 |
this.newTriggerNumber, |
| 460 |
params |
| 461 |
); |
| 462 |
|
| 463 |
this.ruleInfo = { |
| 464 |
issuelength: rules[0].issuelength, |
| 465 |
decreaseloanholds: rules[0].decreaseloanholds, |
| 466 |
fine: rules[0].fine, |
| 467 |
chargeperiod: rules[0].chargeperiod, |
| 468 |
lengthunit: rules[0].lengthunit, |
| 469 |
numberOfTriggers: numberOfTriggers, |
| 470 |
}; |
| 402 |
}, |
471 |
}, |
| 403 |
error => {} |
472 |
error => {} |
| 404 |
); |
473 |
); |
|
|
474 |
}, |
| 475 |
filterCircRulesByContext(effectiveRule) { |
| 476 |
const context = effectiveRule.context; |
| 405 |
|
477 |
|
| 406 |
params.effective = false; |
478 |
// Filter rules that match the context |
| 407 |
await client.circRules.getAll({}, params).then( |
479 |
let contextRules = this.circRules.filter(rule => { |
| 408 |
rules => { |
480 |
return Object.keys(context).every(key => { |
| 409 |
if (rules.length === 0) { |
481 |
return context[key] === rule.context[key]; |
| 410 |
this.newTriggerNumber = 1; |
482 |
}); |
|
|
483 |
}); |
| 411 |
|
484 |
|
| 412 |
this.assignTriggerValues( |
485 |
// Calculate the number of 'overdue_X_' triggers in the effectiveRule |
| 413 |
"circRuleTrigger", |
486 |
const regex = /overdue_(\d+)_delay/g; |
| 414 |
this.circRules, |
487 |
const numberOfTriggers = Object.keys(effectiveRule).filter( |
| 415 |
this.newTriggerNumber, |
488 |
key => regex.test(key) && effectiveRule[key] !== null |
| 416 |
params |
489 |
).length; |
| 417 |
); |
490 |
|
| 418 |
this.assignTriggerValues( |
491 |
// Ensure there is one contextRule per 'X' from 1 to numberOfTriggers |
| 419 |
"effectiveRule", |
492 |
for (let i = 1; i <= numberOfTriggers; i++) { |
| 420 |
this.circRules, |
493 |
// Check if there's already a rule for overdue_X_ in contextRules |
| 421 |
this.newTriggerNumber, |
494 |
const matchingRule = contextRules.find( |
| 422 |
params |
495 |
rule => rule[`overdue_${i}_delay`] !== undefined |
| 423 |
); |
496 |
); |
| 424 |
} else { |
497 |
|
| 425 |
const regex = /overdue_(\d+)_delay/g; |
498 |
if (!matchingRule) { |
| 426 |
const numberOfTriggers = Object.keys(rules[0]).filter( |
499 |
// Create a new rule with the same context and null overdue_X_* keys |
| 427 |
key => regex.test(key) && rules[0][key] !== null |
500 |
const placeholderRule = { |
| 428 |
).length; |
501 |
context: { ...context }, // Clone the context |
| 429 |
this.newTriggerNumber = editMode |
502 |
[`overdue_${i}_delay`]: null, |
| 430 |
? routeParams.triggerNumber |
503 |
[`overdue_${i}_notice`]: null, |
| 431 |
: numberOfTriggers + 1; |
504 |
[`overdue_${i}_mtt`]: null, |
| 432 |
const { rulesPerTrigger } = |
505 |
[`overdue_${i}_restrict`]: null, |
| 433 |
this.splitCircRulesByTriggerNumber(rules); |
506 |
}; |
| 434 |
const triggerToDisplay = editMode |
507 |
|
| 435 |
? routeParams.triggerNumber |
508 |
// Add the new rule to contextRules |
| 436 |
: numberOfTriggers; |
509 |
contextRules.push(placeholderRule); |
| 437 |
this.assignTriggerValues( |
510 |
} |
| 438 |
"circRuleTrigger", |
511 |
} |
| 439 |
rulesPerTrigger, |
512 |
|
| 440 |
triggerToDisplay |
513 |
// Sort contextRules by the 'X' value in 'overdue_X_delay' |
| 441 |
); |
514 |
contextRules.sort((a, b) => { |
| 442 |
this.assignTriggerValues( |
515 |
const getX = rule => { |
| 443 |
"effectiveRule", |
516 |
const match = Object.keys(rule).find(key => |
| 444 |
rulesPerTrigger, |
517 |
regex.test(key) |
| 445 |
triggerToDisplay |
518 |
); |
| 446 |
); |
519 |
return match ? parseInt(match.match(/\d+/)[0], 10) : 0; |
| 447 |
} |
520 |
}; |
| 448 |
}, |
521 |
|
| 449 |
error => {} |
522 |
return getX(a) - getX(b); |
| 450 |
); |
523 |
}); |
|
|
524 |
|
| 525 |
return contextRules; |
| 451 |
}, |
526 |
}, |
| 452 |
assignTriggerValues(prop, rules, triggerNumber, context = null) { |
527 |
findFallbackRule(currentContext, key) { |
| 453 |
this[prop] = { |
528 |
// Filter rules to only those with non-null values for the specified key and not the current context |
|
|
529 |
const relevantRules = this.circRules.filter(rule => { |
| 530 |
return ( |
| 531 |
Object.keys(currentContext).some( |
| 532 |
key => currentContext[key] !== rule.context[key] |
| 533 |
) && |
| 534 |
rule[key] !== null && |
| 535 |
rule[key] !== undefined |
| 536 |
); |
| 537 |
}); |
| 538 |
|
| 539 |
// Function to calculate specificity score |
| 540 |
const getSpecificityScore = ruleContext => { |
| 541 |
let score = 0; |
| 542 |
if ( |
| 543 |
ruleContext.library_id !== "*" && |
| 544 |
ruleContext.library_id === currentContext.library_id |
| 545 |
) |
| 546 |
score += 4; |
| 547 |
if ( |
| 548 |
ruleContext.patron_category_id !== "*" && |
| 549 |
ruleContext.patron_category_id === |
| 550 |
currentContext.patron_category_id |
| 551 |
) |
| 552 |
score += 2; |
| 553 |
if ( |
| 554 |
ruleContext.item_type_id !== "*" && |
| 555 |
ruleContext.item_type_id === currentContext.item_type_id |
| 556 |
) |
| 557 |
score += 1; |
| 558 |
return score; |
| 559 |
}; |
| 560 |
|
| 561 |
// Sort the rules based on specificity score, descending |
| 562 |
const sortedRules = relevantRules.sort((a, b) => { |
| 563 |
return ( |
| 564 |
getSpecificityScore(b.context) - |
| 565 |
getSpecificityScore(a.context) |
| 566 |
); |
| 567 |
}); |
| 568 |
|
| 569 |
// If no rule found, return null |
| 570 |
if (sortedRules.length === 0) { |
| 571 |
return null; |
| 572 |
} |
| 573 |
|
| 574 |
// Get the value from the most specific rule |
| 575 |
const bestRule = sortedRules[0]; |
| 576 |
return bestRule[key]; |
| 577 |
}, |
| 578 |
assignTriggerValues(rules, triggerNumber, context = null) { |
| 579 |
this.newRule = { |
| 454 |
item_type_id: context |
580 |
item_type_id: context |
| 455 |
? context.item_type_id |
581 |
? context.item_type_id |
| 456 |
: rules[triggerNumber - 1].context.item_type_id || "*", |
582 |
: rules[triggerNumber - 1].context.item_type_id || "*", |
|
Lines 461-481
export default {
Link Here
|
| 461 |
? context.patron_category_id |
587 |
? context.patron_category_id |
| 462 |
: rules[triggerNumber - 1].context.patron_category_id || |
588 |
: rules[triggerNumber - 1].context.patron_category_id || |
| 463 |
"*", |
589 |
"*", |
| 464 |
delay: rules[triggerNumber - 1][ |
590 |
delay: rules[triggerNumber - 1] |
|
|
591 |
? rules[triggerNumber - 1][`overdue_${triggerNumber}_delay`] |
| 592 |
: null, |
| 593 |
notice: rules[triggerNumber - 1] |
| 594 |
? rules[triggerNumber - 1][ |
| 595 |
`overdue_${triggerNumber}_notice` |
| 596 |
] |
| 597 |
: null, |
| 598 |
mtt: rules[triggerNumber - 1] |
| 599 |
? rules[triggerNumber - 1][`overdue_${triggerNumber}_mtt`] |
| 600 |
? rules[triggerNumber - 1][ |
| 601 |
`overdue_${triggerNumber}_mtt` |
| 602 |
].split(",") |
| 603 |
: [] |
| 604 |
: null, |
| 605 |
restrict: rules[triggerNumber - 1] |
| 606 |
? rules[triggerNumber - 1][ |
| 607 |
`overdue_${triggerNumber}_restrict` |
| 608 |
] |
| 609 |
: null, |
| 610 |
}; |
| 611 |
this.fallbackRule = { |
| 612 |
delay: this.findFallbackRule( |
| 613 |
context, |
| 465 |
`overdue_${triggerNumber}_delay` |
614 |
`overdue_${triggerNumber}_delay` |
| 466 |
], |
615 |
), |
| 467 |
notice: rules[triggerNumber - 1][ |
616 |
notice: this.findFallbackRule( |
|
|
617 |
context, |
| 468 |
`overdue_${triggerNumber}_notice` |
618 |
`overdue_${triggerNumber}_notice` |
| 469 |
], |
619 |
), |
| 470 |
mtt: rules[triggerNumber - 1][`overdue_${triggerNumber}_mtt`] |
620 |
mtt: this.findFallbackRule( |
| 471 |
? rules[triggerNumber - 1][ |
621 |
context, |
| 472 |
`overdue_${triggerNumber}_mtt` |
622 |
`overdue_${triggerNumber}_mtt` |
| 473 |
].split(",") |
623 |
), |
| 474 |
: [], |
624 |
restrict: this.findFallbackRule( |
| 475 |
restrict: |
625 |
context, |
| 476 |
rules[triggerNumber - 1][ |
626 |
`overdue_${triggerNumber}_restrict` |
| 477 |
`overdue_${triggerNumber}_restrict` |
627 |
), |
| 478 |
], |
|
|
| 479 |
}; |
628 |
}; |
| 480 |
}, |
629 |
}, |
| 481 |
}, |
630 |
}, |