[freeside-commits] branch master updated. c1285aad3e79b4fd9312002cd03c0bdc325acc25

Mark Wells mark at 420.am
Sat Sep 28 17:53:18 PDT 2013


The branch, master has been updated
       via  c1285aad3e79b4fd9312002cd03c0bdc325acc25 (commit)
      from  eb3bd392a89b8b666dc512951e78913c05b98810 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit c1285aad3e79b4fd9312002cd03c0bdc325acc25
Author: Mark Wells <mark at freeside.biz>
Date:   Sat Sep 28 17:52:54 2013 -0700

    report showing phone number breakdown by state, #24789

diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index edb5e81..c8fe5f2 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -197,6 +197,10 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
       [ $fsurl. 'search/report_svc_phone_usage.html',
         'Total usage (minutes, and amount billed) for the specified time period, per phone number.',
       ];
+    $report_svc{"${name} by state"} =
+      [ $fsurl. 'search/phone_state.html',
+        'Current or historical phone services broken down by state.',
+      ];
 
   }
 
diff --git a/httemplate/search/phone_state.html b/httemplate/search/phone_state.html
new file mode 100644
index 0000000..7b3acbb
--- /dev/null
+++ b/httemplate/search/phone_state.html
@@ -0,0 +1,161 @@
+<& elements/search.html,
+  'title'       => $title,
+  'name'        => 'states',
+  'query'       => $query,
+  'count_query' => $count_query,
+  'count_addl'  => $count_addl,
+  'header'      => [ 'State', # if we add more group fields, change this
+                     'Count',
+                     'Phone numbers'
+                   ],
+  'fields'      => [ 'state',
+                     'num_svcnums',
+                     $detail_sub
+                   ],
+  'html_init'   => include('.head', $time),
+&>
+<%def .head>
+% my $time = shift;
+<FORM STYLE="display:inline" ACTION=<% $cgi->url %> METHOD="GET">
+Active phone services as of <& /elements/input-date-field.html, {
+  'name'    => 'date',
+  'value'   => $time,
+  'format'  => FS::Conf->new->config('date_format') || '%m/%d/%Y'
+} &>
+<INPUT TYPE="hidden" NAME="order_by" VALUE="<% $cgi->param('order_by') %>">
+<INPUT TYPE="submit" VALUE="Refresh">
+</FORM>
+<BR>
+<BR>
+</%def>
+<%init>
+# svc_phone-specific for now; may change later
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right('Services: Phone numbers');
+my $title = 'Phone services by state';
+
+my $time = time;
+if ( $cgi->param('date') ) {
+  $time = parse_datetime($cgi->param('date'));
+  $title .= time2str(' (%b %o, %Y)', $time);
+}
+
+my @tables = qw(svc_phone cust_svc cust_pkg cust_location cust_main);
+my @pkeys =  qw(svcnum    svcnum   pkgnum   locationnum   custnum);
+my @h_tables = map "h_$_", @tables;
+
+my $addl_from = '';
+my @where;
+
+for(my $i = 0; $i < scalar(@tables); $i++) {
+  my $last_table = $h_tables[$i-1];
+  my $pkey = $pkeys[$i];
+  my $table = $tables[$i];
+  my $h_table = $h_tables[$i];
+  # alias the preceding table, and join to a subquery that finds the most 
+  # recent change to $table.$pkey before $time
+  my $alias = $h_table;
+  my $inside = '';
+  if ( $i > 0 ) {
+    $alias = "t$i";
+    $inside = " AS $alias";
+  }
+  $inside .= "
+      JOIN 
+        (SELECT $pkey AS num, MAX(history_date) AS history_date
+                FROM $h_table 
+                WHERE history_date <= $time AND 
+                      history_action IN ('insert', 'replace_new') 
+                GROUP BY $pkey
+        ) AS mostrecent_$table
+        ON ($alias.$pkey = mostrecent_$table.num AND
+            $alias.history_date = mostrecent_$table.history_date AND
+            $alias.history_action IN ('insert', 'replace_new')
+        )
+      LEFT JOIN
+        (SELECT $pkey AS num, MAX(history_date) AS history_date, 1 AS deleted
+                FROM $h_table
+                WHERE history_date <= $time AND
+                      history_action = 'delete'
+                GROUP BY $pkey
+        ) AS deleted_$table
+        ON (mostrecent_$table.num = deleted_$table.num AND
+            mostrecent_$table.history_date < deleted_$table.history_date
+        )
+";
+  # join to the preceding table if there is one, and filter out 
+  # deleted records
+  if ( $i > 0 ) {
+    $addl_from .= "
+      LEFT JOIN ( $h_table $inside ) AS $h_table
+        ON ($h_table.$pkey = $last_table.$pkey)";
+    push @where, "$h_table.deleted IS NULL";
+  } else {
+    $addl_from .= $inside;
+    push @where, "deleted_$table.deleted IS NULL";
+  }
+}
+
+# so that we know which services are still active
+$addl_from .= "
+  LEFT JOIN svc_phone ON (h_svc_phone.svcnum = svc_phone.svcnum AND
+                          h_svc_phone.phonenum = svc_phone.phonenum)";
+
+#warn "\n\nJOIN EXPRESSION:\n$addl_from\n\n";
+
+push @where, $curuser->agentnums_sql(
+  'table' => 'h_cust_main',
+  'null_right' => 'View/link unlinked services'
+);
+my $where = " WHERE ".join(' AND ', map "($_)", @where);
+
+my $group_field = 'h_cust_location.state';
+my @select = (
+  "$group_field AS state",
+  'count(DISTINCT h_svc_phone.svcnum) AS num_svcnums',
+  # don't DISTINCT these (it reorders them)
+  "array_to_string(array_agg(h_svc_phone.phonenum), ',') AS all_phonenums",
+  "array_to_string(array_agg(h_svc_phone.svcnum), ',') AS all_svcnums",
+  "array_to_string(array_agg(svc_phone.svcnum), ',') AS active_svcnums",
+);
+
+my $query = {
+  'select'    => join(',', @select),
+  'table'     => 'h_svc_phone',
+  'addl_from' => $addl_from,
+  'extra_sql' => " $where GROUP BY $group_field",
+};
+
+# DISTINCT on these because of cross-producting effects when a cust_pkg 
+# record (usually) was replaced more than once within one second.
+my $count_query =
+  "SELECT COUNT(DISTINCT $group_field), COUNT(DISTINCT h_svc_phone.svcnum) ".
+  "FROM h_svc_phone $addl_from $where";  
+my $count_addl = [ '%d phone services' ];
+
+my $detail_sub = sub {
+  my $rec = shift;
+  warn Dumper $rec;
+  my @svcnums = split(',', $rec->all_svcnums);
+  my @phonenums = split(',', $rec->all_phonenums);
+  # identifies services that still exist with the same svcnum+phonenum
+  my %active = map { $_ => 1 } split(',', $rec->active_svcnums);
+  # make a single column of phonenums
+  my @return;
+  my %seen;
+  while (my $svcnum = shift @svcnums) {
+    my $phonenum = shift @phonenums;
+    next if $seen{$svcnum};
+    $seen{$svcnum} = 1;
+    my $link = $active{$svcnum} ?
+                $p.'view/svc_phone.cgi?'.$svcnum :
+                '';
+    push @return, [ { data => $phonenum,
+                      link => $link,
+                      data_style => ($active{$svcnum} ? '' : 'i')
+                     } ];
+  }
+  \@return;
+};
+
+</%init>

-----------------------------------------------------------------------

Summary of changes:
 httemplate/elements/menu.html      |    4 +
 httemplate/search/phone_state.html |  161 ++++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+), 0 deletions(-)
 create mode 100644 httemplate/search/phone_state.html




More information about the freeside-commits mailing list