added new tc_companion table, updated tc_companionship table, linked tc_calling table...
[eq/.git] / bin / import_ward_data
1 #!/usr/bin/perl
2
3 use DBI;
4 use Getopt::Std;
5
6 $mydir = `cd \$(dirname $0) 2>/dev/null; pwd`; chomp($mydir);
7 unshift @INC,("$mydir/../setup");
8 if( -f "$mydir/../setup/db_config.local") { require "db_config.local"; }
9 else { require "db_config"; }
10
11 %hometeaching_data = ();
12 %membership_data = ();
13 getopts('vsn:o:');
14
15 $monthname2num{'Jan'} = '01';
16 $monthname2num{'Feb'} = '02';
17 $monthname2num{'Mar'} = '03';
18 $monthname2num{'Apr'} = '04';
19 $monthname2num{'May'} = '05';
20 $monthname2num{'Jun'} = '06';
21 $monthname2num{'Jul'} = '07';
22 $monthname2num{'Aug'} = '08';
23 $monthname2num{'Sep'} = '09';
24 $monthname2num{'Oct'} = '10';
25 $monthname2num{'Nov'} = '11';
26 $monthname2num{'Dec'} = '12';
27
28 ######################################################################
29 # SUBROUTINES
30 ######################################################################
31 sub csv_to_hash
32 {
33         my ($filename, $hashref) = @_;
34
35         open(FILE,$filename) || die "-E- Could not open $filename for reading\n";
36
37         my $found_header = 0; my $index = 0;
38         while(<FILE>) {
39                 $line = $_;
40                 @data = split /\",/, $line;
41                 if(!$found_header) { 
42                         @header = @data; 
43                         $found_header = 1; 
44                 } else {
45                         foreach $i (0..$#data-1) {
46                                 $data[$i] =~ s/\"//g;
47                                 $header[$i] =~ s/\"//g;
48                                 $hashref->{$index}{$header[$i]} = $data[$i];
49                                 #print "$index: $i: $header[$i]: $data[$i]\n";
50                         }
51                         $index++;
52                 }
53         }
54
55         close(FILE);
56 }
57
58 sub optional_csv_to_hash
59 {
60         my ($filename, $hashref) = @_;
61
62         my $opened = open(FILE,$filename);
63
64         if ($opened) {
65                 my $found_header = 0; my $index = 0;
66                 while(<FILE>) {
67                         $line = $_;
68                         @data = split /\",/, $line;
69                         if(!$found_header) { 
70                                 @header = @data; 
71                                 $found_header = 1; 
72                         } else {
73                                 foreach $i (0..$#data-1) {
74                                         $data[$i] =~ s/\"//g;
75                                         $header[$i] =~ s/\"//g;
76                                         $hashref->{$index}{$header[$i]} = $data[$i];
77                                         #print "$index: $i: $header[$i]: $data[$i]\n";
78                                 }
79                                 $index++;
80                         }
81                 }
82
83                 close(FILE);
84         }
85         else
86         {
87         print "-W- could not open optional csv file $filename\n";
88         }
89 }
90
91 ######################################################################
92 sub print_hash
93 {
94         my ($hashref) = @_;
95
96         foreach $key (sort {$a <=> $b} keys %$hashref) {
97                 print "Index: $key\n";
98                 foreach $field (keys %{$hashref->{$key}}) {
99                         print "$field: $hashref->{$key}{$field}\n";
100                 }
101                 print "\n";
102         }
103 }
104
105 ######################################################################
106
107 # TC_INDIVIDUAL
108 #+----------------------+------------------+------+-----+---------+----------------+
109 #| Field                | Type             | Null | Key | Default | Extra          |
110 #+----------------------+------------------+------+-----+---------+----------------+
111 #| individual           | int(16) unsigned |      | PRI | NULL    | auto_increment |
112 #| mls_id               | int(16) unsigned |      |     | NULL    |                |
113 #| name                 | varchar(60)      | YES  |     | NULL    |                |
114 #| fullname             | varchar(60)      | YES  |     | NULL    |                |
115 #| phone                | varchar(12)      | YES  |     | NULL    |                |
116 #| email                | varchar(120)     | YES  |     | NULL    |                |
117 #| priesthood           | enum             | YES  |     | NULL    |                |
118 #| scheduling_priority  | int(10) unsigned | YES  |     | 30      |                |
119 #| attending            | tinyint(1)       | YES  |     | 0       |                |
120 #| valid                | tinyint(1)       | YES  |     | NULL    |                |
121 #+----------------------+------------------+------+-----+---------+----------------+
122 sub update_tc_individual_table
123 {
124         print "\n-> Updating tc_individual table\n";
125
126         # Set all records to be invalid. Only mark them as valid if they appear on the new list.
127         $sth = $dbh->prepare("update tc_individual set valid=0");
128         $sth->execute or die "-E- DB error: $DBI::errstr\n";
129
130         foreach $index (keys %membership_data)
131         {
132                 $hashref = $membership_data{$index};
133                 $id = $membership_data{$index}{'Indiv ID'};
134                 $individual_name = $membership_data{$index}{'Preferred Name'};
135                 $full_name = $membership_data{$index}{'Full Name'};
136                 $address = $membership_data{$index}{'Street 1'};
137                 if($membership_data{$index}{'Street 2'} ne "") { 
138                         $address .= " " . $membership_data{$index}{'Street 2'};
139                 }
140                 $phone = $membership_data{$index}{'Household Phone'};
141                 $priesthood = $membership_data{$index}{'Priesthood'};
142                 $hhposition = $membership_data{$index}{'HH Position'};
143                 $steward = ""; # This will be set correctly in a later method
144                 # Set the default stewardship if the "Organization data per member.csv" isn't available.
145                 # Only validate priesthood holders that match the $default_stewardship since 
146                 # we don't have any other data available to us to make this call if we don't have the report.
147                 if((! -e "$datadir/Organization\ class\ per\ member.csv") && ($priesthood =~ /$default_stewardship/i)) { 
148                         $steward = "$default_stewardship";
149                 }
150                 $attending = 0;
151                 if(($organization =~ /Elders/) ||
152                    ($organization =~ /Young Men/) ||
153                    ($organization =~ /Sunday School/) ||
154                    ($organization =~ /Primary/)
155                   ) { $attending = 1; }
156                 if($phone =~ /(\d\d\d-\d\d\d\d)/) { $phone = "$areacode-$1"; }
157                 if($phone =~ /^\(\d\d\d\) (\d\d\d-\d\d\d\d)/) { $phone = "$1-$2"; }
158                 $email = $membership_data{$index}{'indiv E-mail'};
159                 if ($email eq "") { $email = $membership_data{$index}{'Household E-mail'}; }
160                 $sth = $dbh->prepare("select * from tc_individual where mls_id='$id'");
161                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
162                 my @data = ();
163                 while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); }
164                 my $rows = scalar @data;
165                 if($rows == 0) {
166                         # No existing records found for this individual, make a new entry
167                         print "   Adding new individual: $individual_name\n";
168                         $sth = $dbh->prepare("insert into tc_individual values (NULL,'$id',\"$individual_name\",\"$full_name\",'$address','$phone','$email','$hhposition','$priesthood','$steward',NULL,$attending,1)");
169                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
170                 } elsif($rows == 1) {
171                         # An existing record was found for this individual, update it
172                         print "   Updating existing individual: $individual_name\n";
173                         $sth = $dbh->prepare("update tc_individual set valid=1 where mls_id='$id'");
174                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
175                         if($phone ne "") { 
176                                 $sth = $dbh->prepare("update tc_individual set phone='$phone' where mls_id='$id'");
177                         } else {
178                                 $sth = $dbh->prepare("update tc_individual set phone=NULL where mls_id='$id'");
179                         }
180                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
181                         if($address ne "") { 
182                                 $sth = $dbh->prepare("update tc_individual set address='$address' where mls_id='$id'");
183                         } else {
184                                 $sth = $dbh->prepare("update tc_individual set address=NULL where mls_id='$id'");
185                         }
186                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
187                         $sth = $dbh->prepare("update tc_individual set attending='$attending' where mls_id='$id'");
188                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
189                         $sth = $dbh->prepare("update tc_individual set name=\"$individual_name\" where mls_id='$id'");
190                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
191                         $sth = $dbh->prepare("update tc_individual set fullname=\"$full_name\" where mls_id='$id'");
192                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
193                         $sth = $dbh->prepare("update tc_individual set priesthood='$priesthood' where mls_id='$id'");
194                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
195                         $sth = $dbh->prepare("update tc_individual set email='$email' where mls_id='$id'");
196                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
197                         $sth = $dbh->prepare("update tc_individual set hh_position='$hhposition' where mls_id='$id'");
198                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
199                 } else {
200                         # More than one record was found. Error! This shouldn't happen.
201                         print "   -E- More than one record found ($rows) for individual: $individual_name\n";
202                 }
203         }
204         $sth->finish();
205 }
206
207 # TC_CALLING
208 #+--------------+------------------+------+-----+---------+-------+
209 #| Field        | Type             | Null | Key | Default | Extra |
210 #+--------------+------------------+------+-----+---------+-------+
211 #| name         | varchar(30)      | YES  |     | NULL    |       |
212 #| organization | varchar(30)      | YES  |     | NULL    |       |
213 #| position     | varchar(30)      | YES  |     | NULL    |       |
214 #| sustained    | date             | YES  |     | NULL    |       |
215 #+--------------+------------------+------+-----+---------+-------+
216 sub update_tc_calling_table()
217 {
218         print "\n-> Updating tc_calling table\n";
219
220         #print "-> Organization Data Dump\n\n";
221         #&print_hash(\%organization_data);
222
223         # Delete all records from the calling table. We have no history to
224         # save here. Just re-populate with the latest calling information.
225         $sth = $dbh->prepare("delete from tc_calling ");
226         $sth->execute or die "-E- DB error: $DBI::errstr\n";
227
228         foreach $index (keys %organization_data)
229         {
230                 $name = $organization_data{$index}{'Indiv Name'};
231                 $name =~ s/\'/\\'/g; #'
232                 $organization = $organization_data{$index}{'Organization'};
233                 $organization_by_name{$name} = $organization;
234                 $indiv_id = $organization_data{$index}{'Indiv ID'};
235                 $organization_by_id{$indiv_id} = $organization;
236                 $position = $organization_data{$index}{'Position'};
237                 $sustained = $organization_data{$index}{'Sustained'};
238                 $sustained =~ /(\S+) (\d+)/; $month=$1; $year=$2;
239                 if($name eq "") { next; }
240                 
241                 $sth = $dbh->prepare("select * from tc_individual where mls_id='$indiv_id'");
242                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
243                 my @data = ();
244                 while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); }
245                 my $rows = scalar @data;
246                 if($rows != 1) { next; }
247                 $individual = $data[0]{'individual'};
248
249                 print "   Adding new Calling: $name -> $position\n";
250                 $sth = $dbh->prepare("insert into tc_calling values ('$individual','$organization','$position','$month $year')");
251                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
252         }
253 }
254
255
256 # TC_COMPANION
257 #+----------------------+------------------+------+-----+---------+-------+
258 #| Field                | Type             | Null | Key | Default | Extra |
259 #+----------------------+------------------+------+-----+---------+-------+
260 #| companion            | int(16) unsigned |      | PRI | 0       |       |
261 #| individual           | int(16) unsigned | YES  |     | NULL    |       |
262 #| companionship        | int(16) unsigned | YES  |     | NULL    |       |
263 #| scheduling_priority  | int(10) unsigned | YES  |     | 30      |       |
264 #| valid                | tinyint(1)       | YES  |     | NULL    |       |
265 #+----------------------+------------------+------+-----+---------+-------+
266 #
267 # TC_COMPANIONSHIP
268 #+----------------------+------------------+------+-----+---------+-------+
269 #| Field                | Type             | Null | Key | Default | Extra |
270 #+----------------------+------------------+------+-----+---------+-------+
271 #| companionship        | int(16) unsigned |      | PRI | 0       |       |
272 #| district             | int(16) unsigned | YES  |     | NULL    |       |
273 #| valid                | tinyint(1)       | YES  |     | NULL    |       |
274 #+----------------------+------------------+------+-----+---------+-------+
275 sub update_tc_companionship_table
276 {
277         print "\n-> Updating tc_companionship table\n";
278
279         my %companionships = {};
280
281         # build up hash for each access of companionships and what families they teach
282         foreach $index (keys %hometeaching_data) {
283                 $hashref = $hometeaching_data{$index};
284                 my $compid = $hometeaching_data{$index}{'Comp ID'};
285                 my $household = $hometeaching_data{$index}{'Household'};
286                 #print "household = $household  ::  ";
287                 if ($household =~ /(.*)\s&.*/) { $household = $1; }
288                 #print "household = $household\n";
289                 my $district = $hometeaching_data{$index}{'HT District'};
290                 my $ht1 = $hometeaching_data{$index}{'Home Teacher 1'};
291                 my $ht2 = $hometeaching_data{$index}{'Home Teacher 2'};
292                 my $quorum = $hometeaching_data{$index}{'Quorum'};
293                 if (($compid ne '') && ($quorum =~ m/($default_stewardship)/i)) {
294                         #print "compid=$compid, household=$household, district=$district, ht1=$ht1, ht2=$ht2, quorum=$quorum\n";
295                         $companionships->{$compid}->{'families'}->{$household} = 1;
296                         $companionships->{$compid}->{'district'} = $district;
297                         #print "$district  $companionships->{$compid}->{'district'}\n";
298                         if ($ht1 ne "") { $companionships->{$compid}->{'companions'}->{$ht1} = 1; }
299                         if ($ht2 ne "") { $companionships->{$compid}->{'companions'}->{$ht2} = 1; }
300                 }
301         }
302
303         # loop through each mls companionship and see if there are any changes to companions or familes from what we have in 3rd Counselor
304         for my $companionship (keys %$companionships) {
305                 #print "companionship = $companionship\n";
306                 my $changed = 0;
307                 my $tc_companionship_id = 0;
308                 my $district = $companionships->{$companionship}->{'district'};
309                 #print "district = $district\n";
310                 for my $companion (keys %{$companionships->{$companionship}->{'companions'}}) {
311                         #print "companion = $companion\n";
312                         # see if $companion is in tc_companion
313                         $sth = $dbh->prepare("SELECT * FROM tc_companion AS tc JOIN (tc_individual AS ti, tc_companionship AS tp) WHERE tc.individual=ti.individual AND tc.companionship=tp.companionship AND tp.mls_id=$companionship AND ti.name='$companion' COLLATE latin1_general_cs AND tc.valid=1");
314                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
315                         my @data = ();
316                         while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); }
317                         my $rows = scalar @data;
318                         if($rows == 0) {
319                                 print "   $companion is not in tc_companion\n";
320                                 $changed = 1;
321                                 last;
322                         }
323                         $db_individual = $data[0]->{'individual'};
324                         if ($tc_companionship_id == 0) {
325                                 # set tc_companionship to what was in database
326                                 $tc_companionship_id = $data[0]->{'companionship'};
327                         } elsif ($tc_companionship_id != $data[0]->{'companionship'}) {
328                                 # companionship doesn't match what was in the database, we have a change
329                                 print "   companionship doesn't match what is in database, $tc_companionship_id != $data[0]->{'companionship'}\n";
330                                 $changed = 1;
331                                 last;
332                         }
333
334                         # get list of families assigned to this companionship in database
335                         #print "SELECT * FROM tc_family AS tf JOIN tc_individual AS ti WHERE tf.individual=ti.individual AND tf.companionship=$tc_companionship_id AND tf.valid=1\n";
336                         $sth = $dbh->prepare("SELECT * FROM tc_family AS tf JOIN tc_individual AS ti WHERE tf.individual=ti.individual AND tf.companionship=$tc_companionship_id AND tf.valid=1");
337                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
338                         @data = ();
339                         while ($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); }
340                         for my $row (@data) {
341                                 #print "name: $row->{'name'}\n";
342                                 #print "companionship: $row->{'companionship'}\n";
343                                 # if family is not assigned, we have a change
344                                 if (! exists $companionships->{$companionship}->{'families'}->{$row->{'name'}}) {
345                                         print "   family is not assigned, we have a change:  $row->{'name'}\n";
346                                         $changed = 1;
347                                         last;
348                                 }
349                                 # if companionship assigned to family in database isn't this companionship, we have a change
350                                 if ($tc_companionship_id != $row->{'companionship'}) {
351                                         "companionship assigned to this family in the database isn't this companionship:  $tc_companionship_id, $row->{'companionship'}\n";
352                                         $changed = 1;
353                                         last;
354                                 }
355                         }
356
357                         # loop through families from HomeTeaching.csv
358                         for my $family (keys %{$companionships->{$companionship}->{'families'}}) {
359                                 #print "SELECT * FROM tc_family AS tf JOIN (tc_companionship AS tc, tc_individual AS ti) WHERE tf.companionship=tc.companionship AND tf.individual=ti.individual AND ti.name=\"$family\" COLLATE latin1_general_cs AND tf.valid=1\n";
360                                 $sth = $dbh->prepare("SELECT * FROM tc_family AS tf JOIN (tc_companionship AS tc, tc_individual AS ti) WHERE tf.companionship=tc.companionship AND tf.individual=ti.individual AND ti.name=\"$family\" COLLATE latin1_general_cs AND tf.valid=1");
361                                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
362                                 # if family isn't in tc_family table, we have a change
363                                 # if family in tc_family has a different companionship assigned to it, we have a change
364                                 # no rows here means we have a change
365                                 @familydata = ();
366                                 while ($sqlhashref = $sth->fetchrow_hashref) { push(@familydata, $sqlhashref); }
367                                 if (scalar @familydata == 0) {
368                                         print "   new family, not in db:  $family\n";
369                                         $changed = 1;
370                                         last;
371                                 }
372                         }
373
374                         # last check to break out if we discovered a change
375                         if ($changed == 1)  { last; }
376                 }
377
378                 # we found a change to the companionship
379                 if ($changed == 1) {
380                         # invalidate existing companionship in database
381                         print "   invalidating companionship:$tc_companionship_id\n";
382                         $sth = $dbh->prepare("UPDATE tc_companionship SET valid=0 WHERE companionship='$tc_companionship_id'");
383                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
384                         
385                         # create new companionship in database
386                         print "   creating a new companionship\n";
387                         $sth = $dbh->prepare("INSERT INTO tc_companionship values (NULL,$companionship,$district,1)");
388                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
389                         $comp_id = $dbh->last_insert_id(NULL,NULL,'tc_companionship',NULL);
390                         
391                         # create new companions in database
392                         for my $companion (keys %{$companionships->{$companionship}->{'companions'}}) {
393                                 print "   companion=$companion\n";
394                                 # if companion exists, preserve scheduling_priority
395                                 $sth = $dbh->prepare("SELECT * FROM tc_companion AS tc JOIN (tc_individual AS ti, tc_companionship AS tp) WHERE tc.individual=ti.individual AND tc.companionship=tp.companionship AND tp.mls_id=$companionship AND ti.name=\"$companion\" COLLATE latin1_general_cs AND tc.valid=1");
396                                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
397                                 if ($sqlhashref = $sth->fetchrow_hashref) {
398                                         my $individual = $sqlhashref->{'individual'};
399                                         my $scheduling_priority = $sqlhashref->{'scheduling_priority'};
400                                         print "   adding new companion $individual\n";
401                                         $sth = $dbh->prepare("INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)");
402                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
403                                 } else {
404                                         # new companion, create scheduling_priority first
405                                         print "   adding new companion without existing scheduling_priority\n";
406                                         $sth = $dbh->prepare("INSERT INTO tc_scheduling_priority values (NULL,30,'')");
407                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
408                                         my $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
409                                         
410                                         #print "SELECT * FROM tc_individual WHERE name=\"$companion\" AND valid='1'\n";
411                                         $sth = $dbh->prepare("SELECT * FROM tc_individual WHERE name=\"$companion\" COLLATE latin1_general_cs AND valid='1'");
412                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
413                                         if ($sqlhashref = $sth->fetchrow_hashref) {
414                                                 my $individual = $sqlhashref->{'individual'};
415                                                 #print "INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)\n";
416                                                 $sth = $dbh->prepare("INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)");
417                                                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
418                                         } else {
419                                                 die "trying to add $companion as a companion but doesn't exist in tc_individual - how is this possible!!!\n";
420                                         }
421                                 }
422                         }
423                         
424                         # invalidate existing old companions in database
425                         $sth = $dbh->prepare("UPDATE tc_companion SET valid=0 WHERE companionship=$tc_companionship_id AND valid=1");
426                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
427                         
428                         # don't worry about linking families, that will be done in update_tc_family_table()
429                 } else {
430                         # companionship is the same, just update district in case it changed
431                         $sth = $dbh->prepare("UPDATE tc_companionship SET district=$district WHERE companionship=$tc_companionship_id");
432                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
433                 }
434         }
435 }
436
437 # TC_FAMILY
438 #+----------------------+------------------+------+-----+---------+-------+
439 #| Field                | Type             | Null | Key | Default | Extra |
440 #+----------------------+------------------+------+-----+---------+-------+
441 #| family               | int(16) unsigned |      | PRI | 0       |   A   |
442 #| individual           | int(16) unsigned | YES  |     | NULL    |       |
443 #| companionship        | int(16) unsigned | YES  |     | NULL    |       |
444 #| scheduling_priority  | int(10) unsigned | YES  |     | 30      |       |
445 #| valid                | tinyint(1)       | YES  |     | NULL    |       |
446 #+----------------------+------------------+------+-----+---------+-------+
447 sub update_tc_family_table
448 {
449         print "\n-> Updating tc_family table\n";
450
451         # Set all records to be invalid. Only mark them as valid if they appear on the new list.
452         $sth = $dbh->prepare("update tc_family set valid=0 and companionship=0");
453         $sth->execute or die "-E- DB error: $DBI::errstr\n";
454
455         # find head of households in tc_individual
456         $sth = $dbh->prepare("SELECT * FROM tc_individual WHERE hh_position='Head of Household' and valid=1");
457         $sth->execute or die "-E- DB error: $DBI::errstr\n";
458         my @individual_data = ();
459         while ($sqlhashref = $sth->fetchrow_hashref) { push(@individual_data, $sqlhashref); }
460         my $individual_count = scalar @individual_data;
461         for($i=0;$i<$individual_count;$i++) {
462                 $individual = $individual_data[$i]{'individual'};
463                 $name = $individual_data[$i]{'name'};
464                 
465                 $sth2 = $dbh->prepare("SELECT * FROM tc_family WHERE individual='$individual'");
466                 $sth2->execute or die "-E- DB error: $DBI::errstr\n";
467                 
468                 my @data = ();
469                 while($sqlhashref2 = $sth2->fetchrow_hashref) { push(@data, $sqlhashref2); }
470                 my $rows = scalar @data;
471
472                 if($rows == 0) {
473                         # No existing records found for this family, make a new entry
474                         print "   Adding new Family: $name\n";
475                         $sth2 = $dbh->prepare("INSERT INTO tc_family VALUES (NULL,'$individual','0',NULL,1)");
476                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
477                 } elsif($rows == 1) {
478                         # An existing record was found for this family, update it
479                         print "   Updating existing family: $name\n";
480                         $sth2 = $dbh->prepare("UPDATE tc_family SET valid='1' WHERE individual='$individual'");
481                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
482                 } else {
483                         # More than one record was found. Error! This shouldn't happen.
484                         print "   -E- More than one record found ($rows) for family name: $name\n";
485                 }
486                 
487                 # Now update the hometeaching field for this family
488                 foreach $index (keys %hometeaching_data)
489                 {
490                         $hashref = $hometeaching_data{$index};
491                         foreach $key (keys %$hashref) {
492                                 #if($hometeaching_data{$index}{'Household'} =~ /(\S+)\s+(\S+),\s+(\S+)\s+(.*)/) {
493                                         #$a = $1; $b = $2; $c = $3; $d = $4;
494                                         #if($name =~ /$a/ && $hometeaching_data{$index}{'Household'} !~ /$name/i) { 
495                                                 #print "I: Adjusting hometeaching match from: $hometeaching_data{$index}{'Household'} to $a, $c $d\n";
496                                                 #$hometeaching_data{$index}{'Household'} = "$a, $c $d";
497                                         #}
498                                 #}
499                                 if($key =~ /Quorum/i &&
500                                    $hometeaching_data{$index}{$key} =~ /Elders/i &&
501                                    $hometeaching_data{$index}{'Household'} =~ /$name/i &&
502                                    $data[0]->{companionship} != $hometeaching_data{$index}{'Comp ID'}
503                                   )
504                                 {
505                                         print "   Updating hometeaching assignment for $name family\n";
506                                         $companionship = $hometeaching_data{$index}{'Comp ID'};
507                                         $sth2 = $dbh->prepare("SELECT * FROM tc_companionship WHERE mls_id=$companionship AND valid=1");
508                                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
509                                         if ($sqlhashref = $sth2->fetchrow_hashref) {
510                                                 $companionship = $sqlhashref->{'companionship'};
511                                                 $sth2 = $dbh->prepare("update tc_family set companionship='$companionship' where individual='$individual'");
512                                                 $sth2->execute or die "-E- DB error: $DBI::errstr\n";
513                                         } else {
514                                                 die "-E- companionship doesn't exist for family!\n";
515                                         }
516                                 }
517                         }
518                 }
519                 $sth->finish();
520         }
521 }
522
523 # TC_VISIT
524 #+----------------+------------------+------+-----+---------+-------+
525 #| Field          | Type             | Null | Key | Default | Extra |
526 #+----------------+------------------+------+-----+---------+-------+
527 #| visit          | int(16) unsigned |      | PRI | 0       |   A   |
528 #| family         | int(16) unsigned | YES  | UNI | NULL    |       |
529 #| companionship  | int(16) unsigned | YES  |     | NULL    |       |
530 #| date           | date             | YES  |     | NULL    |       |
531 #| notes          | varchar(128)     | YES  |     | NULL    |       |
532 #| visited        | varchar(1)       | YES  |     | NULL    |       |
533 #+----------------+------------------+------+-----+---------+-------+
534 sub update_tc_visit_table
535 {
536         print "\n-> updating tc_visit table\n";
537         
538         my $month_header_retrieved = 0;
539         my $month_header;
540         my @data_months;
541         my %months = ('Jan', 1, 'Feb', 2, 'Mar', 3, 'Apr', 4, 'May', 5, 'Jun', 6, 'Jul', 7, 'Aug', 8, 'Sep', 9, 'Oct', 10, 'Nov', 11, 'Dec', 12);
542         ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
543         my %visit_status = ('X', 'y', '-', 'n', '', '');
544         
545         foreach $index (keys %hometeaching_stats_data)
546         {
547                 $hashref = $hometeaching_stats_data{$index};
548                 #foreach $key (keys %$hashref) {print "$key\n";}
549                 
550                 $family_name = $hometeaching_stats_data{$index}{"Preferred Name"};
551                 print "   Updating visit data: $family_name\n";
552
553                 # get family id from tc_family
554                 $sth = $dbh->prepare("SELECT * FROM tc_family AS tf JOIN tc_individual AS ti WHERE tf.individual=ti.individual AND ti.name=\"$family_name\" COLLATE latin1_general_cs AND tf.valid=1");
555                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
556                 my @family_data = ();
557                 while($sqlhashref = $sth->fetchrow_hashref) { push(@family_data, $sqlhashref); }
558                 my $family_rows = scalar @family_data;
559                 if($family_rows > 0) { 
560                         $family_id = $family_data[0]->{'family'}; 
561                         $comp_id = $family_data[0]->{'companionship'};
562                 }
563                 else { next; }
564                 #print "family_id = $family_id\n";
565                 #print "comp_id = $comp_id\n";
566                 
567                 # ignore visits that weren't done by the quorum
568                 if ($comp_id == 0) { next; }
569                 
570                 # retrieve the month header if not already done
571                 if ($month_header_retrieved == 0)
572                 {
573                         foreach $key (keys %$hashref) 
574                         {
575                                 if (($key ne "Preferred Name") && ($key ne "Home Teachers"))
576                                 {
577                                         $month_header = $key;
578                                         @data_months = split /\t/, $key;
579                                 }
580                         }
581                         $month_header_retrieved = 1;
582                 }
583                 
584                 # loop through history data
585                 @history = split /\t/, $hometeaching_stats_data{$index}{$month_header};
586                 my $data_year = 1900 + $yearOffset;
587                 my $data_month = $months{$data_months[-1]};
588                 #print "$month_header\n";
589                 #print $hometeaching_stats_data{$index}{$month_header};
590                 #print "\n";
591                 foreach $i (reverse(0..$#history-1)) {
592                         # went back a calendar year, decrement $data_year
593                         if ($months{$data_months[$i]} > $data_month)
594                         {
595                                 $data_year -= 1;
596                         }
597                         $data_month = $months{$data_months[$i]};
598                         my $visit_date = sprintf("%4d-%02d-01\n", $data_year, $data_month);
599                         #print "$visit_date\n";
600                         my $importing_status = $visit_status{$history[$i]};
601                         #print "importing_status = $importing_status\n";
602                         #print "select * from tc_visit where family=$family_id and companionship=$comp_id and date='$visit_date'\n";
603                         $sth = $dbh->prepare("select * from tc_visit where family=$family_id and companionship=$comp_id and date='$visit_date'");
604                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
605                         my @visit_data = ();
606                         while($sqlhashref = $sth->fetchrow_hashref) { push(@visit_data, $sqlhashref); }
607                         my $visit_rows = scalar @visit_data;
608                         if($visit_rows > 0) { 
609                                 my $visited = $visit_data[0]->{'visited'}; 
610                                 #print "visited = $visited\n";
611                                 # update visit if data is different in tc_visit
612                                 if ($visited ne $importing_status)
613                                 {
614                                         #print "importing_status = $importing_status\n";
615                                         $sth = $dbh->prepare("update tc_visit set visited='$importing_status' where family='$family_id' and date='$visit_date' and companionship='$comp_id'");
616                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
617                                 }
618                         } else {
619                                 if ($importing_status ne '')
620                                 {
621                                         # add visit if it doesn't exist in tc_visit
622                                         $sth = $dbh->prepare("insert into tc_visit values (NULL, '$family_id', '$comp_id', '', '', '$visit_date', '', '$importing_status', 'hometeaching')");
623                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
624                                 }
625                         }
626                 }
627         }
628 }
629
630 ######################################################################
631 sub check_for_changed_ids
632 {
633         # If the Indiv ID & HofH ID has changed between data sets, we could have problems
634         my ($oldhashref, $newhashref) = @_;
635         my $found_problem = 0;
636
637         foreach $oldindex (keys %$oldhashref)
638         {
639                 $mls_id = $oldhashref->{$oldindex}{'Indiv ID'};
640                 $hofh_id  = $oldhashref->{$oldindex}{'HofH ID'};
641                 $full_name = $oldhashref->{$oldindex}{'Full Name'};
642                 $hh_position = $oldhashref->{$oldindex}{'HH Position'};
643                 if($hh_position =~ /Other/i) { next; }
644
645                 foreach $newindex (keys %$newhashref)
646                 {
647                         if($newhashref->{$newindex}{'Full Name'} eq $full_name &&
648                            $mls_id != $newhashref->{$newindex}{'Indiv ID'})
649                         {
650                                 print "-W- Indiv ID for $full_name changed from $mls_id to $newhashref->{$newindex}{'Indiv ID'}\n";
651                                 $found_problem = 1;
652                         }
653
654                         if($newhashref->{$newindex}{'Full Name'} eq $full_name &&
655                            $hofh_id != $newhashref->{$newindex}{'HofH ID'})
656                         {
657                                 print "-W- HofH ID for $full_name changed from $hofh_id to $newhashref->{$newindex}{'HofH ID'}\n";
658                                 $found_problem = 1;
659                         }
660                 }
661         }
662
663         return $found_problem;
664 }
665
666 sub update_organization_class_data
667 {
668         print "\n-> Updating organization class info in tc_individual table\n";
669
670         foreach $index (keys %organization_class_data)
671         {
672                 # get name and organization info for each individual
673                 $name = $organization_class_data{$index}{'Preferred Name'};
674                 $fullname = $organization_class_data{$index}{'Full Name'};
675                 $org_class = $organization_class_data{$index}{'Organization Class'};
676
677                 if ($org_class =~ m/Elder/i) {
678                         #print "   $name:  Elder\n";
679                         $sth = $dbh->prepare("update tc_individual set steward='Elder' where name=\"$name\" COLLATE latin1_general_cs AND fullname=\"$fullname\" COLLATE latin1_general_cs");
680                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
681                 }
682                 if ($org_class =~ m/High Priest/i) {
683                         #print "   $name:  High Priest\n";
684                         $sth = $dbh->prepare("update tc_individual set steward='High Priest' where name=\"$name\" COLLATE latin1_general_cs AND fullname=\"$fullname\" COLLATE latin1_general_cs");
685                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
686                 }
687         }
688 }
689
690 sub update_tc_scheduling_priority_table
691 {
692         print "\n-> Updating scheduling priority table\n";
693         
694         # individuals
695         $sth = $dbh->prepare("select * from tc_individual where steward='$default_stewardship' and valid=1");
696         $sth->execute or die "-E- DB error: $DBI::errstr\n";
697         while($sqlhashref = $sth->fetchrow_hashref) {
698                 $individual = $sqlhashref->{individual};
699                 $scheduling_priority = $sqlhashref->{scheduling_priority};
700                 if ($scheduling_priority == 'NULL')
701                 {
702                         $sth2 = $dbh->prepare("insert into tc_scheduling_priority values (NULL, 30, '')");
703                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
704                         $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
705                         $sth2 = $dbh->prepare("update tc_individual set scheduling_priority=$scheduling_priority where individual=$individual");
706                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
707                 }
708         }
709         &remove_obsolete_scheduling_priority("tc_individual");
710         
711         # families
712         $sth = $dbh->prepare("select tf.scheduling_priority, tf.family from tc_family AS tf JOIN tc_individual AS ti ON tf.individual=ti.individual and tf.companionship!='0' and tf.valid=1");
713         $sth->execute or die "-E- DB error: $DBI::errstr\n";
714         while($sqlhashref = $sth->fetchrow_hashref) {
715                 $family = $sqlhashref->{family};
716                 $scheduling_priority = $sqlhashref->{scheduling_priority};
717                 #print "$family   $scheduling_priority\n";
718                 if ($scheduling_priority == 'NULL')
719                 {
720                         $sth2 = $dbh->prepare("insert into tc_scheduling_priority values (NULL, 30, '')");
721                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
722                         $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
723                         $sth2 = $dbh->prepare("update tc_family set scheduling_priority=$scheduling_priority where family=$family");
724                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
725                 }
726         }
727         &remove_obsolete_scheduling_priority("tc_family");
728         
729         # companions
730         $sth = $dbh->prepare("select tc.individual, tc.scheduling_priority from tc_companion AS tc JOIN tc_individual AS ti ON tc.individual=ti.individual and (ti.steward='$default_stewardship' or ti.steward='') and tc.valid=1");
731         $sth->execute or die "-E- DB error: $DBI::errstr\n";
732         while($sqlhashref = $sth->fetchrow_hashref) {
733                 $individual = $sqlhashref->{individual};
734                 $scheduling_priority = $sqlhashref->{scheduling_priority};
735                 #print "$individual   $scheduling_priority\n";
736                 if ($scheduling_priority == 'NULL')
737                 {
738                         $sth2 = $dbh->prepare("insert into tc_scheduling_priority values (NULL, 30, '')");
739                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
740                         $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
741                         $sth2 = $dbh->prepare("update tc_companion set scheduling_priority=$scheduling_priority where individual=$individual");
742                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
743                 }
744         }
745         &remove_obsolete_scheduling_priority("tc_companion");
746 }
747
748 sub remove_obsolete_scheduling_priority
749 {
750         my $table_name = $_[0];
751
752         #print "\n-> Cleaning $table_name\n";
753         
754         #$sth = $dbh->prepare("SELECT scheduling_priority FROM $table_name where scheduling_priority IS NOT NULL AND valid=0");
755         $sth = $dbh->prepare("SELECT * FROM $table_name WHERE valid=0");
756         $sth->execute or die "-E- DB error: $DBI::errstr\n";
757         while($sqlhashref = $sth->fetchrow_hashref) {
758                 $scheduling_priority = $sqlhashref->{scheduling_priority};
759                 $individual = $sqlhashref->{individual};
760                 #$name = $sqlhashref->{name};
761                 if ($scheduling_priority != "NULL") {
762                         #print "$name\n";
763                         # set scheduling_priority to NULL
764                         #print "UPDATE $table_name SET scheduling_priority=NULL WHERE individual=$individual\n";
765                         $sth2 = $dbh->prepare("UPDATE $table_name SET scheduling_priority=NULL WHERE individual=$individual");
766                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
767                         
768                         # remove entry from tc_scheduling_priority
769                         #print "DELETE FROM tc_scheduling_priority WHERE scheduling_priority=$scheduling_priority\n";
770                         $sth2 = $dbh->prepare("DELETE FROM tc_scheduling_priority WHERE scheduling_priority=$scheduling_priority");
771                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
772                 }
773         }
774 }
775
776 ######################################################################
777 # MAIN
778 ######################################################################
779
780 ###################################################
781 # Open a connection to the database
782 $dbh=DBI->connect("dbi:mysql:dbname=$dbname:host=$dbhost:port=$dbport",$dbuser,$dbpass,{
783     AutoCommit=>0,
784     PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2;
785
786 ###################################################
787 # Check old directory against new directory to ensure
788 # that the Indiv ID & HofH ID have not changed between updates
789 if(defined $opt_o) {
790         print "-> Comparing old data files to new ones: $opt_o => $opt_n\n";
791         my %old_membership_data = ();
792         my %new_membership_data = ();
793         &csv_to_hash("$opt_o/Membership.csv",\%old_membership_data);
794         &csv_to_hash("$opt_n/Membership.csv",\%new_membership_data);
795
796         $changed_ids=&check_for_changed_ids(\%old_membership_data, \%new_membership_data);
797
798         if($changed_ids) {
799                 print "\n";
800                 print "-E- Some Indiv IDs and HofH IDs have changed for Head of Households between \n";
801                 print "    $opt_o and $opt_n data sets.\n";
802                 print "    This script is not currently setup to handle this properly.\n";
803                 print "\n";
804                 print "    Exiting without updating...\n\n";
805                 exit;
806         }
807 }
808
809 ###################################################
810 # Process command line options
811 our $datadir;
812 if(defined $opt_n) { $datadir = $opt_n; }
813 else { $datadir = shift(@ARGV); }
814 print "\n-> Processing all ward data files in $datadir\n";
815
816 ###################################################
817 # Parse Ward Data Files
818 &optional_csv_to_hash("$datadir/Organization\ class\ per\ member.csv", \%organization_class_data);
819 &csv_to_hash("$datadir/Membership.csv",\%membership_data);
820 &csv_to_hash("$datadir/HomeTeaching.csv",\%hometeaching_data);
821 &csv_to_hash("$datadir/Organization.csv",\%organization_data);
822 &optional_csv_to_hash("$datadir/Home\ Teacher\ per\ Companionship.csv", \%hometeaching_stats_data);
823 %organization_by_name = ();
824 %organization_by_id = ();
825
826 if($opt_v) {
827         print "-> Membership Data Dump\n\n";
828         &print_hash(\%membership_data);
829         print "-> HomeTeaching Data Dump\n\n";
830         &print_hash(\%hometeaching_data);
831         print "-> Organization Data Dump\n\n";
832         &print_hash(\%organization_data);
833         print "-> HomeTeaching Stats Data Dump\n\n";
834         &print_hash(\%hometeaching_stats_data);
835 }
836
837 if($opt_s) { $dbh->disconnect(); exit; }
838
839 # Now update the various DB tables
840 &update_tc_individual_table();
841 &update_tc_calling_table();
842 &update_tc_companionship_table();
843 &update_tc_family_table();
844 &update_tc_visit_table();
845 &update_organization_class_data();
846 &update_tc_scheduling_priority_table();
847
848 print "\n-> Import Successful! DONE...\n";
849
850 ###################################################
851 # Disconnect from the database
852 $dbh->disconnect();
853
854 ######################################################################
855
856