From f02dbfe276a992b3b1c674cc1b4075fd97c875e2 Mon Sep 17 00:00:00 2001 From: Alan Jack Pippin Date: Fri, 18 Nov 2005 23:29:50 -0700 Subject: [PATCH] Initial commit --- eq.jpg | Bin 0 -> 71420 bytes import_ward_data | 611 +++++++++++++++++++++++++++++++++++++++++++++++ parse_ward_data | 136 +++++++++++ 3 files changed, 747 insertions(+) create mode 100644 eq.jpg create mode 100755 import_ward_data create mode 100755 parse_ward_data diff --git a/eq.jpg b/eq.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f1886d722345ed8eae5f7ac891300814d4f34ad GIT binary patch literal 71420 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 + { + $line = $_; + @data = split /\",/, $line; + if(!$found_header) { @header = @data; $found_header = 1; } + else { + foreach $i (0..$#data-1) { + $data[$i] =~ s/\"//g; + $header[$i] =~ s/\"//g; + $hashref->{$index}{$header[$i]} = $data[$i]; + #print "$index: $i: $header[$i]: $data[$i]\n"; + } + $index++; + } + } + + close(FILE); +} + +###################################################################### +sub print_hash +{ + my ($hashref) = @_; + + foreach $key (sort {$a <=> $b} keys %$hashref) { + print "Index: $key\n"; + foreach $field (keys %{$hashref->{$key}}) { + print "$field: $hashref->{$key}{$field}\n"; + } + print "\n"; + } +} + +###################################################################### + +# EQ_AARONIC +#+-------+--------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+-------+--------------------+------+-----+---------+-------+ +#| aaronic | int(16) unsigned | | PRI | 0 | A | +#| name | varchar(60) | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+-------+--------------------+------+-----+---------+-------+ +sub update_eq_aaronic_table +{ + print "-> Updating eq_aaronic table\n"; + foreach $index (keys %membership_data) + { + $hashref = $membership_data{$index}; + foreach $key (keys %$hashref) { + if($key =~ /Priesthood/i && + ($membership_data{$index}{$key} =~ /^Teacher\s*$/i || + $membership_data{$index}{$key} =~ /^Priest\s*$/i)) { + $aaronic_name = $membership_data{$index}{'Preferred Name'}; + $sth = $dbh->prepare("select * from eq_aaronic where name='$aaronic_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + my @data = (); + while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); } + my $rows = scalar @data; + if($rows == 0) { + # No existing records found for this aaronic, make a new entry + print " Adding new Aaronic: $aaronic_name\n"; + $sth = $dbh->prepare("insert into eq_aaronic values (NULL,'$aaronic_name',1)"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } elsif($rows == 1) { + # An existing record was found for this aaronic, update it if it is valid + if($data[0]->{valid} == 1) { + print " Updating existing aaronic: $aaronic_name\n"; + } + } else { + # More than one record was found. Error! This shouldn't happen. + print " -E- More than one record found ($rows) for aaronic name: $aaronic_name\n"; + } + } + } + } + $sth->finish(); +} + +# EQ_ELDER +#+------------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+------------+------------------+------+-----+---------+-------+ +#| elder | int(16) unsigned | | PRI | 0 | A | +#| name | varchar(60) | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+------------+------------------+------+-----+---------+-------+ +sub update_eq_elder_table +{ + print "-> Updating eq_elder table\n"; + + # Set all records to be invalid. Only mark them as valid if they appear on the new list. + $sth = $dbh->prepare("update eq_elder set valid=0"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + + foreach $index (keys %membership_data) + { + $hashref = $membership_data{$index}; + foreach $key (keys %$hashref) { + if($key =~ /Priesthood/i && $membership_data{$index}{$key} =~ /Elder/i) { + $elder_name = $membership_data{$index}{'Preferred Name'}; + $sth = $dbh->prepare("select * from eq_elder where name='$elder_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + my @data = (); + while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); } + my $rows = scalar @data; + if($rows == 0) { + # No existing records found for this elder, make a new entry + print " Adding new Elder: $elder_name\n"; + $sth = $dbh->prepare("insert into eq_elder values (NULL,'$elder_name',1)"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } elsif($rows == 1) { + # An existing record was found for this elder, update it + print " Updating existing Elder: $elder_name\n"; + $sth = $dbh->prepare("update eq_elder set valid=1 where name='$elder_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } else { + # More than one record was found. Error! This shouldn't happen. + print " -E- More than one record found ($rows) for Elder: $elder_name\n"; + } + } + } + } + $sth->finish(); +} + +# EQ_DISTRICT +#+------------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+------------+------------------+------+-----+---------+-------+ +#| district | int(16) unsigned | | PRI | 0 | | +#| name | varchar(30) | YES | | NULL | | +#| supervisor | int(16) unsigned | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+------------+------------------+------+-----+---------+-------+ +sub update_eq_district_table +{ + # Districts should be created by hand. This subroutine only + # updates the supervisor's ID in each district. + print "-> Updating eq_district table\n"; + $sth = $dbh->prepare("select * from eq_district"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + while($sqlhashref = $sth->fetchrow_hashref) { + $supervisor_name = $sqlhashref->{name}; + $district = $sqlhashref->{district}; + $sth2 = $dbh->prepare("select * from eq_elder where name='$supervisor_name'"); + $sth2->execute or die "-E- DB error: $DBI::errstr\n"; + $sqlhashref2 = $sth2->fetchrow_hashref; + $supervisor_id = $sqlhashref2->{elder}; + $sth2->finish(); + $sth2 = $dbh->prepare("update eq_district set supervisor='$supervisor_id' where district='$district'"); + $sth2->execute or die "-E- DB error: $DBI::errstr\n"; + $sth2->finish(); + } + $sth->finish(); +} + +# EQ_COMPANIONSHIP +#+---------------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+---------------+------------------+------+-----+---------+-------+ +#| companionship | int(16) unsigned | | | 0 | | +#| elder | int(16) unsigned | YES | | NULL | | +#| aaronic | int(16) unsigned | YES | | NULL | | +#| district | int(16) unsigned | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+---------------+------------------+------+-----+---------+-------+ +sub update_eq_companionship_table +{ + print "-> Updating eq_companionship table\n"; + + # First, mark all existing companionships as invalid in case they have been dissolved + $sth = $dbh->prepare("update eq_companionship set valid=0"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + # Second, mark all the aaronic invalid. We'll only mark the ones as valid that are assigned to hometeach + $sth = $dbh->prepare("update eq_aaronic set valid=0"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + + foreach $index (keys %hometeaching_data) + { + $hashref = $hometeaching_data{$index}; + foreach $key (keys %$hashref) { + if($key =~ /Quorum/i && $hometeaching_data{$index}{$key} =~ /Elders/i) { + foreach $field ("Home Teacher 1","Home Teacher 2") { + $elder_name = $hometeaching_data{$index}{$field}; + if($elder_name eq "") { next; } + $sth2 = $dbh->prepare("select * from eq_elder where name='$elder_name'"); + $sth2->execute or die "-E- DB error: $DBI::errstr\n"; + $sqlhashref2 = $sth2->fetchrow_hashref; + $elder = $sqlhashref2->{elder}; + $aaronic = "NULL"; + if($elder eq "") { + $sth2 = $dbh->prepare("select * from eq_aaronic where name='$elder_name'"); + $sth2->execute or die "-E- DB error: $DBI::errstr\n"; + $sqlhashref2 = $sth2->fetchrow_hashref; + $aaronic = $sqlhashref2->{aaronic}; + $elder = "NULL"; + if($aaronic eq "") { print "-W- Unable to find $elder_name in eq_elder or eq_aaronic tables\n"; } + } + $id = $hometeaching_data{$index}{'Comp ID'}; + $district = $hometeaching_data{$index}{'HT District'}; + $sth = $dbh->prepare("select * from eq_companionship where elder='$elder' and aaronic='$aaronic'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + my @data = (); + while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); } + my $rows = scalar @data; + if($rows == 0) { + # No existing records found for this companionship, make a new entry + print " Adding Elder to companionship: $elder_name -> $id\n"; + $sth = $dbh->prepare("insert into eq_companionship values ($id,'$elder','$aaronic','$district',1)"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } else { + # An existing companionship was found for this companionship, update it + $sth2 = $dbh->prepare("select * from eq_companionship where district='$district' and companionship='$id'"); + $sth2->execute or die "-E- DB error: $DBI::errstr\n"; + if($elder ne "NULL") { + print " Updating Companionship with Elder: $elder_name ($elder) -> $id\n"; + $sth = $dbh->prepare("update eq_companionship set district='$district' where elder='$elder'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_companionship set companionship='$id' where elder='$elder'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_companionship set valid=1 where elder='$elder'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } else { + print " Updating Companionship with Aaronic: $elder_name ($aaronic) -> $id\n"; + $sth = $dbh->prepare("update eq_companionship set district='$district' where aaronic='$aaronic'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_companionship set companionship='$id' where aaronic='$aaronic'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_companionship set valid=1 where aaronic='$aaronic'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_aaronic set valid=1 where aaronic='$aaronic'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } + } + $sth->finish(); + $sth2->finish(); + } + } + } + } +} + +# EQ_FAMILY +#+---------------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+---------------+------------------+------+-----+---------+-------+ +#| family | int(16) unsigned | | PRI | 0 | A | +#| hofh_id | int(16) unsigned | YES | | NULL | | +#| name | varchar(30) | YES | | NULL | | +#| companionship | int(16) unsigned | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+---------------+------------------+------+-----+---------+-------+ +sub update_eq_family_table +{ + print "-> Updating eq_family table\n"; + + # Set all records to be invalid. Only mark them as valid if they appear on the new list. + $sth = $dbh->prepare("update eq_family set valid=0"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + + foreach $index (keys %membership_data) + { + $hashref = $membership_data{$index}; + foreach $key (keys %$hashref) { + if($key =~ /HH Position/i && $membership_data{$index}{$key} =~ /Head of Household/i) { + $family_name = $membership_data{$index}{'Preferred Name'}; + $family_name =~ s/\'/\\'/g; #' + $id = $membership_data{$index}{'HofH ID'}; + + # Find out how many families match this family's name + $sth = $dbh->prepare("select * from eq_family where name='$family_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + my @data = (); + while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); } + my $rows = scalar @data; + + if($rows == 0) { + # No existing records found for this family, make a new entry + print " Adding new Family: $family_name\n"; + $sth = $dbh->prepare("insert into eq_family values (NULL,$id,'$family_name','0',1)"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } elsif($rows == 1) { + # An existing record was found for this family, update it + print " Updating existing family: $family_name\n"; + $sth = $dbh->prepare("update eq_family set hofh_id=$id where name='$family_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_family set valid=1 where name='$family_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } else { + # More than one record was found. Error! This shouldn't happen. + print " -E- More than one record found ($rows) for family name: $family_name\n"; + } + # Now update the hometeaching field for this family + foreach $index (keys %hometeaching_data) + { + $hashref = $hometeaching_data{$index}; + foreach $key (keys %$hashref) { + if($hometeaching_data{$index}{'Household'} =~ /(\S+)\s+(\S+),\s+(\S+)\s+(.*)/) { + print "I: Adjusting hometeaching match from: $hometeaching_data{$index}{'Household'} to $1, $3 $4\n"; + $hometeaching_data{$index}{'Household'} = "$1, $3 $4"; + } + if($key =~ /Quorum/i && + $hometeaching_data{$index}{$key} =~ /Elders/i && + $hometeaching_data{$index}{'Household'} =~ /$family_name/ && + $data[0]->{companionship} != $hometeaching_data{$index}{'Comp ID'} + ) + { + print " Updating hometeaching assignment for $family_name family\n"; + $companionship = $hometeaching_data{$index}{'Comp ID'}; + $sth = $dbh->prepare("update eq_family set companionship='$companionship' where name='$family_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } + } + } + $sth->finish(); + } + } + } +} + +# EQ_PARENT +#+----------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+----------+------------------+------+-----+---------+-------+ +#| parent | int(16) unsigned | | PRI | 0 | A | +#| family | int(16) unsigned | YES | | NULL | | +#| name | varchar(30) | YES | | NULL | | +#| birthday | date | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+----------+------------------+------+-----+---------+-------+ +sub update_eq_parent_table +{ + print "-> Updating eq_parent table\n"; + + # Set all records to be invalid. Only mark them as valid if they appear on the new list. + $sth = $dbh->prepare("update eq_parent set valid=0"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + + foreach $index (keys %membership_data) + { + $hashref = $membership_data{$index}; + foreach $key (keys %$hashref) { + if($key =~ /HH Position/i && + $membership_data{$index}{$key} =~ /Head of Household/i || + $membership_data{$index}{$key} =~ /Spouse/i + ) { + # Get some information from the hash about this parent + $parent_name = $membership_data{$index}{'Preferred Name'}; + $parent_name =~ s/\'/\\'/g; #' + $birthday = $membership_data{$index}{'Birth'}; + $birthday =~ /(\d+) (\S+) (\d+)/; $day=$1; $month=$monthname2num{$2}; $year=$3; + $hofh_id = $membership_data{$index}{'HofH ID'}; + + # Find the family id for this parent's HofH_ID. + $sth = $dbh->prepare("select * from eq_family where hofh_id='$hofh_id'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sqlhashref = $sth->fetchrow_hashref(); + $family_id = $sqlhashref->{'family'}; + + # Find out how many parents match this parent's name + $sth = $dbh->prepare("select * from eq_parent where name='$parent_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + my @data = (); + while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); } + my $rows = scalar @data; + + if($rows == 0) { + # No existing records found for this parent, make a new entry + print " Adding new Parent: $parent_name\n"; + $sth = $dbh->prepare("insert into eq_parent values (NULL,$family_id,'$parent_name','$year-$month-$day',1)"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } elsif($rows == 1) { + # An existing record was found for this parent, update it + print " Updating existing parent: $parent_name\n"; + $sth = $dbh->prepare("update eq_parent set family='$family_id' where name='$parent_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_parent set birthday='$year-$month-$day' where name='$parent_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_parent set valid=1 where name='$parent_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } else { + # More than one record was found. Error! This shouldn't happen. + print " -E- More than one record found with same parent name: $parent_name\n"; + } + $sth->finish(); + } + } + } +} + +# EQ_CHILD +#+----------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+----------+------------------+------+-----+---------+-------+ +#| child | int(16) unsigned | | PRI | 0 | A | +#| family | int(16) unsigned | YES | | NULL | | +#| name | varchar(30) | YES | | NULL | | +#| birthday | date | YES | | NULL | | +#| valid | tinyint(1) | YES | | NULL | | +#+----------+------------------+------+-----+---------+-------+ +sub update_eq_child_table +{ + print "-> Updating eq_child table\n"; + + # Set all records to be invalid. Only mark them as valid if they appear on the new list. + $sth = $dbh->prepare("update eq_child set valid=0"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + + foreach $index (keys %membership_data) + { + $hashref = $membership_data{$index}; + foreach $key (keys %$hashref) { + if($key =~ /HH Position/i && $membership_data{$index}{$key} =~ /Other/i ) { + $child_name = $membership_data{$index}{'Full Name'}; + $child_name =~ s/\'/\\'/g; #' + $birthday = $membership_data{$index}{'Birth'}; + $birthday =~ /(\d+) (\S+) (\d+)/; $day=$1; $month=$monthname2num{$2}; $year=$3; + $id = $membership_data{$index}{'Indiv ID'}; + $hofh_id = $membership_data{$index}{'HofH ID'}; + + # Find the family id for this child's HofH_ID. + $sth = $dbh->prepare("select * from eq_family where hofh_id='$hofh_id'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sqlhashref = $sth->fetchrow_hashref(); + $family_id = $sqlhashref->{'family'}; + + # Find out how many children have the same name for the same family + $sth = $dbh->prepare("select * from eq_child where name='$child_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + my @data = (); + while($sqlhashref = $sth->fetchrow_hashref) { push(@data, $sqlhashref); } + my $rows = scalar @data; + + if($rows == 0) { + # No existing records found for this child, make a new entry + print " Adding new Child: $child_name\n"; + $sth = $dbh->prepare("insert into eq_child values (NULL,$family_id,'$child_name','$year-$month-$day',1)"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } elsif($rows == 1) { + # An existing record was found for this child, update it + print " Updating existing child: $child_name\n"; + $sth = $dbh->prepare("update eq_child set family='$family_id' where name='$child_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_child set birthday='$year-$month-$day' where name='$child_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + $sth = $dbh->prepare("update eq_child set valid=1 where name='$child_name'"); + $sth->execute or die "-E- DB error: $DBI::errstr\n"; + } else { + # More than one record was found. Error! This shouldn't happen. + print " -E- More than one record found ($rows) with same child name: $child_name\n"; + } + $sth->finish(); + } + } + } +} + +###################################################################### +sub check_for_changed_ids +{ + # If the Indiv ID & HofH ID has changed between data sets, we could have problems + my ($oldhashref, $newhashref) = @_; + my $found_problem = 0; + + foreach $oldindex (keys %$oldhashref) + { + $indiv_id = $oldhashref->{$oldindex}{'Indiv ID'}; + $hofh_id = $oldhashref->{$oldindex}{'HofH ID'}; + $full_name = $oldhashref->{$oldindex}{'Full Name'}; + $hh_position = $oldhashref->{$oldindex}{'HH Position'}; + if($hh_position =~ /Other/i) { next; } + + foreach $newindex (keys %$newhashref) + { + if($newhashref->{$newindex}{'Full Name'} eq $full_name && + $indiv_id != $newhashref->{$newindex}{'Indiv ID'}) + { + print "-W- Indiv ID for $full_name changed from $indiv_id to $newhashref->{$newindex}{'Indiv ID'}\n"; + $found_problem = 1; + } + + if($newhashref->{$newindex}{'Full Name'} eq $full_name && + $hofh_id != $newhashref->{$newindex}{'HofH ID'}) + { + print "-W- HofH ID for $full_name changed from $hofh_id to $newhashref->{$newindex}{'HofH ID'}\n"; + $found_problem = 1; + } + } + } + + return $found_problem; +} + +###################################################################### +# MAIN +###################################################################### + +################################################### +# Open a connection to the database +$dbh=DBI->connect("dbi:mysql:dbname=$dbname;host=$dbhost port=$dbport",$dbuser,$dbpass,{ + AutoCommit=>0, + PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2; + +################################################### +# Check old directory against new directory to ensure +# that the Indiv ID & HofH ID have not changed between updates +if(defined $opt_o) { + print "-> Comparing old data files to new ones: $opt_o => $opt_n\n"; + my %old_membership_data = (); + my %new_membership_data = (); + &csv_to_hash("$opt_o/Membership.csv",\%old_membership_data); + &csv_to_hash("$opt_n/Membership.csv",\%new_membership_data); + + $changed_ids=&check_for_changed_ids(\%old_membership_data, \%new_membership_data); + + if($changed_ids) { + print "\n"; + print "-E- Some Indiv IDs and HofH IDs have changed for Head of Households between \n"; + print " $opt_o and $opt_n data sets.\n"; + print " This script is not currently setup to handle this properly.\n"; + print "\n"; + print " Exiting without updating...\n\n"; + exit; + } +} + +################################################### +# Process command line options +if(defined $opt_n) { $datadir = $opt_n; } +else { $datadir = shift(@ARGV); } +print "-> Processing all ward data files in $datadir\n"; + +################################################### +# Parse Ward Data Files +&csv_to_hash("$datadir/Membership.csv",\%membership_data); +&csv_to_hash("$datadir/HomeTeaching.csv",\%hometeaching_data); + +if($opt_v) { + print "-> Membership Data Dump\n\n"; + &print_hash(\%membership_data); + print "-> HomeTeaching Data Dump\n\n"; + &print_hash(\%hometeaching_data); +} + +if($opt_s) { $dbh->disconnect(); exit; } + +# Now update the various eq DB tables +&update_eq_elder_table(); +&update_eq_aaronic_table(); +&update_eq_district_table(); +&update_eq_companionship_table(); +&update_eq_family_table(); +&update_eq_parent_table(); +&update_eq_child_table(); + +################################################### +# Disconnect from the database +$dbh->disconnect(); + +###################################################################### + + + + + + + + + + + + diff --git a/parse_ward_data b/parse_ward_data new file mode 100755 index 0000000..82a1730 --- /dev/null +++ b/parse_ward_data @@ -0,0 +1,136 @@ +#!/usr/bin/perl + +use DBI; +use Getopt::Std; +################################################### +# GLOBALS +$dbname = "phpgroupware"; +$dbhost = "192.168.0.2"; +$dbport = 3306; +$dbuser = "phpgroupware"; +$dbpass = "phpgroupware"; +%hometeaching_data = (); +%membership_data = (); +getopts('vsn:o:b'); + +$monthname2num{'Jan'} = '01'; +$monthname2num{'Feb'} = '02'; +$monthname2num{'Mar'} = '03'; +$monthname2num{'Apr'} = '04'; +$monthname2num{'May'} = '05'; +$monthname2num{'Jun'} = '06'; +$monthname2num{'Jul'} = '07'; +$monthname2num{'Aug'} = '08'; +$monthname2num{'Sep'} = '09'; +$monthname2num{'Oct'} = '10'; +$monthname2num{'Nov'} = '11'; +$monthname2num{'Dec'} = '12'; + +###################################################################### +# SUBROUTINES +###################################################################### +sub csv_to_hash +{ + my ($filename, $hashref) = @_; + + open(FILE,$filename) || die "-E- Could not open $filename for reading\n"; + + my $found_header = 0; my $index = 0; + while() + { + $line = $_; + @data = split /\",/, $line; + if(!$found_header) { @header = @data; $found_header = 1; } + else { + foreach $i (0..$#data-1) { + $data[$i] =~ s/\"//g; + $header[$i] =~ s/\"//g; + $hashref->{$index}{$header[$i]} = $data[$i]; + #print "$index: $i: $header[$i]: $data[$i]\n"; + } + $index++; + } + } + + close(FILE); +} + +###################################################################### +sub print_hash +{ + my ($hashref) = @_; + + foreach $key (sort {$a <=> $b} keys %$hashref) { + print "Index: $key\n"; + foreach $field (keys %{$hashref->{$key}}) { + print "$field: $hashref->{$key}{$field}\n"; + } + print "\n"; + } +} + +###################################################################### +sub print_birthdays +{ + my ($hashref) = @_; + + foreach $key (sort {$a <=> $b} keys %$hashref) { + $name = ""; + $birthday = ""; + foreach $field (keys %{$hashref->{$key}}) { + if($field =~ /Full Name/) { $name = $hashref->{$key}{$field}; } + if($field =~ /Birth/) { $birthday = $hashref->{$key}{$field}; } + } + if($name ne "" && $birthday ne "") { printf "%-30s %-10s\n",$name,$birthday; } + } +} + +###################################################################### +# MAIN +###################################################################### + +################################################### +# Open a connection to the database +$dbh=DBI->connect("dbi:mysql:dbname=$dbname;host=$dbhost port=$dbport",$dbuser,$dbpass,{ + AutoCommit=>0, + PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2; + +################################################### +# Process command line options +if(defined $opt_n) { $datadir = $opt_n; } +else { $datadir = shift(@ARGV); } +print "-> Processing all ward data files in $datadir\n"; + +################################################### +# Parse Ward Data Files +&csv_to_hash("$datadir/Membership.csv",\%membership_data); +&csv_to_hash("$datadir/HomeTeaching.csv",\%hometeaching_data); + +if($opt_v) { + print "-> Membership Data Dump\n\n"; + &print_hash(\%membership_data); + print "-> HomeTeaching Data Dump\n\n"; + &print_hash(\%hometeaching_data); +} + +if($opt_b) { &print_birthdays(\%membership_data); } + +if($opt_s) { $dbh->disconnect(); exit; } + +################################################### +# Disconnect from the database +$dbh->disconnect(); + +###################################################################### + + + + + + + + + + + + -- 2.34.1