View | Details | Raw Unified | Return to bug 11126
Collapse All | Expand All

(-)a/C4/Reserves.pm (-7 / +42 lines)
Lines 847-853 sub CheckReserves { Link Here
847
           items.biblioitemnumber,
847
           items.biblioitemnumber,
848
           itemtypes.notforloan,
848
           itemtypes.notforloan,
849
           items.notforloan AS itemnotforloan,
849
           items.notforloan AS itemnotforloan,
850
           items.itemnumber
850
           items.itemnumber,
851
           items.homebranch,
852
           items.holdingbranch
851
           FROM   items
853
           FROM   items
852
           LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
854
           LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
853
           LEFT JOIN itemtypes   ON items.itype   = itemtypes.itemtype
855
           LEFT JOIN itemtypes   ON items.itype   = itemtypes.itemtype
Lines 859-865 sub CheckReserves { Link Here
859
           items.biblioitemnumber,
861
           items.biblioitemnumber,
860
           itemtypes.notforloan,
862
           itemtypes.notforloan,
861
           items.notforloan AS itemnotforloan,
863
           items.notforloan AS itemnotforloan,
862
           items.itemnumber
864
           items.itemnumber,
865
           items.homebranch,
866
           items.holdingbranch
863
           FROM   items
867
           FROM   items
864
           LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
868
           LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
865
           LEFT JOIN itemtypes   ON biblioitems.itemtype   = itemtypes.itemtype
869
           LEFT JOIN itemtypes   ON biblioitems.itemtype   = itemtypes.itemtype
Lines 875-886 sub CheckReserves { Link Here
875
        $sth->execute($barcode);
879
        $sth->execute($barcode);
876
    }
880
    }
877
    # note: we get the itemnumber because we might have started w/ just the barcode.  Now we know for sure we have it.
881
    # note: we get the itemnumber because we might have started w/ just the barcode.  Now we know for sure we have it.
878
    my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item, $itemnumber ) = $sth->fetchrow_array;
882
    my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item,
883
        $itemnumber, $item_homebranch, $item_holdingbranch )
884
      = $sth->fetchrow_array;
879
885
880
    return ( '' ) unless $itemnumber; # bail if we got nothing.
886
    return ( '' ) unless $itemnumber; # bail if we got nothing.
881
887
882
    # if item is not for loan it cannot be reserved either.....
888
    # if item is not for loan it cannot be reserved either.....
883
    #    execpt where items.notforloan < 0 :  This indicates the item is holdable. 
889
    # except where items.notforloan < 0 :  This indicates the item is holdable. 
884
    return ( '' ) if  ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype;
890
    return ( '' ) if  ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype;
885
891
886
    # Find this item in the reserves
892
    # Find this item in the reserves
Lines 892-912 sub CheckReserves { Link Here
892
    # $highest is the most important item we've seen so far.
898
    # $highest is the most important item we've seen so far.
893
    my $highest;
899
    my $highest;
894
    if (scalar @reserves) {
900
    if (scalar @reserves) {
901
        my $LocalHoldsPriority = C4::Context->preference('LocalHoldsPriority');
902
        my $LocalHoldsPriorityPatronControl = C4::Context->preference('LocalHoldsPriorityPatronControl');
903
        my $LocalHoldsPriorityItemControl = C4::Context->preference('LocalHoldsPriorityItemControl');
904
895
        my $priority = 10000000;
905
        my $priority = 10000000;
896
        foreach my $res (@reserves) {
906
        foreach my $res (@reserves) {
897
            if ( $res->{'itemnumber'} == $itemnumber && $res->{'priority'} == 0) {
907
            if ( $res->{'itemnumber'} == $itemnumber && $res->{'priority'} == 0) {
898
                return ( "Waiting", $res, \@reserves ); # Found it
908
                return ( "Waiting", $res, \@reserves ); # Found it
899
            } else {
909
            } else {
910
                # Lazy fetch for borrower and item. We only need to know about the patron and item
911
                # each and every time if we are using LocalHoldsPriority. This is a great place to
912
                # leverage the inherent lazy fetching of DBIx::Class.
913
                my $borrowerinfo; 
914
                my $iteminfo;
915
916
                my $local_hold_match;
917
                if ($LocalHoldsPriority) {
918
                    $borrowerinfo = C4::Members::GetMember( borrowernumber => $res->{'borrowernumber'} );
919
                    $iteminfo = C4::Items::GetItem($itemnumber);
920
921
                    my $local_holds_priority_item_branchcode =
922
                      $iteminfo->{$LocalHoldsPriorityItemControl};
923
                    my $local_holds_priority_patron_branchcode =
924
                      ( $LocalHoldsPriorityPatronControl eq 'PickupLibrary' )
925
                      ? $res->{branchcode}
926
                      : ( $LocalHoldsPriorityPatronControl eq 'HomeLibrary' )
927
                      ? $borrowerinfo->{branchcode}
928
                      : undef;
929
                    $local_hold_match =
930
                      $local_holds_priority_item_branchcode eq
931
                      $local_holds_priority_patron_branchcode;
932
                }
933
900
                # See if this item is more important than what we've got so far
934
                # See if this item is more important than what we've got so far
901
                if ( $res->{'priority'} && $res->{'priority'} < $priority ) {
935
                if ( ( $res->{'priority'} && $res->{'priority'} < $priority ) || $local_hold_match ) {
902
                    my $borrowerinfo=C4::Members::GetMember(borrowernumber => $res->{'borrowernumber'});
936
                    $borrowerinfo ||= C4::Members::GetMember( borrowernumber => $res->{'borrowernumber'} );
903
                    my $iteminfo=C4::Items::GetItem($itemnumber);
937
                    $iteminfo ||= C4::Items::GetItem($itemnumber);
904
                    my $branch = GetReservesControlBranch( $iteminfo, $borrowerinfo );
938
                    my $branch = GetReservesControlBranch( $iteminfo, $borrowerinfo );
905
                    my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$iteminfo->{'itype'});
939
                    my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$iteminfo->{'itype'});
906
                    next if ($branchitemrule->{'holdallowed'} == 0);
940
                    next if ($branchitemrule->{'holdallowed'} == 0);
907
                    next if (($branchitemrule->{'holdallowed'} == 1) && ($branch ne $borrowerinfo->{'branchcode'}));
941
                    next if (($branchitemrule->{'holdallowed'} == 1) && ($branch ne $borrowerinfo->{'branchcode'}));
908
                    $priority = $res->{'priority'};
942
                    $priority = $res->{'priority'};
909
                    $highest  = $res;
943
                    $highest  = $res;
944
                    last if $local_hold_match;
910
                }
945
                }
911
            }
946
            }
912
        }
947
        }
(-)a/installer/data/mysql/sysprefs.sql (+3 lines)
Lines 170-175 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
170
('LinkerOptions','','','A pipe-separated list of options for the linker.','free'),
170
('LinkerOptions','','','A pipe-separated list of options for the linker.','free'),
171
('LinkerRelink','1',NULL,'If ON the authority linker will relink headings that have previously been linked every time it runs.','YesNo'),
171
('LinkerRelink','1',NULL,'If ON the authority linker will relink headings that have previously been linked every time it runs.','YesNo'),
172
('LocalCoverImages','0','1','Display local cover images on intranet details pages.','YesNo'),
172
('LocalCoverImages','0','1','Display local cover images on intranet details pages.','YesNo'),
173
('LocalHoldsPriority',  '0', NULL,  'Enables the LocalHoldsPriority feature',  'YesNo'),
174
('LocalHoldsPriorityItemControl',  'holdingbranch',  'holdingbranch|homebranch',  'decides if the feature operates using the item''s home or holding library.',  'Choice'),
175
('LocalHoldsPriorityPatronControl',  'PickupLibrary',  'HomeLibrary|PickupLibrary',  'decides if the feature operates using the library set as the patron''s home library, or the library set as the pickup library for the given hold.',  'Choice'),
173
('ManInvInNoissuesCharge','1',NULL,'MANUAL_INV charges block checkouts (added to noissuescharge).','YesNo'),
176
('ManInvInNoissuesCharge','1',NULL,'MANUAL_INV charges block checkouts (added to noissuescharge).','YesNo'),
174
('MARCAuthorityControlField008','|| aca||aabn           | a|a     d',NULL,NULL,'Textarea'),
177
('MARCAuthorityControlField008','|| aca||aabn           | a|a     d',NULL,NULL,'Textarea'),
175
('MARCOrgCode','OSt','','Define MARC Organization Code - http://www.loc.gov/marc/organizations/orgshome.html','free'),
178
('MARCOrgCode','OSt','','Define MARC Organization Code - http://www.loc.gov/marc/organizations/orgshome.html','free'),
(-)a/installer/data/mysql/updatedatabase.pl (+12 lines)
Lines 7330-7335 if ( CheckVersion($DBversion) ) { Link Here
7330
    SetVersion($DBversion);
7330
    SetVersion($DBversion);
7331
}
7331
}
7332
7332
7333
$DBversion = "3.13.00.XXX";
7334
if ( CheckVersion($DBversion) ) {
7335
    $dbh->do(q{
7336
        INSERT INTO systempreferences ( variable, value, options, explanation, type ) VALUES 
7337
        ('LocalHoldsPriority',  '0', NULL,  'Enables the LocalHoldsPriority feature',  'YesNo'),
7338
        ('LocalHoldsPriorityItemControl',  'holdingbranch',  'holdingbranch|homebranch',  'decides if the feature operates using the item''s home or holding library.',  'Choice'),
7339
        ('LocalHoldsPriorityPatronControl',  'PickupLibrary',  'HomeLibrary|PickupLibrary',  'decides if the feature operates using the library set as the patron''s home library, or the library set as the pickup library for the given hold.',  'Choice')
7340
    });
7341
    print "Upgrade to $DBversion done (Bug 11126 - Make the holds system optionally give precedence to local holds)\n";
7342
    SetVersion($DBversion);
7343
}
7344
7333
=head1 FUNCTIONS
7345
=head1 FUNCTIONS
7334
7346
7335
=head2 TableExists($table)
7347
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (+15 lines)
Lines 489-494 Circulation: Link Here
489
                  yes: Allow
489
                  yes: Allow
490
                  no: "Don't allow"
490
                  no: "Don't allow"
491
            - a patron to place a hold on a record where the patron already has one or more items attached to that record checked out.
491
            - a patron to place a hold on a record where the patron already has one or more items attached to that record checked out.
492
        -
493
            - pref: LocalHoldsPriority
494
              choices:
495
                  yes: Give
496
                  no: "Don't give"
497
            - priority for filling holds to patrons whose
498
            - pref: LocalHoldsPriorityPatronControl
499
              choices:
500
                  PickupLibrary: "pickup library"
501
                  HomeLibrary: "home library"
502
            - matches the item's
503
            - pref: LocalHoldsPriorityItemControl
504
              choices:
505
                  homebranch: "home library"
506
                  holdingbranch: "holding library"
492
    Fines Policy:
507
    Fines Policy:
493
        -
508
        -
494
            - Calculate fines based on days overdue
509
            - Calculate fines based on days overdue
(-)a/t/db_dependent/Holds/LocalHoldsPriority.t (-1 / +119 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
use strict;
4
use warnings;
5
6
use t::lib::Mocks;
7
use C4::Context;
8
use C4::Branch;
9
10
use Test::More tests => 6;
11
use MARC::Record;
12
use C4::Biblio;
13
use C4::Items;
14
use C4::Members;
15
16
BEGIN {
17
    use FindBin;
18
    use lib $FindBin::Bin;
19
    use_ok('C4::Reserves');
20
}
21
22
my $dbh = C4::Context->dbh;
23
24
# Start transaction
25
$dbh->{AutoCommit} = 0;
26
$dbh->{RaiseError} = 1;
27
28
my $borrowers_count = 5;
29
30
# Setup Test------------------------
31
# Helper biblio.
32
diag("Creating biblio instance for testing.");
33
my ( $bibnum, $title, $bibitemnum ) = create_helper_biblio();
34
35
# Helper item for that biblio.
36
diag("Creating item instance for testing.");
37
my ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
38
  AddItem( { homebranch => 'MPL', holdingbranch => 'CPL' }, $bibnum );
39
40
my @branchcodes = qw{XXX RPL CPL MPL CPL MPL};
41
42
# Create some borrowers
43
diag("Creating borrowers.");
44
my @borrowernumbers;
45
foreach ( 1 .. $borrowers_count ) {
46
    my $borrowernumber = AddMember(
47
        firstname    => 'my firstname',
48
        surname      => 'my surname ' . $_,
49
        categorycode => 'S',
50
        branchcode   => $branchcodes[$_],
51
    );
52
    push @borrowernumbers, $borrowernumber;
53
}
54
55
my $biblionumber = $bibnum;
56
57
my @branches = GetBranchesLoop();
58
my $branch   = $branches[0][0]{value};
59
60
# Create five item level holds
61
diag("Creating holds.");
62
my $i = 1;
63
foreach my $borrowernumber (@borrowernumbers) {
64
    AddReserve(
65
        $branchcodes[$i],
66
        $borrowernumber,
67
        $biblionumber,
68
        my $constraint = 'a',
69
        my $bibitems   = q{},
70
        my $priority = $i,
71
        my $resdate,
72
        my $expdate,
73
        my $notes = q{},
74
        $title,
75
        my $checkitem,
76
        my $found,
77
    );
78
79
    $i++;
80
}
81
82
my ($status, $reserve, $all_reserves);
83
84
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 0 );
85
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
86
ok( $reserve->{borrowernumber} eq $borrowernumbers[0], "Recieved expected results with LocalHoldsPriority disabled" );
87
88
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 1 );
89
90
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'PickupLibrary' );
91
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
92
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
93
ok( $reserve->{borrowernumber} eq $borrowernumbers[2], "Received expected results with PickupLibrary/homebranch" );
94
95
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'PickupLibrary' );
96
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'holdingbranch' );
97
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
98
ok( $reserve->{borrowernumber} eq $borrowernumbers[1], "Received expected results with PickupLibrary/holdingbranch" );
99
100
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
101
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'holdingbranch' );
102
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
103
ok( $reserve->{borrowernumber} eq $borrowernumbers[1], "Received expected results with HomeLibrary/holdingbranch" );
104
105
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
106
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
107
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
108
ok( $reserve->{borrowernumber} eq $borrowernumbers[2], "Received expected results with HomeLibrary/homebranch" );
109
110
# Helper method to set up a Biblio.
111
sub create_helper_biblio {
112
    my $bib   = MARC::Record->new();
113
    my $title = 'Silence in the library';
114
    $bib->append_fields(
115
        MARC::Field->new( '100', ' ', ' ', a => 'Moffat, Steven' ),
116
        MARC::Field->new( '245', ' ', ' ', a => $title ),
117
    );
118
    return ( $bibnum, $title, $bibitemnum ) = AddBiblio( $bib, '' );
119
}

Return to bug 11126