X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=bin%2Fbulk_void;h=5da7d15f6cd421777e91b1fc0546b1267a347d02;hp=a1428180e3fe16296a068b857f7767602b584008;hb=368ed08e24400e9d1faf401a1e4e23ea54d2c969;hpb=4b05b20576ddb14577d59c87c8257c6804449410 diff --git a/bin/bulk_void b/bin/bulk_void index a1428180e..5da7d15f6 100755 --- a/bin/bulk_void +++ b/bin/bulk_void @@ -1,9 +1,15 @@ #!/usr/bin/perl +use strict; +use warnings; +use vars qw( %opt ); +use Date::Format; +use File::Slurp; use FS::Misc::Getopt; use FS::Record qw(qsearch qsearchs dbh); -getopts('cpifXr:'); +getopts('cpiXr:t:u:vk:f'); + my $dbh = dbh; $FS::UID::AutoCommit = 0; @@ -11,11 +17,20 @@ sub usage() { "Usage: bulk_void -s start -e end -r void_reason { -c | -p | -i } + [ -t payby ] + [ -u filename ] + [ -k pkgpart ] + [ -v ] [ -X ] -s, -e: date range (required) -r: void reason text (required) --c, -p, -i, -f: void credits, payments, invoices +-c, -p, -i: void credits, payments, invoices +-u: specifies a filename of customer numbers - only void for those customers +-k: skip invoices with only this pkgpart +-t: only void payments with this payby +-f: force - continue voiding invoices even if some have errors +-v: verbose - show more detail -X: commit changes "; } @@ -26,7 +41,16 @@ if (!$opt{start} or !$opt{end} or !$opt{r}) { print "DRY RUN--changes will not be committed.\n" unless $opt{X}; -my $date = " WHERE _date >= $opt{start} AND _date <= $opt{end}"; +my %search = (); +$search{payby} = $opt{t} if $opt{t} && $opt{p}; + +my $extra_sql = (keys %search ? ' AND ' : ' WHERE '). + " _date >= $opt{start} AND _date <= $opt{end}"; + +if ( $opt{u} ) { + my @custnums = map { chomp; $_; } read_file($opt{u}); + $extra_sql .= ' AND custnum IN ('. join(',', @custnums). ') '; +} my %tables = ( c => 'cust_credit', @@ -36,25 +60,43 @@ my %tables = ( 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 $pkey = ''; my $cursor = FS::Cursor->new({ table => $table, - extra_sql => $date, + hashref => \%search, + extra_sql => $extra_sql, }); my $error; while (my $record = $cursor->fetch) { + + if ( $opt{k} && $opt{i} ) { + my @other_pkgs = grep { $_->pkgpart != $opt{k} } + grep $_, map $_->cust_pkg, $record->cust_bill_pkg; + next if ! @other_pkgs; + } + + if ( $opt{v} ) { + $pkey ||= $record->primary_key; + my $num = $record->get($pkey); + my $date = time2str('%x', $record->_date); + my $name = $record->cust_main->name; + warn "Voiding $table #$num ($date) for $name\n"; + } + $error = $record->void($reason); if ( $error ) { $error = "$table #" . $record->get($record->primary_key) . ": $error"; print "$error\n"; $error_count++; - if ( $opt{X} ) { + if ( $opt{X} && ! $opt{f} ) { $dbh->rollback; exit(1); }