X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_pkg%2FSearch.pm;h=89809de6cb35ca3c1a3cb24e85342f6bce942ea3;hb=0eedfd553057f9fd8d69197675f33dbc893e6c51;hp=1a9132df62fd1203dbce46ad1fae45913893a1b8;hpb=e5770f1c578ba47f730488df7fb5a03307ac71ab;p=freeside.git diff --git a/FS/FS/cust_pkg/Search.pm b/FS/FS/cust_pkg/Search.pm index 1a9132df6..89809de6c 100644 --- a/FS/FS/cust_pkg/Search.pm +++ b/FS/FS/cust_pkg/Search.pm @@ -112,6 +112,21 @@ Limit to packages whose locations have geocodes. Limit to packages whose locations do not have geocodes. +=item towernum + +Limit to packages associated with a svc_broadband, associated with a sector, +associated with this towernum (or any of these, if it's an arrayref) (or NO +towernum, if it's zero). This is an extreme niche case. + +=item 477part, 477rownum, date + +Limit to packages included in a specific row of one of the FCC 477 reports. +'477part' is the section name (see L methods), 'date' +is the report as-of date (completely unrelated to the package setup/bill/ +other date fields), and '477rownum' is the row number of the report starting +with zero. Row numbers have no inherent meaning, so this is useful only +for explaining a 477 report you've already run. + =back =cut @@ -266,6 +281,21 @@ sub search { } ### + # parse refnum (advertising source) + ### + + if ( exists($params->{'refnum'}) ) { + my @refnum; + if (ref $params->{'refnum'}) { + @refnum = @{ $params->{'refnum'} }; + } else { + @refnum = ( $params->{'refnum'} ); + } + my $in = join(',', grep /^\d+$/, @refnum); + push @where, "refnum IN($in)" if length $in; + } + + ### # parse package report options ### @@ -282,10 +312,10 @@ sub search { if (@report_option) { # this will result in the empty set for the dangling comma case as it should push @where, - map{ "0 < ( SELECT count(*) FROM part_pkg_option - WHERE part_pkg_option.pkgpart = part_pkg.pkgpart - AND optionname = 'report_option_$_' - AND optionvalue = '1' )" + map{ "EXISTS ( SELECT 1 FROM part_pkg_option + WHERE part_pkg_option.pkgpart = part_pkg.pkgpart + AND optionname = 'report_option_$_' + AND optionvalue = '1' )" } @report_option; } @@ -301,10 +331,10 @@ sub search { if (@report_option_any) { # this will result in the empty set for the dangling comma case as it should push @where, ' ( '. join(' OR ', - map{ "0 < ( SELECT count(*) FROM part_pkg_option - WHERE part_pkg_option.pkgpart = part_pkg.pkgpart - AND optionname = 'report_option_$_' - AND optionvalue = '1' )" + map{ "EXISTS ( SELECT 1 FROM part_pkg_option + WHERE part_pkg_option.pkgpart = part_pkg.pkgpart + AND optionname = 'report_option_$_' + AND optionvalue = '1' )" } @report_option_any ). ' ) '; } @@ -351,7 +381,7 @@ sub search { } ### - # parse country/state + # parse country/state/zip ### for (qw(state country)) { # parsing rules are the same for these if ( exists($params->{$_}) @@ -361,6 +391,9 @@ sub search { push @where, "cust_location.$_ = '$1'"; } } + if ( exists($params->{zip}) ) { + push @where, "cust_location.zip = " . dbh->quote($params->{zip}); + } ### # location_* flags @@ -433,6 +466,9 @@ sub search { "NOT (".FS::cust_pkg->onetime_sql . ")"; } else { + my $exclude_change_from = 0; + my $exclude_change_to = 0; + foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end change_date cancel )) { next unless exists($params->{$field}); @@ -448,6 +484,27 @@ sub search { $orderby ||= "ORDER BY cust_pkg.$field"; + if ( $field eq 'setup' ) { + $exclude_change_from = 1; + } elsif ( $field eq 'cancel' ) { + $exclude_change_to = 1; + } elsif ( $field eq 'change_date' ) { + # if we are given setup and change_date ranges, and the setup date + # falls in _both_ ranges, then include the package whether it was + # a change or not + $exclude_change_from = 0; + } + } + + if ($exclude_change_from) { + push @where, "change_pkgnum IS NULL"; + } + if ($exclude_change_to) { + # a join might be more efficient here + push @where, "NOT EXISTS( + SELECT 1 FROM cust_pkg AS changed_to_pkg + WHERE cust_pkg.pkgnum = changed_to_pkg.change_pkgnum + )"; } } @@ -487,6 +544,59 @@ sub search { } ## + # parse the extremely weird 'towernum' param + ## + + if ($params->{towernum}) { + my $towernum = $params->{towernum}; + $towernum = [ $towernum ] if !ref($towernum); + my $in = join(',', grep /^\d+$/, @$towernum); + if (length $in) { + # inefficient, but this is an obscure feature + eval "use FS::Report::Table"; + FS::Report::Table->_init_tower_pkg_cache; # probably does nothing + push @where, "EXISTS( + SELECT 1 FROM tower_pkg_cache + WHERE tower_pkg_cache.pkgnum = cust_pkg.pkgnum + AND tower_pkg_cache.towernum IN ($in) + )" + } + } + + ## + # parse the 477 report drill-down options + ## + + if ($params->{'477part'} =~ /^([a-z]+)$/) { + my $section = $1; + my ($date, $rownum, $agentnum); + if ($params->{'date'} =~ /^(\d+)$/) { + $date = $1; + } + if ($params->{'477rownum'} =~ /^(\d+)$/) { + $rownum = $1; + } + if ($params->{'agentnum'} =~ /^(\d+)$/) { + $agentnum = $1; + } + if ($date and defined($rownum)) { + my $report = FS::Report::FCC_477->report($section, + 'date' => $date, + 'agentnum' => $agentnum, + 'detail' => 1 + ); + my $pkgnums = $report->{detail}->[$rownum] + or die "row $rownum is past the end of the report"; + # '0' so that if there are no pkgnums (empty string) it will create + # a valid query that returns nothing + warn "PKGNUMS:\n$pkgnums\n\n"; # XXX debug + + # and this overrides everything + @where = ( "cust_pkg.pkgnum IN($pkgnums)" ); + } # else we're missing some params, ignore the whole business + } + + ## # setup queries, links, subs, etc. for the search ##