use OpenILS::Application::AppUtils;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
use OpenSRF::AppSession;
use OpenILS::Utils::ModsParser;
use OpenILS::Event;
Retrieve a circ object by id
@param authtoken Login session key
@pararm circid The id of the circ object
- @param all_circ Returns an action.all_circulation object instead
+ @param all_circ Returns an action.all_circulation_slim object instead
of an action.circulation object to pick up aged circs.
/
);
my $e = new_editor(authtoken => $a);
return $e->event unless $e->checkauth;
my $method = $all_circ ?
- 'retrieve_action_all_circulation' :
+ 'retrieve_action_all_circulation_slim' :
'retrieve_action_circulation';
my $circ = $e->$method($i) or return $e->event;
if( $e->requestor->id ne ($circ->usr || '') ) {
return 1;
}
+__PACKAGE__->register_method(
+ method => "update_latest_inventory",
+ api_name => "open-ils.circ.circulation.update_latest_inventory");
+
+sub update_latest_inventory {
+ my( $self, $conn, $auth, $args ) = @_;
+ my $e = new_editor(authtoken=>$auth, xact=>1);
+ return $e->die_event unless $e->checkauth;
+
+ my $copies = $$args{copy_list};
+ foreach my $copyid (@$copies) {
+ my $copy = $e->retrieve_asset_copy($copyid);
+ my $alci = $e->search_asset_latest_inventory({copy => $copyid})->[0];
+
+ if($alci) {
+ $alci->inventory_date('now');
+ $alci->inventory_workstation($e->requestor->wsid);
+ $e->update_asset_latest_inventory($alci) or return $e->die_event;
+ } else {
+ my $alci = Fieldmapper::asset::latest_inventory->new;
+ $alci->inventory_date('now');
+ $alci->inventory_workstation($e->requestor->wsid);
+ $alci->copy($copy->id);
+ $e->create_asset_latest_inventory($alci) or return $e->die_event;
+ }
+
+ $copy->latest_inventory($alci);
+ }
+ $e->commit;
+ return 1;
+}
__PACKAGE__->register_method(
method => "set_circ_claims_returned",
$circ->stop_fines_time('now') unless $circ->stop_fines_time;
if( $backdate ) {
- $backdate = cleanse_ISO8601($backdate);
+ $backdate = clean_ISO8601($backdate);
- my $original_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($circ->due_date));
+ my $original_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
my $new_date = DateTime::Format::ISO8601->new->parse_datetime($backdate);
$backdate = $new_date->ymd . 'T' . $original_date->strftime('%T%z');
# clean it up once again; need a : in the timezone offset. E.g. -06:00 not -0600
- $backdate = cleanse_ISO8601($backdate);
+ $backdate = clean_ISO8601($backdate);
# make it look like the circ stopped at the cliams returned time
$circ->stop_fines_time($backdate);
$backdate and $circ->checkin_time;
# update the checkin and stop_fines times to reflect the new backdate
- $circ->stop_fines_time(cleanse_ISO8601($backdate));
- $circ->checkin_time(cleanse_ISO8601($backdate));
+ $circ->stop_fines_time(clean_ISO8601($backdate));
+ $circ->checkin_time(clean_ISO8601($backdate));
$e->update_action_circulation($circ) or return $e->die_event;
# now void the overdues "erased" by the back-dating
or return $e->die_event;
return $e->die_event unless $e->allowed('CIRC_OVERRIDE_DUE_DATE', $circ->circ_lib);
- $date = cleanse_ISO8601($date);
+ $date = clean_ISO8601($date);
if (!(interval_to_seconds($circ->duration) % 86400)) { # duration is divisible by days
- my $original_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($circ->due_date));
+ my $original_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
my $new_date = DateTime::Format::ISO8601->new->parse_datetime($date);
- $date = cleanse_ISO8601( $new_date->ymd . 'T' . $original_date->strftime('%T%z') );
+
+ # since the new date may be coming in as UTC, convert it
+ # to the same time zone as the original due date so that
+ # ->ymd is more likely to yield the expected results
+ $new_date->set_time_zone($original_date->time_zone());
+ $date = clean_ISO8601( $new_date->ymd . 'T' . $original_date->strftime('%T%z') );
}
$circ->due_date($date);
}
if( $use_time ne 'now' ) {
- $use_time = cleanse_ISO8601($use_time);
+ $use_time = clean_ISO8601($use_time);
$logger->debug("in_house_use setting use time to $use_time");
}
$count = 4 unless defined $count;
}
- return $e->search_action_all_circulation([
+ return $e->search_action_all_circulation_slim([
{target_copy => $copyid},
- {limit => $count, order_by => { combcirc => "xact_start DESC" }}
+ {limit => $count, order_by => { aacs => "xact_start DESC" }}
]);
}
# find the most recent circulation for the requested copy,
# be it active, completed, or aged.
- my $circ = $e->search_action_all_circulation([
+ my $circ = $e->search_action_all_circulation_slim([
{ target_copy => $copy_id },
{
flesh => 1,
flesh_fields => {
- combcirc => [
+ aacs => [
'workstation',
'checkin_workstation',
'duration_rule',
'recurring_fine_rule'
],
},
- order_by => { combcirc => 'xact_start desc' },
+ order_by => { aacs => 'xact_start desc' },
limit => 1
}
])->[0];
sub mark_item {
my( $self, $conn, $auth, $copy_id, $args ) = @_;
- my $e = new_editor(authtoken=>$auth, xact =>1);
- return $e->die_event unless $e->checkauth;
$args ||= {};
+ my $e = new_editor(authtoken=>$auth);
+ return $e->die_event unless $e->checkauth;
my $copy = $e->retrieve_asset_copy([
$copy_id,
- {flesh => 1, flesh_fields => {'acp' => ['call_number']}}])
+ {flesh => 1, flesh_fields => {'acp' => ['call_number','status']}}])
or return $e->die_event;
- my $owning_lib =
+ my $owning_lib =
($copy->call_number->id == OILS_PRECAT_CALL_NUMBER) ?
$copy->circ_lib : $copy->call_number->owning_lib;
+ my $evt; # For later.
my $perm = 'MARK_ITEM_MISSING';
my $stat = OILS_COPY_STATUS_MISSING;
if( $self->api_name =~ /damaged/ ) {
$perm = 'MARK_ITEM_DAMAGED';
$stat = OILS_COPY_STATUS_DAMAGED;
- my $evt = handle_mark_damaged($e, $copy, $owning_lib, $args);
- return $evt if $evt;
-
} elsif ( $self->api_name =~ /bindery/ ) {
$perm = 'MARK_ITEM_BINDERY';
$stat = OILS_COPY_STATUS_BINDERY;
# caller may proceed if either perm is allowed
return $e->die_event unless $e->allowed([$perm, 'UPDATE_COPY'], $owning_lib);
- $copy->status($stat);
- $copy->edit_date('now');
- $copy->editor($e->requestor->id);
-
- $e->update_asset_copy($copy) or return $e->die_event;
+ # Copy status checks.
+ if ($copy->status->id() == OILS_COPY_STATUS_CHECKED_OUT) {
+ # Items must be checked in before any attempt is made to change its status.
+ if ($args->{handle_checkin}) {
+ $evt = try_checkin($auth, $copy_id);
+ } else {
+ $evt = OpenILS::Event->new('ITEM_TO_MARK_CHECKED_OUT');
+ }
+ } elsif ($copy->status->id() == OILS_COPY_STATUS_IN_TRANSIT) {
+ # Items in transit need to have the transit aborted before being marked.
+ if ($args->{handle_transit}) {
+ $evt = try_abort_transit($auth, $copy_id);
+ } else {
+ $evt = OpenILS::Event->new('ITEM_TO_MARK_IN_TRANSIT');
+ }
+ } elsif ($U->is_true($copy->status->restrict_copy_delete()) && $self->api_name =~ /discard/) {
+ # Items with restrict_copy_delete status require the
+ # COPY_DELETE_WARNING.override permission to be marked for
+ # discard.
+ if ($args->{handle_copy_delete_warning}) {
+ $evt = $e->event unless $e->allowed(['COPY_DELETE_WARNING.override'], $owning_lib);
+ } else {
+ $evt = OpenILS::Event->new('COPY_DELETE_WARNING');
+ }
+ }
+ return $evt if $evt;
- my $holds = $e->search_action_hold_request(
- {
+ # Retrieving holds for later use.
+ my $holds = $e->search_action_hold_request([
+ {
current_copy => $copy->id,
fulfillment_time => undef,
cancel_time => undef,
+ },
+ {flesh=>1, flesh_fields=>{ahr=>['eligible_copies']}}
+ ]);
+
+ # Throw event if attempting to mark discard the only copy to fill a hold.
+ if ($self->api_name =~ /discard/) {
+ if (!$args->{handle_last_hold_copy}) {
+ for my $hold (@$holds) {
+ my $eligible = $hold->eligible_copies();
+ if (!defined($eligible) || scalar(@{$eligible}) < 2) {
+ $evt = OpenILS::Event->new('ITEM_TO_MARK_LAST_HOLD_COPY');
+ last;
+ }
+ }
}
- );
+ }
+ return $evt if $evt;
+
+ # Things below here require a transaction and there is nothing left to interfere with it.
+ $e->xact_begin;
+
+ # Handle extra mark damaged charges, etc.
+ if ($self->api_name =~ /damaged/) {
+ $evt = handle_mark_damaged($e, $copy, $owning_lib, $args);
+ return $evt if $evt;
+ }
+
+ # Mark the copy.
+ $copy->status($stat);
+ $copy->edit_date('now');
+ $copy->editor($e->requestor->id);
+
+ $e->update_asset_copy($copy) or return $e->die_event;
$e->commit;
return 1;
}
+sub try_checkin {
+ my($auth, $copy_id) = @_;
+
+ my $checkin = $U->simplereq(
+ 'open-ils.circ',
+ 'open-ils.circ.checkin.override',
+ $auth, {
+ copy_id => $copy_id,
+ noop => 1
+ }
+ );
+ if(ref $checkin ne 'ARRAY') { $checkin = [$checkin]; }
+
+ my $evt_code = $checkin->[0]->{textcode};
+ $logger->info("try_checkin() received event: $evt_code");
+
+ if($evt_code eq 'SUCCESS' || $evt_code eq 'NO_CHANGE') {
+ $logger->info('try_checkin() successful checkin');
+ return undef;
+ } else {
+ $logger->warn('try_checkin() un-successful checkin');
+ return $checkin;
+ }
+}
+
+sub try_abort_transit {
+ my ($auth, $copy_id) = @_;
+
+ my $abort = $U->simplereq(
+ 'open-ils.circ',
+ 'open-ils.circ.transit.abort',
+ $auth, {copyid => $copy_id}
+ );
+ # Above returns 1 or an event.
+ return $abort if (ref $abort);
+ return undef;
+}
+
sub handle_mark_damaged {
my($e, $copy, $owning_lib, $args) = @_;
my $evt2 = OpenILS::Utils::Penalty->calculate_penalties($e, $circ->usr->id, $e->requestor->ws_ou);
return $evt2 if $evt2;
- return undef;
-
} else {
return OpenILS::Event->new('DAMAGE_CHARGE',
payload => {
$logger->info('open-ils.circ.mark_item_missing_pieces: item needed for hold, shortening due date');
my $due_date = DateTime->now(time_zone => 'local');
- $co_params->{'due_date'} = cleanse_ISO8601( $due_date->strftime('%FT%T%z') );
+ $co_params->{'due_date'} = clean_ISO8601( $due_date->strftime('%FT%T%z') );
} else {
$logger->info('open-ils.circ.mark_item_missing_pieces: item not needed for hold');
}
my $chain = $e->json_query({from => ['action.all_circ_chain', $circ_id]});
for my $circ_info (@$chain) {
- my $circ = Fieldmapper::action::all_circulation->new;
+ my $circ = Fieldmapper::action::all_circulation_slim->new;
$circ->$_($circ_info->{$_}) for keys %$circ_info;
$conn->respond($circ);
}
my $first_circ =
$e->json_query({from => ['action.all_circ_chain', $circ_id]})->[0];
- my $prev_circ = $e->search_action_all_circulation([
+ my $prev_circ = $e->search_action_all_circulation_slim([
{ target_copy => $first_circ->{target_copy},
xact_start => {'<' => $first_circ->{xact_start}}
}, {
flesh => 1,
flesh_fields => {
- combcirc => [
+ aacs => [
'active_circ',
'aged_circ'
]
},
- order_by => { combcirc => 'xact_start desc' },
+ order_by => { aacs => 'xact_start desc' },
limit => 1
}
])->[0];
{from => ['action.all_circ_chain', $prev_circ->id]});
for my $circ_info (@$chain) {
- my $circ = Fieldmapper::action::all_circulation->new;
+ my $circ = Fieldmapper::action::all_circulation_slim->new;
$circ->$_($circ_info->{$_}) for keys %$circ_info;
$conn->respond($circ);
}