2 # ---------------------------------------------------------------
3 # Copyright (C) 2022 King County Library System
4 # Author: Bill Erickson <berickxx@gmail.com>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 # ---------------------------------------------------------------
20 use OpenSRF::AppSession;
21 use OpenSRF::Utils::SettingsClient;
22 use OpenILS::Utils::Fieldmapper;
23 use OpenSRF::Utils::Logger q/$logger/;
24 use OpenILS::Utils::CStoreEditor;
25 use OpenILS::Application::AppUtils;
27 my $U = 'OpenILS::Application::AppUtils';
28 $ENV{OSRF_LOG_CLIENT} = 1;
30 my $osrf_config = '/openils/conf/opensrf_core.xml';
32 my $process_as = 'admin';
35 my $has_open_circ = 0;
47 'osrf-config=s' => \$osrf_config,
48 'ids-file=s' => \$ids_file,
49 'process-as=s' => \$process_as,
50 'min-id=s' => \$min_id,
51 'max-id=s' => \$max_id,
52 'has-open-circ' => \$has_open_circ,
53 'owes-more-than=s' => \$owes_more_than,
54 'owes-less-than=s' => \$owes_less_than,
55 'has-penalty=s' => \$has_penalty,
56 'no-has-penalty=s' => \$no_has_penalty,
57 'verbose' => \$verbose,
65 Update patron penalties in batch with options for filtering which
72 --osrf-config [/openils/conf/opensrf_core.xml]
74 --process-as <eg-account>
75 Username of an Evergreen account to use for creating the
76 internal auth session. Defaults to 'admin'.
78 --has-penalty <penalty-type-id>
79 Limit to patrons that currently have a specific penalty.
81 --no-has-penalty <penalty-type-id>
82 Limit to patrons that do not currently have a specific penalty.
85 Lowest patron ID to process.
88 Highest patron ID to process.
90 Together with --min-id, these are useful for running parallel
91 batches of this script without overlapping and/or processing
92 chunks of a controlled size.
95 Limit to patrons that have at least on open circulation.
96 For simplicity, "open" in this context means null xact finish.
98 --owes-more-than <amount>
99 Limit to patrons who have an outstanding balance greater than
100 the specified amount.
102 --owes-less-than <amount>
103 Limit to patrons who have an outstanding balance less than
104 the specified amount.
107 Log debug info to STDOUT. This script logs various information
108 via \$logger regardless of this option.
116 help() if $help or !$ops;
118 # $lvl should match a $logger logging function. E.g. 'info', 'error', etc.
124 # always announce errors and warnings
125 return unless $verbose || $lvl =~ /error|warn/;
127 my $date_str = DateTime->now(time_zone => 'local')->strftime('%F %T');
128 print "$date_str $msg\n";
132 my ($limit, $offset) = @_;
136 open(IDS_FILE, '<', $ids_file)
137 or die "Cannot open user IDs file: $ids_file: $!\n";
139 my @ids = <IDS_FILE>;
143 @ids = grep { defined $_ } @ids[$offset..($offset + $limit)];
151 mus => ['balance_owed']
164 order_by => [{class => 'au', field => 'id'}]
167 my @where = ({'+au' => {deleted => 'f'}});
169 if (defined $max_id) {
172 '+au' => { # min_id defaults to 0.
173 id => {between => [$min_id, $max_id]}
177 } elsif (defined $min_id) {
181 # min_id defaults to 0.
182 id => {'>' => $min_id}
191 select => {ausp => ['id']},
194 usr => {'=' => {'+au' => 'id'}},
195 standing_penalty => $has_penalty,
197 {stop_date => undef},
198 {stop_date => {'>' => 'now'}}
206 if ($no_has_penalty) {
210 select => {ausp => ['id']},
213 usr => {'=' => {'+au' => 'id'}},
214 standing_penalty => $no_has_penalty,
216 {stop_date => undef},
217 {stop_date => {'>' => 'now'}}
226 # For owes more / less, there is a special case because not all
227 # patrons have a money.usr_summary row. If they don't, they
228 # effectively owe $0.00.
230 if (defined $owes_more_than) {
232 if ($owes_more_than > 0) {
236 balance_owed => {'>' => $owes_more_than}
244 balance_owed => {'>' => $owes_more_than}
248 usr => undef # owes $0.00
255 if (defined $owes_less_than) {
257 if ($owes_less_than < 0) {
260 balance_owed => {'<' => $owes_less_than}
262 }) if $owes_less_than;
269 balance_owed => {'<' => $owes_less_than}
273 usr => undef # owes $0.00
282 select => {circ => ['id']},
285 usr => {'=' => {'+au' => 'id'}},
290 }) if $has_open_circ;
292 $query->{where}->{'-and'} = \@where;
294 my $resp = $e->json_query($query);
296 return [map {$_->{id}} @$resp];
301 my $limit = $batch_size;
307 my $user_ids = get_user_ids($limit, $offset);
309 my $num = scalar(@$user_ids);
316 "Processing batch $batches; count=$num; offset=$offset; ids=" .
317 @$user_ids[0] . '..' . @$user_ids[$#$user_ids]);
319 for my $user_id (@$user_ids) {
323 'open-ils.actor.user.penalties.update',
330 $offset += $batch_size;
333 announce('debug', "$counter total patrons processed.");
338 my $auth_user = $e->search_actor_user(
339 {usrname => $process_as, deleted => 'f'})->[0];
341 die "No such user '$process_as' to use for authentication\n" unless $auth_user;
343 my $auth_resp = $U->simplereq(
344 'open-ils.auth_internal',
345 'open-ils.auth_internal.session.create',
346 {user_id => $auth_user->id, login_type => 'staff'}
349 die "Could not create an internal auth session\n" unless (
351 $auth_resp->{payload} &&
352 ($authtoken = $auth_resp->{payload}->{authtoken})
357 OpenSRF::System->bootstrap_client(config_file => $osrf_config);
358 Fieldmapper->import(IDL =>
359 OpenSRF::Utils::SettingsClient->new->config_value("IDL"));
360 OpenILS::Utils::CStoreEditor::init();
361 $e = OpenILS::Utils::CStoreEditor->new;