$self->ctx->{page} = 'place_hold';
my @targets = $cgi->param('hold_target');
+ my @parts = $cgi->param('part');
+
$ctx->{hold_type} = $cgi->param('hold_type');
$ctx->{default_pickup_lib} = $e->requestor->home_ou; # unless changed below
return $self->generic_redirect unless @targets;
- $logger->info("Looking at hold targets: @targets");
+ $logger->info("Looking at hold_type: " . $ctx->{hold_type} . " and targets: @targets");
# if the staff client provides a patron barcode, fetch the patron
if (my $bc = $self->cgi->cookie("patron_barcode")) {
my $type_dispatch = {
T => sub {
my $recs = $e->batch_retrieve_biblio_record_entry(\@targets, {substream => 1});
+
for my $id (@targets) { # force back into the correct order
my ($rec) = grep {$_->id eq $id} @$recs;
- push(@hold_data, {target => $rec, record => $rec});
+
+ # NOTE: if tpac ever supports locked-down pickup libs,
+ # we'll need to pass a pickup_lib param along with the
+ # record to filter the set of monographic parts.
+ my $parts = $U->simplereq(
+ 'open-ils.search',
+ 'open-ils.search.biblio.record_hold_parts',
+ {record => $rec->id}
+ );
+
+ # T holds on records that have parts are OK, but if the record has
+ # no non-part copies, the hold will ultimately fail. When that
+ # happens, require the user to select a part.
+ my $part_required = 0;
+ if (@$parts) {
+ my $np_copies = $e->json_query({
+ select => { acp => [{column => 'id', transform => 'count', alias => 'count'}]},
+ from => {acp => {acn => {}, acpm => {type => 'left'}}},
+ where => {
+ '+acp' => {deleted => 'f'},
+ '+acn' => {deleted => 'f', record => $rec->id},
+ '+acpm' => {id => undef}
+ }
+ });
+ $part_required = 1 if $np_copies->[0]->{count} == 0;
+ }
+
+ push(@hold_data, {
+ target => $rec,
+ record => $rec,
+ parts => $parts,
+ part_required => $part_required
+ });
}
},
V => sub {
$ctx->{orig_params} = $cgi->Vars;
delete $ctx->{orig_params}{submit};
delete $ctx->{orig_params}{hold_target};
+ delete $ctx->{orig_params}{part};
my $usr = $e->requestor->id;
}
}
+ # target_id is the true target_id for holds placement.
+ # needed for attempt_hold_placement()
+ # With the exception of P-type holds, target_id == target->id.
+ $_->{target_id} = $_->{target}->id for @hold_data;
+
+ if ($ctx->{hold_type} eq 'T') {
+
+ # Much like quantum wave-particles, P-type holds pop into
+ # and out of existence at the user's whim. For our purposes,
+ # we treat such holds as T(itle) holds with a selected_part
+ # designation. When the time comes to pass the hold information
+ # off for holds possibility testing and placement, make it look
+ # like a real P-type hold.
+ my (@p_holds, @t_holds);
+
+ for my $idx (0..$#parts) {
+ my $hdata = $hold_data[$idx];
+ if (my $part = $parts[$idx]) {
+ $hdata->{target_id} = $part;
+ $hdata->{selected_part} = $part;
+ push(@p_holds, $hdata);
+ } else {
+ push(@t_holds, $hdata);
+ }
+ }
+
+ $self->attempt_hold_placement($usr, $pickup_lib, 'P', @p_holds) if @p_holds;
+ $self->attempt_hold_placement($usr, $pickup_lib, 'T', @t_holds) if @t_holds;
+
+ } else {
+ $self->attempt_hold_placement($usr, $pickup_lib, $ctx->{hold_type}, @hold_data);
+ }
+
+ # NOTE: we are leaving the staff-placed patron barcode cookie
+ # in place. Otherwise, it's not possible to place more than
+ # one hold for the patron within a staff/patron session. This
+ # does leave the barcode to linger longer than is ideal, but
+ # normal staff work flow will cause the cookie to be replaced
+ # with each new patron anyway.
+ # TODO: See about getting the staff client to clear the cookie
+
+ # return to the place_hold page so the results of the hold
+ # placement attempt can be reported to the user
+ return Apache2::Const::OK;
+}
+
+sub attempt_hold_placement {
+ my ($self, $usr, $pickup_lib, $hold_type, @hold_data) = @_;
+ my $cgi = $self->cgi;
+ my $ctx = $self->ctx;
+ my $e = $self->editor;
+
# First see if we should warn/block for any holds that
# might have locally available items.
for my $hdata (@hold_data) {
my ($local_block, $local_alert) = $self->local_avail_concern(
- $hdata->{target}->id, $ctx->{hold_type}, $pickup_lib);
+ $hdata->{target_id}, $hold_type, $pickup_lib);
if ($local_block) {
$hdata->{hold_failed} = 1;
}
}
-
my $method = 'open-ils.circ.holds.test_and_create.batch';
$method .= '.override' if $cgi->param('override');
- my @create_targets = map {$_->{target}->id} (grep { !$_->{hold_failed} } @hold_data);
+ my @create_targets = map {$_->{target_id}} (grep { !$_->{hold_failed} } @hold_data);
if(@create_targets) {
$e->authtoken,
{ patronid => $usr,
pickup_lib => $pickup_lib,
- hold_type => $ctx->{hold_type}
+ hold_type => $hold_type
},
\@create_targets
);
last;
}
- my ($hdata) = grep {$_->{target}->id eq $resp->{target}} @hold_data;
+ my ($hdata) = grep {$_->{target_id} eq $resp->{target}} @hold_data;
my $result = $resp->{result};
if ($U->event_code($result)) {
$bses->kill_me;
}
-
- # NOTE: we are leaving the staff-placed patron barcode cookie
- # in place. Otherwise, it's not possible to place more than
- # one hold for the patron within a staff/patron session. This
- # does leave the barcode to linger longer than is ideal, but
- # normal staff work flow will cause the cookie to be replaced
- # with each new patron anyway.
- # TODO: See about getting the staff client to clear the cookie
-
- # return to the place_hold page so the results of the hold
- # placement attempt can be reported to the user
- return Apache2::Const::OK;
}
sub fetch_user_circs {
<td>
<input type="hidden" name="hold_target" value="[% hdata.target.id | html %]" />
<div class='hold-items-list-title'>[% attrs.title_extended | html %]</div>
+ [% IF hdata.parts %]
+ [% IF hdata.parts.size > 0 %]
+ <div style='padding-left: 10px'>
+ <span>[% hdata.part_required ? l('Select a Part:') : l('Select a Part (optional):') %]</span>
+ <select name='part'>
+ [% IF !hdata.part_required %]
+ <option selected='selected' value=''>[% l('- All Parts -') %]</option>
+ [% END %]
+ [% FOR part IN hdata.parts %]
+ <option value='[% part.id %]'>[% part.label | html %]</option>
+ [% END %]
+ </select>
+ </div>
+ [% ELSE %]
+ <input type='hidden' name='part' value=''/>
+ [% END %]
+ [% END %]
</td>
</tr>
[% END %]
[% PROCESS "opac/parts/org_selector.tt2";
PROCESS build_org_selector name='pickup_lib' value=ctx.default_pickup_lib id='pickup_lib' can_have_vols_only=1 %]
</p>
- <p>
- [% |l %]If you use the Traveling Library Center (TLC) and ABC Express
- services, please select "Outreach" to have the item delivered
- during your scheduled visit.[% END %]
- </p>
<input type="submit" name="submit" value="[% l('Submit') %]" title="[% l('Submit') %]"
alt="[% l('Submit') %]" class="opac-button" />
<input type="reset" name="cancel" onclick="javascript:history.go(-1);"
value="[% l('Cancel') %]" id="holds_cancel" class="opac-button" />
</form>
- <br /><br />
- <p>
- [% |l %]* If you need your item today, and it is checked in at your
- library, please place your hold and then call your library to set it
- aside. Placing a hold without calling the library will increase your
- wait time.[% END %]
- <br /><a href="#">[% l('Library phone numbers.') %]</a>
- </p>
- <p>
- [% |l %]* For best possible service, we recommend keeping
- a printed copy of your most recent holds list.[% END %]
- </p>
</div>