From 0d1ef7c7e0f22ab33e211344a58eca70cc9d8896 Mon Sep 17 00:00:00 2001
From: miker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Date: Thu, 10 Jun 2010 19:15:13 +0000
Subject: [PATCH] Trunk port of a patch from James Fournie of SITKA:

There was some discussion about problems with holds fulfillment at the
holds roundtable at EG2010.  I am pleased to share this patch with the
community which has been thoroughly tested by the folks at
Thompson-Nicola Regional District Library.  (thanks guys!)

Background:

Evergreen's default out-of-the-box behaviour for holds fulfillment is
a gas-saving method.  Holds are fulfilled by proximity.  In a
multibranch library, holds are fulfilled at the local branch first.
Many libraries, particularly single branch libraries may be ok with
this, but it may be problematic for other libraries.

Imagine a scenario where you have a large central branch and a small
rural branch of the same library system.  At the large branch, there
are many copies of Popular New DVD with lots of holds.   There are no
copies at the rural branch.  Patrons at the small rural branch who
want to pick up Popular New DVD at their home branch may never get
their hold fulfilled because the copies will stay at the large branch
as long as there are holds for pickup there.

This patch adds an org unit setting that changes the opportunistic
check-in so that items checked in will be assigned to holds by request
date first, rather than proximity.   This setting can be applied to
any level of the org tree, so in some situations you may even want to
activate FIFO for large libraries, but leave the original setting for
smaller libraries with less traffic who want to keep their copies more
local.

Also credit to Jeff Godin who thought of the same patch and
contributed the setting name "holds FIFO" for the setting

[ NOTE:  Implications of mixed FIFO and non-FIFO environments that are
not sufficiently segregated by the use of Hard Boundaries for Holds
present a potenial for user confusion.  Beware that mixing FIFO and
non-FIFO settings within a resource-sharing group will likely result in
severe imbalance of hold fulfillment, though further configuration,
development, tuning and testing may be able to mitigate these issues.
 --miker ]



git-svn-id: svn://svn.open-ils.org/ILS/trunk@16659 dcc99617-32d9-48b4-a31d-7c20da2025e4
---
 Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm          | 4 +++-
 .../src/perlmods/OpenILS/Application/Storage/Publisher/action.pm | 7 ++++++-
 Open-ILS/src/sql/Pg/002.schema.config.sql                        | 2 +-
 Open-ILS/src/sql/Pg/950.data.seed-values.sql                     | 5 +++++
 Open-ILS/src/sql/Pg/upgrade/0302.data.fifo-holds-ou-setting.sql  | 9 +++++++++
 5 files changed, 24 insertions(+), 3 deletions(-)
 create mode 100644 Open-ILS/src/sql/Pg/upgrade/0302.data.fifo-holds-ou-setting.sql

diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm
index 2904cb0f49..8e540d132b 100644
--- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm
+++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm
@@ -1971,10 +1971,12 @@ sub find_nearest_permitted_hold {
 	$logger->info("circulator: searching for best hold at org ".$user->ws_ou.
         " and copy $bc with a hold stalling interval of ". ($hold_stall_interval || "(none)"));
 
+	my $fifo = $U->ou_ancestor_setting_value($user->ws_ou, 'circ.hold_fifo');
+
 	# search for what should be the best holds for this copy to fulfill
 	my $best_holds = $U->storagereq(
         "open-ils.storage.action.hold_request.nearest_hold.atomic", 
-		$user->ws_ou, $copy->id, 10, $hold_stall_interval );
+		$user->ws_ou, $copy->id, 10, $hold_stall_interval, $fifo );
 
 	unless(@$best_holds) {
 
diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm
index 6df974ed0d..315a7bc2d2 100644
--- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm
+++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm
@@ -283,6 +283,11 @@ sub nearest_hold {
 	my $cp = shift;
 	my $limit = int(shift()) || 10;
 	my $age = shift() || '0 seconds';
+	my $fifo = shift();
+
+	my $holdsort = isTrue($fifo) ?
+            "CASE WHEN h.cut_in_line IS TRUE THEN 0 ELSE 1 END, h.request_time, h.selection_depth DESC, p.prox " :
+            "p.prox, CASE WHEN h.cut_in_line IS TRUE THEN 0 ELSE 1 END, h.selection_depth DESC, h.request_time ";
 
 	my $ids = action::hold_request->db_Main->selectcol_arrayref(<<"	SQL", {}, $here, $cp, $age);
 		SELECT	h.id
@@ -295,7 +300,7 @@ sub nearest_hold {
 		  	AND h.cancel_time IS NULL
 		  	AND (h.expire_time IS NULL OR h.expire_time > NOW())
             AND h.frozen IS FALSE
-		ORDER BY
+		ORDER BY $holdsort
 			p.prox,
             CASE WHEN h.cut_in_line IS TRUE THEN 0 ELSE 1 END,
 			h.selection_depth DESC,
diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 06207450d2..a6e5e8e798 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -68,7 +68,7 @@ CREATE TABLE config.upgrade_log (
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0301'); -- gmc
+INSERT INTO config.upgrade_log (version) VALUES ('0302'); -- miker
 
 CREATE TABLE config.bib_source (
 	id		SERIAL	PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index 6ffbcfd4a7..7d21bf771f 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -1802,6 +1802,11 @@ INSERT into config.org_unit_setting_type
   'Lost items are usable on checkin instead of going ''home'' first',
   'bool' ),
 
+( 'circ.holds_fifo',
+  'Holds: FIFO',
+  'Force holds to a more strict First-In, First-Out capture',
+  'bool' ),
+
 ( 'opac.allow_pending_address',
   'OPAC: Allow pending addresses',
   'If enabled, patrons can create and edit existing addresses.  Addresses are kept in a pending state until staff approves the changes',
diff --git a/Open-ILS/src/sql/Pg/upgrade/0302.data.fifo-holds-ou-setting.sql b/Open-ILS/src/sql/Pg/upgrade/0302.data.fifo-holds-ou-setting.sql
new file mode 100644
index 0000000000..24662ccda7
--- /dev/null
+++ b/Open-ILS/src/sql/Pg/upgrade/0302.data.fifo-holds-ou-setting.sql
@@ -0,0 +1,9 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0302'); --miker
+
+INSERT INTO config.org_unit_setting_type (name,label,description,datatype)
+    VALUES ('circ.holds_fifo', 'Holds: FIFO', 'Force holds to a more strict First-In, First-Out capture', 'bool' ),
+
+COMMIT;
+
-- 
2.11.0