summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2013-07-02 21:11:29 -0700
committerIvan Kohler <ivan@freeside.biz>2013-07-02 21:11:29 -0700
commit3d0a1bb06b895c5be6e3f0517d355442a6b1e125 (patch)
tree84069ebc3254825b952a482e11cdbbbc69f6fe85 /bin
parentf3b99c11d6eed33f467dda360180a698a85c54e8 (diff)
parentd62206a94d9d49ef96640e0a8ec492679f8345e9 (diff)
Merge branch 'master' of git.freeside.biz:/home/git/freeside
Diffstat (limited to 'bin')
-rwxr-xr-xbin/23diff2
-rwxr-xr-xbin/32add22
-rwxr-xr-xbin/32commit29
-rwxr-xr-xbin/3add19
-rwxr-xr-xbin/3commit26
-rwxr-xr-xbin/3diff13
-rw-r--r--bin/cch.finish_failed51
-rw-r--r--bin/cch.redelete52
-rwxr-xr-xbin/cdr-netsapiens.import1
-rwxr-xr-xbin/cdr_upstream_rate.import2
-rwxr-xr-xbin/cust_main-bulk_change54
-rwxr-xr-xbin/cust_pay_histogram2
-rwxr-xr-xbin/fs-migrate-supplemental151
-rwxr-xr-xbin/fs-migrate-svc_acct_sm227
-rwxr-xr-xbin/fs-radius-add-check8
-rwxr-xr-xbin/fs-radius-add-reply8
-rwxr-xr-xbin/generate-table-module2
-rwxr-xr-xbin/megapop.pl114
-rwxr-xr-xbin/rebill2
-rwxr-xr-xbin/usps-webtools-test-script38
20 files changed, 570 insertions, 253 deletions
diff --git a/bin/23diff b/bin/23diff
index d38c84834..1dc1659d2 100755
--- a/bin/23diff
+++ b/bin/23diff
@@ -7,7 +7,7 @@ $dir =~ s/freeside(\/?)/freeside2.3$1/;
warn $dir;
#$cmd = "diff -u $file $dir/$file";
-$cmd = "diff -u $dir/$file $file";
+$cmd = "diff -ubBw $dir/$file $file";
print "$cmd\n";
system($cmd);
diff --git a/bin/32add b/bin/32add
new file mode 100755
index 000000000..856c2f133
--- /dev/null
+++ b/bin/32add
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+use Cwd;
+use String::ShellQuote;
+
+my $USER = $ENV{USER};
+
+my $dir = getcwd;
+( my $prefix = $dir ) =~ s(^/home/$USER/freeside/?)() or die $dir; #eventually from anywhere
+
+system join('',
+ "git add @ARGV ; ",
+ "( for file in @ARGV; do ",
+ "cp -i \$file /home/$USER/freeside3/$prefix/`dirname \$file`;",
+ "cp -i \$file /home/$USER/freeside2.3/$prefix/`dirname \$file`;",
+ "done ) && ",
+ "cd /home/$USER/freeside3/$prefix/ && ",
+ "git add @ARGV; ",
+ "cd /home/$USER/freeside2.3/$prefix/ && ",
+ "git add @ARGV"
+);
+
diff --git a/bin/32commit b/bin/32commit
new file mode 100755
index 000000000..903722e4e
--- /dev/null
+++ b/bin/32commit
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+# usage: 32commit 'log message' filename filename ...
+
+use Cwd;
+use String::ShellQuote;
+
+my $USER = $ENV{USER};
+
+my $dir = getcwd;
+( my $prefix = $dir ) =~ s(^/home/$USER/freeside/?)() or die $dir; #eventually from anywhere
+
+my $desc = shell_quote(shift @ARGV); # -m
+
+die "no files!" unless @ARGV;
+
+#warn "$prefix";
+
+#print <<END;
+system join('',
+ "( cd /home/$USER/freeside3/$prefix; git pull ) && ",
+ "( cd /home/$USER/freeside2.3/$prefix; git pull ) && ",
+ "git diff -u @ARGV | ( cd /home/$USER/freeside3/$prefix; patch -p1 ) ",
+ " && git diff -u @ARGV | ( cd /home/$USER/freeside2.3/$prefix; patch -p1 ) ",
+ " && ( ( git pull && git commit -m $desc @ARGV && git push); ",
+ "( cd /home/$USER/freeside3/$prefix; git commit -m $desc @ARGV && git push); ",
+ "( cd /home/$USER/freeside2.3/$prefix; git commit -m $desc @ARGV && git push) )"
+);
+
diff --git a/bin/3add b/bin/3add
new file mode 100755
index 000000000..8bc034d9c
--- /dev/null
+++ b/bin/3add
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+use Cwd;
+use String::ShellQuote;
+
+my $USER = $ENV{USER};
+
+my $dir = getcwd;
+( my $prefix = $dir ) =~ s(^/home/$USER/freeside/?)() or die $dir; #eventually from anywhere
+
+system join('',
+ "git add @ARGV ; ",
+ "( for file in @ARGV; do ",
+ "cp -i \$file /home/$USER/freeside3/$prefix/`dirname \$file`;",
+ "done ) && ",
+ "cd /home/$USER/freeside3/$prefix/ && ",
+ "git add @ARGV"
+);
+
diff --git a/bin/3commit b/bin/3commit
new file mode 100755
index 000000000..37b500063
--- /dev/null
+++ b/bin/3commit
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+# usage: 3commit 'log message' filename filename ...
+
+use Cwd;
+use String::ShellQuote;
+
+my $USER = $ENV{USER};
+
+my $dir = getcwd;
+( my $prefix = $dir ) =~ s(^/home/$USER/freeside/?)() or die $dir; #eventually from anywhere
+
+my $desc = shell_quote(shift @ARGV); # -m
+
+die "no files!" unless @ARGV;
+
+#warn "$prefix";
+
+#print <<END;
+system join('',
+ "( cd /home/$USER/freeside3/$prefix; git pull ) && ",
+ "git diff -u @ARGV | ( cd /home/$USER/freeside3/$prefix; patch -p1 ) ",
+ " && ( ( git pull && git commit -m $desc @ARGV && git push ); ",
+ "( cd /home/$USER/freeside3/$prefix; git commit -m $desc @ARGV && git push ) )"
+);
+
diff --git a/bin/3diff b/bin/3diff
new file mode 100755
index 000000000..badafd579
--- /dev/null
+++ b/bin/3diff
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+
+my $file = shift;
+
+chomp(my $dir = `pwd`);
+$dir =~ s/freeside(\/?)/freeside3$1/;
+warn $dir;
+
+#$cmd = "diff -u $file $dir/$file";
+$cmd = "diff -ubBw $dir/$file $file";
+print "$cmd\n";
+system($cmd);
+
diff --git a/bin/cch.finish_failed b/bin/cch.finish_failed
new file mode 100644
index 000000000..cb2533044
--- /dev/null
+++ b/bin/cch.finish_failed
@@ -0,0 +1,51 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Storable qw( thaw nfreeze );
+use MIME::Base64;
+use FS::UID qw( adminsuidsetup );
+use FS::tax_rate;
+
+adminsuidsetup(shift);
+
+#my @namelist = qw( code detail geocode plus4 txmatrix zip );
+my @namelist = qw( code detail plus4 txmatrix zip );
+
+my $cache_dir = '/usr/local/etc/freeside/cache.'. $FS::UID::datasrc. '/';
+my $dir = $cache_dir.'taxdata/cch';
+
+my @list = ();
+foreach my $name ( @namelist ) {
+ my $difffile = "$dir.new/$name.txt";
+ if (1) { # ($update) {
+ #my $error = $job->update_statustext( "0,Comparing to previous $name" );
+ #die $error if $error;
+ warn "processing $dir.new/$name.txt\n"; # if $DEBUG;
+ #my $olddir = $update ? "$dir.1" : "";
+ my $olddir = "$dir.1";
+ $difffile = FS::tax_rate::_perform_cch_diff( $name, "$dir.new", $olddir );
+ }
+ $difffile =~ s/^$cache_dir//;
+ push @list, "${name}file:$difffile";
+}
+
+# perform the import
+local $FS::tax_rate::keep_cch_files = 1;
+my $param = {
+ 'format' => 'cch-update',
+ 'uploaded_files' => join( ',', @list ),
+};
+my $error =
+ #_perform_batch_import( $job, encode_base64( nfreeze( $param ) ) );
+ FS::tax_rate::_perform_batch_import( '', encode_base64( nfreeze( $param ) ) );
+
+if ( $error ) {
+ warn "ERROR: $error\n";
+} else {
+ warn "success!\n";
+}
+
+#XXX do this manually
+#rename "$dir.new", "$dir"
+# or die "cch tax update processed, but can't rename $dir.new: $!\n";
+
diff --git a/bin/cch.redelete b/bin/cch.redelete
new file mode 100644
index 000000000..2cff389ad
--- /dev/null
+++ b/bin/cch.redelete
@@ -0,0 +1,52 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Storable qw( thaw nfreeze );
+use MIME::Base64;
+use FS::UID qw( adminsuidsetup );
+use FS::tax_rate;
+
+adminsuidsetup(shift);
+
+#my @namelist = qw( code detail geocode plus4 txmatrix zip );
+my @namelist = qw( plus4 txmatrix zip );
+
+my $cache_dir = '/usr/local/etc/freeside/cache.'. $FS::UID::datasrc. '/';
+my $dir = $cache_dir.'taxdata/cch';
+
+my @list = ();
+foreach my $name ( @namelist ) {
+ my $difffile = "$dir.new/$name.txt";
+ if (1) { # ($update) {
+ #my $error = $job->update_statustext( "0,Comparing to previous $name" );
+ #die $error if $error;
+ warn "processing $dir.new/$name.txt\n"; # if $DEBUG;
+ #my $olddir = $update ? "$dir.1" : "";
+ my $olddir = "$dir.1";
+ $difffile = FS::tax_rate::_perform_cch_diff( $name, "$dir.new", $olddir );
+ }
+ $difffile =~ s/^$cache_dir//;
+ push @list, "${name}file:$difffile";
+}
+
+# perform the import
+local $FS::tax_rate::keep_cch_files = 1;
+my $param = {
+ 'format' => 'cch-update',
+ 'uploaded_files' => join( ',', @list ),
+ 'delete_only' => 1,
+};
+my $error =
+ #_perform_batch_import( $job, encode_base64( nfreeze( $param ) ) );
+ FS::tax_rate::_perform_batch_import( '', encode_base64( nfreeze( $param ) ) );
+
+if ( $error ) {
+ warn "ERROR: $error\n";
+} else {
+ warn "success!\n";
+}
+
+#XXX do this manually
+#rename "$dir.new", "$dir"
+# or die "cch tax update processed, but can't rename $dir.new: $!\n";
+
diff --git a/bin/cdr-netsapiens.import b/bin/cdr-netsapiens.import
index 8aa4ac0b7..1cce461e2 100755
--- a/bin/cdr-netsapiens.import
+++ b/bin/cdr-netsapiens.import
@@ -37,6 +37,7 @@ do {
my $ns = $part_export->ns_command( 'GET', '/cdr/',
'time_release' => "$time_release,",
'_sort' => '+time_release',
+ '_limit' => '500',
);
#loop over them, double check duplicates, insert the rest
diff --git a/bin/cdr_upstream_rate.import b/bin/cdr_upstream_rate.import
index fda3883b5..ac2856cee 100755
--- a/bin/cdr_upstream_rate.import
+++ b/bin/cdr_upstream_rate.import
@@ -6,7 +6,7 @@
#
# Example: bin/cdr_upstream_rate.import ivan 1 ~ivan/convergent/sample_rate_table.csv
#
-# username: a freeside login (from /usr/local/etc/freeside/mapsecrets)
+# username: a freeside login
# ratenum: rate plan (FS::rate) created with the web UI
# filename: CSV file
#
diff --git a/bin/cust_main-bulk_change b/bin/cust_main-bulk_change
index fdf53d999..32a6d7bd6 100755
--- a/bin/cust_main-bulk_change
+++ b/bin/cust_main-bulk_change
@@ -1,13 +1,15 @@
#!/usr/bin/perl
use strict;
-use vars qw( $opt_p );
+use vars qw( $opt_a $opt_p $opt_t $opt_k );
use Getopt::Std;
use FS::UID qw(adminsuidsetup);
-use FS::Record qw(qsearchs);
+use FS::Record qw(qsearch qsearchs);
use FS::cust_main;
+use FS::cust_tag;
+use FS::cust_pkg;
-getopts('p:');
+getopts('a:p:t:k:');
my $user = shift or &usage;
adminsuidsetup $user;
@@ -31,17 +33,41 @@ while (<STDIN>) {
next;
}
- if ( $opt_p ) {
- $cust_main->payby($opt_p);
+ my %cust_tag = ( custnum=>$custnum, tagnum=>$opt_t );
+ if ( $opt_t && ! qsearchs('cust_tag', \%cust_tag) ) {
+ my $cust_tag = new FS::cust_tag \%cust_tag;
+ my $error = $cust_tag->insert;
+ die "$error\n" if $error;
}
- my $error = $cust_main->replace;
- die "$error\n" if $error;
+ if ( $opt_p || $opt_a ) {
+ $cust_main->agentnum($opt_a) if $opt_a;
+ $cust_main->payby($opt_p) if $opt_p;
+
+ my $error = $cust_main->replace;
+ die "$error\n" if $error;
+ }
+
+ if ( $opt_k ) {
+ foreach my $k (split(/\s*,\s*/, $opt_k)) {
+ my($old, $new) = split(/\s*:\s*/, $k);
+ foreach my $cust_pkg ( qsearch('cust_pkg', {
+ 'custnum' => $cust_main->custnum,
+ 'pkgpart' => $old,
+ })
+ )
+ {
+ $cust_pkg->pkgpart($new);
+ my $error = $cust_pkg->replace;
+ die "$error\n" if $error;
+ }
+ }
+ }
}
sub usage {
- die "usage: cust_main-bulk_change -p NEW_PAYBY employee_username <custnums.txt\n";
+ die "usage: cust_main-bulk_change [ -a agentnum ] [ -p NEW_PAYBY ] [ -t tagnum ] [ -k old_pkgpart:new_pkgpart,... ] employee_username <custnums.txt\n";
}
=head1 NAME
@@ -50,13 +76,19 @@ cust_main-bulk_change
=head1 SYNOPSIS
- cust_main-bulk_change -p NEW_PAYBY username <custnums.txt
+ cust_main-bulk_change [ -a agentnum ] [ -p NEW_PAYBY ] [ -t tagnum ] [ -k old_pkgpart:new_pkgpart,... ] username <custnums.txt
=head1 DESCRIPTION
-Command-line tool to change the payby field for a group of customers.
+Command-line tool to make bulk changes to a group of customers.
+
+-a: new agentnum
+
+-p: new payby, for example, I<CARD> or I<DCRD>
+
+-t: tagnum to add if not present
--p: new payby, for example, I<CARD> or I<DCRD>.
+-k: old_pkgpart:new_pkgpart, for example, I<5:4>. Multiple entries can be comma-separated.
user: Employee username
diff --git a/bin/cust_pay_histogram b/bin/cust_pay_histogram
index 714b32140..42bd8844d 100755
--- a/bin/cust_pay_histogram
+++ b/bin/cust_pay_histogram
@@ -103,7 +103,7 @@ Displays a histogram of cust_pay records in the database.
-a: Only process payments of customers with the specified agentnum
-user: From the mapsecrets file - see config.html from the base documentation
+user: Freeside username
=head1 BUGS
diff --git a/bin/fs-migrate-supplemental b/bin/fs-migrate-supplemental
new file mode 100755
index 000000000..dbef95fc1
--- /dev/null
+++ b/bin/fs-migrate-supplemental
@@ -0,0 +1,151 @@
+#!/usr/bin/perl
+
+use strict;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearch qsearchs);
+use FS::cust_pkg;
+use FS::part_pkg;
+
+my $user = shift or die &usage;
+my @pkgparts = @ARGV or die &usage;
+my $dbh = adminsuidsetup $user;
+
+$FS::UID::AutoCommit = 0;
+
+my %stats = (
+ mainpkgs => 0,
+ created => 0,
+ linked => 0,
+ errors => 0,
+);
+
+my %pkg_freq; # cache
+foreach my $pkgpart (@pkgparts) {
+ my $part_pkg = FS::part_pkg->by_key($pkgpart)
+ or die "pkgpart $pkgpart not found.\n";
+ $pkg_freq{$pkgpart} = $part_pkg->freq;
+ my @links = $part_pkg->supp_part_pkg_link
+ or die "pkgpart $pkgpart has no supplemental packages.\n";
+ CUST_PKG: foreach my $cust_pkg (
+ qsearch('cust_pkg', {
+ 'pkgpart' => $pkgpart,
+ 'cancel' => '',
+ })
+ ) {
+ my $cust_main = $cust_pkg->cust_main;
+ my @existing = $cust_pkg->supplemental_pkgs;
+ my @active = grep { !$_->main_pkgnum } $cust_main->ncancelled_pkgs;
+ LINK: foreach my $link (@links) {
+ # yeah, it's expensive
+ # see if there's an existing package with this link identity
+ foreach (@existing) {
+ if ($_->pkglinknum == $link->pkglinknum) {
+ next LINK;
+ }
+ }
+ # no? then is there one with this pkgpart?
+ my $i = 0;
+ foreach (@active) {
+ if ( $_->pkgpart == $link->dst_pkgpart ) {
+ set_link($cust_pkg, $link, $_);
+ splice(@active, $i, 1); # delete it so we don't reuse it
+ next LINK;
+ }
+ }
+ # no? then create one
+ create_linked($cust_pkg, $link);
+ } #foreach $link
+ $stats{mainpkgs}++;
+ } #foreach $cust_pkg
+} #foreach $pkgpart
+
+print "
+Main packages: $stats{mainpkgs}
+Supplemental packages linked: $stats{linked}
+Supplemental packages ordered: $stats{created}
+Errors: $stats{errors}
+";
+
+$dbh->commit or die $dbh->errstr;
+
+sub set_link {
+ my ($main_pkg, $part_pkg_link, $supp_pkg) = @_;
+ my $task = "linking package ".$supp_pkg->pkgnum.
+ " to package ".$main_pkg->pkgnum;
+ $supp_pkg->set('main_pkgnum', $main_pkg->pkgnum);
+ $supp_pkg->set('pkglinknum', $part_pkg_link->pkglinknum);
+ # Set the next bill date of the supplemental package to the nearest one in
+ # the future that lines up with the main package. If the main package
+ # hasn't started billing yet, use its future start date.
+ my $new_bill = $main_pkg->get('bill') || $main_pkg->get('start_date');
+ if ( $new_bill ) {
+ my $old_bill = $supp_pkg->get('bill');
+ my $diff = $new_bill - $old_bill;
+ my $main_freq = $pkg_freq{$main_pkg->pkgpart};
+ my $prev_bill = 0;
+ while ($diff < 0) {
+ # this will exit once $new_bill has overtaken the existing bill date.
+ # if there is no existing bill date, then this will exit right away
+ # and set bill to the bill date of the main package, which is correct.
+ $prev_bill = $new_bill;
+ $new_bill = FS::part_pkg->add_freq($new_bill, $main_freq);
+ $diff = $new_bill - $old_bill;
+ }
+ # then, of $new_bill and $prev_bill, pick the one that's closer to $old_bill
+ if ( $prev_bill > 0 and
+ $new_bill - $old_bill > $old_bill - $prev_bill ) {
+ $supp_pkg->set('bill', $prev_bill);
+ } else {
+ $supp_pkg->set('bill', $new_bill);
+ }
+ } else {
+ # otherwise the main package hasn't been billed yet and has no
+ # start date, so we can't sync the supplemental to it yet.
+ # but we can still link them.
+ warn "$task: main package has no next bill date.\n";
+ }
+ my $error = $supp_pkg->replace;
+ if ( $error ) {
+ warn "$task:\n $error\n";
+ $stats{errors}++;
+ } else {
+ $stats{linked}++;
+ }
+ return;
+}
+
+sub create_linked {
+ my ($main_pkg, $part_pkg_link) = @_;
+ my $task = "creating pkgpart ".$part_pkg_link->dst_pkgpart.
+ " supplemental to package ".$main_pkg->pkgnum;
+ my $supp_pkg = FS::cust_pkg->new({
+ 'pkgpart' => $part_pkg_link->dst_pkgpart,
+ 'pkglinknum' => $part_pkg_link->pkglinknum,
+ 'custnum' => $main_pkg->custnum,
+ 'main_pkgnum' => $main_pkg->pkgnum,
+ 'locationnum' => $main_pkg->locationnum,
+ 'start_date' => $main_pkg->start_date,
+ 'order_date' => $main_pkg->order_date,
+ 'expire' => $main_pkg->expire,
+ 'adjourn' => $main_pkg->adjourn,
+ 'contract_end' => $main_pkg->contract_end,
+ 'susp' => $main_pkg->susp,
+ 'bill' => $main_pkg->bill,
+ 'refnum' => $main_pkg->refnum,
+ 'discountnum' => $main_pkg->discountnum,
+ 'waive_setup' => $main_pkg->waive_setup,
+ });
+ my $error = $supp_pkg->insert;
+ if ( $error ) {
+ warn "$task:\n $error\n";
+ $stats{errors}++;
+ } else {
+ $stats{created}++;
+ }
+ return;
+}
+
+sub usage {
+ die "Usage:\n fs-migrate-supplemental user main_pkgpart\n";
+}
+
diff --git a/bin/fs-migrate-svc_acct_sm b/bin/fs-migrate-svc_acct_sm
deleted file mode 100755
index 07f7b611c..000000000
--- a/bin/fs-migrate-svc_acct_sm
+++ /dev/null
@@ -1,227 +0,0 @@
-#!/usr/bin/perl -Tw
-#
-# jeff@cmh.net 01-Jul-20
-
-#to delay loading dbdef until we're ready
-#BEGIN { $FS::Record::setup_hack = 1; }
-
-use strict;
-use Term::Query qw(query);
-#use DBI;
-#use DBIx::DBSchema;
-#use DBIx::DBSchema::Table;
-#use DBIx::DBSchema::Column;
-#use DBIx::DBSchema::ColGroup::Unique;
-#use DBIx::DBSchema::ColGroup::Index;
-use FS::Conf;
-use FS::UID qw(adminsuidsetup datasrc checkeuid getsecrets);
-use FS::Record qw(qsearch qsearchs);
-use FS::svc_domain;
-use FS::svc_forward;
-use vars qw( $conf $old_default_domain %part_domain_svc %part_acct_svc %part_forward_svc $svc_acct $svc_acct_sm $error);
-
-die "Not running uid freeside!" unless checkeuid();
-
-my $user = shift or die &usage;
-getsecrets($user);
-
-$conf = new FS::Conf;
-$old_default_domain = $conf->config('domain');
-
-#needs to match FS::Record
-#my($dbdef_file) = "/usr/local/etc/freeside/dbdef.". datasrc;
-
-###
-# This section would be the appropriate place to manipulate
-# the schema & tables.
-###
-
-## we need to add the domsvc to svc_acct
-## we must add a svc_forward record....
-## I am thinking that the fields svcnum (int), destsvc (int), and
-## dest (varchar (80)) are appropriate, with destsvc/dest an either/or
-## much in the spirit of cust_main_invoice
-
-###
-# massage the data
-###
-
-my($dbh)=adminsuidsetup $user;
-
-$|=1;
-
-$FS::svc_Common::noexport_hack = 1;
-$FS::svc_domain::whois_hack = 1;
-
-%part_domain_svc=map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_domain'});
-%part_acct_svc=map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_acct'});
-%part_forward_svc=map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_forward'});
-
-die "No services with svcdb svc_domain!\n" unless %part_domain_svc;
-die "No services with svcdb svc_acct!\n" unless %part_acct_svc;
-die "No services with svcdb svc_forward!\n" unless %part_forward_svc;
-
-my($svc_domain) = qsearchs('svc_domain', { 'domain' => $old_default_domain });
-if (! $svc_domain || $svc_domain->domain != $old_default_domain) {
- print <<EOF;
-
-Your database currently does not contain a svc_domain record for the
-domain $old_default_domain. Would you like me to add one for you?
-EOF
-
- my($response)=scalar(<STDIN>);
- chop $response;
- if ($response =~ /^[yY]/) {
- print "\n\n", &menu_domain_svc, "\n", <<END;
-I need to create new domain accounts. Which service shall I use for that?
-END
- my($domain_svcpart)=&getdomainpart;
-
- $svc_domain = new FS::svc_domain {
- 'domain' => $old_default_domain,
- 'svcpart' => $domain_svcpart,
- 'action' => 'M',
- };
-# $error=$svc_domain->insert && die "Error adding domain $old_default_domain: $error";
- $error=$svc_domain->insert;
- die "Error adding domain $old_default_domain: $error" if $error;
- }else{
- print <<EOF;
-
- This program cannot function properly until a svc_domain record matching
-your conf_dir/domain file exists.
-EOF
-
- exit 1;
- }
-}
-
-print "\n\n", &menu_acct_svc, "\n", <<END;
-I may need to create some new pop accounts and set up forwarding to them
-for some users. Which service shall I use for that?
-END
-my($pop_svcpart)=&getacctpart;
-
-print "\n\n", &menu_forward_svc, "\n", <<END;
-I may need to create some new forwarding for some users. Which service
-shall I use for that?
-END
-my($forward_svcpart)=&getforwardpart;
-
-sub menu_domain_svc {
- ( join "\n", map "$_: ".$part_domain_svc{$_}->svc, sort keys %part_domain_svc ). "\n";
-}
-sub menu_acct_svc {
- ( join "\n", map "$_: ".$part_acct_svc{$_}->svc, sort keys %part_acct_svc ). "\n";
-}
-sub menu_forward_svc {
- ( join "\n", map "$_: ".$part_forward_svc{$_}->svc, sort keys %part_forward_svc ). "\n";
-}
-sub getdomainpart {
- $^W=0; # Term::Query isn't -w-safe
- my $return = query "Enter part number:", 'irk', [ keys %part_domain_svc ];
- $^W=1;
- $return;
-}
-sub getacctpart {
- $^W=0; # Term::Query isn't -w-safe
- my $return = query "Enter part number:", 'irk', [ keys %part_acct_svc ];
- $^W=1;
- $return;
-}
-sub getforwardpart {
- $^W=0; # Term::Query isn't -w-safe
- my $return = query "Enter part number:", 'irk', [ keys %part_forward_svc ];
- $^W=1;
- $return;
-}
-
-
-#migrate data
-
-my(@svc_accts) = qsearch('svc_acct', {});
-foreach $svc_acct (@svc_accts) {
- my(@svc_acct_sms) = qsearch('svc_acct_sm', {
- domuid => $svc_acct->getfield('uid'),
- }
- );
-
- # Ok.. we've got the svc_acct record, and an array of svc_acct_sm's
- # What do we do from here?
-
- # The intuitive:
- # plop the svc_acct into the 'default domain'
- # and then represent the svc_acct_sm's with svc_forwards
- # they can be gussied up manually, later
- #
- # Perhaps better:
- # when no svc_acct_sm exists, place svc_acct in 'default domain'
- # when one svc_acct_sm exists, place svc_acct in corresponding
- # domain & possibly create a svc_forward in 'default domain'
- # when multiple svc_acct_sm's exists (in different domains) we'd
- # better use the 'intuitive' approach.
- #
- # Specific way:
- # as 'perhaps better,' but we may be able to guess which domain
- # is correct by comparing the svcnum of domains to the username
- # of the svc_acct
- #
-
- # The intuitive way:
-
- my $def_acct = new FS::svc_acct ( { $svc_acct->hash } );
- $def_acct->setfield('domsvc' => $svc_domain->getfield('svcnum'));
- $error = $def_acct->replace($svc_acct);
- die "Error replacing svc_acct for " . $def_acct->username . " : $error" if $error;
-
- foreach $svc_acct_sm (@svc_acct_sms) {
-
- my($domrec)=qsearchs('svc_domain', {
- svcnum => $svc_acct_sm->getfield('domsvc'),
- }) || die "svc_acct_sm references invalid domsvc $svc_acct_sm->getfield('domsvc')\n";
-
- if ($svc_acct_sm->getfield('domuser') =~ /^\*$/) {
-
- my($newdom) = new FS::svc_domain ( { $domrec->hash } );
- $newdom->setfield('catchall', $svc_acct->svcnum);
- $newdom->setfield('action', "M");
- $error = $newdom->replace($domrec);
- die "Error replacing svc_domain for (anything)@" . $domrec->domain . " : $error" if $error;
-
- } else {
-
- my($newacct) = new FS::svc_acct {
- 'svcpart' => $pop_svcpart,
- 'username' => $svc_acct_sm->getfield('domuser'),
- 'domsvc' => $svc_acct_sm->getfield('domsvc'),
- 'dir' => '/dev/null',
- };
- $error = $newacct->insert;
- die "Error adding svc_acct for " . $newacct->username . " : $error" if $error;
-
- my($newforward) = new FS::svc_forward {
- 'svcpart' => $forward_svcpart,
- 'srcsvc' => $newacct->getfield('svcnum'),
- 'dstsvc' => $def_acct->getfield('svcnum'),
- };
- $error = $newforward->insert;
- die "Error adding svc_forward for " . $newacct->username ." : $error" if $error;
- }
-
- $error = $svc_acct_sm->delete;
- die "Error deleting svc_acct_sm for " . $svc_acct_sm->domuser ." : $error" if $error;
-
- };
-
-};
-
-
-$dbh->commit or die $dbh->errstr;
-$dbh->disconnect or die $dbh->errstr;
-
-print "svc_acct_sm records sucessfully migrated\n";
-
-sub usage {
- die "Usage:\n fs-migrate-svc_acct_sm user\n";
-}
-
diff --git a/bin/fs-radius-add-check b/bin/fs-radius-add-check
index 4e4769e58..ee093b375 100755
--- a/bin/fs-radius-add-check
+++ b/bin/fs-radius-add-check
@@ -1,20 +1,18 @@
#!/usr/bin/perl -Tw
# quick'n'dirty hack of fs-setup to add radius attributes
+# (i'm not sure this even works in the new world of schema changes - everyone
+# uses attributes via groups now)
use strict;
use DBI;
-use FS::UID qw(adminsuidsetup checkeuid getsecrets);
+use FS::UID qw(adminsuidsetup);
use FS::raddb;
-die "Not running uid freeside!" unless checkeuid();
-
my %attrib2db =
map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
my $user = shift or die &usage;
-getsecrets($user);
-
my $dbh = adminsuidsetup $user;
###
diff --git a/bin/fs-radius-add-reply b/bin/fs-radius-add-reply
index 3de01374f..c6c24e039 100755
--- a/bin/fs-radius-add-reply
+++ b/bin/fs-radius-add-reply
@@ -1,20 +1,18 @@
#!/usr/bin/perl -Tw
# quick'n'dirty hack of fs-setup to add radius attributes
+# (i'm not sure this even works in the new world of schema changes - everyone
+# uses attributes via groups now)
use strict;
use DBI;
-use FS::UID qw(adminsuidsetup checkeuid getsecrets);
+use FS::UID qw(adminsuidsetup);
use FS::raddb;
-die "Not running uid freeside!" unless checkeuid();
-
my %attrib2db =
map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
my $user = shift or die &usage;
-getsecrets($user);
-
my $dbh = adminsuidsetup $user;
###
diff --git a/bin/generate-table-module b/bin/generate-table-module
index e7fc99258..b536360c5 100755
--- a/bin/generate-table-module
+++ b/bin/generate-table-module
@@ -95,7 +95,7 @@ close TEST;
# add them to MANIFEST
###
-system('cvs edit FS/MANIFEST');
+#system('cvs edit FS/MANIFEST');
open(MANIFEST,">>FS/MANIFEST") or die $!;
print MANIFEST "FS/$table.pm\n",
diff --git a/bin/megapop.pl b/bin/megapop.pl
new file mode 100755
index 000000000..e2930fb55
--- /dev/null
+++ b/bin/megapop.pl
@@ -0,0 +1,114 @@
+#!/usr/bin/perl -Tw
+#
+# this will break when megapop changes the URL or format of their listing page.
+# that's stupid. perhaps they can provide a machine-readable listing?
+
+use strict;
+use LWP::UserAgent;
+use FS::UID qw(adminsuidsetup);
+use FS::svc_acct_pop;
+
+my $url = "http://www.megapop.com/location.htm";
+
+my $user = shift or die &usage;
+adminsuidsetup($user);
+
+my %state2usps = &state2usps;
+$state2usps{'WASHINGTON STATE'} = 'WA'; #megapop's on crack
+$state2usps{'CANADA'} = 'CANADA'; #freeside's on crack
+
+my $ua = new LWP::UserAgent;
+my $request = new HTTP::Request('GET', $url);
+my $response = $ua->request($request);
+die $response->error_as_HTML unless $response->is_success;
+my $line;
+my $usps = '';
+foreach $line ( split("\n", $response->content) ) {
+ if ( $line =~ /\W(\w[\w\s]*\w)\s+LOCATIONS/i ) {
+ $usps = $state2usps{uc($1)}
+ or warn "warning: unknown state $1\n";
+ } elsif ( $line =~ /(\d{3})\-(\d{3})\-(\d{4})\s+(\w[\w\s]*\w)/ ) {
+ print "$1 $2 $3 $4 $usps\n";
+ my $svc_acct_pop = new FS::svc_acct_pop ( {
+ 'city' => $4,
+ 'state' => $usps,
+ 'ac' => $1,
+ 'exch' => $2,
+ } );
+ my $error = $svc_acct_pop->insert;
+ die $error if $error;
+ }
+}
+
+sub usage {
+ die "Usage:\n $0 user\n";
+}
+
+sub state2usps{ (
+ 'ALABAMA' => 'AL',
+ 'ALASKA' => 'AK',
+ 'AMERICAN SAMOA' => 'AS',
+ 'ARIZONA' => 'AZ',
+ 'ARKANSAS' => 'AR',
+ 'CALIFORNIA' => 'CA',
+ 'COLORADO' => 'CO',
+ 'CONNECTICUT' => 'CT',
+ 'DELAWARE' => 'DE',
+ 'DISTRICT OF COLUMBIA' => 'DC',
+ 'FEDERATED STATES OF MICRONESIA' => 'FM',
+ 'FLORIDA' => 'FL',
+ 'GEORGIA' => 'GA',
+ 'GUAM' => 'GU',
+ 'HAWAII' => 'HI',
+ 'IDAHO' => 'ID',
+ 'ILLINOIS' => 'IL',
+ 'INDIANA' => 'IN',
+ 'IOWA' => 'IA',
+ 'KANSAS' => 'KS',
+ 'KENTUCKY' => 'KY',
+ 'LOUISIANA' => 'LA',
+ 'MAINE' => 'ME',
+ 'MARSHALL ISLANDS' => 'MH',
+ 'MARYLAND' => 'MD',
+ 'MASSACHUSETTS' => 'MA',
+ 'MICHIGAN' => 'MI',
+ 'MINNESOTA' => 'MN',
+ 'MISSISSIPPI' => 'MS',
+ 'MISSOURI' => 'MO',
+ 'MONTANA' => 'MT',
+ 'NEBRASKA' => 'NE',
+ 'NEVADA' => 'NV',
+ 'NEW HAMPSHIRE' => 'NH',
+ 'NEW JERSEY' => 'NJ',
+ 'NEW MEXICO' => 'NM',
+ 'NEW YORK' => 'NY',
+ 'NORTH CAROLINA' => 'NC',
+ 'NORTH DAKOTA' => 'ND',
+ 'NORTHERN MARIANA ISLANDS' => 'MP',
+ 'OHIO' => 'OH',
+ 'OKLAHOMA' => 'OK',
+ 'OREGON' => 'OR',
+ 'PALAU' => 'PW',
+ 'PENNSYLVANIA' => 'PA',
+ 'PUERTO RICO' => 'PR',
+ 'RHODE ISLAND' => 'RI',
+ 'SOUTH CAROLINA' => 'SC',
+ 'SOUTH DAKOTA' => 'SD',
+ 'TENNESSEE' => 'TN',
+ 'TEXAS' => 'TX',
+ 'UTAH' => 'UT',
+ 'VERMONT' => 'VT',
+ 'VIRGIN ISLANDS' => 'VI',
+ 'VIRGINIA' => 'VA',
+ 'WASHINGTON' => 'WA',
+ 'WEST VIRGINIA' => 'WV',
+ 'WISCONSIN' => 'WI',
+ 'WYOMING' => 'WY',
+ 'ARMED FORCES AFRICA' => 'AE',
+ 'ARMED FORCES AMERICAS' => 'AA',
+ 'ARMED FORCES CANADA' => 'AE',
+ 'ARMED FORCES EUROPE' => 'AE',
+ 'ARMED FORCES MIDDLE EAST' => 'AE',
+ 'ARMED FORCES PACIFIC' => 'AP',
+) }
+
diff --git a/bin/rebill b/bin/rebill
index 4f052384d..cf473398a 100755
--- a/bin/rebill
+++ b/bin/rebill
@@ -117,7 +117,7 @@ the bill and collect methods of a cust_main object. See L<FS::cust_main>.
-k: skip notify_flat_delay and vacuum
-user: From the mapsecrets file - see config.html from the base documentation
+user: Freeside user
custnum: if one or more customer numbers are specified, only bills those
customers. Otherwise, bills all customers.
diff --git a/bin/usps-webtools-test-script b/bin/usps-webtools-test-script
new file mode 100755
index 000000000..414ae4cad
--- /dev/null
+++ b/bin/usps-webtools-test-script
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+use FS::Misc::Geo 'standardize';
+use Data::Dumper; $Data::Dumper::Terse = 1;
+my @tests = (
+ {
+ address1 => '6406 Ivy Lane',
+ address2 => '',
+ city => 'Greenbelt',
+ state => 'MD',
+ zip => '',
+ },
+ {
+ address1 => '8 Wildwood Drive',
+ address2 => '',
+ city => 'Old Lyme',
+ state => 'CT',
+ zip => '06371',
+ },
+);
+
+my ($userid, $password) = @ARGV;
+
+my %opt = (
+ userid => $userid,
+ password=> $password,
+ test => 1,
+);
+my $i = 1;
+foreach (@tests) {
+ print "Test $i\n";
+ my $result = eval { standardize($_, %opt) };
+ print "ERROR: $@\n\n" if $@;
+ print Dumper($result);
+ $i++;
+}
+
+1;