97149c8c8d5874aa71fd984227a39b39228157be
[migration-tools.git] / ils-specific / unicorn / unicorn_patron_xml2text.pl
1 #!/usr/bin/perl
2 use strict;
3 use warnings;
4
5 use DateTime;
6 use Time::HiRes qw/time/;
7 use XML::LibXML;
8
9 my %s_map;
10
11 my $doc = XML::LibXML->new->parse_file($ARGV[0]);
12
13 my $starttime = time;
14 my $count = 1;
15
16 my @base_elements = (
17     "user_id",
18     "user_altid",
19     "user_pin",
20     "user_profile",
21     "user_status",
22     "user_library",
23     "user_priv_granted",
24     "user_priv_expires",
25     "user_mailingaddr",
26     "birthdate",
27     "last_name",
28     "first_name",
29     "middle_name",
30     "suffix_name",
31     "note",
32     "note1",
33     "comment",
34     "staff",
35     "webcatpref",
36     "user_category1",
37     "user_category2",
38     "user_category3",
39     "user_category4",
40     "dept",
41     "guardian",
42     "license",
43     "aup",
44     "photo",
45     "notify_via",
46     "user_claims_ret",
47     "user_environment",
48     "user_department",
49     "ums_id"
50 );
51
52 my @addr_elements = (
53     "std_line1",
54     "std_line2",
55     "std_city",
56     "std_state",
57     "std_zip",
58     "phone",
59     "dayphone",
60     "homephone",
61     "workphone",
62     "cellphone",
63     "email",
64     "location",
65     "usefor",
66     "care_of",
67     "known_bad"
68 );
69
70 print STDOUT join("\t", @base_elements);
71 foreach my $addr ( 1..3 ) {
72     print STDOUT "\t" . join("\t", @addr_elements);
73 }
74 print STDOUT "\tuserid_active\tinactive_barcode1\tinactive_barcode2";
75 print STDOUT "\n";
76
77 for my $patron ( $doc->documentElement->childNodes ) {
78         next if ($patron->nodeType == 3);
79
80         my $bc = $patron->findvalue( 'user_id' ); $bc =~ s/^\s+//; $bc =~ s/\s+$//;
81         if (exists($s_map{$bc})) {
82                 $count++;
83                 warn "\n!!! already saw barcode $bc, skipping\n";
84                 next;
85         } else {
86                 $s_map{$bc} = 1;
87         }
88
89         unless (defined($bc)) {
90                 my $xml = $patron->toString;
91                 warn "\n!!! no barcode found in UMS data, user number $count, xml => $xml \n";
92                 $count++;
93                 next;
94         }
95
96     foreach my $e ( @base_elements ) {
97         my $v = $patron->findvalue( $e ); $v =~ s/^\s+//; $v =~ s/\s+$//;
98         if ( $v && ( $e eq 'birthdate' || $e eq 'user_priv_granted' || $e eq 'user_priv_expires' ) ) { $v = parse_date($v); }
99         print STDOUT ( $v ? $v : '' ) . "\t";
100     }
101
102         my %addresses;
103
104         for my $addr ( $patron->findnodes( "Address" ) ) {
105                 my $addr_type = $addr->getAttribute('addr_type');
106                 $addresses{$addr_type} = $addr;
107         }
108
109     foreach my $t ( 1..3 ) {
110         if ($addresses{$t}) {
111             foreach my $e ( @addr_elements ) {
112                 my $v;
113                 if ($e eq "known_bad") {
114                     $v = $addresses{$t}->getAttribute( $e ); if ($v) { $v =~ s/^\s+//; $v =~ s/\s+$//; }
115                 } else {
116                     $v = $addresses{$t}->findvalue( $e ); $v =~ s/^\s+//; $v =~ s/\s+$//;
117                 }
118                 print STDOUT ( $v ? $v : '' ) . "\t";
119             }
120         } else {
121             foreach ( @addr_elements ) { print STDOUT "\t"; }
122         }
123     }
124
125     my $inactive_barcode1 = '';
126     my $inactive_barcode2 = '';
127     my $userid_active = 't';
128     my @barcodes = $patron->findnodes( "barcodes" );
129     for my $i_bc ( $barcodes[0]->findnodes( "barcode" ) ) {
130         my $active = $i_bc->getAttribute('active');
131         if ($active eq "0" && $i_bc->textContent eq $bc) {
132             $userid_active = 'f';
133         }
134         if ($active eq "0" && $i_bc->textContent ne $bc) {
135             if (! $inactive_barcode1 ) {
136                 $inactive_barcode1 = $i_bc->textContent;
137                 $inactive_barcode1 =~ s/^\s+//;
138                 $inactive_barcode1 =~ s/\s+$//;
139             } else {
140                 if (! $inactive_barcode2 ) {
141                     $inactive_barcode2 = $i_bc->textContent;
142                     $inactive_barcode2 =~ s/^\s+//;
143                     $inactive_barcode2 =~ s/\s+$//;
144                 } else {
145                     warn "Extra barcode (" . $i_bc->textContent . ") for user with id = " . $bc . "\n";
146                 }
147             }
148         }
149     }
150     print STDOUT "$userid_active\t$inactive_barcode1\t$inactive_barcode2";
151
152     print STDOUT "\n";
153         $count++;
154 }
155
156 sub parse_date {
157         my $string = shift;
158         my $group = shift;
159
160         my ($y,$m,$d);
161
162         if ($string eq 'NEVER') {
163                 my (undef,undef,undef,$d,$m,$y) = localtime();
164                 return sprintf('%04d-%02d-%02d', $y + 1920, $m + 1, $d);
165         } elsif (length($string) == 8 && $string =~ /^(\d{4})(\d{2})(\d{2})$/o) {
166                 ($y,$m,$d) = ($1,$2,$3);
167         } elsif ($string =~ /(\d+)\D(\d+)\D(\d+)/o) { #looks like it's parsable
168                 if ( length($3) > 2 )  { # looks like mm.dd.yyyy
169                         if ( $1 < 99 && $2 < 99 && $1 > 0 && $2 > 0 && $3 > 0) {
170                                 if ($1 > 12 && $1 < 31 && $2 < 13) { # well, actually it looks like dd.mm.yyyy
171                                         ($y,$m,$d) = ($3,$2,$1);
172                                 } elsif ($2 > 12 && $2 < 31 && $1 < 13) {
173                                         ($y,$m,$d) = ($3,$1,$2);
174                                 }
175                         }
176                 } elsif ( length($1) > 3 ) { # format probably yyyy.mm.dd
177                         if ( $3 < 99 && $2 < 99 && $1 > 0 && $2 > 0 && $3 > 0) {
178                                 if ($2 > 12 && $2 < 32 && $3 < 13) { # well, actually it looks like yyyy.dd.mm -- why, I don't konw
179                                         ($y,$m,$d) = ($1,$3,$2);
180                                 } elsif ($3 > 12 && $3 < 31 && $2 < 13) {
181                                         ($y,$m,$d) = ($1,$2,$3);
182                                 }
183                         }
184                 } elsif ( $1 < 99 && $2 < 99 && $3 < 99 && $1 > 0 && $2 > 0 && $3 > 0) {
185                         if ($3 < 7) { # probably 2000 or greater, mm.dd.yy
186                                 $y = $3 + 2000;
187                                 if ($1 > 12 && $1 < 32 && $2 < 13) { # well, actually it looks like dd.mm.yyyy
188                                         ($m,$d) = ($2,$1);
189                                 } elsif ($2 > 12 && $2 < 32 && $1 < 13) {
190                                         ($m,$d) = ($1,$2);
191                                 }
192                         } else { # probably before 2000, mm.dd.yy
193                                 $y = $3 + 1900;
194                                 if ($1 > 12 && $1 < 32 && $2 < 13) { # well, actually it looks like dd.mm.yyyy
195                                         ($m,$d) = ($2,$1);
196                                 } elsif ($2 > 12 && $2 < 32 && $1 < 13) {
197                                         ($m,$d) = ($1,$2);
198                                 }
199                         }
200                 }
201         }
202
203         my $date = $string;
204         if ($y && $m && $d) {
205                 eval {
206                         $date = sprintf('%04d-%02d-%-2d',$y, $m, $d)
207                                 if (new DateTime ( year => $y, month => $m, day => $d ));
208                 }
209         }
210
211         return $date;
212 }
213