#!/usr/bin/perl -w use strict; #use Getopt::Std; use FS::UID qw( adminsuidsetup dbh ); use FS::Record qw( qsearch ); use FS::part_bill_event; use FS::part_event; use FS::cust_bill_event; use FS::cust_event; #use vars qw( $opt_m ); #getopts('m'); my $user = shift or die &usage; adminsuidsetup($user); my %plan2action = ( 'fee' => 'fee', 'fee_percent' => 'NOTYET', #XXX need fee_percent action 'suspend' => 'suspend', 'suspend-if-balance' => 'suspend', #"if balance" becomes the balance cond 'suspend-if-pkgpart' => 'suspend_if_pkgpart', 'suspend-unless-pkgpart' => 'suspend_unless_pkgpart', 'cancel' => 'cancel', 'addpost' => 'addpost', 'comp' => 'NOTYET', #XXX or N/A or something 'credit' => 'writeoff', 'realtime-card' => 'cust_bill_realtime_card', 'realtime-check' => 'cust_bill_realtime_check', 'realtime-lec' => 'cust_bill_realtime_lec', 'batch-card' => 'cust_bill_batch', #?'retriable' => 'send' => 'cust_bill_send', 'send_email' => 'cust_bill_email', 'send_alternate' => 'cust_bill_send_alternate', 'send_if_newest' => 'cust_bill_send_if_newest', 'send_agent' => 'cust_bill_send_agent', 'send_csv_ftp' => 'cust_bill_send_csv_ftp', 'spool_csv', => 'cust_bill_spool_csv', 'bill' => 'bill', 'apply' => 'apply', 'collect' => 'collect', ); foreach my $part_bill_event ( qsearch({ 'table' => 'part_bill_event', }) ) { print $part_bill_event->event; my $action = $plan2action{ $part_bill_event->plan }; if ( $action eq 'NOTYET' ) { warn "not migrating part_bill_event.eventpart ".$part_bill_event->eventpart. "; ". $part_bill_event->plan. " plan not (yet) handled"; next; } elsif ( ! $action ) { warn "not migrating part_bill_event.eventpart ".$part_bill_event->eventpart. "; unknown plan ". $part_bill_event->plan; next; } my %plandata = map { /^(\w+) (.*)$/; ($1, $2); } split(/\n/, $part_bill_event->plandata); #XXX may need to fudge some other plandata2option names my $balanceover = 0; my $honor_dundate = 0; if ( $part_bill_event->plan eq 'suspend-if-balance' ) { $balanceover = delete $plandata{'balanceover'}; $honor_dundate = ( (delete $plandata{'balance_honor_dundate'}) =~ /1/ ); } my $part_event = new FS::part_event { 'event' => $part_bill_event->event, 'eventtable' => 'cust_bill', 'check_freq' => $part_bill_event->freq || '1d', 'weight' => $part_bill_event->weight, 'action' => $action, 'disabled' => $part_bill_event->disabled, }; my $error = $part_event->insert(\%plandata); die "error inserting part_event: $error\n" if $error; print ' '. $part_event->eventpart; my $once = new FS::part_event_condition { 'eventpart' => $part_event->eventpart, 'conditionname' => 'once' }; $error = $once->insert; die $error if $error; my $balance = new FS::part_event_condition { 'eventpart' => $part_event->eventpart, 'conditionname' => 'balance' }; $error = $balance->insert( 'balance' => $balanceover ); die $error if $error; my $cust_bill_owed = new FS::part_event_condition { 'eventpart' => $part_event->eventpart, 'conditionname' => 'cust_bill_owed' }; $error = $cust_bill_owed->insert( 'owed' => 0 ); die $error if $error; my $payby = new FS::part_event_condition { 'eventpart' => $part_event->eventpart, 'conditionname' => 'payby' }; $error = $payby->insert( 'payby' => { $part_bill_event->payby => 1 } ); die $error if $error; if ( $part_bill_event->seconds ) { my $age = new FS::part_event_condition { 'eventpart' => $part_event->eventpart, 'conditionname' => 'cust_bill_age' }; $error = $age->insert( 'age' => ($part_bill_event->seconds/86400 ).'d' ); die $error if $error; } if ( $honor_dundate ) { my $dundate = new FS::part_event_condition { 'eventpart' => $part_event->eventpart, 'conditionname' => 'dundate' }; $error = $dundate->insert(); die $error if $error; } #my $derror = $part_bill_event->delete; #die "error removing part_bill_event: $derror\n" if $derror; # if ( $opt_m ) { my $sth = dbh->prepare(' INSERT INTO cust_event ( eventpart, tablenum, _date, status, statustext ) SELECT ? , invnum , _date, status, statustext FROM cust_bill_event WHERE eventpart = ? ') or die dbh->errstr; $sth->execute( $part_event->eventpart, $part_bill_event->eventpart ) or die $sth->errstr; # } else { # # foreach my $cust_bill_event ( # qsearch({ # 'table' => 'cust_bill_event', # 'hashref' => { 'eventpart' => $part_bill_event->eventpart, }, # }) # ) { # # my $cust_event = new FS::cust_event { # 'eventpart' => $part_event->eventpart, # 'tablenum' => $cust_bill_event->invnum, # '_date' => $cust_bill_event->_date, # 'status' => $cust_bill_event->status, # 'statustext' => $cust_bill_event->statustext, # }; # # my $cerror = $cust_event->insert; # #die "error inserting cust_event: $cerror\n" if $cerror; # warn "error inserting cust_event: $cerror\n" if $cerror; # # #my $dcerror = $cust_bill_event->delete; # #die "error removing cust_bill_event: $dcerror\n" if $dcerror; # # print "."; # # } # # } print "\n"; } sub usage { die "Usage:\n freeside-migrate-events user\n"; } =head1 NAME freeside-migrate-events - Migrates 1.7/1.8-style invoice events to 1.9/2.0-style billing events =head1 SYNOPSIS freeside-migrate-events =head1 DESCRIPTION Migrates events from L to L and friends, and from L records to L =head1 BUGS Doesn't migrate any action options yet. Doesn't translate option names that changed. Doesn't migrate reasons. Doesn't delete the old events (which is not a big deal, since the new code won't run them...) Can take lots of memory for large databases. =head1 SEE ALSO =cut 1; __END__ #part_bill_event part_event # #eventpart n/a #event event #freq check_freq #payby part_event_condition.conditionname = payby #eventcode PARSE_WITH_REGEX (probably can just get from plandata) #seconds part_event_condition.conditionname = cust_bill_age #plandata PARSE_WITH_REGEX (along with eventcode, yuck) #reason part_event_option.optionname = reason #disabled disabled # #these might help parse existing eventcode $c =~ /^\s*\$cust_main\->(suspend|cancel|invoicing_list_addpost|bill|collect)\(\);\s*("";)?\s*$/ or $c =~ /^\s*\$cust_bill\->(comp|realtime_(card|ach|lec)|batch_card|send)\((%options)*\);\s*$/ or $c =~ /^\s*\$cust_bill\->send(_if_newest)?\(\'[\w\-\s]+\'\s*(,\s*(\d+|\[\s*\d+(,\s*\d+)*\s*\])\s*,\s*'[\w\@\.\-\+]*'\s*)?\);\s*$/ # or $c =~ /^\s*\$cust_main\->apply_payments; \$cust_main->apply_credits; "";\s*$/ or $c =~ /^\s*\$cust_main\->apply_payments_and_credits; "";\s*$/ or $c =~ /^\s*\$cust_main\->charge\( \s*\d*\.?\d*\s*,\s*\'[\w \!\@\#\$\%\&\(\)\-\+\;\:\"\,\.\?\/]*\'\s*\);\s*$/ or $c =~ /^\s*\$cust_main\->suspend_(if|unless)_pkgpart\([\d\,\s]*\);\s*$/ or $c =~ /^\s*\$cust_bill\->cust_suspend_if_balance_over\([\d\.\s]*\);\s*$/ or do { #log return "illegal eventcode: $c"; }; }