track/update census codes by year, #15381
[freeside.git] / FS / bin / freeside-censustract-update
1 #!/usr/bin/perl
2
3 use strict;
4 use Getopt::Std;
5 use Date::Parse 'str2time';
6 use FS::UID qw(adminsuidsetup);
7 use FS::Record qw(qsearch dbh);
8 use FS::Conf;
9 use FS::cust_main;
10 use FS::h_cust_main;
11
12 my %opt;
13 getopts('d:', \%opt);
14
15 my $user = shift or die &usage;
16 adminsuidsetup($user);
17 $FS::UID::AutoCommit = 0;
18 my $dbh = dbh;
19
20 my $conf = FS::Conf->new;
21 my $current_year = $conf->config('census_year') 
22   or die "No current census year configured.\n";
23 my $date = str2time($opt{d}) if $opt{d};
24 $date ||= time;
25 my %h_cust_main = map { $_->custnum => $_ }
26   qsearch(
27     'h_cust_main',
28     { censusyear => { op => '!=', value => $current_year } },
29     FS::h_cust_main->sql_h_search($date),
30   ) ; #the state of these customers as of $date
31
32 my @cust_main = qsearch( 'cust_main',
33   { censusyear => { op => '!=', value => $current_year } },
34 ); # all possibly interesting customers
35
36 warn scalar(@cust_main)." records found.\n";
37 my $queued = 0; my $updated = 0;
38 foreach my $cust_main (@cust_main) {
39   my $error;
40   my $h = $h_cust_main{$cust_main->custnum};
41   if ( defined($h) and $h->censustract eq $cust_main->censustract ) {
42     # the tract code hasn't been changed since $date
43     # so update it now
44     my $job = FS::queue->new({
45         job => 'FS::cust_main::process_censustract_update'
46     });
47     $error = $job->insert($cust_main->custnum);
48     $queued++;
49   }
50   elsif ($cust_main->censusyear eq '') {
51     # the tract number is assumed current, so just set the year
52     $cust_main->set('censusyear', $current_year);
53     $error = $cust_main->replace;
54     $updated++;
55   }
56   if ( $error ) {
57     $dbh->rollback;
58     die "error updating ".$cust_main->custnum.": $error\n";
59   }
60 }
61 warn "Queued $queued census code lookups, updated year in $updated records.\n";
62 $dbh->commit;
63
64 sub usage {
65     "Usage:\n\n  freeside-censustract-update [ -d date ] user\n\n"
66   }
67
68 =head1 NAME
69
70 freeside-censustract-update - Update census tract codes to the current year.
71
72 =head1 SYNOPSIS
73
74   freeside-censustract-update [ -d date ] user
75
76 =head1 DESCRIPTION
77
78 Finds all customers whose census tract codes don't appear to be current 
79 and updates them to the current year.  The "current year" is defined by 
80 the I<census_tract> configuration variable, not the calendar year.
81
82 The -d option tells the script to assume that tract codes last modified
83 after some date are already current.  Those customers will just have 
84 their 'censusyear' field set to the current year.  For all other 
85 customers with non-current censusyear values, the current tract code 
86 will be looked up externally and stored in the censustract field.
87
88 The actual tract code lookup runs from the job queue, because it's slow.
89 A separate job will be created for each customer.
90
91 =cut