RT#71995: Cancel Packages [parse emails in cust_main-bulk_change]
[freeside.git] / bin / cust_main-bulk_change
1 #!/usr/bin/perl
2
3 use strict;
4 use vars qw( $opt_a $opt_p $opt_t $opt_k $opt_c $opt_v $opt_E );
5 use Getopt::Std;
6 use FS::UID qw(adminsuidsetup);
7 use FS::Record qw(qsearch qsearchs);
8 use FS::cust_main;
9 use FS::cust_main::Search;
10 use FS::cust_tag;
11 use FS::cust_pkg;
12
13 getopts('a:p:t:k:c:vE');
14
15 my $user = shift or &usage;
16 adminsuidsetup $user;
17
18 $FS::cust_main::skip_fuzzyfiles = 1;
19 $FS::cust_main::skip_fuzzyfiles = 1;
20 $FS::cust_main::import = 1;
21 $FS::cust_main::import = 1;
22
23 while (<STDIN>) {
24
25   my ($custnum,$cust_main);
26   if ($opt_E) {
27     # don't really need to validate input here, search will quote safely
28     unless ( /^\s*(.*)\s*$/ ) { 
29       warn "unparsable line: $_";
30       next;
31     }
32     my @cust_main = FS::cust_main::Search::email_search( 'email' => $1 );
33     if (@cust_main > 1) {
34       warn "muliple matching customers for address, skipping: $_";
35       next;
36     } elsif (@cust_main < 1) {
37       warn "could not find matching customer for address, skipping: $_";
38       next;
39     }
40     $cust_main = $cust_main[0];
41     $custnum = $cust_main->custnum;
42   } else {
43     unless ( /^\s*(\d+)\s*$/ ) { 
44       warn "unparsable line: $_";
45       next;
46     }
47     my $custnum = $1;
48     $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
49     unless ( $cust_main ) {
50       warn "unknown custnum $custnum\n";
51       next;
52     }
53   }
54
55   if ( $opt_v ) {
56     print $cust_main->custnum . ": " . $cust_main->name . "\n";
57   }
58
59   my %cust_tag = ( custnum=>$custnum, tagnum=>$opt_t );
60   if ( $opt_t && ! qsearchs('cust_tag', \%cust_tag) ) {
61     my $cust_tag = new FS::cust_tag \%cust_tag;
62     my $error = $cust_tag->insert;
63     die "$error\n" if $error;
64   }
65
66   if ( $opt_p || $opt_a ) {
67     $cust_main->agentnum($opt_a) if $opt_a;
68     $cust_main->payby($opt_p)    if $opt_p;
69
70     my $error = $cust_main->replace;
71     die "$error\n" if $error;
72   }
73
74   if ( $opt_k ) {
75     foreach my $k (split(/\s*,\s*/, $opt_k)) {
76       my($old, $new) = split(/\s*:\s*/, $k);
77       foreach my $cust_pkg ( qsearch('cust_pkg', {
78                                        'custnum' => $cust_main->custnum,
79                                        'pkgpart' => $old,
80                                     })
81                            )
82       {
83         $cust_pkg->pkgpart($new);
84         my $error = $cust_pkg->replace;
85         die "$error\n" if $error;
86       }
87     }
88   }
89
90   if ( $opt_c ) {
91     my @error = $cust_main->cancel( 'reason' => $opt_c );
92     die join(' / ', @error). "\n" if @error;
93   }
94
95 }
96
97 sub usage {
98   die "usage: cust_main-bulk_change [ -a agentnum ] [ -p NEW_PAYBY ] [ -t tagnum ] [ -k old_pkgpart:new_pkgpart,... ] [-v] [-E] employee_username <custnums.txt\n";
99 }
100
101 =head1 NAME
102
103 cust_main-bulk_change
104
105 =head1 SYNOPSIS
106
107   cust_main-bulk_change [ -a agentnum ] [ -p NEW_PAYBY ] [ -t tagnum ] [ -k old_pkgpart:new_pkgpart,... ] [ -c reasonnum ] username <custnums.txt
108
109 =head1 DESCRIPTION
110
111 Command-line tool to make bulk changes to a group of customers.
112
113 -a: new agentnum
114
115 -p: new payby, for example, I<CARD> or I<DCRD>
116
117 -t: tagnum to add if not present
118
119 -k: old_pkgpart:new_pkgpart, for example, I<5:4>.  Multiple entries can be comma-separated.
120
121 -c: Cancel customer
122
123 -v: verbose
124
125 -E: input is customer emails, rather than customer numbers
126
127 user: Employee username
128
129 =head1 BUGS
130
131 =head1 SEE ALSO
132
133 L<FS::payinfo_Mixin>, L<FS::cust_main>, L<FS::payby>
134
135 =cut
136
137 1;