From 2c7d49828c2831eece9450cafc2d7b69cfb377b0 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Mon, 8 Sep 2025 18:47:01 +0100 Subject: [PATCH] Bug 3492: Add hold fees to circulation rules system This commit integrates hold fee configuration into the main circulation rules system, providing granular control over hold fees based on patron category, item type, and branch combinations. Changes: - Add hold_fee as a new circulation rule type with full scope support - Remove deprecated reservefee column mapping from Koha::Patron::Category - Integrate hold fee input into the circulation rules admin interface - Add hold fee column to the main circulation rules matrix - Enable proper rule hierarchy resolution for hold fees Hold fees can now be configured at multiple levels with automatic fallback handling following standard circulation rule patterns. Sponsored-by: OpenFifth Signed-off-by: Jackie Usher --- Koha/CirculationRules.pm | 4 ++++ Koha/Patron/Category.pm | 1 - admin/smart-rules.pl | 3 +++ .../prog/en/modules/admin/smart-rules.tt | 13 ++++++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Koha/CirculationRules.pm b/Koha/CirculationRules.pm index b0b2bd00c2b..dc599d5f7df 100644 --- a/Koha/CirculationRules.pm +++ b/Koha/CirculationRules.pm @@ -86,6 +86,10 @@ our $RULE_KINDS = { scope => [ 'branchcode', 'categorycode' ], is_monetary => 1, }, + hold_fee => { + scope => [ 'branchcode', 'categorycode', 'itemtype' ], + is_monetary => 1, + }, open_article_requests_limit => { scope => [ 'branchcode', 'categorycode' ], }, diff --git a/Koha/Patron/Category.pm b/Koha/Patron/Category.pm index 772df75497d..cc78f750e1d 100644 --- a/Koha/Patron/Category.pm +++ b/Koha/Patron/Category.pm @@ -311,7 +311,6 @@ sub to_api_mapping { dateofbirthrequired => 'lower_age_limit', enrolmentfee => 'enrolment_fee', overduenoticerequired => 'overdue_notice_required', - reservefee => 'reserve_fee', hidelostitems => 'hide_lost_items', category_type => 'category_type', BlockExpiredPatronOpacActions => 'block_expired_patron_opac_actions', diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl index 7f5448f511c..0598307b0ee 100755 --- a/admin/smart-rules.pl +++ b/admin/smart-rules.pl @@ -121,6 +121,7 @@ if ( $op eq 'cud-delete' ) { recall_shelf_time => undef, decreaseloanholds => undef, holds_pickup_period => undef, + hold_fee => undef, } } ); @@ -318,6 +319,7 @@ elsif ( $op eq 'cud-add' ) { my $recall_overdue_fine = $input->param('recall_overdue_fine'); my $recall_shelf_time = $input->param('recall_shelf_time'); my $holds_pickup_period = strip_non_numeric( scalar $input->param('holds_pickup_period') ); + my $hold_fee = $input->param('hold_fee') || q{}; my $rules = { maxissueqty => $maxissueqty, @@ -361,6 +363,7 @@ elsif ( $op eq 'cud-add' ) { recall_overdue_fine => $recall_overdue_fine, recall_shelf_time => $recall_shelf_time, holds_pickup_period => $holds_pickup_period, + hold_fee => $hold_fee, }; Koha::CirculationRules->set_rules( diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt index a1b9d79a41e..4461752757e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt @@ -156,6 +156,7 @@ On shelf holds allowed OPAC item level holds Holds pickup period (day) + Hold fee [% IF Koha.Preference('ArticleRequests') %] Article requests [% END %] @@ -218,8 +219,9 @@ [% SET recall_overdue_fine = all_rules.$c.$i.recall_overdue_fine %] [% SET recall_shelf_time = all_rules.$c.$i.recall_shelf_time %] [% SET holds_pickup_period = all_rules.$c.$i.holds_pickup_period %] + [% SET hold_fee = all_rules.$c.$i.hold_fee %] - [% SET show_rule = note || maxissueqty || maxonsiteissueqty || issuelength || daysmode || lengthunit || hardduedate || hardduedatecompare || fine || chargeperiod || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || expire_reserves_charge || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed || unseenrenewalsallowed || renewalperiod || norenewalbefore || noautorenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || rentaldiscount || decreaseloanholds || recalls_allowed || recalls_per_record || on_shelf_recalls || recall_due_date_interval || recall_overdue_fine || recall_shelf_time || holds_pickup_period %] + [% SET show_rule = note || maxissueqty || maxonsiteissueqty || issuelength || daysmode || lengthunit || hardduedate || hardduedatecompare || fine || chargeperiod || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || expire_reserves_charge || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed || unseenrenewalsallowed || renewalperiod || norenewalbefore || noautorenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || rentaldiscount || decreaseloanholds || recalls_allowed || recalls_per_record || on_shelf_recalls || recall_due_date_interval || recall_overdue_fine || recall_shelf_time || holds_pickup_period || hold_fee %] [% IF show_rule %] [% SET row_count = row_count + 1 %] @@ -412,6 +414,13 @@ [% holds_pickup_period | html %] [% END %] + + [% IF hold_fee.defined && hold_fee != '' %] + [% hold_fee | $Price %] + [% ELSE %] + 0.00 + [% END %] + [% IF Koha.Preference('ArticleRequests') %] [% IF article_requests == 'no' %] @@ -565,6 +574,7 @@ + [% IF Koha.Preference('ArticleRequests') %]