From b524f7b109e3aea8d3a360bba307738cdbeefa1b 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. --- 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 7bae491af56..d48e934041d 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 ab4973b544a..b7aad5f43f5 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 2c1ed57a44f..d0385051dde 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 49301081770..118162419ba 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') %]