my $client = shift;
my $idlist = $self->api_name =~/id_list/o ? 1 : 0;
-
+
$client->respond( $idlist ? $_ : $_->to_fieldmapper ) for ( overdue_circs('', $idlist) );
return undef;
ORDER BY CASE WHEN h.hold_type IN ('R','F') THEN 0 ELSE 1 END, $holdsort
LIMIT $limit
SQL
-
+
$client->respond( $_ ) for ( @$ids );
return undef;
}
my $ctype = ref($c);
$ctype =~ s/^.+::(\w+)$/$1/;
-
+
my $due_date_method = 'due_date';
my $target_copy_method = 'target_copy';
my $circ_lib_method = 'circ_lib';
my $due_dt = $parser->parse_datetime( cleanse_ISO8601( $c->$due_date_method ) );
-
+
my $due = $due_dt->epoch;
my $now = time;
my $fine_interval = $c->fine_interval;
$fine_interval =~ s/(\d{2}):(\d{2}):(\d{2})/$1 h $2 m $3 s/o;
$fine_interval = interval_to_seconds( $fine_interval );
-
+
if ( $fine_interval == 0 || int($c->$recurring_fine_method * 100) == 0 || int($c->max_fine * 100) == 0 ) {
$client->respond( "Fine Generator skipping circ due to 0 fine interval, 0 fine rate, or 0 max fine.\n" );
$log->info( "Fine Generator skipping circ " . $c->id . " due to 0 fine interval, 0 fine rate, or 0 max fine." );
return;
}
- if ( $is_reservation and $fine_interval >= interval_to_seconds('1d') ) {
+ if ( $is_reservation and $fine_interval >= interval_to_seconds('1d') ) {
my $tz_offset_s = 0;
if ($due_dt->strftime('%z') =~ /(-|\+)(\d{2}):?(\d{2})/) {
$tz_offset_s = $1 . interval_to_seconds( "${2}h ${3}m");
}
-
+
$due -= ($due % $fine_interval) + $tz_offset_s;
$now -= ($now % $fine_interval) + $tz_offset_s;
}
-
+
$client->respond(
"ARG! Overdue $ctype ".$c->id.
" for item ".$c->$target_copy_method.
" (user ".$c->usr.").\n".
"\tItem was due on or before: ".localtime($due)."\n");
-
+
my @fines = money::billing->search_where(
{ xact => $c->id,
btype => 1,
my $current_fine_total = 0;
$current_fine_total += int($_->amount * 100) for (grep { $_ and !$_->voided } @fines);
-
+
my $last_fine;
if ($fine) {
$client->respond( "Last billing time: ".$fine->billing_ts." (clensed format: ".cleanse_ISO8601( $fine->billing_ts ).")");
my ($latest_billing_ts, $latest_amount) = ('',0);
for (my $bill = 1; $bill <= $pending_fine_count; $bill++) {
-
+
if ($current_fine_total >= $max_fine) {
$c->update({stop_fines => 'MAXFINES', stop_fines_time => 'now'}) if ($ctype eq 'circulation');
$client->respond(
"\tNo more fines will be generated.\n" );
last;
}
-
+
# XXX Use org time zone (or default to 'local') once we have the ou setting built for that
my $billing_ts = DateTime->from_epoch( epoch => $last_fine, time_zone => 'local' );
my $current_bill_count = $bill;
if (my $h = $hoo{$c->$circ_lib_method}) {
next if ( $h->$dow_open eq '00:00:00' and $h->$dow_close eq '00:00:00');
}
-
+
my @cl = actor::org_unit::closed_date->search_where(
{ close_start => { '<=' => $timestamptz },
close_end => { '>=' => $timestamptz },
$self->method_lookup('open-ils.storage.transaction.commit')->run;
- if(1) {
+ if(1) {
# Caluclate penalties inline
OpenILS::Utils::Penalty->calculate_penalties(
# Calculate penalties with an aysnc call to the penalty server. This approach
# may lead to duplicate penalties since multiple penalty processes for a
- # given user may be running at the same time. Leave this here for reference
+ # given user may be running at the same time. Leave this here for reference
# in case we later find that asyc calls are needed in some environments.
$penalty->request(
'open-ils.penalty.patron_penalty.calculate',
if ( DateTime->compare($ex_time, DateTime->now) < 0 ) {
# cancel cause = un-targeted expiration
- $hold->update( { cancel_time => 'now', cancel_cause => 1 } );
+ $hold->update( { cancel_time => 'now', cancel_cause => 1 } );
# refresh fields from the DB while still in the xact
- my $fm_hold = $hold->to_fieldmapper;
+ my $fm_hold = $hold->to_fieldmapper;
$self->method_lookup('open-ils.storage.transaction.commit')->run;
# tell A/T the hold was cancelled
my $ses = OpenSRF::AppSession->create('open-ils.trigger');
- $ses->request('open-ils.trigger.event.autocreate',
+ $ses->request('open-ils.trigger.event.autocreate',
'hold_request.cancel.expire_no_target', $fm_hold, $fm_hold->pickup_lib);
die "OK\n";
deleted => 'f' }
)
] if (@part_maps);
-
+
} elsif ($hold->hold_type eq 'I') {
my ($itree) = $self
->method_lookup( 'open-ils.storage.serial.issuance.ranged_tree')
{ id => [map {$_->unit->id} @{ $itree->items }],
deleted => 'f' }
) if ($itree && @{ $itree->items });
-
+
} elsif ($hold->hold_type eq 'C' || $hold->hold_type eq 'R' || $hold->hold_type eq 'F') {
my $_cp = asset::copy->retrieve($hold->target);
push @$all_copies, $_cp if $_cp;
# Force and recall holds bypass pretty much everything
if ($hold->hold_type ne 'R' && $hold->hold_type ne 'F') {
# trim unholdables
- @$all_copies = grep { isTrue($_->status->holdable) &&
- isTrue($_->location->holdable) &&
+ @$all_copies = grep { isTrue($_->status->holdable) &&
+ isTrue($_->location->holdable) &&
isTrue($_->holdable) &&
!isTrue($_->deleted) &&
(isTrue($hold->mint_condition) ? isTrue($_->mint_condition) : 1) &&
# let 'em know we're still working
$client->status( new OpenSRF::DomainObject::oilsContinueStatus );
-
+
# if we have no copies ...
if (!ref $all_copies || !@$all_copies) {
$log->info("\tNo copies available for targeting at all!\n");
my $old_best_still_valid = 0; # Assume no, but the next line says yes if it is still a potential.
$old_best_still_valid = 1 if ( $old_best && grep { ''.$old_best->id eq ''.$_->id } @$all_copies );
$hold->update({ current_copy => undef }) if ($old_best);
-
+
if (!scalar(@good_copies)) {
$log->info("\tNo (non-current) copies eligible to fill the hold.");
if ( $old_best_still_valid ) {
my %circ_lib_map = map { (''.$_->circ_lib => 1) } @$all_copies;
my $circ_lib_list = [keys %circ_lib_map];
-
+
my $cstore = OpenSRF::AppSession->create('open-ils.cstore');
-
+
# Grab the "biggest" loop for this hold so far
my $current_loop = $cstore->request(
'open-ils.cstore.json_query',
where => { hold => $hold->id}
}
)->gather(1);
-
+
$current_loop = $current_loop->{max} if ($current_loop);
$current_loop ||= 1;
-
+
my $exclude_list = $cstore->request(
'open-ils.cstore.json_query.atomic',
{ distinct => 1,
where => { hold => $hold->id}
}
)->gather(1);
-
+
my @keepers;
if ($exclude_list && @$exclude_list) {
$exclude_list = [map {$_->{circ_lib}} @$exclude_list];
} else {
@keepers = @$circ_lib_list;
}
-
+
$current_loop++ if (!@keepers);
-
+
if ($self->{max_loops}{$pu_lib} && $self->{max_loops}{$pu_lib} >= $current_loop) {
# We haven't exceeded max_loops yet
my @keeper_copies;
$_->delete for (@oldmaps);
# cancel cause = un-targeted expiration
- $hold->update( { cancel_time => 'now', cancel_cause => 1 } );
+ $hold->update( { cancel_time => 'now', cancel_cause => 1 } );
# refresh fields from the DB while still in the xact
- my $fm_hold = $hold->to_fieldmapper;
+ my $fm_hold = $hold->to_fieldmapper;
$self->method_lookup('open-ils.storage.transaction.commit')->run;
# tell A/T the hold was cancelled
my $ses = OpenSRF::AppSession->create('open-ils.trigger');
- $ses->request('open-ils.trigger.event.autocreate',
+ $ses->request('open-ils.trigger.event.autocreate',
'hold_request.cancel.expire_no_target', $fm_hold, $fm_hold->pickup_lib);
die "OK\n";
$client->status( new OpenSRF::DomainObject::oilsContinueStatus );
if ($old_best) {
# hold wasn't fulfilled, record the fact
-
+
$log->info("\tHold was not (but should have been) fulfilled by ".$old_best->id);
action::unfulfilled_hold_list->create(
{ hold => ''.$hold->id,
{ current_copy => $old_best->id,
fulfillment_time => undef,
cancel_time => undef,
- }
+ }
) &&
( OpenILS::Utils::PermitHold::permit_copy_hold(
{ title => $old_best->call_number->record->to_fieldmapper,
retarget => 1
}
))
- ) {
+ ) {
$hold->update( { prev_check_time => 'now', current_copy => ''.$old_best->id } );
$log->debug( "\tRetargeting the previously targeted copy [".$old_best->id."]" );
} else {
if (DateTime->compare($end_time, DateTime->now) < 0) {
# cancel cause = un-targeted expiration
- $bresv->update( { cancel_time => 'now' } );
+ $bresv->update( { cancel_time => 'now' } );
# refresh fields from the DB while still in the xact
my $fm_bresv = $bresv->to_fieldmapper;
# tell A/T the reservation was cancelled
my $ses = OpenSRF::AppSession->create('open-ils.trigger');
- $ses->request('open-ils.trigger.event.autocreate',
+ $ses->request('open-ils.trigger.event.autocreate',
'booking.reservation.cancel.expire_no_target', $fm_bresv, $fm_bresv->pickup_lib);
die "OK\n";
# let 'em know we're still working
$client->status( new OpenSRF::DomainObject::oilsContinueStatus );
-
+
# if we have no copies ...
if (!@good_resources) {
$log->info("\tNo resources available for targeting at all!\n");
for (my $i = 0; $i < @$cps; $i++) {
next unless $$cps[$i];
-
+
my $cn = $cache{cns}{$copies[$i]->call_number};
my $rec = $cache{titles}{$cn->record};
$copies[$i] = undef if ($copies[$i] && !grep{ $copies[$i]->status eq $_->id}@$statuses);
my $count = @copies;
return unless ($count);
-
+
action::hold_copy_map->search( hold => $hold->id )->delete_all;
-
+
my @maps;
$self->{client}->respond( "\tMapping ".scalar(@copies)." eligable copies for hold ".$hold->id."\n");
for my $c (@copies) {
my $cp_list;
try {
$cp_list = [ asset::copy->search( call_number => \@v_ids ) ];
-
+
} catch Error with {
my $e = shift;
warn "Could not retrieve copy list:\n\n$e\n";
my $cn_list;
try {
($cn_list) = $self->method_lookup('open-ils.storage.direct.asset.call_number.search.record.atomic')->run( \@t_ids );
-
+
} catch Error with {
my $e = shift;
warn "Could not retrieve volume list:\n\n$e\n";
my $titles;
try {
$titles = [ metabib::metarecord_source_map->search( metarecord => $hold->target) ];
-
+
} catch Error with {
my $e = shift;
die "Could not retrieve initial title list:\n\n$e\n";
};
try {
- my @recs = map {$_->record} metabib::record_descriptor->search( record => $titles, item_type => [split '', $hold->holdable_formats] );
+ my @recs = map {$_->record} metabib::record_descriptor->search( record => $titles, item_type => [split '', $hold->holdable_formats] );
$titles = [ biblio::record_entry->search( id => \@recs ) ];
-
+
} catch Error with {
my $e = shift;
die "Could not retrieve format-pruned title list:\n\n$e\n";