From a58bd9386e1e5fa1cdd16936fc29093ed67714db Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 24 Aug 2009 06:39:58 +0000 Subject: (start of) customer move script, RT#5351 --- bin/move-customers | 497 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100755 bin/move-customers (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers new file mode 100755 index 000000000..40219551e --- /dev/null +++ b/bin/move-customers @@ -0,0 +1,497 @@ +#!/usr/bin/perl -w + +#script to move customers from one installation to another +# script is kinda-specific to a somewhat old source installation (1.7? older?) +# target installation has to be 1.9 (after 9/2009) + +use strict; +use vars qw( $sdbh ); +use DBI; +use FS::UID qw( adminsuidsetup dbh ); +use FS::Schema qw( dbdef ); +use FS::Record qw( qsearchs ); +use FS::agent; +use FS::cust_main; +use FS::part_pkg; +use FS::part_svc; +use FS::cust_bill_ApplicationCommon; + +my $DANGEROUS = 1; + +#ssh -p 2222 -L 1080:66.209.32.4:7219 -L 5454:localhost:5432 66.209.32.4 + +#my $source_datasrc = 'DBI:Pg:host=66.209.32.4;dbname=freeside;sslmode=require'; +my $source_datasrc = 'DBI:Pg:host=localhost;port=5454;dbname=freeside'; +my $source_user = 'readonly'; +my $source_pw = ''; + +my @source_agents = ( 2, 7, 3, 4, 5, 1 ); + + +my $dest_agent_typenum = 1; #? + +my $dest_refnum = 1; #XXX + +my $dest_legacy_credit_reasontype = 4; + +my $dest_pkg_classnum = 1; + +#-- + +my $user = shift + or die "Usage:\n (edit variables at top of script and then)\n". + " move-customers user\n"; +adminsuidsetup $user; + +$sdbh = DBI->connect($source_datasrc, $source_user, $source_pw) + or die $DBI::errstr; + +import_table('pkg_class', 'nomap' => 1); + +my $agent_sth = $sdbh->prepare( + 'SELECT * FROM agent WHERE agentnum IN ( '. join(',', @source_agents ). ')' +) or die $sdbh->errstr; + +$agent_sth->execute or die $agent_sth->errstr; + +my %map = (); + +$FS::cust_main::ignore_expired_card = 1; +$FS::cust_main::ignore_expired_card = 1; + +$FS::part_pkg::skip_pkg_svc_hack = 1; +$FS::part_pkg::skip_pkg_svc_hack = 1; + +$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; +$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; + +while ( my $agentrow = $agent_sth->fetchrow_hashref ) { + + my $src_agent = $agentrow->{'agent'}; + + warn "importing customers for $src_agent\n"; + + my $agent = qsearchs('agent', { 'agent' => $src_agent } ); + + if ( $agent ) { + + warn " using existing agentnum ". $agent->agentnum. "\n"; + + if ( $DANGEROUS ) { + warn "DELETING ALL CUSTOMERS OF $src_agent locally \n"; + + foreach my $statement ( + 'DELETE FROM cust_main WHERE agentnum = '. $agent->agentnum, + ( map { "DELETE FROM $_ + WHERE 0 = ( SELECT COUNT(*) FROM cust_main + WHERE cust_main.custnum = $_.custnum ) + " + } + qw( + cust_credit + cust_main_invoice + cust_main_note + cust_pay + cust_refund + ) + ) + #part_pkg, pkg_svc, part_svc, part_svc_column + #pkg_class + ) { + + #warn $statement; + my $sth = dbh->prepare($statement) or die dbh->errstr; + $sth->execute or die $sth->errstr; + + } + + dbh->commit or die dbh->errstr; + + } + + } else { + + warn " creating new agent...\n"; + + $agent = new FS::agent { 'agent' => $src_agent, + 'typenum' => $dest_agent_typenum }; + my $error = $agent->insert; + die $error if $error; + + warn " agentnum ". $agent->agentnum. "\n"; + + } + + my $customer_sth = $sdbh->prepare( + 'SELECT * FROM cust_main WHERE agentnum = '. $agentrow->{'agentnum'} + ) or die $sdbh->errstr; + + $customer_sth->execute or die $customer_sth->errstr; + + while ( my $customerrow = $customer_sth->fetchrow_hashref ) { + #use Data::Dumper; + # warn Dumper($customerrow); + my $src_custnum = $customerrow->{'custnum'}; + + warn " $src_custnum has referral_custnum ". $customerrow->{'referral_custnum'} + if $customerrow->{'referral_custnum'}; + + my $cust_main = new FS::cust_main { + %{ $customerrow }, + 'custnum' => '', + 'referral_custnum' => '', #restore afterwords? + 'refnum' => $dest_refnum, + 'agentnum' => $agent->agentnum, + 'agent_custid' => $src_custnum, + }; + + $cust_main->ship_country('') if $cust_main->ship_country eq ' '; + + my $error = $cust_main->insert; + if ( $error ) { + warn "*** WARNING: error importing customer src custnum $src_custnum: $error"; + use Data::Dumper; + warn Dumper($cust_main) if $src_custnum == 6854; + next; + } + + warn "inserting dest customer ". $cust_main->custnum. " for $src_custnum\n"; + + $map{'cust_main'}->{$src_custnum} = $cust_main->custnum; + + #easy direct cust_main relations: + + #XXX ivan showing up as cust_pay otaker? just deal? + + foreach my $table ( qw( + cust_main_note + cust_pay + ) ) { + import_table( $table, 'custnum' => $src_custnum ); + } + + # crap, cust_credit.reason is text in old db +#*** WARNING: error importing cust_credit src crednum 2200: failed to set reason for [ FS::cust_credit ]: at ./move-customers line 232. + import_table( 'cust_credit', 'custnum' => $src_custnum, + 'insert_opts' => [ 'reason_type' => $dest_legacy_credit_reasontype ], + 'preinsert_callback' => sub { + my($row, $object) = @_; + $object->reason('(none)') if $object->get('reason') =~ /^\s*$/; + }, + ); + + import_table( 'cust_refund', 'custnum' => $src_custnum, + 'post_callback' => sub { + #my( $src_refundnum, $dst_refundnum ) = @_; + my $src_refundnum = shift; + + # cust_credit_refund (map refundnum and crednum...) + import_table( 'cust_credit_refund', + 'refundnum' => $src_refundnum, + 'search' => 'refundum', + 'map' => 'cust_refund', + 'map2' => 'cust_credit', + 'map2key' => 'crednum', + ); + + # cust_pay_refund (map refundnum and paynum...) + import_table( 'cust_pay_refund', + 'refundnum' => $src_refundnum, + 'search' => 'refundum', + 'map' => 'cust_refund', + 'map2' => 'cust_pay', + 'map2key' => 'paynum', + ); + + }, + ); + + # dunno what's up with this (ship_country ' ', fixed) +#*** WARNING: error importing customer src custnum 6854: Illegal (name) (error code illegal_name) ship_last: at ./move-customers line 129. + + # XXX cust_pay_void (something w/ paynum??? huh) or just deal? there's only 110 + + # (not in old db: cust_attachment, cust_statement, cust_location, + # cust_main_exemption, cust_pay_pending ) + # (not used in old db: cust_pay_batch, cust_tax_exempt) + # (not useful to migrate: queue) + + #werid direct cust_main relations: + + # cust_pkg (part_pkg, part_svc, etc.) + import_table( 'cust_pkg', 'custnum' => $src_custnum, + 'preinsert_callback' => sub { + my($row, $object) = @_; + my $src_pkgpart = $row->{'pkgpart'} or die "wtf"; + my $dest_pkgpart = $map{'part_pkg'}->{$src_pkgpart}; + if ( $dest_pkgpart ) { + $object->pkgpart($dest_pkgpart); + return; + } + + my $sth = $sdbh->prepare( + "SELECT * FROM part_pkg WHERE pkgpart = $src_pkgpart" + ) or die $sdbh->errstr; + + $sth->execute or die $sth->errstr; + + my $part_pkg_row = $sth->fetchrow_hashref + or die "cust_pkg.pkgpart missing in part_pkg?!"; + + my $hashref = { + %{ $part_pkg_row }, + 'pkgpart' => '', + }; + my $src_classnum = $part_pkg_row->{'classnum'}; + $hashref->{'classnum'} = $map{'pkg_class'}->{ $src_classnum } + if $src_classnum; + + my $part_pkg = new FS::part_pkg $hashref; + my $error = $part_pkg->insert( 'options' => {} ); + die "*** FATAL: error importing part_pkg src pkgpart $src_pkgpart ". + ": $error" + if $error; + + $map{ 'part_pkg' }->{ $part_pkg_row->{'pkgpart'} } = $part_pkg->pkgpart; + + # part_pkg_option + import_table( 'part_pkg_option', + 'pkgpart' => $src_pkgpart, + 'search' => 'pkgpart', + 'map' => 'part_pkg', + ); + + my $osth = $sdbh->prepare( + "SELECT * FROM part_pkg_option WHERE pkgpart = $src_pkgpart" + ) or die $sdbh->errstr; + + # pkg_svc, part_svc, part_svc_column + import_table( 'pkg_svc', + 'pkgpart' => $src_pkgpart, + 'search' => 'pkgpart', + 'map' => 'part_pkg', + 'preinsert_callback' => sub { + + my($row, $object) = @_; + my $src_svcpart = $row->{'svcpart'} or die "wtf2"; + my $dest_svcpart = $map{'part_svc'}->{$src_svcpart}; + if ( $dest_svcpart ) { + $object->svcpart($dest_svcpart); + return; + } + + my $sth = $sdbh->prepare( + "SELECT * FROM part_svc WHERE svcpart = $src_svcpart" + ) or die $sdbh->errstr; + + $sth->execute or die $sth->errstr; + + my $part_svc_row = $sth->fetchrow_hashref + or die "svcpart missing in part_svc?!"; + + my $hashref = { + %{ $part_svc_row }, + 'svcpart' => '', + }; + + my $part_svc = new FS::part_svc $hashref; + $part_svc->disabled('') if $part_svc->disabled =~ /^\s+$/; + my $error = $part_svc->insert; + die "*** FATAL: error importing part_svc src svcpart $src_svcpart ". + ": $error" + if $error; + + $map{ 'part_svc' }->{ $part_svc_row->{'svcpart'} } = $part_svc->svcpart; + + # part_svc_column + import_table( 'part_svc_column', + 'svcpart' => $src_svcpart, + 'search' => 'svcpart', + 'map' => 'part_svc', + ); + + #what we came here for in the first place + $object->svcpart( $part_svc->svcpart ); + + } + ); + + #what we came here for in the first place + $object->pkgpart( $part_pkg->pkgpart ); + + }, + ); + # end of cust_pkg (part_pkg, part_svc, etc.) + + # cust_bill (invnum move) + import_table( 'cust_bill', 'custnum' => $src_custnum, + 'preinsert_callback' => sub { + my($row, $object) = @_; + $object->agent_invid( $row->{'invnum'} ); + }, + 'post_callback' => sub { + #my( $src_invnum, $dst_invnum ) = @_; + my $src_invnum = shift; + + # cust_bill_pkg ( map invnum and pkgnum... ) + import_table( 'cust_bill_pkg', + 'invnum' => $src_invnum, + 'search' => 'invnum', + 'map' => 'cust_bill', + 'map2' => 'cust_pkg', + 'map2key' => 'pkgnum', + 'post_callback' => sub { + my $src_billpkgnum = shift; + + import_table( 'cust_bill_pkg_detail', + 'billpkgnum' => $src_billpkgnum, + 'search' => 'billpkgnum', + 'map' => 'cust_bill_pkg', + 'addl_from' => 'left join cust_bill_pkg using ( invnum, pkgnum )', + ); + + }, + ); + + # cust_credit_bill (map invnum and crednum... ) + import_table( 'cust_credit_bill', + 'invnum' => $src_invnum, + 'search' => 'invnum', + 'map' => 'cust_bill', + 'map2' => 'cust_credit', + 'map2key' => 'crednum', + 'post_callback' => sub { + my $src_creditbillnum = shift; + #map creditbillnum and billpkgnum + import_table( 'cust_credit_bill_pkg', + 'creditbillnum' => $src_creditbillnum, + 'search' => 'creditbillnum', + 'map' => 'cust_credit_bill', + 'map2' => 'cust_bill_pkg', + 'map2key' => 'billpkgnum', + ); + + }, + ); + + # cust_bill_pay (map invnum and paynum...) + import_table( 'cust_bill_pay', + 'invnum' => $src_invnum, + 'search' => 'invnum', + 'map' => 'cust_bill', + 'map2' => 'cust_pay', + 'map2key' => 'paynum', + 'post_callback' => sub { + my $src_billpaynum = shift; + #map billpaynum and billpkgnum + import_table( 'cust_bill_pay_pkg', + 'billpaynum' => $src_billpaynum, + 'search' => 'billpaynum', + 'map' => 'cust_bill_pay', + 'map2' => 'cust_bill_pkg', + 'map2key' => 'billpkgnum', + ); + }, + ); + }, + ); + + # --- + + # XXX last of the stuff to import... + # & + # cust_pkg_reason (shit, and bring in/remap reasons) + # cust_svc + # then + # svc_acct + # radius_usergroup + # svc_domain + # (rest not in old db) + # svc_acct_pop??? looks like it + # + # (not in old db: cust_pkg_detail) + # (not used in old db: cust_bill_pay_batch, cust_pkg_option) + + # --- + + # (not in old db: cust_bill_pkg_display, cust_bill_pkg_tax_location, + # cust_bill_pkg_tax_rate_location, cust_tax_adjustment, cust_svc_option, ) + # (not used in old db: cust_tax_exempt_pkg) + + #XXX then: + #need to do something about events. mark initial stuff as done or something? + # what else? that's it? + + #do this last, so no notices go out + import_table( 'cust_main_invoice', 'custnum' => $src_custnum ); + + #dbh->commit or die dbh->errstr; + warn "customer ". $cust_main->custnum. " inserted\n"; + #exit; + + } + +} + +sub import_table { + my( $table, %opt ) = @_; + + eval "use FS::$table;"; + die $@ if $@; + + my $map = $opt{'map'} || 'cust_main'; + my $search = $opt{'search'} || 'custnum'; + + $opt{'insert_opts'} ||= []; + + my $primary_key = dbdef->table($table)->primary_key; + + my $addl_from = defined($opt{'addl_from'}) ? $opt{'addl_from'} : ''; + + my $sth = $sdbh->prepare( + "SELECT * FROM $table $addl_from ". + ( $opt{'nomap'} ? '' : " WHERE $search = ". $opt{$search} ) + ) or die $sdbh->errstr; + + $sth->execute or die "(searching $table): ". $sth->errstr; + + while ( my $row = $sth->fetchrow_hashref ) { + #my $src_custnum = $customerrow->{'custnum'}; + + my $hashref = { + %{ $row }, + $primary_key => '', + }; + $hashref->{ $search } = $map{$map}->{ $row->{$search} } + unless $opt{'nomap'}; + + if ( $opt{'map2'} ) { + my $key2 = $opt{'map2key'}; + $hashref->{$key2} = $map{ $opt{'map2'} }->{ $row->{$key2} } + unless $opt{map2key} eq 'pkgnum' && $row->{$key2} eq '0'; + #warn "map $opt{map2}.$opt{map2key}: ". $row->{$key2}. " to ". $map{ $opt{'map2'} }->{ $row->{$key2} }; + } + + my $object = eval "new FS::$table \$hashref;"; + die $@ if $@; + + &{ $opt{preinsert_callback} }( $row, $object ) + if $opt{preinsert_callback}; + + my $error = $object->insert( @{ $opt{'insert_opts'} } ); + if ( $error ) { + warn "*** WARNING: error importing $table src $primary_key ". $row->{$primary_key}. ": $error"; + next; + } + + $map{ $table }->{ $row->{$primary_key} } = $object->get($primary_key); + + &{ $opt{post_callback} }( $row->{$primary_key}, $object->get($primary_key) ) + if $opt{post_callback}; + + } + +} + +1; + -- cgit v1.2.1 From 426211afa7e8c85bde1473f53e15d166df60461a Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 24 Aug 2009 06:50:00 +0000 Subject: (start of) customer move script, RT#5351 --- bin/move-customers | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index 40219551e..1da39b89e 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -146,6 +146,7 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { }; $cust_main->ship_country('') if $cust_main->ship_country eq ' '; + $cust_main->tax('') if $cust_main->tax =~ /^\s+$/; my $error = $cust_main->insert; if ( $error ) { @@ -188,7 +189,7 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { # cust_credit_refund (map refundnum and crednum...) import_table( 'cust_credit_refund', 'refundnum' => $src_refundnum, - 'search' => 'refundum', + 'search' => 'refundnum', 'map' => 'cust_refund', 'map2' => 'cust_credit', 'map2key' => 'crednum', @@ -197,7 +198,7 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { # cust_pay_refund (map refundnum and paynum...) import_table( 'cust_pay_refund', 'refundnum' => $src_refundnum, - 'search' => 'refundum', + 'search' => 'refundnum', 'map' => 'cust_refund', 'map2' => 'cust_pay', 'map2key' => 'paynum', -- cgit v1.2.1 From 6859dc3c623542c1a1f823cc6c18c0191527380a Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 24 Aug 2009 07:08:11 +0000 Subject: (start of) customer move script, RT#5351 --- bin/move-customers | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index 1da39b89e..f1abfb522 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -17,6 +17,7 @@ use FS::part_svc; use FS::cust_bill_ApplicationCommon; my $DANGEROUS = 1; +my $DRY = 1; #ssh -p 2222 -L 1080:66.209.32.4:7219 -L 5454:localhost:5432 66.209.32.4 @@ -46,6 +47,8 @@ adminsuidsetup $user; $sdbh = DBI->connect($source_datasrc, $source_user, $source_pw) or die $DBI::errstr; +$sdbh->{ChopBlanks} = 1; + import_table('pkg_class', 'nomap' => 1); my $agent_sth = $sdbh->prepare( @@ -145,8 +148,8 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { 'agent_custid' => $src_custnum, }; - $cust_main->ship_country('') if $cust_main->ship_country eq ' '; - $cust_main->tax('') if $cust_main->tax =~ /^\s+$/; + #$cust_main->ship_country('') if $cust_main->ship_country eq ' '; + #$cust_main->tax('') if $cust_main->tax =~ /^\s+$/; my $error = $cust_main->insert; if ( $error ) { @@ -248,6 +251,10 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { if $src_classnum; my $part_pkg = new FS::part_pkg $hashref; + + #$part_pkg->setuptax('') if $part_pkg->setuptax =~ /^\s+$/; + #$part_pkg->recurtax('') if $part_pkg->recurtax =~ /^\s+$/; + my $error = $part_pkg->insert( 'options' => {} ); die "*** FATAL: error importing part_pkg src pkgpart $src_pkgpart ". ": $error" @@ -434,6 +441,18 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { } + +warn "import successful!\n" +if ( $DRY ) { + warn "rolling back (dry run)\n"; + dbh->rollback or die dbh->errstr; + warn "rolled back\n" +} else { + warn "commiting\n"; + dbh->commit or die dbh->errstr; + warn "committed\n"; +} + sub import_table { my( $table, %opt ) = @_; -- cgit v1.2.1 From d9a702d507ac900c84a21b9336db3112da313ed8 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 24 Aug 2009 08:50:47 +0000 Subject: (start of) customer move script, RT#5351 --- bin/move-customers | 137 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 27 deletions(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index f1abfb522..8fc7f32bc 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -15,9 +15,10 @@ use FS::cust_main; use FS::part_pkg; use FS::part_svc; use FS::cust_bill_ApplicationCommon; +use FS::svc_Common; my $DANGEROUS = 1; -my $DRY = 1; +my $DRY = 0; #ssh -p 2222 -L 1080:66.209.32.4:7219 -L 5454:localhost:5432 66.209.32.4 @@ -26,7 +27,8 @@ my $source_datasrc = 'DBI:Pg:host=localhost;port=5454;dbname=freeside'; my $source_user = 'readonly'; my $source_pw = ''; -my @source_agents = ( 2, 7, 3, 4, 5, 1 ); +#my @source_agents = ( 2, 7, 3, 4, 5, 1 ); +my @source_agents = ( 1, 2, 3, 4, 5, 7 ); my $dest_agent_typenum = 1; #? @@ -37,6 +39,15 @@ my $dest_legacy_credit_reasontype = 4; my $dest_pkg_classnum = 1; +my %domsvc_map = ( + 1 => 1, + 3653 => 1, + 7634 => 1, +); + +# XXX set passwordmin conf to 4 +# XXX set passwordmax conf to 21 + #-- my $user = shift @@ -50,6 +61,7 @@ $sdbh = DBI->connect($source_datasrc, $source_user, $source_pw) $sdbh->{ChopBlanks} = 1; import_table('pkg_class', 'nomap' => 1); +import_table('svc_acct_pop', 'nomap' => 1); my $agent_sth = $sdbh->prepare( 'SELECT * FROM agent WHERE agentnum IN ( '. join(',', @source_agents ). ')' @@ -58,6 +70,7 @@ my $agent_sth = $sdbh->prepare( $agent_sth->execute or die $agent_sth->errstr; my %map = (); +$map{'_DOMSVC'} = \%domsvc_map; $FS::cust_main::ignore_expired_card = 1; $FS::cust_main::ignore_expired_card = 1; @@ -68,6 +81,9 @@ $FS::part_pkg::skip_pkg_svc_hack = 1; $FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; $FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; +$FS::svc_Common::noexport_hack = 1; +$FS::svc_Common::noexport_hack = 1; + while ( my $agentrow = $agent_sth->fetchrow_hashref ) { my $src_agent = $agentrow->{'agent'}; @@ -125,13 +141,22 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { } - my $customer_sth = $sdbh->prepare( - 'SELECT * FROM cust_main WHERE agentnum = '. $agentrow->{'agentnum'} - ) or die $sdbh->errstr; + $map{'agent'}->{ $agentrow->{'agentnum'} } = $agent->agentnum; + +} - $customer_sth->execute or die $customer_sth->errstr; + #my $customer_sth = $sdbh->prepare( + # 'SELECT * FROM cust_main WHERE agentnum = '. $agentrow->{'agentnum'} + #) or die $sdbh->errstr; +my $customer_sth = $sdbh->prepare( + 'SELECT * FROM cust_main WHERE agentnum IN ( '. join(',', @source_agents ). ') + ORDER BY custnum' +) or die $sdbh->errstr; + +$customer_sth->execute or die $customer_sth->errstr; + +while ( my $customerrow = $customer_sth->fetchrow_hashref ) { - while ( my $customerrow = $customer_sth->fetchrow_hashref ) { #use Data::Dumper; # warn Dumper($customerrow); my $src_custnum = $customerrow->{'custnum'}; @@ -144,7 +169,7 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { 'custnum' => '', 'referral_custnum' => '', #restore afterwords? 'refnum' => $dest_refnum, - 'agentnum' => $agent->agentnum, + 'agentnum' => $map{'agent'}->{ $customerrow->{'agentnum'} }, 'agent_custid' => $src_custnum, }; @@ -180,7 +205,7 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { 'insert_opts' => [ 'reason_type' => $dest_legacy_credit_reasontype ], 'preinsert_callback' => sub { my($row, $object) = @_; - $object->reason('(none)') if $object->get('reason') =~ /^\s*$/; + $object->set('reason', '(none)') if $object->get('reason') =~ /^\s*$/; }, ); @@ -316,6 +341,12 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { 'svcpart' => $src_svcpart, 'search' => 'svcpart', 'map' => 'part_svc', + 'preinsert_callback' => sub { + my($row, $object) = @_; + if ( $object->columnname eq 'domsvc' ) { + $object->columnvalue( $map{'_DOMSVC'}->{ $object->columnvalue } ); + } + }, ); #what we came here for in the first place @@ -328,6 +359,60 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { $object->pkgpart( $part_pkg->pkgpart ); }, + + 'post_callback' => sub { + #my( $src_pkgnum, $dst_pkgnum ) = @_; + my $src_pkgnum = shift; + + #cust_svc + import_table( 'cust_svc', + 'pkgnum' => $src_pkgnum, + 'search' => 'pkgnum', + 'map' => 'cust_pkg', + 'map2' => 'part_svc', + 'map2key' => 'svcpart', + 'post_callback' => sub { + #my( $src_svcnum, $dst_svcnum ) = @_; + my $src_svcnum = shift; + + #svc_domain + import_table( 'svc_domain', + 'svcnum' => $src_svcnum, + 'search' => 'svcnum', + 'map' => 'cust_svc', + 'noblank_primary' => 1, + ); + + #svc_acct + import_table( 'svc_acct', + 'svcnum' => $src_svcnum, + 'search' => 'svcnum', + 'map' => 'cust_svc', + 'noblank_primary' => 1, + 'map2' => 'svc_acct_pop', + 'map2key' => 'popnum', + #'map3' => 'svc_domain', + 'map3' => '_DOMSVC', + 'map3key' => 'domsvc', + ); + + #radius_usergroup + import_table( 'radius_usergroup', + 'svcnum' => $src_svcnum, + 'search' => 'svcnum', + 'map' => 'cust_svc', + ); + + #other svc_ tables not in old db + + }, + ); + + }, + + + + ); # end of cust_pkg (part_pkg, part_svc, etc.) @@ -406,17 +491,9 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { # --- - # XXX last of the stuff to import... - # & + # XXX # cust_pkg_reason (shit, and bring in/remap reasons) - # cust_svc - # then - # svc_acct - # radius_usergroup - # svc_domain - # (rest not in old db) - # svc_acct_pop??? looks like it - # + # (not in old db: cust_pkg_detail) # (not used in old db: cust_bill_pay_batch, cust_pkg_option) @@ -437,12 +514,10 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { warn "customer ". $cust_main->custnum. " inserted\n"; #exit; - } - } -warn "import successful!\n" +warn "import successful!\n"; if ( $DRY ) { warn "rolling back (dry run)\n"; dbh->rollback or die dbh->errstr; @@ -478,20 +553,28 @@ sub import_table { while ( my $row = $sth->fetchrow_hashref ) { #my $src_custnum = $customerrow->{'custnum'}; - my $hashref = { - %{ $row }, - $primary_key => '', - }; + my $hashref = { %$row }; + $hashref->{$primary_key} = '' + unless $opt{'noblank_primary'}; $hashref->{ $search } = $map{$map}->{ $row->{$search} } unless $opt{'nomap'}; if ( $opt{'map2'} ) { my $key2 = $opt{'map2key'}; $hashref->{$key2} = $map{ $opt{'map2'} }->{ $row->{$key2} } - unless $opt{map2key} eq 'pkgnum' && $row->{$key2} eq '0'; + unless $opt{map2key} eq 'pkgnum' && ( $row->{$key2} eq '0' + || $row->{$key2} eq '-1' + ) + or ! defined($row->{$key2}) + or $row->{$key2} eq ''; #warn "map $opt{map2}.$opt{map2key}: ". $row->{$key2}. " to ". $map{ $opt{'map2'} }->{ $row->{$key2} }; } + if ( $opt{'map3'} ) { + my $key3 = $opt{'map3key'}; + $hashref->{$key3} = $map{ $opt{'map3'} }->{ $row->{$key3} }; + } + my $object = eval "new FS::$table \$hashref;"; die $@ if $@; -- cgit v1.2.1 From 523c992d512823f3d2fc16f5a6328a8a72cfecf4 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 24 Aug 2009 11:09:30 +0000 Subject: customer move script, RT#5351 --- bin/move-customers | 153 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 115 insertions(+), 38 deletions(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index 8fc7f32bc..e9f29822a 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -1,6 +1,7 @@ #!/usr/bin/perl -w #script to move customers from one installation to another +# source is remote, destination is local # script is kinda-specific to a somewhat old source installation (1.7? older?) # target installation has to be 1.9 (after 9/2009) @@ -16,6 +17,7 @@ use FS::part_pkg; use FS::part_svc; use FS::cust_bill_ApplicationCommon; use FS::svc_Common; +use FS::cust_event; my $DANGEROUS = 1; my $DRY = 0; @@ -30,59 +32,96 @@ my $source_pw = ''; #my @source_agents = ( 2, 7, 3, 4, 5, 1 ); my @source_agents = ( 1, 2, 3, 4, 5, 7 ); +my $dest_agent_typenum = 1; #XXX change for production -my $dest_agent_typenum = 1; #? +my $dest_refnum = 1; #XXX change for production -my $dest_refnum = 1; #XXX +my $dest_legacy_credit_reasontype = 4; #XXX change for production -my $dest_legacy_credit_reasontype = 4; - -my $dest_pkg_classnum = 1; +my $dest_pkg_classnum = 1; #XXX change for production +#XXX change for production my %domsvc_map = ( 1 => 1, 3653 => 1, 7634 => 1, ); +#XXX change for production +#testing +my %eventparts = ( + 'CARD' => [ 1, ], + 'CHEK' => [], + 'BILL' => [], + 'DCHK' => [], + 'DCRD' => [], + 'COMP' => [], +); +#production +#my %eventparts = ( +# 'CARD' => [ 1, ], +# 'CHEK' => [ 2, ], +# 'BILL' => [ 5, ], +# 'DCHK' => [ 12, ], +# 'DCRD' => [ 15, ], +# 'COMP' => [], +#) + # XXX set passwordmin conf to 4 # XXX set passwordmax conf to 21 #-- +# target(local) setup + my $user = shift or die "Usage:\n (edit variables at top of script and then)\n". " move-customers user\n"; adminsuidsetup $user; +$FS::cust_main::ignore_expired_card = 1; +$FS::cust_main::ignore_expired_card = 1; +$FS::part_pkg::skip_pkg_svc_hack = 1; +$FS::part_pkg::skip_pkg_svc_hack = 1; +$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; +$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; +$FS::svc_Common::noexport_hack = 1; +$FS::svc_Common::noexport_hack = 1; + +my $void_paynum = 2147483646; #top of int range + +# -- + +# source(remote) setup + $sdbh = DBI->connect($source_datasrc, $source_user, $source_pw) or die $DBI::errstr; $sdbh->{ChopBlanks} = 1; +# -- + +my %map = (); +$map{'_DOMSVC'} = \%domsvc_map; + import_table('pkg_class', 'nomap' => 1); import_table('svc_acct_pop', 'nomap' => 1); +#XXX +#import_table('reason_type', 'nomap' => 1); +#foreach my $src_typenum ( keys %{ $map{'reason_type'} } ) { +# import_table('reason', 'reason_type' => $src_typenum, +# 'search' => 'reason_type', +# 'map' => 'reason_type', +# ); +#} + my $agent_sth = $sdbh->prepare( 'SELECT * FROM agent WHERE agentnum IN ( '. join(',', @source_agents ). ')' ) or die $sdbh->errstr; $agent_sth->execute or die $agent_sth->errstr; -my %map = (); -$map{'_DOMSVC'} = \%domsvc_map; - -$FS::cust_main::ignore_expired_card = 1; -$FS::cust_main::ignore_expired_card = 1; - -$FS::part_pkg::skip_pkg_svc_hack = 1; -$FS::part_pkg::skip_pkg_svc_hack = 1; - -$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; -$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; - -$FS::svc_Common::noexport_hack = 1; -$FS::svc_Common::noexport_hack = 1; while ( my $agentrow = $agent_sth->fetchrow_hashref ) { @@ -114,8 +153,9 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { cust_refund ) ) + #pkg_class, part_pkg_pop #part_pkg, pkg_svc, part_svc, part_svc_column - #pkg_class + #XXX more... does it matter? ) { #warn $statement; @@ -188,16 +228,26 @@ while ( my $customerrow = $customer_sth->fetchrow_hashref ) { $map{'cust_main'}->{$src_custnum} = $cust_main->custnum; - #easy direct cust_main relations: + #now import the relations, easy and hard: - #XXX ivan showing up as cust_pay otaker? just deal? + import_table( 'cust_main_note', 'custnum' => $src_custnum ); - foreach my $table ( qw( - cust_main_note - cust_pay - ) ) { - import_table( $table, 'custnum' => $src_custnum ); - } + import_table( 'cust_pay', 'custnum' => $src_custnum, + #ivan showing up as cust_pay otaker + # old db doesn't have cust_pay.otaker, pull it from history + 'preinsert_callback' => sub { + my($row, $cust_pay) = @_; + + my $sth = $sdbh->prepare( + "SELECT history_user FROM h_cust_pay WHERE history_action = 'insert' + AND paynum = ". $row->{'paynum'} + ) or die $sdbh->errstr; + $sth->execute or die $sth->errstr; + my $otaker = $sth->fetchrow_arrayref->[0]; + + $cust_pay->otaker($otaker); + }, + ); # crap, cust_credit.reason is text in old db #*** WARNING: error importing cust_credit src crednum 2200: failed to set reason for [ FS::cust_credit ]: at ./move-customers line 232. @@ -238,7 +288,13 @@ while ( my $customerrow = $customer_sth->fetchrow_hashref ) { # dunno what's up with this (ship_country ' ', fixed) #*** WARNING: error importing customer src custnum 6854: Illegal (name) (error code illegal_name) ship_last: at ./move-customers line 129. - # XXX cust_pay_void (something w/ paynum??? huh) or just deal? there's only 110 + # cust_pay_void + import_table( 'cust_pay_void', 'custnum' => $src_custnum, + 'preinsert_callback' => sub { + my($row, $object) = @_; + $object->paynum( $void_paynum-- ); + }, + ); # (not in old db: cust_attachment, cust_statement, cust_location, # cust_main_exemption, cust_pay_pending ) @@ -364,6 +420,16 @@ while ( my $customerrow = $customer_sth->fetchrow_hashref ) { #my( $src_pkgnum, $dst_pkgnum ) = @_; my $src_pkgnum = shift; + #XXX grr... action makes this very hard... + ## cust_pkg_reason (shit, and bring in/remap reasons) + #import_table( 'cust_pkg_reason', + # 'pkgnum' => $src_pkgnum, + # 'search' => 'pkgnum', + # 'map' => 'cust_pkg', + # 'map2' => 'reason', + # 'map2key' => 'reasonnum', + # ); + #cust_svc import_table( 'cust_svc', 'pkgnum' => $src_pkgnum, @@ -423,8 +489,8 @@ while ( my $customerrow = $customer_sth->fetchrow_hashref ) { $object->agent_invid( $row->{'invnum'} ); }, 'post_callback' => sub { - #my( $src_invnum, $dst_invnum ) = @_; - my $src_invnum = shift; + my( $src_invnum, $dst_invnum ) = @_; + #my $src_invnum = shift; # cust_bill_pkg ( map invnum and pkgnum... ) import_table( 'cust_bill_pkg', @@ -486,14 +552,29 @@ while ( my $customerrow = $customer_sth->fetchrow_hashref ) { ); }, ); + + #need to do something about events. mark initial stuff as done + foreach my $eventpart ( @{ $eventparts{$cust_main->payby} } ) { + + my $cust_event = new FS::cust_event { + 'eventpart' => $eventpart, + 'tablenum' => $dst_invnum, + '_date' => time, # XXX something? probably not + 'status' => 'done', + }; + + my $error = $cust_event->insert; + die "*** FATAL: error inserting cust_event for eventpart $eventpart,". + " tablenum (invnum) $dst_invnum: $error" + if $error; + + } + }, ); # --- - # XXX - # cust_pkg_reason (shit, and bring in/remap reasons) - # (not in old db: cust_pkg_detail) # (not used in old db: cust_bill_pay_batch, cust_pkg_option) @@ -503,10 +584,6 @@ while ( my $customerrow = $customer_sth->fetchrow_hashref ) { # cust_bill_pkg_tax_rate_location, cust_tax_adjustment, cust_svc_option, ) # (not used in old db: cust_tax_exempt_pkg) - #XXX then: - #need to do something about events. mark initial stuff as done or something? - # what else? that's it? - #do this last, so no notices go out import_table( 'cust_main_invoice', 'custnum' => $src_custnum ); -- cgit v1.2.1 From f407a661ea76f6cc7621e10a23ab32eb74ced115 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 27 Aug 2009 10:04:50 +0000 Subject: ok --- bin/move-customers | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index e9f29822a..c78b6ac25 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -18,8 +18,9 @@ use FS::part_svc; use FS::cust_bill_ApplicationCommon; use FS::svc_Common; use FS::cust_event; +use FS::svc_domain; -my $DANGEROUS = 1; +my $DANGEROUS = 0; my $DRY = 0; #ssh -p 2222 -L 1080:66.209.32.4:7219 -L 5454:localhost:5432 66.209.32.4 @@ -32,43 +33,38 @@ my $source_pw = ''; #my @source_agents = ( 2, 7, 3, 4, 5, 1 ); my @source_agents = ( 1, 2, 3, 4, 5, 7 ); -my $dest_agent_typenum = 1; #XXX change for production +my $dest_agent_typenum = 12; -my $dest_refnum = 1; #XXX change for production +my $dest_refnum = 60; -my $dest_legacy_credit_reasontype = 4; #XXX change for production +my $dest_legacy_credit_reasontype = 5; -my $dest_pkg_classnum = 1; #XXX change for production +my $dest_pkg_classnum = 6; -#XXX change for production my %domsvc_map = ( - 1 => 1, - 3653 => 1, - 7634 => 1, + 1 => 20450, + 3653 => 20162, + 7634 => 20451, ); -#XXX change for production #testing -my %eventparts = ( - 'CARD' => [ 1, ], - 'CHEK' => [], - 'BILL' => [], - 'DCHK' => [], - 'DCRD' => [], - 'COMP' => [], -); -#production #my %eventparts = ( # 'CARD' => [ 1, ], -# 'CHEK' => [ 2, ], -# 'BILL' => [ 5, ], -# 'DCHK' => [ 12, ], -# 'DCRD' => [ 15, ], +# 'CHEK' => [], +# 'BILL' => [], +# 'DCHK' => [], +# 'DCRD' => [], # 'COMP' => [], -#) - -# XXX set passwordmin conf to 4 -# XXX set passwordmax conf to 21 +); +#production +my %eventparts = ( + 'CARD' => [ 1, ], + 'CHEK' => [ 2, ], + 'BILL' => [ 5, ], + 'DCHK' => [ 12, ], + 'DCRD' => [ 15, ], + 'COMP' => [], +) #-- @@ -87,6 +83,8 @@ $FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; $FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1; $FS::svc_Common::noexport_hack = 1; $FS::svc_Common::noexport_hack = 1; +$FS::svc_domain::whois_hack = 1; +$FS::svc_domain::whois_hack = 1; my $void_paynum = 2147483646; #top of int range -- cgit v1.2.1 From 55332cb444a9d80e168737e5132c458f1cc44450 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 27 Aug 2009 10:23:12 +0000 Subject: doh --- bin/move-customers | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index c78b6ac25..d237d1237 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -55,7 +55,7 @@ my %domsvc_map = ( # 'DCHK' => [], # 'DCRD' => [], # 'COMP' => [], -); +#); #production my %eventparts = ( 'CARD' => [ 1, ], @@ -64,7 +64,7 @@ my %eventparts = ( 'DCHK' => [ 12, ], 'DCRD' => [ 15, ], 'COMP' => [], -) +); #-- -- cgit v1.2.1 From 524540eab151b455d661b2cc2adf71e38f5ca6eb Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 27 Aug 2009 10:26:41 +0000 Subject: try, try again --- bin/move-customers | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'bin/move-customers') diff --git a/bin/move-customers b/bin/move-customers index d237d1237..a7ea19781 100755 --- a/bin/move-customers +++ b/bin/move-customers @@ -19,6 +19,7 @@ use FS::cust_bill_ApplicationCommon; use FS::svc_Common; use FS::cust_event; use FS::svc_domain; +use FS::cust_pkg; my $DANGEROUS = 0; my $DRY = 0; @@ -85,6 +86,8 @@ $FS::svc_Common::noexport_hack = 1; $FS::svc_Common::noexport_hack = 1; $FS::svc_domain::whois_hack = 1; $FS::svc_domain::whois_hack = 1; +$FS::cust_pkg::disable_agentcheck = 1; +$FS::cust_pkg::disable_agentcheck = 1; my $void_paynum = 2147483646; #top of int range @@ -127,7 +130,7 @@ while ( my $agentrow = $agent_sth->fetchrow_hashref ) { warn "importing customers for $src_agent\n"; - my $agent = qsearchs('agent', { 'agent' => $src_agent } ); + my $agent = qsearchs('agent', { 'agent' => $src_agent, 'disabled' => '' } ); if ( $agent ) { -- cgit v1.2.1