__PACKAGE__->register_method(
- method => "user_visible_circs",
- api_name => "open-ils.actor.history.circ.visible",
+ method => "user_circ_history",
+ api_name => "open-ils.actor.history.circ",
stream => 1,
+ authoritative => 1,
signature => {
- desc => 'Returns the set of opt-in visible circulations accompanied by circulation chain summaries',
+ desc => 'Returns user circ history objects for the calling user',
params => [
{ desc => 'Authentication token', type => 'string'},
- { desc => 'User ID. If no user id is present, the authenticated user is assumed', type => 'number' },
{ desc => 'Options hash. Supported fields are "limit" and "offset"', type => 'object' },
],
return => {
- desc => q/An object with 2 fields: circulation and summary.
- circulation is the "circ" object. summary is the related "accs" object/,
+ desc => q/Stream of 'auch' circ history objects/,
type => 'object',
}
}
);
__PACKAGE__->register_method(
- method => "user_visible_circs",
- api_name => "open-ils.actor.history.circ.visible.print",
+ method => "user_circ_history",
+ api_name => "open-ils.actor.history.circ.clear",
stream => 1,
signature => {
- desc => 'Returns printable output for the set of opt-in visible circulations',
+ desc => 'Delete all user circ history entries for the calling user',
+ params => [
+ { desc => 'Authentication token', type => 'string'},
+ ],
+ return => {
+ desc => q/1 on success, event on error/,
+ type => 'object',
+ }
+ }
+);
+
+__PACKAGE__->register_method(
+ method => "user_circ_history",
+ api_name => "open-ils.actor.history.circ.print",
+ stream => 1,
+ signature => {
+ desc => q/Returns printable output for the caller's circ history objects/,
params => [
{ desc => 'Authentication token', type => 'string'},
- { desc => 'User ID. If no user id is present, the authenticated user is assumed', type => 'number' },
{ desc => 'Options hash. Supported fields are "limit" and "offset"', type => 'object' },
],
return => {
);
__PACKAGE__->register_method(
- method => "user_visible_circs",
- api_name => "open-ils.actor.history.circ.visible.email",
+ method => "user_circ_history",
+ api_name => "open-ils.actor.history.circ.email",
stream => 1,
signature => {
- desc => 'Emails the set of opt-in visible circulations to the requestor',
+ desc => q/Emails the caller's circ history/,
params => [
{ desc => 'Authentication token', type => 'string'},
{ desc => 'User ID. If no user id is present, the authenticated user is assumed', type => 'number' },
}
);
+sub user_circ_history {
+ my ($self, $conn, $auth, $options) = @_;
+ $options ||= {};
+
+ my $for_print = ($self->api_name =~ /print/);
+ my $for_email = ($self->api_name =~ /email/);
+ my $for_clear = ($self->api_name =~ /clear/);
+
+ # No perm check is performed. Caller may only access his/her own
+ # circ history entries.
+ my $e = new_editor(authtoken => $auth);
+ return $e->event unless $e->checkauth;
+
+ my %limits = ();
+ if (!$for_clear) { # clear deletes all
+ $limits{offset} = $options->{offset} if defined $options->{offset};
+ $limits{limit} = $options->{limit} if defined $options->{limit};
+ }
+
+ my $circs = $e->search_action_user_circ_history([
+ {usr => $e->requestor->id},
+ { # order newest to oldest by default
+ order_by => {auch => 'xact_start DESC'},
+ %limits
+ },
+ {substream => 1} # could be a large list
+ ]);
+
+ if ($for_print) {
+ return $U->fire_object_event(undef,
+ 'circ.format.history.print', $circs, $e->requestor->home_ou);
+ }
+
+ $e->xact_begin if $for_clear;
+ $conn->respond_complete(1) if $for_email; # no sense in waiting
+
+ for my $circ (@$circs) {
+
+ if ($for_email) {
+ # events will be fired from action_trigger_runner
+ $U->create_events_for_hook('circ.format.history.email',
+ $circ, $e->editor->home_ou, undef, undef, 1);
+
+ } elsif ($for_clear) {
+
+ $e->delete_action_user_circ_history($circ)
+ or return $e->die_event;
+
+ } else {
+ $conn->respond($circ);
+ }
+ }
+
+ if ($for_clear) {
+ $e->commit;
+ return 1;
+ }
+
+ return undef;
+}
+
+
__PACKAGE__->register_method(
method => "user_visible_circs",
api_name => "open-ils.actor.history.hold.visible",
}
);
-sub user_visible_circs {
+sub user_visible_holds {
my($self, $conn, $auth, $user_id, $options) = @_;
- my $is_hold = ($self->api_name =~ /hold/);
+ my $is_hold = 1;
my $for_print = ($self->api_name =~ /print/);
my $for_email = ($self->api_name =~ /email/);
my $e = new_editor(authtoken => $auth);
$settings{$key}= $val unless $$set_map{$key} eq $val;
}
+ # Used by the settings update form when warning on history delete.
+ my $clear_circ_history = 0;
+ my $clear_hold_history = 0;
+
+ # true if we need to show the warning on next page load.
+ my $hist_warning_needed = 0;
+ my $hist_clear_confirmed = $self->cgi->param('history_delete_confirmed');
+
my $now = DateTime->now->strftime('%F');
- foreach my $key (qw/history.circ.retention_start history.hold.retention_start/) {
+ foreach my $key (
+ qw/history.circ.retention_start history.hold.retention_start/) {
+
my $val = $self->cgi->param($key);
if($val and $val eq 'on') {
# Set the start time to 'now' unless a start time already exists for the user
$settings{$key} = $now unless $$set_map{$key};
+
} else {
- # clear the start time if one previously existed for the user
- $settings{$key} = undef if $$set_map{$key};
+
+ next unless $$set_map{$key}; # nothing to do
+
+ $clear_circ_history = 1 if $key =~ /circ/;
+ $clear_hold_history = 1 if $key =~ /hold/;
+
+ if (!$hist_clear_confirmed) {
+ # when clearing circ history, only warn if history data exists.
+
+ if ($clear_circ_history) {
+
+ if ($self->fetch_user_circ_history(0, 1)->[0]) {
+ $hist_warning_needed = 1;
+ next; # no history updates while confirmation pending
+ }
+
+ } else {
+
+ my $one_hold = $e->json_query({
+ select => {
+ au => [{
+ column => 'id',
+ transform => 'action.usr_visible_holds',
+ result_field => 'id'
+ }]
+ },
+ from => 'au',
+ where => {id => $e->requestor->id},
+ limit => 1
+ })->[0];
+
+ if ($one_hold) {
+ $hist_warning_needed = 1;
+ next; # no history updates while confirmation pending
+ }
+ }
+ }
+
+ $settings{$key} = undef;
+
+ if ($key eq 'history.circ.retention_start') {
+ # delete existing circulation history data.
+ $U->simplereq(
+ 'open-ils.actor',
+ 'open-ils.actor.history.circ.clear',
+ $self->editor->authtoken);
+ }
}
}
+ # Warn patrons before clearing circ/hold history
+ if ($hist_warning_needed) {
+ $self->ctx->{clear_circ_history} = $clear_circ_history;
+ $self->ctx->{clear_hold_history} = $clear_hold_history;
+ $self->ctx->{confirm_history_delete} = 1;
+ }
+
# Send the modified settings off to be saved
$U->simplereq(
'open-ils.actor',
$ctx->{circ_history_limit} = $limit;
$ctx->{circ_history_offset} = $offset;
- my $circ_ids;
- if ($self->cgi->param('sort') ne "") { # Defer limitation to circ_history.tt2
- $circ_ids = $e->json_query({
- select => {
- au => [{
- column => 'id',
- transform => 'action.usr_visible_circs',
- result_field => 'id'
- }]
+ # Defer limitation to circ_history.tt2 when sorting
+ if ($self->cgi->param('sort')) {
+ $limit = undef;
+ $offset = undef;
+ }
+
+ $ctx->{circs} = $self->fetch_user_circ_history(1, $limit, $offset);
+ return Apache2::Const::OK;
+}
+
+# if 'flesh' is set, copy data etc. is loaded and the return value is
+# a hash of 'circ' and 'marc_xml'. Othwerwise, it's just a list of
+# auch objects.
+sub fetch_user_circ_history {
+ my ($self, $flesh, $limit, $offset) = @_;
+ my $e = $self->editor;
+
+ my %limits = ();
+ $limits{offset} = $offset if defined $offset;
+ $limits{limit} = $limit if defined $limit;
+
+ my %flesh_ops = (
+ flesh => 3,
+ flesh_fields => {
+ auch => ['target_copy'],
+ acp => ['call_number'],
+ acn => ['record']
},
- from => 'au',
- where => {id => $e->requestor->id}
- });
+ );
- } else {
- $circ_ids = $e->json_query({
- select => {
- au => [{
- column => 'id',
- transform => 'action.usr_visible_circs',
- result_field => 'id'
- }]
+ $e->xact_begin;
+ my $circs = $e->search_action_user_circ_history([
+ {usr => $e->requestor->id},
+ { # order newest to oldest by default
+ order_by => {auch => 'xact_start DESC'},
+ $flesh ? %flesh_ops : (),
+ %limits
},
- from => 'au',
- where => {id => $e->requestor->id},
- limit => $limit,
- offset => $offset
+ {substream => 1}
+ ]);
+ $e->rollback;
+
+ return $circs unless $flesh;
+
+ my @circs;
+ for my $circ (@$circs) {
+ push(@circs, {
+ circ => $circ,
+ marc_xml => ($circ->target_copy->call_number->id != -1) ?
+ XML::LibXML->new->parse_string(
+ $circ->target_copy->call_number->record->marc) :
+ undef # pre-cat copy, use the dummy title/author instead
});
}
- $ctx->{circs} = $self->fetch_user_circs(1, [map { $_->{id} } @$circ_ids]);
- return Apache2::Const::OK;
+ return \@circs;
}
# TODO: action.usr_visible_holds does not return cancelled holds. Should it?
my $e = $self->editor;
my $filename = $self->cgi->param('filename') || 'circ_history.csv';
- my $ids = $e->json_query({
- select => {
- au => [{
- column => 'id',
- transform => 'action.usr_visible_circs',
- result_field => 'id'
- }]
- },
- from => 'au',
- where => {id => $e->requestor->id}
- });
+ my $circs = $self->fetch_user_circ_history;
$self->ctx->{csv} = $U->fire_object_event(
undef,
'circ.format.history.csv',
- $e->search_action_circulation({id => [map {$_->{id}} @$ids]}, {substream =>1}),
+ $e->search_action_circulation(
+ {id => [map {$_->id} @$circs]}, {substream =>1}),
$self->editor->requestor->home_ou
);
text-align: center;
font-style: italic;
}
+
+#clear-history-confirm {
+ font-weight: bold;
+ color: [% css_colors.text_badnews %];
+ padding: 10px;
+}
<td>
<input id='[% setting %]' name='[% setting %]'
type="checkbox" title="[% circ_name %]"
- [% IF ctx.user_setting_map.$setting; %] checked='checked' [% END %]/>
+ [% IF ctx.user_setting_map.$setting
+ AND !ctx.clear_circ_history; %] checked='checked' [% END %]/>
</td>
</tr>
[%- setting = 'history.hold.retention_start' -%]
<td>
<input id='[% setting %]' name='[% setting %]'
type="checkbox" title="[% hold_name %]"
- [% IF ctx.user_setting_map.$setting; %] checked='checked' [% END %]/>
+ [% IF ctx.user_setting_map.$setting
+ AND !ctx.clear_hold_history; %] checked='checked' [% END %]/>
</td>
</tr>
[%- setting = 'opac.temporary_list_no_warn' -%]
</tbody>
</table>
+ [% IF ctx.confirm_history_delete %]
+ <div id='clear-history-confirm'>
+ [% l('Disabling checkout or holds history will permanently remove all items from your history.') %]
+ <br/>
+ [% l('Are you sure you wish to continue?') %]
+ </div>
+ <a href="[% mkurl() %]">[% l('Cancel') %]</a>
+ <input type='hidden' name='history_delete_confirmed' value='1'/>
+ <input type="submit" value="[% l('Confirm') %]" class="opac-button"/>
+ [% ELSE %]
<input type="submit" value="[% l('Save') %]" class="opac-button"/>
+ [% END %]
</form>
[% INCLUDE "opac/parts/myopac/prefs_hints.tt2" %]
[% END %]