diff options
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/bulk_void | 75 | ||||
-rwxr-xr-x | bin/rate-intl.import | 113 |
2 files changed, 188 insertions, 0 deletions
diff --git a/bin/bulk_void b/bin/bulk_void new file mode 100755 index 000000000..a1428180e --- /dev/null +++ b/bin/bulk_void @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +use FS::Misc::Getopt; +use FS::Record qw(qsearch qsearchs dbh); + +getopts('cpifXr:'); +my $dbh = dbh; +$FS::UID::AutoCommit = 0; + +sub usage() { + "Usage: bulk_void -s start -e end + -r void_reason + { -c | -p | -i } + [ -X ] + <user> +-s, -e: date range (required) +-r: void reason text (required) +-c, -p, -i, -f: void credits, payments, invoices +-X: commit changes +"; +} + +if (!$opt{start} or !$opt{end} or !$opt{r}) { + die usage; +} + +print "DRY RUN--changes will not be committed.\n" unless $opt{X}; + +my $date = " WHERE _date >= $opt{start} AND _date <= $opt{end}"; + +my %tables = ( + c => 'cust_credit', + p => 'cust_pay', + i => 'cust_bill', +); + +my $reason = $opt{r}; + +foreach my $k (keys %tables) { + next unless $opt{$k}; + my $table = $tables{$k}; + debug("$table:"); + my $done_count = 0; + my $error_count = 0; + + my $cursor = FS::Cursor->new({ + table => $table, + extra_sql => $date, + }); + my $error; + while (my $record = $cursor->fetch) { + $error = $record->void($reason); + if ( $error ) { + $error = "$table #" . $record->get($record->primary_key) . ": $error"; + print "$error\n"; + $error_count++; + if ( $opt{X} ) { + $dbh->rollback; + exit(1); + } + } else { + $done_count++; + } + } + print " $table voided: $done_count\n errors: $error_count\n"; +} + +if ( $opt{X} ) { + $dbh->commit; + print "Committed changes.\n"; +} else { + $dbh->rollback; + print "Reverted changes.\n"; +} + diff --git a/bin/rate-intl.import b/bin/rate-intl.import new file mode 100755 index 000000000..7eef5878f --- /dev/null +++ b/bin/rate-intl.import @@ -0,0 +1,113 @@ +#!/usr/bin/perl + +use strict; +use Text::CSV; +use FS::Misc::Getopt; +use FS::Record qw(qsearchs qsearch dbh); +use FS::rate; +use FS::rate_region; +use FS::rate_prefix; +use FS::rate_detail; + +getopts(''); + +$FS::UID::AutoCommit = 0; +my $dbh = dbh; + +my $file = shift or usage(); +open my $in, '<', $file or die "$file: $!\n"; +my $csv = Text::CSV->new({ binary => 1, auto_diag => 2 }); +# set header row +$csv->column_names($csv->getline($in)); + +my $error; + +my $granularity = 1; +# default is to charge per second; edit this if needed + +while (my $row = $csv->getline_hr($in)) { + print $csv->string; + + # ProfileKey is just a number + my $rate = qsearchs('rate', { 'ratename' => $row->{'ProfileKey'} }); + if (!$rate) { + $rate = FS::rate->new({ 'ratename' => $row->{'ProfileKey'} }); + $error = $rate->insert; + die $error if $error; + } + + # DestinationId looks like "Country - City" or "Country - Mobile - + # Carrier" (or sometimes just "Country - Mobile"). + my $region = qsearchs('rate_region', { + 'regionname' => $row->{'DestinationId'} + }); + if (!$region) { + $region = FS::rate_region->new({ + 'regionname' => $row->{'DestinationId'} + }); + $error = $region->insert; + die $error if $error; + } + + # Prefix strings found in there look like + # "e164:123-45-6nnnnnnn-" + # The first group of digits is the country code, any others are the + # prefix. Sometimes the nnnn's are NNNN's. The dashes are not guaranteed + # to be anywhere specific. + # Catchall prefixes start with "-A", which has a meaning like "match + # anything, but at a lower priority than a digit match". + # NANPA numbers use "1-", and for a catchall area code use "1-AAA-". + my $cc_long = $row->{CountryCodeLong}; + $cc_long =~ /^e164:(\d+)-([\d-]*)A*-?n+-$/i; + my $countrycode = $1; + if (!$countrycode) { # totally legit reasons for this, e.g. 1-AAA-411 + warn "can't parse number prefix:\n$cc_long\n"; + next; + } + my $prefix = $2; + $prefix =~ s/-//g; + + my %prefix = ( + 'regionnum' => $region->regionnum, + 'countrycode' => $countrycode, + 'npa' => $prefix, + ); + my $rate_prefix = qsearchs('rate_prefix', \%prefix); + if (!$rate_prefix) { + $rate_prefix = FS::rate_prefix->new(\%prefix); + $error = $rate_prefix->insert; + die $error if $error; + } + + # enough to identify the detail + my %detail = ( + 'ratenum' => $rate->ratenum, + 'dest_regionnum' => $region->regionnum, + 'cdrtypenum' => '', + 'ratetimenum' => '', + ); + my $dest_detail = qsearchs('rate_detail', \%detail); + # ProfileRate is 5 decimal places, same as rate_detail.min_charge + if (!$dest_detail) { + $dest_detail = FS::rate_detail->new({ + %detail, + 'min_included' => 0, + 'min_charge' => $row->{ProfileRate}, + 'sec_granularity' => $granularity, + }); + $error = $dest_detail->insert; + } else { + local $FS::Record::nowarn_identical = 1; + $dest_detail->set('min_charge' => $row->{ProfileRate}); + $error = $dest_detail->replace; + } + die $error if $error; +} +dbh->commit; +print "Finished.\n"; + + +sub usage { + die "Usage: rate-intl.import <user> <file>.csv\n\n"; +} + |