e0fbb2be93f6caa26e4ccbfea87205d9c761b484
[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                                 next;
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                                 #print "SELECT tc.* 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\" AND tc.valid=1\n";
396                                 $sth = $dbh->prepare("SELECT tc.* 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\" AND tc.valid=1");
397                                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
398                                 if ($sqlhashref = $sth->fetchrow_hashref) {
399                                         my $individual = $sqlhashref->{'individual'};
400                                         my $scheduling_priority = $sqlhashref->{'scheduling_priority'};
401                                         print "   adding new companion $individual\n";
402                                         #print "INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)\n";
403                                         $sth = $dbh->prepare("INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)");
404                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
405                                 } else {
406                                         # new companion, create scheduling_priority first
407                                         print "   adding new companion without existing scheduling_priority\n";
408                                         $sth = $dbh->prepare("INSERT INTO tc_scheduling_priority values (NULL,30,'')");
409                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
410                                         my $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
411                                         
412                                         #print "SELECT * FROM tc_individual WHERE name=\"$companion\" AND valid='1'\n";
413                                         $sth = $dbh->prepare("SELECT * FROM tc_individual WHERE name=\"$companion\" COLLATE latin1_general_cs AND valid='1'");
414                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
415                                         if ($sqlhashref = $sth->fetchrow_hashref) {
416                                                 my $individual = $sqlhashref->{'individual'};
417                                                 #print "INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)\n";
418                                                 $sth = $dbh->prepare("INSERT INTO tc_companion values (NULL,$individual,$comp_id,$scheduling_priority,1)");
419                                                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
420                                         } else {
421                                                 die "trying to add $companion as a companion but doesn't exist in tc_individual - how is this possible!!!\n";
422                                         }
423                                 }
424                         }
425                         
426                         # invalidate existing old companions in database
427                         #print "UPDATE tc_companion SET valid=0 WHERE companionship=$tc_companionship_id AND valid=1\n";
428                         $sth = $dbh->prepare("UPDATE tc_companion SET valid=0 WHERE companionship=$tc_companionship_id AND valid=1");
429                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
430                         
431                         # don't worry about linking families, that will be done in update_tc_family_table()
432                 } else {
433                         # companionship is the same, just update district in case it changed
434                         $sth = $dbh->prepare("UPDATE tc_companionship SET district=$district WHERE companionship=$tc_companionship_id");
435                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
436                 }
437         }
438 }
439
440 # TC_FAMILY
441 #+----------------------+------------------+------+-----+---------+-------+
442 #| Field                | Type             | Null | Key | Default | Extra |
443 #+----------------------+------------------+------+-----+---------+-------+
444 #| family               | int(16) unsigned |      | PRI | 0       |   A   |
445 #| individual           | int(16) unsigned | YES  |     | NULL    |       |
446 #| companionship        | int(16) unsigned | YES  |     | NULL    |       |
447 #| scheduling_priority  | int(10) unsigned | YES  |     | 30      |       |
448 #| valid                | tinyint(1)       | YES  |     | NULL    |       |
449 #+----------------------+------------------+------+-----+---------+-------+
450 sub update_tc_family_table
451 {
452         print "\n-> Updating tc_family table\n";
453
454         # Set all records to be invalid. Only mark them as valid if they appear on the new list.
455         $sth = $dbh->prepare("update tc_family set valid=0 and companionship=0");
456         $sth->execute or die "-E- DB error: $DBI::errstr\n";
457
458         # find head of households in tc_individual
459         $sth = $dbh->prepare("SELECT * FROM tc_individual WHERE hh_position='Head of Household' and valid=1");
460         $sth->execute or die "-E- DB error: $DBI::errstr\n";
461         my @individual_data = ();
462         while ($sqlhashref = $sth->fetchrow_hashref) { push(@individual_data, $sqlhashref); }
463         my $individual_count = scalar @individual_data;
464         for($i=0;$i<$individual_count;$i++) {
465                 $individual = $individual_data[$i]{'individual'};
466                 $name = $individual_data[$i]{'name'};
467                 
468                 $sth2 = $dbh->prepare("SELECT * FROM tc_family WHERE individual='$individual'");
469                 $sth2->execute or die "-E- DB error: $DBI::errstr\n";
470                 
471                 my @data = ();
472                 while($sqlhashref2 = $sth2->fetchrow_hashref) { push(@data, $sqlhashref2); }
473                 my $rows = scalar @data;
474
475                 if($rows == 0) {
476                         # No existing records found for this family, make a new entry
477                         print "   Adding new Family: $name\n";
478                         $sth2 = $dbh->prepare("INSERT INTO tc_family VALUES (NULL,'$individual','0',NULL,1)");
479                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
480                 } elsif($rows == 1) {
481                         # An existing record was found for this family, update it
482                         print "   Updating existing family: $name\n";
483                         $sth2 = $dbh->prepare("UPDATE tc_family SET valid='1' WHERE individual='$individual'");
484                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
485                 } else {
486                         # More than one record was found. Error! This shouldn't happen.
487                         print "   -E- More than one record found ($rows) for family name: $name\n";
488                 }
489                 
490                 # Now update the hometeaching field for this family
491                 foreach $index (keys %hometeaching_data)
492                 {
493                         $hashref = $hometeaching_data{$index};
494                         foreach $key (keys %$hashref) {
495                                 if($key =~ /Quorum/i &&
496                                    $hometeaching_data{$index}{$key} =~ /Elders/i &&
497                                    $hometeaching_data{$index}{'Household'} =~ /$name/i &&
498                                    $data[0]->{companionship} != $hometeaching_data{$index}{'Comp ID'}
499                                   )
500                                 {
501                                         print "   Updating hometeaching assignment for $name family\n";
502                                         $companionship = $hometeaching_data{$index}{'Comp ID'};
503                                         $sth2 = $dbh->prepare("SELECT * FROM tc_companionship WHERE mls_id=$companionship AND valid=1");
504                                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
505                                         if ($sqlhashref = $sth2->fetchrow_hashref) {
506                                                 $companionship = $sqlhashref->{'companionship'};
507                                                 $sth2 = $dbh->prepare("update tc_family set companionship='$companionship' where individual='$individual'");
508                                                 $sth2->execute or die "-E- DB error: $DBI::errstr\n";
509                                         } else {
510                                                 die "-E- companionship doesn't exist for family!\n";
511                                         }
512                                 }
513                         }
514                 }
515                 $sth->finish();
516         }
517 }
518
519 # TC_VISIT
520 #+----------------+------------------+------+-----+---------+-------+
521 #| Field          | Type             | Null | Key | Default | Extra |
522 #+----------------+------------------+------+-----+---------+-------+
523 #| visit          | int(16) unsigned |      | PRI | 0       |   A   |
524 #| family         | int(16) unsigned | YES  | UNI | NULL    |       |
525 #| companionship  | int(16) unsigned | YES  |     | NULL    |       |
526 #| date           | date             | YES  |     | NULL    |       |
527 #| notes          | varchar(128)     | YES  |     | NULL    |       |
528 #| visited        | varchar(1)       | YES  |     | NULL    |       |
529 #+----------------+------------------+------+-----+---------+-------+
530 sub update_tc_visit_table
531 {
532         print "\n-> updating tc_visit table\n";
533         
534         my $month_header_retrieved = 0;
535         my $month_header;
536         my @data_months;
537         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);
538         ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
539         my %visit_status = ('X', 'y', '-', 'n', '', '');
540         
541         foreach $index (keys %hometeaching_stats_data)
542         {
543                 $hashref = $hometeaching_stats_data{$index};
544                 #foreach $key (keys %$hashref) {print "$key\n";}
545                 
546                 $family_name = $hometeaching_stats_data{$index}{"Preferred Name"};
547                 print "   Updating visit data: $family_name\n";
548
549                 # get family id from tc_family
550                 $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");
551                 $sth->execute or die "-E- DB error: $DBI::errstr\n";
552                 my @family_data = ();
553                 while($sqlhashref = $sth->fetchrow_hashref) { push(@family_data, $sqlhashref); }
554                 my $family_rows = scalar @family_data;
555                 if($family_rows > 0) { 
556                         $family_id = $family_data[0]->{'family'}; 
557                         $comp_id = $family_data[0]->{'companionship'};
558                 }
559                 else { next; }
560                 #print "family_id = $family_id\n";
561                 #print "comp_id = $comp_id\n";
562                 
563                 # ignore visits that weren't done by the quorum
564                 if ($comp_id == 0) { next; }
565                 
566                 # retrieve the month header if not already done
567                 if ($month_header_retrieved == 0)
568                 {
569                         foreach $key (keys %$hashref) 
570                         {
571                                 if (($key ne "Preferred Name") && ($key ne "Home Teachers"))
572                                 {
573                                         $month_header = $key;
574                                         @data_months = split /\t/, $key;
575                                 }
576                         }
577                         $month_header_retrieved = 1;
578                 }
579                 
580                 # loop through history data
581                 @history = split /\t/, $hometeaching_stats_data{$index}{$month_header};
582                 my $data_year = 1900 + $yearOffset;
583                 my $data_month = $months{$data_months[-1]};
584                 #print "$month_header\n";
585                 #print $hometeaching_stats_data{$index}{$month_header};
586                 #print "\n";
587                 foreach $i (reverse(0..$#history-1)) {
588                         # went back a calendar year, decrement $data_year
589                         if ($months{$data_months[$i]} > $data_month)
590                         {
591                                 $data_year -= 1;
592                         }
593                         $data_month = $months{$data_months[$i]};
594                         my $visit_date = sprintf("%4d-%02d-01\n", $data_year, $data_month);
595                         #print "$visit_date\n";
596                         my $importing_status = $visit_status{$history[$i]};
597                         #print "importing_status = $importing_status\n";
598                         #print "select * from tc_visit where family=$family_id and companionship=$comp_id and date='$visit_date'\n";
599                         $sth = $dbh->prepare("select * from tc_visit where family=$family_id and companionship=$comp_id and date='$visit_date'");
600                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
601                         my @visit_data = ();
602                         while($sqlhashref = $sth->fetchrow_hashref) { push(@visit_data, $sqlhashref); }
603                         my $visit_rows = scalar @visit_data;
604                         if($visit_rows > 0) { 
605                                 my $visited = $visit_data[0]->{'visited'}; 
606                                 #print "visited = $visited\n";
607                                 # update visit if data is different in tc_visit
608                                 if ($visited ne $importing_status)
609                                 {
610                                         #print "importing_status = $importing_status\n";
611                                         $sth = $dbh->prepare("update tc_visit set visited='$importing_status' where family='$family_id' and date='$visit_date' and companionship='$comp_id'");
612                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
613                                 }
614                         } else {
615                                 if ($importing_status ne '')
616                                 {
617                                         # add visit if it doesn't exist in tc_visit
618                                         $sth = $dbh->prepare("insert into tc_visit values (NULL, '$family_id', '$comp_id', '', '', '$visit_date', '', '$importing_status', 'hometeaching')");
619                                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
620                                 }
621                         }
622                 }
623         }
624 }
625
626 ######################################################################
627 sub check_for_changed_ids
628 {
629         # If the Indiv ID & HofH ID has changed between data sets, we could have problems
630         my ($oldhashref, $newhashref) = @_;
631         my $found_problem = 0;
632
633         foreach $oldindex (keys %$oldhashref)
634         {
635                 $mls_id = $oldhashref->{$oldindex}{'Indiv ID'};
636                 $hofh_id  = $oldhashref->{$oldindex}{'HofH ID'};
637                 $full_name = $oldhashref->{$oldindex}{'Full Name'};
638                 $hh_position = $oldhashref->{$oldindex}{'HH Position'};
639                 if($hh_position =~ /Other/i) { next; }
640
641                 foreach $newindex (keys %$newhashref)
642                 {
643                         if($newhashref->{$newindex}{'Full Name'} eq $full_name &&
644                            $mls_id != $newhashref->{$newindex}{'Indiv ID'})
645                         {
646                                 print "-W- Indiv ID for $full_name changed from $mls_id to $newhashref->{$newindex}{'Indiv ID'}\n";
647                                 $found_problem = 1;
648                         }
649
650                         if($newhashref->{$newindex}{'Full Name'} eq $full_name &&
651                            $hofh_id != $newhashref->{$newindex}{'HofH ID'})
652                         {
653                                 print "-W- HofH ID for $full_name changed from $hofh_id to $newhashref->{$newindex}{'HofH ID'}\n";
654                                 $found_problem = 1;
655                         }
656                 }
657         }
658
659         return $found_problem;
660 }
661
662 sub update_organization_class_data
663 {
664         print "\n-> Updating organization class info in tc_individual table\n";
665
666         foreach $index (keys %organization_class_data)
667         {
668                 # get name and organization info for each individual
669                 $name = $organization_class_data{$index}{'Preferred Name'};
670                 $fullname = $organization_class_data{$index}{'Full Name'};
671                 $org_class = $organization_class_data{$index}{'Organization Class'};
672
673                 if ($org_class =~ m/Elder/i) {
674                         #print "   $name:  Elder\n";
675                         $sth = $dbh->prepare("update tc_individual set steward='Elder' where name=\"$name\" COLLATE latin1_general_cs AND fullname=\"$fullname\" COLLATE latin1_general_cs");
676                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
677                 }
678                 if ($org_class =~ m/High Priest/i) {
679                         #print "   $name:  High Priest\n";
680                         $sth = $dbh->prepare("update tc_individual set steward='High Priest' where name=\"$name\" COLLATE latin1_general_cs AND fullname=\"$fullname\" COLLATE latin1_general_cs");
681                         $sth->execute or die "-E- DB error: $DBI::errstr\n";
682                 }
683         }
684 }
685
686 sub update_tc_scheduling_priority_table
687 {
688         print "\n-> Updating scheduling priority table\n";
689         
690         # individuals
691         $sth = $dbh->prepare("select * from tc_individual where steward='$default_stewardship' and valid=1");
692         $sth->execute or die "-E- DB error: $DBI::errstr\n";
693         while($sqlhashref = $sth->fetchrow_hashref) {
694                 $individual = $sqlhashref->{individual};
695                 $scheduling_priority = $sqlhashref->{scheduling_priority};
696                 if ($scheduling_priority == 'NULL')
697                 {
698                         $sth2 = $dbh->prepare("insert into tc_scheduling_priority values (NULL, 30, '')");
699                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
700                         $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
701                         $sth2 = $dbh->prepare("update tc_individual set scheduling_priority=$scheduling_priority where individual=$individual");
702                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
703                 }
704         }
705         &remove_obsolete_scheduling_priority("tc_individual");
706         
707         # families
708         $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");
709         $sth->execute or die "-E- DB error: $DBI::errstr\n";
710         while($sqlhashref = $sth->fetchrow_hashref) {
711                 $family = $sqlhashref->{family};
712                 $scheduling_priority = $sqlhashref->{scheduling_priority};
713                 #print "$family   $scheduling_priority\n";
714                 if ($scheduling_priority == 'NULL')
715                 {
716                         $sth2 = $dbh->prepare("insert into tc_scheduling_priority values (NULL, 30, '')");
717                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
718                         $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
719                         $sth2 = $dbh->prepare("update tc_family set scheduling_priority=$scheduling_priority where family=$family");
720                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
721                 }
722         }
723         &remove_obsolete_scheduling_priority("tc_family");
724         
725         # companions
726         $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");
727         $sth->execute or die "-E- DB error: $DBI::errstr\n";
728         while($sqlhashref = $sth->fetchrow_hashref) {
729                 $individual = $sqlhashref->{individual};
730                 $scheduling_priority = $sqlhashref->{scheduling_priority};
731                 #print "$individual   $scheduling_priority\n";
732                 if ($scheduling_priority == 'NULL')
733                 {
734                         $sth2 = $dbh->prepare("insert into tc_scheduling_priority values (NULL, 30, '')");
735                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
736                         $scheduling_priority = $dbh->last_insert_id(NULL,NULL,'tc_scheduling_priority',NULL);
737                         #print "update tc_companion set scheduling_priority=$scheduling_priority where individual=$individual\n";
738                         $sth2 = $dbh->prepare("update tc_companion set scheduling_priority=$scheduling_priority where individual=$individual");
739                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
740                 }
741         }
742         &remove_obsolete_scheduling_priority("tc_companion");
743 }
744
745 sub remove_obsolete_scheduling_priority
746 {
747         my $table_name = $_[0];
748
749         #print "\n-> Cleaning $table_name\n";
750         
751         $sth = $dbh->prepare("SELECT * FROM $table_name WHERE valid=0");
752         $sth->execute or die "-E- DB error: $DBI::errstr\n";
753         while($sqlhashref = $sth->fetchrow_hashref) {
754                 $scheduling_priority = $sqlhashref->{scheduling_priority};
755                 $individual = $sqlhashref->{individual};
756                 if ($scheduling_priority != "NULL") {
757                         #print "SELECT * FROM $table_name WHERE scheduling_priority=$scheduling_priority AND valid=1\n";
758                         $sth2 = $dbh->prepare("SELECT * FROM $table_name WHERE scheduling_priority=$scheduling_priority AND valid=1");
759                         $sth2->execute or die "-E- DB error: $DBI::errstr\n";
760                         if (!($sqlhashref2 = $sth2->fetchrow_hashref)) {
761                                 #print "$name\n";
762                                 # set scheduling_priority to NULL
763                                 #print "UPDATE $table_name SET scheduling_priority=NULL WHERE individual=$individual\n";
764                                 $sth3 = $dbh->prepare("UPDATE $table_name SET scheduling_priority=NULL WHERE individual=$individual");
765                                 $sth3->execute or die "-E- DB error: $DBI::errstr\n";
766                                 
767                                 # remove entry from tc_scheduling_priority
768                                 #print "DELETE FROM tc_scheduling_priority WHERE scheduling_priority=$scheduling_priority\n";
769                                 $sth3 = $dbh->prepare("DELETE FROM tc_scheduling_priority WHERE scheduling_priority=$scheduling_priority");
770                                 $sth3->execute or die "-E- DB error: $DBI::errstr\n";
771                                 $sth3->finish();
772                         }
773                         $sth2->finish();
774                 }
775         }
776         $sth->finish();
777 }
778
779 ######################################################################
780 # MAIN
781 ######################################################################
782
783 ###################################################
784 # Open a connection to the database
785 $dbh=DBI->connect("dbi:mysql:dbname=$dbname:host=$dbhost:port=$dbport",$dbuser,$dbpass,{
786     AutoCommit=>0,
787     PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2;
788
789 ###################################################
790 # Check old directory against new directory to ensure
791 # that the Indiv ID & HofH ID have not changed between updates
792 if(defined $opt_o) {
793         print "-> Comparing old data files to new ones: $opt_o => $opt_n\n";
794         my %old_membership_data = ();
795         my %new_membership_data = ();
796         &csv_to_hash("$opt_o/Membership.csv",\%old_membership_data);
797         &csv_to_hash("$opt_n/Membership.csv",\%new_membership_data);
798
799         $changed_ids=&check_for_changed_ids(\%old_membership_data, \%new_membership_data);
800
801         if($changed_ids) {
802                 print "\n";
803                 print "-E- Some Indiv IDs and HofH IDs have changed for Head of Households between \n";
804                 print "    $opt_o and $opt_n data sets.\n";
805                 print "    This script is not currently setup to handle this properly.\n";
806                 print "\n";
807                 print "    Exiting without updating...\n\n";
808                 exit;
809         }
810 }
811
812 ###################################################
813 # Process command line options
814 our $datadir;
815 if(defined $opt_n) { $datadir = $opt_n; }
816 else { $datadir = shift(@ARGV); }
817 print "\n-> Processing all ward data files in $datadir\n";
818
819 ###################################################
820 # Parse Ward Data Files
821 &optional_csv_to_hash("$datadir/Organization\ class\ per\ member.csv", \%organization_class_data);
822 &csv_to_hash("$datadir/Membership.csv",\%membership_data);
823 &csv_to_hash("$datadir/HomeTeaching.csv",\%hometeaching_data);
824 &csv_to_hash("$datadir/Organization.csv",\%organization_data);
825 &optional_csv_to_hash("$datadir/Home\ Teacher\ per\ Companionship.csv", \%hometeaching_stats_data);
826 %organization_by_name = ();
827 %organization_by_id = ();
828
829 if($opt_v) {
830         print "-> Membership Data Dump\n\n";
831         &print_hash(\%membership_data);
832         print "-> HomeTeaching Data Dump\n\n";
833         &print_hash(\%hometeaching_data);
834         print "-> Organization Data Dump\n\n";
835         &print_hash(\%organization_data);
836         print "-> HomeTeaching Stats Data Dump\n\n";
837         &print_hash(\%hometeaching_stats_data);
838 }
839
840 if($opt_s) { $dbh->disconnect(); exit; }
841
842 # Now update the various DB tables
843 &update_tc_individual_table();
844 &update_tc_calling_table();
845 &update_tc_companionship_table();
846 &update_tc_family_table();
847 &update_tc_visit_table();
848 &update_organization_class_data();
849 &update_tc_scheduling_priority_table();
850
851 print "\n-> Import Successful! DONE...\n";
852
853 ###################################################
854 # Disconnect from the database
855 $dbh->disconnect();
856
857 ######################################################################
858
859