1 Domain overview
Overdue loans has to be automatically marked as lost (i.e. Aged to lost) depending on certain lost item policy properties. Lost item and Lost item processing fees have to be charged from the borrower, with amounts that are configured in the lost item policy.
These policy properties are:
itemAgedLostOverdue - defines interval, after exceeding since due date, loan is marked as aged to lost;
patronBilledAfterAgedLost - defines when lost fees will be billed from patron;
chargeAmountItemSystem - defines if lost item processing fee is charged or not;
- lostItemProcessingFee - amount of lost item processing fee to charge;
- chargeAmountItem - amount of lost item fee to charge (can be actual cost - not implemented and set cost - fixed amount).
2 Solution overview
We need two scheduled jobs: /circulation/scheduled-age-to-lost and /circulation/scheduled-age-to-lost-fee-charging. The first job is responsible for marking overdue items as Aged to lost and updating loan with date and time when lost fees have to be charged. The second job assigns Lost item and Lost item processing fees per lost item fee policy, and sets lostItemHasBeenBilled = true.
The job that marks items can be triggered every 30 mins (Holly Mistlebauer to confirm) and the second job, that assigns fees, can be executed every 35 mins (in this case we will assigns fees for newly marked items).
3 Age to lost scheduled job
This job is triggered each 30 mins and only marks overdue items as Aged to lost. The job has been limited to 1000 loans to process per run. If there are more than 1000 loans that matches the criteria, they will be processed during the next run. This needed to reduce load on circulation app and whole block of the app. Loans with earlier due date takes priority.
Here is the overall algorithm for the job.
4 Assign fees scheduled job
This job is triggered each 35 mins and assigns lost fees for aged to lost loans with dateLostItemShouldBeBilled < sysDate. The job has been limited to 1000 loans to process per run. If there are more than 1000 loans that matches the criteria, they will be processed during the next run. This needed to reduce load on circulation app and whole block of the app. Loans with earlier dateLostItemShouldBeBilled takes priority.
Here is the overall algorithm for the job.
Q: If overdueMinutes is 7,886 minutes, that will be 5.48 days. The result needs to be rounded up in all cases, making it 6 days. Is it always round up? Or if < 0.5 down, otherwise - round up?
A: Overdues always get rounded up.
Q: What value for Created at should be for fees?
A: Per Jira requirements it should be blank.
Q: How often the jobs should be triggered?
A: Current decision: once per 30 mins for aged to lost job and once per 35 mins for assign fees job. Holly Mistlebauer to confirm.
Q: What will happen if there is no fee/fine owner for the given item or no fee/fine type (either Lost item fee or Lost item processing fee)?
A: No fees assigned, the exceptional situation is logged, however the end-user won't give any feedback.
Q: What happens if 'Items aged to lost after overdue interval' is not defined?
A: In this case the feature is turned off for the loan.
Q: What happens if multiple instances of the jobs overlap?
A: If these two jobs updates same loan than the loan will be updated twice. But if the fee assign job overlaps, and they process the same loan, than fee/fines will be assigned twice. But it is possible to cancel the fees using UI.
>But if the fee assign job overlaps, and they process the same loan, than fee/fines will be assigned twice. But it is possible to cancel the fees using UI.
Point about the quote above. In case of the large number (more than 50?) it will be inconvenient to cancel them one by one on the UI. Are there suggestions on this?
Yep, agree. However there is no need to go through all of the overcharges and cancel them all at once, because anyway the patron should go to the library and pay for the fee and the librarian here can cancel overcharged amount as well as resolve paid amount.
But I do believe that such job overlapping is close to impossible. Even if there will be more than 1 mod-circulation instance deployed, okapi should not notify all of the instances on timer, but use e.g. round-robin algorithm to pick an instance that will be serving the request.
If it becomes a real issue, we will probably need something like pessimistic locking for loans or for the entire process itself.