2 # ---------------------------------------------------------------
3 # Generates the overdue notices XML file
4 # ./eg_gen_overdue.pl <bootstap> 0
5 # generates today's notices
6 # ./eg_gen_overdue.pl <bootstap> 1 0
7 # generates notices for today - 1 and today
8 # ./eg_gen_overdue.pl <bootstap> 2 1 0
9 # ./eg_gen_overdue.pl <bootstap> 3 2 1 0 etc...
10 # ---------------------------------------------------------------
14 use strict; use warnings;
15 require '../../../Open-ILS/src/support-scripts/oils_header.pl';
16 use vars qw/$logger $apputils/;
18 use OpenILS::Const qw/:const/;
20 use DateTime::Format::ISO8601;
21 use OpenSRF::Utils qw/:datetime/;
22 use Unicode::Normalize;
24 my $bsconfig = shift || die "usage: $0 <bootstrap_config>\n";
26 @goback = (0) unless @goback;
27 osrf_connect($bsconfig);
28 my $e = OpenILS::Utils::CStoreEditor->new;
30 my @date = CORE::localtime;
35 my $mon = $date[4] + 1;
36 my $year = $date[5] + 1900;
43 <?xml version='1.0' encoding='UTF-8'?>
44 <file type="notice" date="$day/$mon/$year" time="$hour:$min:$sec">
48 print_notices($_) for @goback;
56 # -----------------------------------------------------------------------
57 # -----------------------------------------------------------------------
61 my $goback = shift || 0;
63 for my $day ( qw/ 7 14 30 / ) {
64 my ($start, $end) = make_date_range($day + $goback);
65 $logger->debug("OD_notice: process date range $start -> $end");
67 my $circs = $e->search_action_circulation(
71 due_date => { between => [ $start, $end ] }
74 order_by => { circ => 'usr, circ_lib' }
80 process_circs( $circs, "${day}day" );
89 return unless @$circs;
91 $logger->debug("OD_notice: processing range $range and circs @$circs");
97 for my $circ (@$circs) {
98 $circ = $e->retrieve_action_circulation($circ);
101 $circ->circ_lib != $org or $circ->usr ne $patron ) {
102 $org = $circ->circ_lib;
103 $patron = $circ->usr;
104 print_notice( $range, \@current ) if @current;
108 push( @current, $circ );
111 print_notice( $range, \@current );
114 sub make_date_range {
115 my $daysback = shift;
117 my $date = DateTime->from_epoch(
118 epoch => ( CORE::time - ($daysback * 24 * 60 * 60) ) );
121 $date->set_minute(0);
122 $date->set_second(0);
126 $date->set_minute(59);
127 $date->set_second(59);
129 return ($start, "$date");
134 my( $range, $circs ) = @_;
135 return unless @$circs;
136 my $org = $circs->[0]->circ_lib;
137 my $usr = $circs->[0]->usr;
138 $logger->debug("OD_notice: printing $range user:$usr org:$org");
139 print "\t\t<notice type='overdue' count='$range'>\n";
140 print_patron_chunk($usr);
141 print_org_chunk($org);
142 print_circ_chunk($_) for @$circs;
143 print "\t\t</notice>\n";
148 sub print_patron_chunk {
151 my $patron = $USER_CACHE{$user_id};
154 $logger->debug("OD_notice: fetching patron $user_id");
156 $patron = $e->retrieve_actor_user(
162 'au' => [qw/ card billing_address mailing_address /]
166 ) or return handle_event($e->event);
168 $USER_CACHE{$user_id} = $patron;
171 my $bc = $patron->card->barcode;
172 my $fn = $patron->first_given_name;
173 my $mn = $patron->second_given_name;
174 my $ln = $patron->family_name;
176 my ( $s1, $s2, $city, $state, $zip );
177 my $baddr = $patron->billing_address || $patron->mailing_address;
179 $s1 = $baddr->street1;
180 $s2 = $baddr->street2;
181 $city = $baddr->city;
182 $state = $baddr->state;
183 $zip = $baddr->post_code;
186 $bc = entityize($bc);
187 $fn = entityize($fn);
188 $mn = entityize($mn);
189 $ln = entityize($ln);
190 $s1 = entityize($s1);
191 $s2 = entityize($s2);
192 $city = entityize($city);
193 $state = entityize($state);
194 $zip = entityize($zip);
199 <id type="barcode">$bc</id>
200 <fullname>$fn $mn $ln</fullname>
201 <street1>$s1 $s2</street1>
202 <city_state_zip>$city, $state $zip</city_state_zip>
208 sub print_org_chunk {
211 my $org = $ORG_CACHE{$org_id};
214 $logger->debug("OD_notice: fetching org $org_id");
216 $org = $e->retrieve_actor_org_unit(
222 { aou => [ qw/billing_address mailing_address/ ] }
225 ) or return handle_event($e->event);
227 $ORG_CACHE{$org_id} = $org;
230 my $name = $org->name;
232 my( $phone, $s1, $s2, $city, $state, $zip );
233 my $baddr = $org->billing_address || $org->mailing_address;
235 $s1 = $baddr->street1;
236 $s2 = $baddr->street2;
237 $city = $baddr->city;
238 $state = $baddr->state;
239 $zip = $baddr->post_code;
242 $name = entityize($name);
243 $phone = entityize($phone);
244 $s1 = entityize($s1);
245 $s2 = entityize($s2);
246 $city = entityize($city);
247 $state = entityize($state);
248 $zip = entityize($zip);
253 <libname>$name</libname>
254 <libphone>$phone</libphone>
255 <libstreet1>$s1 $s2</libstreet1>
256 <libcity_state_zip>$city, $state $zip</libcity_state_zip>
261 sub print_circ_chunk {
268 my $d = $circ->due_date;
269 $d =~ s/[T ].*//og; # just for logging
270 $logger->debug("OD_notice: processing circ ".$circ->id." $d");
272 my $due = DateTime::Format::ISO8601->new->parse_datetime(
273 clense_ISO8601($circ->due_date));
276 my $mon = $due->month;
277 my $year = $due->year;
279 my $copy = $e->retrieve_asset_copy($circ->target_copy)
280 or return handle_event($e->event);
282 my $bc = $copy->barcode;
284 if( $copy->call_number == OILS_PRECAT_CALL_NUMBER ) {
285 $title = $copy->dummy_title || "";
286 $author = $copy->dummy_author || "";
290 my $volume = $e->retrieve_asset_call_number(
296 acn => [ qw/record/ ]
300 ) or return handle_event($e->event);
302 $cn = $volume->label;
303 my $mods = $apputils->record_to_mvr($volume->record);
305 $title = $mods->title || "";
306 $author = $mods->author || "";
310 $title = entityize($title);
311 $author = entityize($author);
312 $cn = entityize($cn);
313 $bc = entityize($bc);
317 <title>$title</title>
318 <author>$author</author>
319 <duedate>$day/$mon/$year</duedate>
321 <barcode>$bc</barcode>
330 warn "OD_notice: ".Dumper($evt) . "\n";
331 $logger->error("OD_notice: ".Dumper($evt));
336 my $stuff = shift || return "";
337 $stuff =~ s/\</</og;
338 $stuff =~ s/\>/>/og;
339 $stuff =~ s/\&/&/og;
340 $stuff = NFC($stuff);
341 $stuff =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;