diff --git a/Koha/Club/Enrollment.pm b/Koha/Club/Enrollment.pm index 168f55bca6..2b4e627a77 100644 --- a/Koha/Club/Enrollment.pm +++ b/Koha/Club/Enrollment.pm @@ -24,6 +24,8 @@ use Carp; use Koha::Database; use Koha::Clubs; use Koha::Patrons; +use Koha::DateUtils qw(dt_from_string); +use DateTime; use base qw(Koha::Object); @@ -71,6 +73,20 @@ sub patron { return scalar Koha::Patrons->find( $self->borrowernumber() ); } +=head3 is_canceled +Determines if enrollment is canceled +=cut + +sub is_canceled { + my ( $self ) = @_; + + return 0 unless $self->date_canceled; + my $today = dt_from_string; + my $date_canceled = dt_from_string( $self->date_canceled ); + + return DateTime->compare($date_canceled, $today) < 1; +} + =head3 type =cut diff --git a/catalogue/search.pl b/catalogue/search.pl index a3a7015efc..8f460de8e3 100755 --- a/catalogue/search.pl +++ b/catalogue/search.pl @@ -203,6 +203,14 @@ if($cgi->cookie("holdfor")){ ); } +if($cgi->cookie("holdforclub")){ + my $holdfor_club = Koha::Clubs->find( $cgi->cookie("holdforclub") ); + $template->param( + holdforclub => $cgi->cookie("holdforclub"), + holdforclub_name => $holdfor_club->name, + ); +} + # get biblionumbers stored in the cart my @cart_list; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/clubs-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/clubs-table.inc new file mode 100644 index 0000000000..62027b1a38 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/clubs-table.inc @@ -0,0 +1,111 @@ + + + + + + + [% UNLESS destination == 'holds' %] + + + [% END %] + + + + + [% UNLESS destination == 'holds' %] + + [% END %] + + + + [% FOREACH c IN clubs %] + [% IF destination == 'holds' %] + [% IF multi_hold %] + [% SET data_url = "/cgi-bin/koha/reserve/request.pl?club=" _ c.id _ "&multi_hold=1&biblionumbers=" _ biblionumbers %] + [% ELSE %] + [% SET data_url = "/cgi-bin/koha/reserve/request.pl?club=" _ c.id _ "&biblionumber=" _ biblionumber %] + [% END %] + + [% ELSE %] + + [% END %] + + + + [% UNLESS destination == 'holds' %] + + + [% END %] + + + + + [% UNLESS destination == 'holds' %] + + [% END %] + + [% END %] + +
NameTemplateDescriptionPublic enrollmentEmail requiredLibraryStart dateEnd dateEnrolled patrons 
[% c.name | html %][% c.club_template.name | html %][% c.description | html %] + [% IF c.club_template.is_enrollable_from_opac %] + Yes + [% ELSE %] + No + [% END %] + + [% IF c.club_template.is_email_required %] + Yes + [% ELSE %] + No + [% END %] + [% Branches.GetName( c.branchcode ) | html %] + [% IF c.date_start %] + [% c.date_start | $KohaDates %] + [% END %] + + [% IF c.date_end %] + [% c.date_end | $KohaDates %] + [% END %] + + [% c.club_enrollments.count | html %] + + +
\ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt index c8af35f986..3d9bbe9f24 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt @@ -123,7 +123,7 @@ [% END # /IF virtualshelves %] [% IF ( CAN_user_reserveforothers_place_holds && DisplayMultiPlaceHold ) %] - [% IF ( holdfor ) %] + [% IF ( holdfor or holdforclub ) %]
[% ELSE %] @@ -422,6 +429,7 @@ [% IF CAN_user_reserveforothers_place_holds %] Holds ([% Biblio.HoldsCount( SEARCH_RESULT.biblionumber ) | html %]) [% IF ( holdfor ) %] | Place hold for [% holdfor_firstname | html %] [% holdfor_surname | html %] ([% holdfor_cardnumber | html %])[% END %] + [% IF ( holdforclub ) %] | Place hold for [% holdforclub_name | html %][% END %] [% ELSE %] Holds ([% Biblio.HoldsCount( SEARCH_RESULT.biblionumber ) | html %]) [% END %] @@ -617,6 +625,7 @@ + @@ -713,6 +722,7 @@ $("#searchheader").on("click",".placehold", function(){ $("#holdFor").val(""); + $("#holdForClub").val(""); placeHold(); $(".btn-group").removeClass("open"); return false; @@ -724,8 +734,14 @@ return false; }); - $("#forgetholdfor").click(function(){ - forgetPatron(); + $(".placeholdforclub").click(function(){ + holdForClub(); + $(".btn-group").removeClass("open"); + return false; + }); + + $("#forgetholdfor, #forgetholdforclub").click(function(){ + forgetPatronAndClub(); $(".btn-group").removeClass("open"); return false; }); @@ -884,8 +900,9 @@ return false; } - function forgetPatron(){ + function forgetPatronAndClub(){ $.removeCookie("holdfor", { path: '/' }); + $.removeCookie("holdforclub", { path: '/' }); $(".holdforlink").remove(); $("#placeholdc").html(" "+_("Place hold")+""); } @@ -936,6 +953,7 @@ function holdfor(){ $("#holdFor").val(""); + $("#holdForClub").val(""); placeHold(); } @@ -943,6 +961,11 @@ $("#holdFor").val("[% holdfor_cardnumber | html %]"); placeHold(); } + + function holdForClub() { + $("#holdForClub").val("[% holdforclub | html %]"); + placeHold(); + } [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/clubs/clubs.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/clubs/clubs.tt index 42d50ff41c..e4176a9da0 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/clubs/clubs.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/clubs/clubs.tt @@ -120,93 +120,7 @@ [% END %] [% IF clubs %] - - - - - - - - - - - - - - - - - [% FOREACH c IN clubs %] - - - - - - - - - - - - - [% END %] - -
NameTemplateDescriptionPublic enrollmentEmail requiredLibraryStart dateEnd dateEnrolled patrons 
[% c.name | html %][% c.club_template.name | html %][% c.description | html %] - [% IF c.club_template.is_enrollable_from_opac %] - Yes - [% ELSE %] - No - [% END %] - - [% IF c.club_template.is_email_required %] - Yes - [% ELSE %] - No - [% END %] - [% Branches.GetName( c.branchcode ) | html %] - [% IF c.date_start %] - [% c.date_start | $KohaDates %] - [% END %] - - [% IF c.date_end %] - [% c.date_end | $KohaDates %] - [% END %] - - [% c.club_enrollments.count | html %] - - -
+ [% INCLUDE 'clubs-table.inc' %] [% ELSE %] [% IF club_templates %]
No clubs defined.
@@ -282,6 +196,13 @@ }); } } + + function SearchToHold(club_id) { + var date = new Date(); + date.setTime(date.getTime() + (10 * 60 * 1000)); + $.cookie("holdforclub", club_id, { path: "/", expires: date }); + location.href="/cgi-bin/koha/catalogue/search.pl"; + } [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt index 4a046b614b..1cbc7afc6d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -870,7 +870,7 @@ if ( $('#clubs-tab').length ) { $('#clubs-tab-link').on('click', function() { $('#clubs-tab').text(_("Loading...")); - $('#clubs-tab').load('/cgi-bin/koha/clubs/patron-clubs-tab.pl?borrowernumber=[% borrowernumber | html %]'); + $('#clubs-tab').load('/cgi-bin/koha/clubs/patron-clubs-tab.pl?borrowernumber=[% patron.borrowernumber | html %]'); }); } diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt index 91e4ebb6b5..5b0c482c20 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt @@ -73,7 +73,7 @@

Confirm holds

[% END %] - [% UNLESS patron OR patron.borrowernumber OR noitems %] + [% UNLESS club OR patron OR patron.borrowernumber OR noitems %] [% IF ( messageborrower ) %]

Patron not found

@@ -81,30 +81,224 @@
[% END %] -
-
- [% UNLESS borrowers %] - -
Enter patron card number or partial name:
- - - [% IF multi_hold %] - - - [% ELSE %] - + [% IF ( messageclub ) %] +
+

Club not found

+

No club with this name, please, try another

+
+ [% END %] +
+ +
+ +
+
+ +
Enter patron card number or partial name:
+ + + [% IF multi_hold %] + + + [% ELSE %] + + [% END %] + + [% IF ( multi_hold ) %] + + + [% END %] + +
+
+
+
Enter club id or partial name:
+ + + [% IF multi_hold %] + + + [% ELSE %] + + [% END %] + + [% IF ( multi_hold ) %] + + + [% END %] +
+
+
+
+

+ [% IF borrowers %] + [% INCLUDE 'circ-patron-search-results.inc' destination = "holds" %] + [% ELSIF clubs %] + [% INCLUDE 'clubs-table.inc' destination = "holds" %] + [% END %] +

+
+ [% ELSIF club %] +
+
+
+ Hold details +
+ + [% IF ( multi_hold ) %] + + + + + [% FOREACH biblioloo IN biblioloop %] + + [% END %] [% ELSE %] - [% INCLUDE 'circ-patron-search-results.inc' destination = "holds" %] + + + + [% END # /IF multi_hold %] +
    +
  1. + Club: [% club.name | html %] +
  2. +
  3. + Description: [% club.description | html %] +
  4. +
  5. + + +
  6. +
+

Members

+
    + [% FOREACH member IN members %] + [% SET patron = member.patron %] +
  1. + + [% IF member.exceeded_maxreserves %] +
    + + Too many holds: Patron can only place a maximum of [% maxreserves | html %] total holds. +
    + [% END %] + [% IF ( member.expiry ) %] +
    + + Account has expired +
    + [% END %] + [% IF patron.is_debarred %] +
    + + Patron has restrictions +
    + [% END %] + [% IF amount_outstanding && Koha.Preference('maxoutstanding') && amount_outstanding > Koha.Preference('maxoutstanding') %] +
    + + Patron has outstanding fines: [% member.amount_outstanding | $Price %] +
    + [% END %] + + [% IF ( member.diffbranch ) %] +
    + + Pickup library is different. Patron's home library: ([% Branches.GetName(patron.branchcode) | html %] / [% patron.branchcode | html %] ) +
    + [% END %] +
  2. + [% END %] +
+ [% UNLESS ( multi_hold ) %] +
+ +
+ [% ELSE %] + + + + + [% UNLESS ( item_level_itypes ) %] + + [% END %] + + + + [% FOREACH biblioloo IN biblioloop %] + [% IF ( biblioloo.warn ) %] + + [% ELSE %] + + [% END %] + + [% END %] + + [% UNLESS ( item_level_itypes ) %] + + [% END %] + + + + [% END # /FOREACH biblioloo %] +
 TitleItem typePriorityInformation
+ [% UNLESS ( biblioloo.warn ) %] + + +
    +
  • + [% biblioloo.title | html %] +
  • + [% IF ( biblioloo.publicationyear ) %] +
  • + Publication year: [% biblioloo.publicationyear | html %] +
  • + [% END %] +
+ [% IF ( biblioloo.warn ) %] + + [% END %] +
+ [% biblioloo.itypename | html %] + [% biblioloo.rank | html %] + [% IF ( biblioloo.checked_previously ) %] + Patron has previously checked out this title
+ [% END %] + [% IF ( biblioloo.alreadyres ) %] +
    + [% ELSE %] + [% IF ( biblioloo.none_avail ) %] +
      + [% END %] + [% END %] + + [% IF ( biblioloo.alreadyres ) %] +
    • + [% patron.firstname | html %] [% patron.surname | html %] + already has a hold on this item +
    • + [% END %] + [% IF ( biblioloo.none_avail ) %] +
    • No items are available to be placed on hold
    • + [% END %] + + [% IF ( biblioloo.alreadyres ) %] +
    + [% ELSE %] + [% IF ( biblioloo.none_avail ) %] +
+ [% END %] + [% END %] +
[% END %] -
- - [% IF ( multi_hold ) %] - - - [% END %] - - + +
[% ELSIF NOT noitems # /UNLESS patron %] [% IF ( checked_previously && !multi_hold ) %] @@ -183,7 +377,7 @@
Hold details -
+ @@ -752,6 +946,11 @@ columns_settings_borrowers_table = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %] $(document).ready(function() { + [% UNLESS clubs %] + $('#circ_holds_select').tabs({active: 0}); + [% ELSE %] + $('#circ_holds_select').tabs({active: 1}); + [% END %] function ToggleHoldsToPlace() { if ( $("#requestany").prop('checked') ) { $("#holds_to_place_count").prop('disabled', false); @@ -793,6 +992,31 @@ "margin-right":"0em" }); + $("#club-request-form").on("submit", function() { + let $t = $(this); + $('.clubalert').addClass('hide'); + let options = { + url: $t.attr('action'), + method: $t.attr('method').toUpperCase(), + contentType: 'application/json', + data: JSON.stringify({ + biblio_id: biblionumber, + pickup_library_id: $('select[name="pickup"]').val() + }) + }; + if($('input[name="checkitem"]:checked').length) + options.data.item_id = $('input[name="checkitem"]:checked').val(); + $.ajax(options) + .then(function(result) { + let url = 'request.pl?biblionumber='+biblionumber+($('input[name="multi_hold"]').length && $('input[name="multi_hold"]').val()?'&multi_hold=1':''); + document.location = url; + }) + .fail(function(err) { + $('.clubalert').removeClass('hide').html(err.responseJSON.error); + }); + return false; + }); + [% UNLESS ( multi_hold ) %] $("#hold-request-form").on("submit", function(){ return check(); diff --git a/reserve/request.pl b/reserve/request.pl index 49ea545826..c7832434a3 100755 --- a/reserve/request.pl +++ b/reserve/request.pl @@ -53,6 +53,7 @@ use Koha::Items; use Koha::ItemTypes; use Koha::Libraries; use Koha::Patrons; +use Koha::Clubs; my $dbh = C4::Context->dbh; my $input = new CGI; @@ -75,8 +76,12 @@ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_l my $findborrower = $input->param('findborrower'); $findborrower = '' unless defined $findborrower; $findborrower =~ s|,| |g; +my $findclub = $input->param('findclub'); +$findclub = '' unless defined $findclub && !$findborrower; my $borrowernumber_hold = $input->param('borrowernumber') || ''; +my $club_hold = $input->param('club')||''; my $messageborrower; +my $messageclub; my $warnings; my $messages; my $exceeded_maxreserves; @@ -135,6 +140,25 @@ if ($findborrower) { } } +if($findclub) { + my $club = Koha::Clubs->find( { name => $findclub } ); + if( $club ) { + $club_hold = $club->id; + } else { + my @clubs = Koha::Clubs->search( [ + { name => { like => '%'.$findclub.'%' } }, + { description => { like => '%'.$findclub.'%' } } + ] ); + if( scalar @clubs == 1 ) { + $club_hold = $clubs[0]->id; + } elsif ( @clubs ) { + $template->param( clubs => \@clubs ); + } else { + $messageclub = "'$findclub'"; + } + } +} + my @biblionumbers = (); my $biblionumber = $input->param('biblionumber'); my $biblionumbers = $input->param('biblionumbers'); @@ -203,7 +227,54 @@ if ($borrowernumber_hold && !$action) { ); } -$template->param( messageborrower => $messageborrower ); +if ($club_hold && !$borrowernumber_hold && !$action) { + my $club = Koha::Clubs->find($club_hold); + + my $enrollments = $club->club_enrollments; + + my $maxreserves = C4::Context->preference('maxreserves'); + my $new_reserves_count = scalar( @biblionumbers ); + + my @members; + + while(my $enrollment = $enrollments->next) { + next if $enrollment->is_canceled; + my $member = { patron => $enrollment->patron->unblessed }; + my $reserves_count = $enrollment->patron->holds->count; + if ( $maxreserves + && ( $reserves_count + $new_reserves_count > $maxreserves ) ) + { + $member->{new_reserves_allowed} = $maxreserves - $reserves_count > 0 + ? $maxreserves - $reserves_count + : 0; + $member->{exceeded_maxreserves} = 1; + } + my $expiry_date = $enrollment->patron->dateexpiry; + $member->{expiry} = 0; # flag set if patron account has expired + if ($expiry_date and $expiry_date ne '0000-00-00' and + Date_to_Days(split /-/,$date) > Date_to_Days(split /-/,$expiry_date)) { + $member->{expiry} = 1; + } + $member->{amount_outstanding} = $enrollment->patron->account->balance; + if ( $enrollment->patron->branchcode ne C4::Context->userenv->{'branch'} ) { + $member->{diffbranch} = 1; + } + + push @members, $member; + } + + $template->param( + club => $club, + members => \@members, + maxreserves => $maxreserves, + new_reserves_count => $new_reserves_count + ); +} + +$template->param( + messageborrower => $messageborrower, + messageclub => $messageclub +); # FIXME launch another time GetMember perhaps until (Joubu: Why?) my $patron = Koha::Patrons->find( $borrowernumber_hold );