From ef6afc4759daca2c218e5cdee08e9b162bbb9c95 Mon Sep 17 00:00:00 2001 From: Rogan Hamby Date: Thu, 3 Aug 2017 15:28:57 -0400 Subject: [PATCH 1/1] adding basic program to convert from Apollo LDF to staging tables --- apollo/README | 11 + apollo/apollo_exporter.pl | 671 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 682 insertions(+), 0 deletions(-) create mode 100644 apollo/README create mode 100755 apollo/apollo_exporter.pl diff --git a/apollo/README b/apollo/README new file mode 100644 index 0000000..15f0696 --- /dev/null +++ b/apollo/README @@ -0,0 +1,11 @@ +apollo_exporter.pl exports from the XML based Apollo LDF format to postgres staging stages. + +To Do: + +authorities +holidays (we usually se those manually) +locations (we've only had single locations to test with so far) +patron attributes not seen in export and not supported here - vacations, wish list, photos, phone carriers +seen in extract and not migrated Purchase Request, Passwords (bcrypted and salted), Call Range, inventoryHolding, problems (notes/Holding), booklists +user defined values are set manually here and should be done programatically so they don't have to be set manually each time probably to a distinct +table rather than in patrons diff --git a/apollo/apollo_exporter.pl b/apollo/apollo_exporter.pl new file mode 100755 index 0000000..f1bc568 --- /dev/null +++ b/apollo/apollo_exporter.pl @@ -0,0 +1,671 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Data::Dumper; +use Getopt::Long; +use XML::LibXML; +use Switch; +use open ':encoding(utf8)'; + +select(STDERR); +$| = 1; +select(STDOUT); +$| = 1; + +my $mig_schema; +my $ldif_xml; + +my $ret = GetOptions( + 'ldif_xml:s' => \$ldif_xml +); +if (!defined $ldif_xml) {$ldif_xml = 'export.xml'}; + +print "Parsing LDIF ... "; +my $parser = XML::LibXML->new(); +my $dom = $parser->parse_file($ldif_xml); +print "done.\n\n"; + +user_defined_values($dom,'user_defined_values.tsv'); +asset_copy_locations($dom,'asset_copy_location_legacy.tsv'); +actor_usr_groups($dom,'actor_usr_legacy_groups.tsv'); +actor_usr($dom,'actor_usr_legacy.tsv','actor_usr_address_legacy.tsv','actor_usr_phones.tsv','actor_usr_note_legacy.tsv','money_billing_legacy.tsv'); +biblio_record_entry($dom,'biblio_record_entry_legacy.tsv'); +action_uses($dom,'action_in_house_use_legacy.tsv','in-library'); +action_uses($dom,'action_circulation_legacy.tsv','circulation'); +action_uses($dom,'action_transit_copy_legacy.tsv','transit'); +action_uses($dom,'action_hold_request_shelf.tsv','reserve'); +action_hold_request($dom,'action_hold_request_legacy.tsv'); +asset_copy($dom,'asset_copy_legacy.tsv'); +asset_copy_note($dom,'asset_copy_note_legacy.tsv'); + +print "Staging tables conversion completed.\n\n"; + +################################################################# +sub user_defined_values { + my $dom = shift; + my $outfile = shift; + + print "Parsing for user defined values... "; + my @user_defined; + foreach my $def ($dom->findnodes('//userdef')) { + push @user_defined, { + id => $def->findvalue('./@id'), + record_type => $def->findvalue('./@record'), + name => $def->findvalue('./@name'), + type => $def->findvalue('./@type') + }; + } + + my $num_rows = @user_defined; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + + print "writing $outfile ... "; + + print $out_fh "id\trecord_type\tname\ttype\n"; + + foreach my $built_hash( @user_defined ) { + print $out_fh "$built_hash->{id}\t"; + print $out_fh "$built_hash->{record_type}\t"; + print $out_fh "$built_hash->{name}\t"; + print $out_fh "$built_hash->{type}\n"; + } + + close $out_fh; + print "$num_rows rows written plus headers.\n"; +} + +sub asset_copy_note { + my $dom = shift; + my $outfile = shift; + + print "Parsing for holdings values... "; + my @holdings; + foreach my $copy ($dom->findnodes('//holding')) { + if (length($copy->findvalue('./@deleted')) > 1) { next; } + foreach my $note ($copy->findnodes('.//holdingNote')) { + push @holdings, { + copy_id => $copy->findvalue('./@id'), + active => $note->findvalue('./@active'), + note => $note->findvalue('./@note') + }; + } + } + + my $num_rows = @holdings; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + print "writing $outfile ... "; + print $out_fh "copy_id\tactive\tnote\n"; + foreach my $built_hash( @holdings ) { + print $out_fh "$built_hash->{copy_id}\t"; + print $out_fh "$built_hash->{active}\t"; + print $out_fh "$built_hash->{note}\n"; + } + + close $out_fh; + print "$num_rows rows written plus headers.\n"; +} + +sub asset_copy { + my $dom = shift; + my $outfile = shift; + + print "Parsing for holdings values... "; + my @holdings; + foreach my $copy ($dom->findnodes('//holding')) { + if (length($copy->findvalue('./@deleted')) > 1) { next; } + my $memberships; + foreach my $mship ($copy->findnodes('./membership')) { + if (defined $memberships) { $memberships = $memberships . '|' . $mship->to_literal; } + else { $memberships = $mship->to_literal; } + } + push @holdings, { + id => $copy->findvalue('./@id'), + memberships => $memberships, + location => $copy->findvalue('./@location'), + deleted_type => $copy->findvalue('./@deletedType'), + status => $copy->findvalue('./@status'), + deleted => $copy->findvalue('./@deleted'), + barcode => $copy->findvalue('./@barcode'), + biblio => $copy->findvalue('./@biblio'), + usage_count => $copy->findvalue('./@usageCount'), + price_cents => $copy->findvalue('./@priceCents'), + call => $copy->findvalue('./@call'), + edited => $copy->findvalue('./@edited') + }; + } + + my $num_rows = @holdings; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + print "writing $outfile ... "; + print $out_fh "id\tmemberships\tlocation\tdeleted_type\tstatus\tdeleted\tbarcode\tbiblio\tusage_count\tprice_cents\tcall\tedited\n"; + foreach my $built_hash( @holdings ) { + print $out_fh "$built_hash->{id}\t"; + print $out_fh "$built_hash->{memberships}\t"; + print $out_fh "$built_hash->{location}\t"; + print $out_fh "$built_hash->{deleted_type}\t"; + print $out_fh "$built_hash->{status}\t"; + print $out_fh "$built_hash->{deleted}\t"; + print $out_fh "$built_hash->{barcode}\t"; + print $out_fh "$built_hash->{biblio}\t"; + print $out_fh "$built_hash->{usage_count}\t"; + print $out_fh "$built_hash->{price_cents}\t"; + print $out_fh "$built_hash->{call}\t"; + print $out_fh "$built_hash->{edited}\n"; + } + + close $out_fh; + print "$num_rows rows written plus headers.\n"; +} + +sub action_hold_request { + my $dom = shift; + my $out_file = shift; + + print "Parsing users data for hold requests ... "; + my @holds; + foreach my $patron ($dom->findnodes('///patron')) { + foreach my $request ($patron->findnodes('.//reserve')) { + if (length($request->findvalue('./@resolved')) > 1) { next; } + push @holds, { #patron id, reserve id should be redundant but leaving in for error checking + id => $request->findvalue('./@id'), + patron_barcode => $patron->findvalue('./@barcode'), + patron_id => $patron->findvalue('./@id'), + biblio => $request->findvalue('./@biblio'), + status => $request->findvalue('./@status'), + resolved => $request->findvalue('./@resolved'), + placed => $request->findvalue('./@placed'), + }; + } + } + + my $num_rows = @holds; + open my $out_fh, ">:utf8", $out_file or die "can not open $out_file file for writing.\n"; + print "writing $out_file ... \n"; + print $out_fh "id\tpatron_barcode\tpatron_id\tbiblio\tstatus\tresolved\tplaced\n"; + foreach my $built_hash( @holds ) { + print $out_fh "$built_hash->{id}\t"; + print $out_fh "$built_hash->{patron_barcode}\t"; + print $out_fh "$built_hash->{patron_id}\t"; + print $out_fh "$built_hash->{biblio}\t"; + print $out_fh "$built_hash->{status}\t"; + print $out_fh "$built_hash->{resolved}\t"; + print $out_fh "$built_hash->{placed}\n"; + } + close $out_fh; + print "$num_rows rows written plus headers to $out_file.\n"; +} + +sub asset_copy_locations { + my $dom = shift; + my $outfile = shift; + + print "Parsing for copy locations... "; + my @copy_locations; + foreach my $membershiplist ($dom->findnodes('///holdingMembershipList')) { + my $membershiplist_id = $membershiplist->findvalue('./@id'); + my $membershiplist_name = $membershiplist->findvalue('./@name'); + foreach my $membership ($membershiplist->findnodes('./holdingMembership')) { + push @copy_locations, { + membership_list_id => $membershiplist_id, + membership_list_name => $membershiplist_name, + membership_number => $membership->findvalue('./@number'), + membership_name => $membership->findvalue('./@name'), + membership_id => $membership->findvalue('./@id') + }; + } + } + + my $num_rows = @copy_locations; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + + print "writing $outfile ... "; + + #print headers + print $out_fh "membership_list_id\tmembership_list_name\tmembership_id\tmembership_number\tmembership_name\n"; + + foreach my $built_hash( @copy_locations ) { + print $out_fh "$built_hash->{membership_list_id}\t"; + print $out_fh "$built_hash->{membership_list_name}\t"; + print $out_fh "$built_hash->{membership_number}\t"; + print $out_fh "$built_hash->{membership_name}\t"; + print $out_fh "$built_hash->{membership_id}\n"; + } + + close $out_fh; + print "$num_rows rows written plus headers.\n"; +} + + +sub action_uses { + my $dom = shift; + my $outfile = shift; + my $table_type = shift; + + switch ($table_type) { + case 'transit' {print "Parsing for copy transits ... ";} + case 'in-library' {print "Parsing for in house uses ... ";} + case 'circulation' {print "Parsing for circulations ... ";} + } + + my @checkouts; #not exporting the memberships since we have the patron id to link + foreach my $circ ($dom->findnodes('//checkout')) { + my $renewals = 0; + if ($table_type eq 'circulation') { + if ($circ->findvalue('./@type') ne 'normal') { next; } + if (length($circ->findvalue('./@due')) < 1) { next; } #bunch of records with no due dates, cause not clear + if (length($circ->findvalue('./@returned')) > 0) { next; } + } + if ($table_type eq 'transit') { + if ($circ->findvalue('./@type') ne 'transt') { next; } + if (length($circ->findvalue('./@returned')) > 0) { next; } + } + if ($table_type eq 'in-library') { + if ($circ->findvalue('./@type') ne 'in-library') { next; } + } + if ($table_type eq 'reserve') { + if ($circ->findvalue('./@type') ne 'reserve') { next; } + if ($circ->findvalue('./@status') ne 'out') { next; } + } + + foreach ($circ->findnodes('./renewal')) { + $renewals++; #normally don't move move over previous circs in renewal sequence so just counting them + } + push @checkouts, { + id => $circ->findvalue('./@id'), + patron => $circ->findvalue('./@patron'), + out => $circ->findvalue('./@out'), + due => $circ->findvalue('./@due'), + status => $circ->findvalue('./@status'), + holding => $circ->findvalue('./@holding'), + returned => $circ->findvalue('./@returned'), + type => $circ->findvalue('./@type'), + out_location => $circ->findvalue('./@outLocation'), + returned_location => $circ->findvalue('./@returnedLocation'), + reserve_id => $circ->findvalue('./@reserveId'), + self_check => $circ->findvalue('./@selfCheck'), + renewals => $renewals + }; + } + + my $num_rows = @checkouts; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + + print "writing $outfile ... "; + + print $out_fh "id\tpatron\tout\tdue\tstatus\tholding\treturned\ttype\tout_location\treturned_location\treserve_id\tself_check\trenewals\n"; + + foreach my $built_hash( @checkouts ) { + print $out_fh "$built_hash->{id}\t"; + print $out_fh "$built_hash->{patron}\t"; + print $out_fh "$built_hash->{out}\t"; + print $out_fh "$built_hash->{due}\t"; + print $out_fh "$built_hash->{status}\t"; + print $out_fh "$built_hash->{holding}\t"; + print $out_fh "$built_hash->{returned}\t"; + print $out_fh "$built_hash->{type}\t"; + print $out_fh "$built_hash->{out_location}\t"; + print $out_fh "$built_hash->{returned_location}\t"; + print $out_fh "$built_hash->{reserve_id}\t"; + print $out_fh "$built_hash->{self_check}\t"; + print $out_fh "$built_hash->{renewals}\n"; + } + close $out_fh; + print "$num_rows rows written plus headers.\n"; + +} + +sub actor_usr_groups { + my $dom = shift; + my $outfile = shift; + + print "Parsing for user groups... "; + my @user_groups; + foreach my $membershiplist ($dom->findnodes('///patronMembershipList')) { + + my $membershiplist_id = $membershiplist->findvalue('./@id'); + my $membershiplist_name = $membershiplist->findvalue('./@name'); + foreach my $membership ($membershiplist->findnodes('./patronMembership')) { + push @user_groups, { + membership_list_id => $membershiplist_id, + membership_list_name => $membershiplist_name, + membership_length_months => $membership->findvalue('./@membershipLengthMonths'), + membership_name => $membership->findvalue('./@name'), + membership_id => $membership->findvalue('./@id'), + membership_number => $membership->findvalue('./@number') + }; + } + } + + my $num_rows = @user_groups; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + + print "writing $outfile ... "; + + print $out_fh "membership_list_id\tmembership_list_name\tmembership_id\tmembership_number\tmembership_name\tmembership_length_months\n"; + + foreach my $built_hash( @user_groups ) { + print $out_fh "$built_hash->{membership_list_id}\t"; + print $out_fh "$built_hash->{membership_list_name}\t"; + print $out_fh "$built_hash->{membership_number}\t"; + print $out_fh "$built_hash->{membership_name}\t"; + print $out_fh "$built_hash->{membership_id}\t"; + print $out_fh "$built_hash->{membership_length_months}\n"; + } + + close $out_fh; + print "$num_rows rows written plus headers.\n"; +} + +sub actor_usr { + my $dom = shift; + my $out_user_file = shift; + my $out_address_file = shift; + my $out_phone_file = shift; + my $out_note_file = shift; + my $out_fine_file = shift; + + my @users; + my @user_addresses; + my @user_phones; + my @user_notes; + my @patron_fines; + + print "Parsing users for addresses, patrons, fines, notes, etc... \n"; + foreach my $patron ($dom->findnodes('///patron')) { + my $first_names; + my $middle_names; + my $preferred_names; + my $birthdates; + foreach my $f_name ($patron->findnodes('.//firstName')) { + if (defined $first_names) { $first_names = $first_names . '|' . $f_name->findvalue('./@name'); } + else { $first_names = $f_name->findvalue('./@name'); } + if (defined $birthdates) { $birthdates = $birthdates . '|' . $f_name->findvalue('./@birthdate'); } + else { $birthdates = $f_name->findvalue('./@birthdate'); } + if (defined $middle_names) { $middle_names = $middle_names . '|' . $f_name->findvalue('./@middleName'); } + else { $middle_names = $f_name->findvalue('./@middleName'); } + if (defined $preferred_names) { $preferred_names = $preferred_names . '|' . $f_name->findvalue('./@preferredName'); } + else { $preferred_names = $f_name->findvalue('./@preferredName'); } + } + my $memberships; + foreach my $mship ($patron->findnodes('.//membership')) { + if (defined $memberships) { $memberships = $memberships . '|' . $mship->to_literal; } + else { $memberships = $mship->to_literal; } + } + my $emails; + foreach my $email ($patron->findnodes('.//email')) { + if (defined $emails) { $emails = $emails . ',' . $email->findvalue('./@address'); } + else { $emails = $email->findvalue('./@address'); } + } + #lazy code, do programatically later + my $u3710; + my $u3714; + foreach my $ud ($patron->findnodes('./userdefVal')) { + if ($ud->findvalue('./@uID') eq 'u3710') { $u3710 = $ud->findvalue('./@value')}; + if ($ud->findvalue('./@uID') eq 'u3714') { $u3714 = $ud->findvalue('./@value')}; + } + push @users, { + patron_barcode => $patron->findvalue('./@barcode'), + created => $patron->findvalue('./@created'), + usage_count => $patron->findvalue('./@usageCount'), + family_id => $patron->findvalue('./@familyID'), + expiration => $patron->findvalue('./@expiration'), + patron_id => $patron->findvalue('./@id'), + last_name => $patron->findvalue('./@lastName'), + edited => $patron->findvalue('./@edited'), + emails => $emails, + first_names => $first_names, + middle_names => $middle_names, + preferred_names => $preferred_names, + birthdates => $birthdates, + memberships => $memberships, + reserve_contact => $patron->findvalue('./reserveContactDefault/@contact'), + reserve_contact_sms => $patron->findvalue('./reserveContactDefault/@sms'), + overdue_contact => $patron->findvalue('./overdueContact/@contact'), + overdue_contact_sms => $patron->findvalue('./overdueContact/@sms'), + due_warning_contact => $patron->findvalue('./dueWarningContact/@contact'), + due_warning_contact_sms => $patron->findvalue('./dueWarningContact/@sms'), + internet => $u3714, + birthdate => $u3710 + }; + + my $lines; + foreach my $address ($patron->findnodes('.//address')) { + foreach my $add_line ($address->findnodes('./line')) { + if (defined $lines) { $lines = $lines . '|' . $add_line->to_literal; } + else { $lines = $add_line->to_literal; } + } + push @user_addresses, { + patron_barcode => $patron->findvalue('./@barcode'), + patron_id => $patron->findvalue('./@id'), + lines => $lines, + locality => $address->findvalue('./@locality'), + country_division => $address->findvalue('./@countryDivision'), + country => $address->findvalue('./@country'), + postal_code => $address->findvalue('./@postalCode'), + mailing => $address->findvalue('./@mailing') + }; + } + + foreach my $phone ($patron->findnodes('.//phone')) { + push @user_phones, { + patron_barcode => $patron->findvalue('./@barcode'), + patron_id => $patron->findvalue('./@id'), + number => $phone->findvalue('./@number'), + area_code => $phone->findvalue('./@areaCode'), + type => $phone->findvalue('./@type'), #should be home/work/mobile/other/none + phone_id => $phone->findvalue('./@id'), + country_code => $phone->findvalue('./@countryCode') + }; + } + + foreach my $note ($patron->findnodes('.//patronNote')) { + my $message = $note->findvalue('./@message'); + $message =~ s/\\$//; + push @user_notes, { + patron_barcode => $patron->findvalue('./@barcode'), + patron_id => $patron->findvalue('./@id'), + active => $note->findvalue('./@active'), + signature => $note->findvalue('./@signature'), + urgent => $note->findvalue('./@urgent'), + sensitive => $note->findvalue('./@sensitive'), + date_added => $note->findvalue('./dateAdded'), + date_cleared => $note->findvalue('./dateCleared'), + last_updated => $note->findvalue('./dateUpdated'), + message => $message + }; + } + + foreach my $fine ($patron->findnodes('.//fine')) { + push @patron_fines, { + patron_barcode => $patron->findvalue('./@barcode'), + patron_id => $patron->findvalue('./@id'), + fine_id => $fine->findvalue('./@id'), + checkout => $fine->findvalue('./@checkout'), + amount_paid_cents => $fine->findvalue('./@amountPaidCents'), + status => $fine->findvalue('./@status'), + updated => $fine->findvalue('./@updated'), + amountCents=> $fine->findvalue('./@amountCents') + }; + } + + } + + my $num_user_rows = @users; + open my $out_user_fh, ">:utf8", $out_user_file or die "can not open $out_user_file file for writing.\n"; + print "writing $out_user_file ... \n"; + print $out_user_fh "patron_id\tpatron_barcode\tcreated\tusage_count\tfamily_id\texpiration\tedited\tlast_name\tfirst_name\tmiddle_name\tpreferred_name\tbirthdates\temails\tmemberships\treserve_contact\treserve_contact_sms\toverdue_contact\toverdue_contact_sms\tdue_warning_contact\tdue_warning_sms\tbirthdate\tinternet\n"; + foreach my $built_user_hash( @users ) { + print $out_user_fh "$built_user_hash->{patron_id}\t"; + print $out_user_fh "$built_user_hash->{patron_barcode}\t"; + print $out_user_fh "$built_user_hash->{created}\t"; + print $out_user_fh "$built_user_hash->{usage_count}\t"; + print $out_user_fh "$built_user_hash->{family_id}\t"; + print $out_user_fh "$built_user_hash->{expiration}\t"; + print $out_user_fh "$built_user_hash->{edited}\t"; + print $out_user_fh "$built_user_hash->{last_name}\t"; + print $out_user_fh "$built_user_hash->{first_names}\t"; #plural names indicate arrays seperated by pipe + print $out_user_fh "$built_user_hash->{middle_names}\t"; + print $out_user_fh "$built_user_hash->{preferred_names}\t"; + print $out_user_fh "$built_user_hash->{birthdates}\t"; + print $out_user_fh "$built_user_hash->{emails}\t"; + print $out_user_fh "$built_user_hash->{memberships}\t"; + print $out_user_fh "$built_user_hash->{reserve_contact}\t"; + print $out_user_fh "$built_user_hash->{reserve_contact_sms}\t"; + print $out_user_fh "$built_user_hash->{overdue_contact}\t"; + print $out_user_fh "$built_user_hash->{overdue_contact_sms}\t"; + print $out_user_fh "$built_user_hash->{due_warning_contact}\t"; + print $out_user_fh "$built_user_hash->{due_warning_contact_sms}\t"; + print $out_user_fh "$built_user_hash->{birthdate}\t"; + print $out_user_fh "$built_user_hash->{internet}\n"; + } + close $out_user_fh; + print "$num_user_rows rows written plus headers to $out_user_file.\n"; + + my $num_address_rows = @user_addresses; + open my $out_address_fh, ">:utf8", $out_address_file or die "can not open $out_address_file file for writing.\n"; + print "writing $out_address_file ... \n"; + print $out_address_fh "patron_id\tpatron_barcode\tlines\tlocality\tcountry_division\tcountry\tpostal_code\tmailing\n"; + foreach my $built_address_hash( @user_addresses ) { + print $out_address_fh "$built_address_hash->{patron_id}\t"; + print $out_address_fh "$built_address_hash->{patron_barcode}\t"; + print $out_address_fh "$built_address_hash->{lines}\t"; + print $out_address_fh "$built_address_hash->{locality}\t"; + print $out_address_fh "$built_address_hash->{country_division}\t"; + print $out_address_fh "$built_address_hash->{country}\t"; + print $out_address_fh "$built_address_hash->{postal_code}\t"; + print $out_address_fh "$built_address_hash->{mailing}\n"; + } + close $out_address_fh; + print "$num_address_rows rows written plus headers to $out_address_file.\n"; + + my $num_phone_rows = @user_phones; + open my $out_phone_fh, ">:utf8", $out_phone_file or die "can not open $out_phone_file file for writing.\n"; + print "writing $out_phone_file ... \n"; + print $out_phone_fh "patron_id\tpatron_barcode\tphone_id\tnumber\tarea_code\ttype\tcountry_code\n"; + foreach my $built_phone_hash( @user_phones ) { + print $out_phone_fh "$built_phone_hash->{patron_id}\t"; + print $out_phone_fh "$built_phone_hash->{patron_barcode}\t"; + print $out_phone_fh "$built_phone_hash->{phone_id}\t"; + print $out_phone_fh "$built_phone_hash->{number}\t"; + print $out_phone_fh "$built_phone_hash->{area_code}\t"; + print $out_phone_fh "$built_phone_hash->{type}\t"; + print $out_phone_fh "$built_phone_hash->{country_code}\n"; + } + close $out_phone_fh; + print "$num_phone_rows rows written plus headers to $out_phone_file.\n"; + + my $num_note_rows = @user_notes; + open my $out_note_fh, ">:utf8", $out_note_file or die "can not open $out_note_file file for writing.\n"; + print "writing $out_note_file ... \n"; + print $out_note_fh "patron_id\tpatron_barcode\tactive\tsignature\turgent\tsensitive\tdate_added\tdate_cleared\tlast_updated\tmessage\n"; + foreach my $built_note_hash( @user_notes ) { + print $out_note_fh "$built_note_hash->{patron_id}\t"; + print $out_note_fh "$built_note_hash->{patron_barcode}\t"; + print $out_note_fh "$built_note_hash->{active}\t"; + print $out_note_fh "$built_note_hash->{signature}\t"; + print $out_note_fh "$built_note_hash->{urgent}\t"; + print $out_note_fh "$built_note_hash->{sensitive}\t"; + print $out_note_fh "$built_note_hash->{date_added}\t"; + print $out_note_fh "$built_note_hash->{date_cleared}\t"; + print $out_note_fh "$built_note_hash->{last_updated}\t"; + print $out_note_fh "$built_note_hash->{message}\n"; + } + close $out_note_fh; + print "$num_note_rows rows written plus headers to $out_note_file.\n"; + + my $num_fine_rows = @patron_fines; + open my $out_fine_fh, ">:utf8", $out_fine_file or die "can not open $out_fine_file file for writing.\n"; + print "writing $out_fine_file ... \n"; + print $out_fine_fh "patron_id\tpatron_barcode\tfine_id\tcheckout\tamount_paid_cents\tstatus\tupdated\tamountCents\n"; + foreach my $built_fine_hash( @patron_fines ) { + print $out_fine_fh "$built_fine_hash->{patron_id}\t"; + print $out_fine_fh "$built_fine_hash->{patron_barcode}\t"; + print $out_fine_fh "$built_fine_hash->{fine_id}\t"; + print $out_fine_fh "$built_fine_hash->{checkout}\t"; + print $out_fine_fh "$built_fine_hash->{amount_paid_cents}\t"; + print $out_fine_fh "$built_fine_hash->{status}\t"; + print $out_fine_fh "$built_fine_hash->{updated}\t"; + print $out_fine_fh "$built_fine_hash->{amountCents}\n"; + } + close $out_fine_fh; + print "$num_fine_rows rows written plus headers to $out_fine_file.\n"; +} + +sub biblio_record_entry { + my $dom = shift; + my $outfile = shift; + + open my $out_fh, ">:utf8", $outfile or die "can not open $outfile file for writing.\n"; + my $num_rows = 0; + print "Parsing for bib records...\n"; + print $out_fh "id\tusage_count\tstatus\tadded\tedited\tmarc\n"; + foreach my $bib ($dom->findnodes('///biblio')) { + my $id = $bib->findvalue('./@id'); + my $usageCount = $bib->findvalue('./@usageCount'); + my $status = $bib->findvalue('./@status'); + my $added = $bib->findvalue('./@added'); + my $edited = $bib->findvalue('./@edited'); + my $marc = $bib->toString; + $marc =~ s///g; + $marc =~ s/<\/bib.+?>//g; + $marc =~ s/\R//g; + $marc =~ s/\s+\s+/>/g; + print $out_fh "$id\t"; + print $out_fh "$usageCount\t"; + print $out_fh "$status\t"; + print $out_fh "$added\t"; + print $out_fh "$edited\t"; + print $out_fh "$marc\n"; + $num_rows++; + } + close $out_fh; + print "$num_rows rows written plus headers.\n"; +} + +sub abort { + my $msg = shift; + print STDERR "$0: $msg", "\n"; + print_usage(); + exit 1; +} + + +sub print_usage { + print <<_USAGE_; + +LDIF Exporter loads an ldif xml file version 032 into staging tables +to load into Evergreen. This implementation assumes that the user +is using a distinct Postgres schema to stage tables from. The Exporter +creates linked tables in the schema to production tables that inherit +sequences and then child tables with data to manipulate. + +For example: patron data will be loaded in m_foo.actor_usr which inherits +from actor.usr and a m_foo.actor_usr_legacy is created. The table is +prepopulated with likely data but legacy value is suppplied in the legacy +table in l_ so it can be non-destrutively manipulated. + +LDIF Exporter requires the following parameter: + + --mig_schema - the staging schema of the migration + +Optionally you may also provide a file with --ldif_xml + +If --ldif_xml is not used then it will assume there is an export.xml file and +fail if not found. + + + +_USAGE_ +} + -- 1.7.2.5