Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / bin / svc_acct-recalculate_usage
1 #!/usr/bin/perl -w
2
3 use strict;
4 use vars qw($opt_s $opt_u $opt_p $opt_k);
5 use Getopt::Std;
6 use FS::UID qw(adminsuidsetup);
7 use FS::Record qw(qsearch qsearchs);
8 use FS::svc_acct;
9 use FS::cust_svc;
10
11 my %field2sub = (
12   'seconds'    => sub {
13     my($svc_acct, $cust_pkg) = @_;
14     $svc_acct->seconds_since_sqlradacct( $cust_pkg->last_bill, time );
15   },
16   'upbytes'    => sub {
17     my($svc_acct, $cust_pkg) = @_;
18     $svc_acct->attribute_since_sqlradacct(
19       $cust_pkg->last_bill, time, 'AcctInputOctets' );
20   },
21   'downbytes'  => sub {
22     my($svc_acct, $cust_pkg) = @_;
23     $svc_acct->attribute_since_sqlradacct(
24       $cust_pkg->last_bill, time, 'AcctOutputOctets' );
25   },
26   'totalbytes' => sub {
27     my($svc_acct, $cust_pkg) = @_;
28     $svc_acct->attribute_since_sqlradacct(
29        $cust_pkg->last_bill, time, 'AcctInputOctets' )
30     +
31     $svc_acct->attribute_since_sqlradacct(
32        $cust_pkg->last_bill, time, 'AcctOutputOctets' )
33     ;
34   },
35 );
36
37 my $user = shift or die &usage;
38 adminsuidsetup $user;
39
40 my $field = shift;
41 die "can only reset seconds, upbytes, downbytes or totalbytes"
42   unless $field2sub{$field};
43
44 my $value = shift;
45
46 #false laziness w/freeside-reexport
47 getopts('s:u:p:k:');
48
49 my @svc_x = ();
50 if ( $opt_s ) {
51   my $cust_svc = qsearchs('cust_svc', { svcnum=>$opt_s } )
52     or die "svcnum $opt_s not found\n";
53   push @svc_x, $cust_svc->svc_x;
54 } elsif ( $opt_u ) {
55   my $svc_x = qsearchs('svc_acct', { username=>$opt_u } )
56     or die "username $opt_u not found\n";
57   push @svc_x, $svc_x;
58 } elsif ( $opt_p ) {
59   push @svc_x, map { $_->svc_x } qsearch('cust_svc', { svcpart=>$opt_p } );
60   die "no services with svcpart $opt_p found\n" unless @svc_x;
61 } elsif ( $opt_k ) {
62   push @svc_x,
63     map { $_->svc_x }
64       qsearch({
65                 table     => 'cust_svc',
66                 addl_from => 'LEFT JOIN cust_pkg USING ( pkgnum )',
67                 extra_sql => "WHERE pkgpart = $opt_k",
68              });
69   die "no services with pkgpart $opt_k found\n" unless @svc_x;
70 }
71
72 warn "setting $field to $value before usage\n";
73 foreach my $svc_x ( @svc_x ) {
74   my $cust_pkg = $svc_x->cust_svc->cust_pkg;
75   my $cust_usage = $value - &{ $field2sub{$field} }( $svc_x, $cust_pkg );
76 #  warn "resetting  ". $svc_x->svcnum.':'.$svc_x->username. " to $cust_usage\n";
77   warn "$field for ". $svc_x->svcnum.':'.$svc_x->username. " reached limit\n"
78     if $cust_usage <= 0;
79   $svc_x->$field($cust_usage);
80
81   my $error = $svc_x->replace;
82   die $error if $error;
83 }
84
85 sub usage {
86   die "Usage:\n\n  svc_acct-recalculate_usage user [ -s svcnum | -u username | -p svcpart ]\n";
87 }
88
89 =head1 NAME
90
91 svc-acct-recalculate_usage - Command line tool to recalculate usage for existing services
92
93 =head1 SYNOPSIS
94
95   svc_acct-recalculate_usage user usagefield initialvalue [ -s svcnum | -u username | -p svcpart ]
96
97   #recalculate a 1gb totalbytes limit for pkgpart 2
98   svc_acct-recalculate_usage ivan totalbytes 1073741824 -k 2
99
100 =head1 DESCRIPTION
101
102 Re-calculates the specified usage field for the specified service(s) (selected
103 by svcnum, username or svcpart).
104
105 =head1 SEE ALSO
106
107 L<FS::svc_acct>, L<freeside-reexport>, L<FS::part_export>
108
109 =cut
110