Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / FS / FS / h_cust_pkg.pm
1 package FS::h_cust_pkg;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::h_Common;
6 use FS::cust_pkg;
7
8 @ISA = qw( FS::h_Common FS::cust_pkg );
9
10 sub table { 'h_cust_pkg' };
11
12 =head1 NAME
13
14 FS::h_cust_pkg - Historical record of customer package changes
15
16 =head1 SYNOPSIS
17
18 =head1 DESCRIPTION
19
20 An FS::h_cust_pkg object represents historical changes to packages.
21 FS::h_cust_pkg inherits from FS::h_Common and FS::cust_pkg.
22
23 =head1 CLASS METHODS
24
25 =over 4
26
27 =item search HASHREF
28
29 Like L<FS::cust_pkg::search>, but adapted for searching historical records.
30 Takes the additional parameter "date", which is the timestamp to perform 
31 the search "as of" (i.e. search the most recent insert or replace_new record
32 for each pkgnum that is not later than that date).
33
34 =cut
35
36 sub search {
37   my ($class, $params) = @_;
38   my $date = delete $params->{'date'};
39   $date =~ /^\d*$/ or die "invalid search date '$date'\n";
40
41   my $query = FS::cust_pkg->search($params);
42
43   # allow multiple status criteria
44   # this might be useful in the base cust_pkg search, but I haven't 
45   # tested it there yet
46   my $status = delete $params->{'status'};
47   if( $status ) {
48     my @status_where;
49     foreach ( split(',', $status) ) {
50       if ( /^active$/ ) {
51         push @status_where, $class->active_sql();
52       } elsif ( /^not[ _]yet[ _]billed$/ ) {
53         push @status_where, $class->not_yet_billed_sql();
54       } elsif ( /^(one-time charge|inactive)$/ ) {
55         push @status_where, $class->inactive_sql();
56       } elsif ( /^suspended$/ ) {
57         push @status_where, $class->suspended_sql();
58       } elsif ( /^cancell?ed$/ ) {
59         push @status_where, $class->cancelled_sql();
60       }
61     }
62     if ( @status_where ) {
63       $query->{'extra_sql'}   .= ' AND ('.join(' OR ', @status_where).')';
64       $query->{'count_query'} .= ' AND ('.join(' OR ', @status_where).')';
65     }
66   }
67
68   # make some adjustments
69   $query->{'table'} = 'h_cust_pkg';
70   foreach (qw(select addl_from extra_sql count_query)) {
71     $query->{$_} =~ s/cust_pkg\b/h_cust_pkg/g;
72     $query->{$_} =~ s/cust_main\b/h_cust_main/g;
73   }
74   
75   my $and_where = " AND h_cust_pkg.historynum = 
76   (SELECT historynum FROM h_cust_pkg AS mostrecent
77   WHERE mostrecent.pkgnum = h_cust_pkg.pkgnum 
78   AND mostrecent.history_date <= $date
79   AND mostrecent.history_action IN ('insert', 'replace_new')
80   ORDER BY history_date DESC,historynum DESC LIMIT 1
81   ) AND h_cust_main.historynum =
82   (SELECT historynum FROM h_cust_main AS mostrecent
83   WHERE mostrecent.custnum = h_cust_main.custnum
84   AND mostrecent.history_date <= h_cust_pkg.history_date
85   AND mostrecent.history_action IN ('insert', 'replace_new')
86   ORDER BY history_date DESC,historynum DESC LIMIT 1
87   )";
88
89   $query->{'extra_sql'} .= $and_where;
90   $query->{'count_query'} .= $and_where;
91
92   $query;
93 }
94
95
96 =head1 BUGS
97
98 =head1 SEE ALSO
99
100 L<FS::cust_pkg>,  L<FS::h_Common>, L<FS::Record>, schema.html from the base
101 documentation.
102
103 =cut
104
105 1;
106
107