kohabug 2186 - improve display of empty import batches
[koha.git] / tools / import_borrowers.pl
1 #!/usr/bin/perl
2
3 # Copyright 2007 Liblime Ltd
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19
20 # Script to take some borrowers data in a known format and load it into Koha
21 #
22 # File format
23 #
24 # cardnumber,surname,firstname,title,othernames,initials,streetnumber,streettype,
25 # address line , address line 2, city, zipcode, email, phone, mobile, fax, work email, work phone,
26 # alternate streetnumber, alternate streettype, alternate address line 1, alternate city,
27 # alternate zipcode, alternate email, alternate phone, date of birth, branchcode,
28 # categorycode, enrollment date, expiry date, noaddress, lost, debarred, contact surname,
29 # contact firstname, contact title, borrower notes, contact relationship, ethnicity, ethnicity notes
30 # gender, username, opac note, contact note, password, sort one, sort two
31 #
32 # any fields except cardnumber can be blank but the number of fields must match
33 # dates should be in the format you have set up Koha to expect
34 # branchcode and categorycode need to be valid
35
36 use strict;
37 use C4::Auth;
38 use C4::Output;
39 use C4::Dates qw(format_date_in_iso);
40 use C4::Context;
41 use C4::Members;
42 use C4::Members::Attributes;
43 use C4::Members::AttributeTypes;
44
45 use Text::CSV;
46 use CGI;
47
48 my @columnkeys = (
49     'cardnumber',    'surname',      'firstname',        'title',
50     'othernames',    'initials',     'streetnumber',     'streettype',
51     'address',       'address2',     'city',             'zipcode',
52     'email',         'phone',        'mobile',           'fax',
53     'emailpro',      'phonepro',     'B_streetnumber',   'B_streettype',
54     'B_address',     'B_city',       'B_zipcode',        'B_email',
55     'B_phone',       'dateofbirth',  'branchcode',       'categorycode',
56     'dateenrolled',  'dateexpiry',   'gonenoaddress',    'lost',
57     'debarred',      'contactname',  'contactfirstname', 'contacttitle',
58     'borrowernotes', 'relationship', 'ethnicity',        'ethnotes',
59     'sex',           'userid',       'opacnote',         'contactnote',
60     'password',      'sort1',        'sort2'
61 );
62 if (C4::Context->preference('ExtendedPatronAttributes')) {
63     push @columnkeys, 'patron_attributes';
64 }
65
66 my $input = new CGI;
67
68 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
69     {
70         template_name   => "tools/import_borrowers.tmpl",
71         query           => $input,
72         type            => "intranet",
73         authnotrequired => 0,
74         flagsrequired   => { tools => 'import_patrons' },
75         debug           => 1,
76     }
77 );
78
79 my $uploadborrowers      = $input->param('uploadborrowers');
80 my $matchpoint           = $input->param('matchpoint');
81 if ($matchpoint) {
82     $matchpoint =~ s/^patron_attribute_//;
83 }
84 my $overwrite_cardnumber = $input->param('overwrite_cardnumber');
85
86 $template->param( SCRIPT_NAME => $ENV{'SCRIPT_NAME'} );
87
88 if (C4::Context->preference('ExtendedPatronAttributes')) {
89     $template->param(ExtendedPatronAttributes => 1);
90 }
91
92 if ( $uploadborrowers && length($uploadborrowers) > 0 ) {
93     my $csv         = Text::CSV->new();
94     my $imported    = 0;
95     my $alreadyindb = 0;
96     my $overwritten = 0;
97     my $invalid     = 0;
98     my $matchpoint_attr_type; 
99
100     if (C4::Context->preference('ExtendedPatronAttributes')) {
101         $matchpoint_attr_type = C4::Members::AttributeTypes->fetch($matchpoint);
102     }
103
104     while ( my $borrowerline = <$uploadborrowers> ) {
105         my $status  = $csv->parse($borrowerline);
106         my @columns = $csv->fields();
107         my %borrower;
108         my $patron_attributes;
109         if ( @columns == @columnkeys ) {
110             @borrower{@columnkeys} = @columns;
111             my @attrs;
112             if (C4::Context->preference('ExtendedPatronAttributes')) {
113                 my $attr_str = $borrower{patron_attributes};
114                 delete $borrower{patron_attributes};
115                 my $ok = $csv->parse($attr_str);
116                 my @list = $csv->fields();
117                 # FIXME error handling
118                 $patron_attributes = [ map { map { my @arr = split /:/, $_, 2; { code => $arr[0], value => $arr[1] } } $_ } @list ];
119             }
120                         foreach (qw(dateofbirth dateenrolled dateexpiry)) {
121                                 my $tempdate = $borrower{$_} or next;
122                                 $borrower{$_} = format_date_in_iso($tempdate) || '';
123                         }
124             my $borrowernumber;
125             if ($matchpoint eq 'cardnumber') {
126                 my $member = GetMember( $borrower{'cardnumber'}, 'cardnumber' );
127                 if ($member) {
128                     $borrowernumber = $member->{'borrowernumber'};
129                 }
130             } elsif (C4::Context->preference('ExtendedPatronAttributes')) {
131                 if (defined($matchpoint_attr_type)) {
132                     foreach my $attr (@$patron_attributes) {
133                         if ($attr->{code} eq $matchpoint and $attr->{value} ne '') {
134                             my @borrowernumbers = $matchpoint_attr_type->get_patrons($attr->{value});
135                             $borrowernumber = $borrowernumbers[0] if scalar(@borrowernumbers) == 1;
136                             last;
137                         }
138                     }
139                 }
140             }
141             
142             if ( $borrowernumber) 
143             {
144                 # borrower exists
145                 if ($overwrite_cardnumber) {
146                     $borrower{'borrowernumber'} = $borrowernumber;
147                     ModMember(%borrower);
148                     if (C4::Context->preference('ExtendedPatronAttributes')) {
149                         C4::Members::Attributes::SetBorrowerAttributes($borrower{'borrowernumber'}, $patron_attributes);
150                     }
151                     $overwritten++;
152                 } else {
153                     $alreadyindb++;
154                 }
155             }
156             else {
157                 if ($borrowernumber = AddMember(%borrower)) {
158                     if (C4::Context->preference('ExtendedPatronAttributes')) {
159                         C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $patron_attributes);
160                     }
161                     $imported++;
162                 } else {
163                     $invalid++;         # was just "$invalid", I assume incrementing was the point --atz
164                 }
165             }
166         } else {
167             $invalid++;
168         }
169     }
170     $template->param( 'uploadborrowers' => 1 );
171     $template->param(
172         'uploadborrowers' => 1,
173         'imported'        => $imported,
174         'overwritten'     => $overwritten,
175         'alreadyindb'     => $alreadyindb,
176         'invalid'         => $invalid,
177         'total'           => $imported + $alreadyindb + $invalid + $overwritten,
178     );
179
180 } else {
181     if (C4::Context->preference('ExtendedPatronAttributes')) {
182         my @matchpoints = ();
183         my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes();
184         foreach my $type (@attr_types) {
185             my $attr_type = C4::Members::AttributeTypes->fetch($type->{code});
186             if ($attr_type->unique_id()) {
187             push @matchpoints, { code =>  "patron_attribute_" . $attr_type->code(), description => $attr_type->description() };
188             }
189         }
190         $template->param(matchpoints => \@matchpoints);
191     }
192 }
193
194 output_html_with_http_headers $input, $cookie, $template->output;
195