Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorJonathan Prykop <jonathan@freeside.biz>
Fri, 18 Nov 2016 11:19:46 +0000 (05:19 -0600)
committerJonathan Prykop <jonathan@freeside.biz>
Fri, 18 Nov 2016 11:19:46 +0000 (05:19 -0600)
13 files changed:
FS/FS/cust_location.pm
FS/FS/cust_main/Search.pm
FS/FS/cust_pkg.pm
FS/FS/geocode_Mixin.pm
FS/FS/svc_cable.pm
FS/FS/svc_hardware.pm
bin/wipe-payment_history [new file with mode: 0755]
httemplate/elements/customer-table.html
httemplate/elements/popup-topreload.html [new file with mode: 0644]
httemplate/misc/batch-cust_pay.html
httemplate/misc/process/batch-cust_pay.cgi
httemplate/search/cust_main.html
httemplate/search/report_cust_main.html

index a9660d8..e1b8533 100644 (file)
@@ -937,7 +937,7 @@ sub _upgrade_data {
     next if $field eq 'disabled';
     foreach my $location (qsearch({
       table => 'cust_location',
-      extra_sql => " WHERE $field LIKE ' %' OR $field LIKE '% '"
+      extra_sql => " WHERE disabled IS NULL AND ($field LIKE ' %' OR $field LIKE '% ')"
     })) {
       my $error = $location->replace;
       die "$error (fixing whitespace in $field, locationnum ".$location->locationnum.')'
index e021140..14dd4b4 100644 (file)
@@ -695,6 +695,21 @@ sub search {
     push @where, FS::cust_main->$method();
   }
 
+  my $current = '';
+  unless ( $params->{location_history} ) {
+    $current = '
+      AND (    cust_location.locationnum IN ( cust_main.bill_locationnum,
+                                              cust_main.ship_locationnum
+                                            )
+            OR cust_location.locationnum IN (
+                 SELECT locationnum FROM cust_pkg
+                  WHERE cust_pkg.custnum = cust_main.custnum
+                    AND locationnum IS NOT NULL
+                    AND '. FS::cust_pkg->ncancelled_recurring_sql.'
+               )
+          )';
+  }
+
   ##
   # address
   ##
@@ -714,6 +729,7 @@ sub search {
         SELECT 1 FROM cust_location 
         WHERE cust_location.custnum = cust_main.custnum
           AND (".join(' OR ',@orwhere).")
+          $current
         )";
     }
   }
@@ -727,6 +743,7 @@ sub search {
       SELECT 1 FROM cust_location
       WHERE cust_location.custnum = cust_main.custnum
         AND cust_location.city = $city
+        $current
     )";
   }
 
@@ -739,6 +756,7 @@ sub search {
       SELECT 1 FROM cust_location
       WHERE cust_location.custnum = cust_main.custnum
         AND cust_location.county = $county
+        $current
     )";
   }
 
@@ -751,6 +769,7 @@ sub search {
       SELECT 1 FROM cust_location
       WHERE cust_location.custnum = cust_main.custnum
         AND cust_location.state = $state
+        $current
     )";
   }
 
@@ -763,6 +782,7 @@ sub search {
       SELECT 1 FROM cust_location
       WHERE cust_location.custnum = cust_main.custnum
         AND cust_location.zip LIKE $zip
+        $current
     )";
   }
 
@@ -775,6 +795,7 @@ sub search {
       SELECT 1 FROM cust_location
       WHERE cust_location.custnum = cust_main.custnum
         AND cust_location.country = '$country'
+        $current
     )";
   }
 
index 714d292..4e9ede3 100644 (file)
@@ -5072,6 +5072,17 @@ sub cancel_sql {
   "cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0";
 }
 
+=item ncancelled_recurring_sql
+
+Returns an SQL expression identifying un-cancelled, recurring packages.
+
+=cut
+
+sub ncancelled_recurring_sql {
+  $_[0]->recurring_sql().
+  " AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) ";
+}
+
 =item status_sql
 
 Returns an SQL expression to give the package status as a string.
index ef16e74..b999be0 100644 (file)
@@ -265,6 +265,7 @@ sub process_district_update {
   my $method = $conf->config('tax_district_method')
     or return; #nothing to do if null
   my $self = $class->by_key($id) or die "object $id not found";
+  return if $self->disabled;
 
   # dies on error, fine
   my $tax_info = get_district({ $self->location_hash }, $method);
index 01c5de7..9e818e1 100644 (file)
@@ -122,11 +122,16 @@ Returns the MAC address and serial number.
 
 sub label {
   my $self = shift;
+  my $part_svc = $self->cust_svc->part_svc;
   my @label = ();
   push @label, 'MAC:'. $self->mac_addr_pretty
     if $self->mac_addr;
-  push @label, 'Serial#'. $self->serialnum
-    if $self->serialnum;
+  if ( $self->serialnum ) {
+    my $serialnum_label = $part_svc->part_svc_column('serialnum');
+    push @label,
+      ($serialnum_label && $serialnum_label->columnlabel || 'Serial#').
+      $self->serialnum;
+  }
   return join(', ', @label);
 }
 
index dbb8b68..4bff483 100644 (file)
@@ -134,15 +134,22 @@ sub search_sql {
 
 sub label {
   my $self = shift;
+  my $part_svc = $self->cust_svc->part_svc;
   my @label = ();
   if (my $type = $self->hardware_type) {
-    push @label, 'Type:' . $type->description;
+    my $typenum_label = $part_svc->part_svc_column('typenum');
+    push @label, ( $typenum_label && $typenum_label->columnlabel || 'Type:' ).
+                 $type->description;
   }
   if (my $ser = $self->serial) {
-    push @label, 'Serial#' . $ser;
+    my $serial_label = $part_svc->part_svc_column('serial');
+    push @label, ( $serial_label && $serial_label->columnlabel || 'Serial#' ).
+                 $ser;
   }
   if (my $mac = $self->display_hw_addr) {
-    push @label, 'MAC:'. $mac;
+    my $hw_addr_label = $part_svc->part_svc_column('hw_addr');
+    push @label, ( $hw_addr_label && $hw_addr_label->columnlabel || 'MAC:').
+    $mac;
   }
   return join(', ', @label);
 }
diff --git a/bin/wipe-payment_history b/bin/wipe-payment_history
new file mode 100755 (executable)
index 0000000..d5a9176
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+
+use FS::Record;
+use FS::UID qw( adminsuidsetup dbh );
+
+adminsuidsetup shift;
+
+foreach $table (qw(
+
+  cust_bill
+   cust_bill_pkg
+    cust_bill_pkg_detail
+    cust_bill_pkg_display
+    cust_bill_pkg_fee
+    cust_bill_pkg_tax_location
+    cust_bill_pkg_tax_rate_location
+    cust_bill_pkg_discount
+
+  cust_bill_void
+    cust_bill_pkg_void
+    cust_bill_pkg_detail_void
+    cust_bill_pkg_display_void
+    cust_bill_pkg_fee_void
+    cust_bill_pkg_tax_location_void
+    cust_bill_pkg_tax_rate_location_void
+    cust_bill_pkg_discount_void
+
+  cust_statement
+
+  cust_pay
+    cust_bill_pay
+    cust_bill_pay_batch
+    cust_bill_pay_pkg
+    cust_pay_refund
+
+  cust_pay_void
+    cust_bill_pay
+
+  cust_credit
+    cust_credit_bill
+    cust_credit_bill_pkg
+    cust_credit_source_bill_pkg
+
+  cust_credit_void
+
+  cust_refund
+    cust_credit_refund
+
+  cust_pay_pending
+
+  pay_batch
+  cust_pay_batch
+
+  bill_batch
+  cust_bill_batch
+  cust_bill_batch_option
+
+  cust_tax_exempt_pkg
+  cust_tax_exempt_pkg_void
+
+)) {
+  foreach $t ( $table, "h_$table" ) {
+    my $sql = "DELETE FROM $t";
+    print "$sql;\n"; #dbh->do($sql);
+  }
+}
+
+foreach my $e ( 'cust_event', 'h_cust_event' ) {
+  my $sql = "DELETE FROM cust_event WHERE 'cust_bill' = ( SELECT eventtable FROM part_event WHERE part_event.eventpart = cust_event.eventpart )"; # and not exists ( select 1 from cust_bill where cust_event.tablenum = cust_bill.invnum )";
+  print "$sql;\n"; #dbh->do($sql);
+}
+
+#cust_event_fee???
+
+1;
index 0aa792d..25c26b5 100644 (file)
@@ -25,7 +25,7 @@ Example:
              'custnum_update_callback' => 'name_of_js_callback' #passed a rownum
 
              #listrefs
-             'types'         => ['immutable', ''], # immutable or ''/text
+             'type'          => ['immutable', ''], # immutable, checkbox, date or ''/text
              'align'         => [ 'c', 'l', 'r', '' ],
              'size'          => [],                # sizes ignored for immutable
              'color'         => [],
@@ -66,7 +66,10 @@ This mason element is currently only used by misc/batch-cust_pay.html,
 and probably should be cleaned up more before being used by anything else.
 
 </%doc>
-
+<LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript">
 
   var num_open_invoices = new Array;
@@ -652,6 +655,12 @@ and probably should be cleaned up more before being used by anything else.
 %     } elsif ( $types->[$col] eq 'checkbox' ) {
       my_input.setAttribute('type', 'checkbox');
       my_input.checked = (values && values.<% $field %>) ? true : false;
+%     } elsif ( $types->[$col] eq 'date' ) {
+      my_input_button = document.createElement('IMG');
+      my_input_button.setAttribute('src', '<% $fsurl %>images/calendar.png');
+      my_input_button.setAttribute('title', <% mt('Select date') |js_string %>);
+      my_input_button.setAttribute('name', '<% $name %>'+thisrownum+'button');
+      my_input_button.setAttribute('id',   '<% $name %>'+thisrownum+'button');
 %     }
       my_input.value = (values && values.<% $field %>) || '';
 %     if ( $opt{onchange}->[$col] ) {
@@ -662,9 +671,21 @@ and probably should be cleaned up more before being used by anything else.
         my_input.onkeyup    = calc_total<%$col%>;
 %     }
       my_cell.appendChild(my_input);
+%     if ( $types->[$col] eq 'date' ) {
+      my_cell.appendChild(my_input_button);
+%     }
 
     row.appendChild(my_cell);
 
+%     if ( $types->[$col] eq 'date' ) {
+      Calendar.setup({
+        inputField: '<% $name %>'+thisrownum,
+        ifFormat:   "<% $date_format %>",
+        button:     '<% $name %>'+thisrownum+'button',
+        align:      "BR"
+      });
+%     }
+
 %     $col++;
 %   }
 
@@ -805,6 +826,7 @@ addRow();
 
 my(%opt) = @_;
 my $conf = new FS::Conf;
+my $date_format = $conf->config('date_format') || '%m/%d/%Y';
 
 my $types = $opt{'type'} ? [ @{$opt{'type'}} ] : [];
 my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
diff --git a/httemplate/elements/popup-topreload.html b/httemplate/elements/popup-topreload.html
new file mode 100644 (file)
index 0000000..00d5cdf
--- /dev/null
@@ -0,0 +1,21 @@
+<%doc>
+
+Example:
+
+  <& /elements/popup-topreload, mt('Action completed') &>
+
+</%doc>
+<& /elements/header-popup.html, encode_entities($message) &>
+  <script src="<% $fsurl %>elements/js.cookie.js"></script>
+  <SCRIPT TYPE="text/javascript">
+    Cookies.set('freeside_status', <% $message |js_string %>,{
+                  expires: 0.0035
+    });
+    topreload();
+  </SCRIPT>
+<& /elements/footer-popup.html &>
+<%init>
+
+my $message = shift;
+
+</%init>
index d4d4afa..e20e4a4 100644 (file)
@@ -469,16 +469,16 @@ die "access denied"
 my $conf = new FS::Conf;
 my $money_char = $conf->config('money_char') || '$';
 
-my @header  = ( 'Amount', 'Check #' );
-my @fields  = ( 'paid', 'payinfo' );
-my @types   = ( '', '' );
-my @align   = ( 'r', 'r' );
-my @sizes   = ( 8, 10 );
-my @colors  = ( '', '' );
+my @header  = ( 'Amount', 'Check #', 'Date override' );
+my @fields  = ( 'paid', 'payinfo', '_date' );
+my @types   = ( '', '', 'date', );
+my @align   = ( 'r', 'r', 'r' );
+my @sizes   = ( 8, 10, 8 );
+my @colors  = ( '', '', '' );
 my %param   = ();
-my @footer  = ( '_TOTAL', '' );
-my @footer_align = ( 'r', 'r' );
-my @onchange = ( '', '' );;
+my @footer  = ( '_TOTAL', '', '' );
+my @footer_align = ( 'r', 'r', '' );
+my @onchange = ( '', '', '' );
 my $use_discounts = '';
 
 # Not entirely sure this works anymore...
index ff78862..b4580bb 100644 (file)
@@ -38,6 +38,7 @@ foreach my $row ( map /^custnum(\d+)$/, keys %$param ) {
                     'paid'           => $param->{"paid$row"},
                     'payby'          => 'BILL',
                     'payinfo'        => $param->{"payinfo$row"},
+                    '_date'          => $param->{"_date$row"},
                     'discount_term'  => $param->{"discount_term$row"},
                     'paybatch'       => $paybatch,
                     'no_auto_apply'  => exists($param->{"no_auto_apply$row"}) ? 'Y' : '',
index 672c201..1aa3390 100755 (executable)
@@ -41,7 +41,8 @@ my %search_hash = ();
 
 #scalars
 my @scalars = qw (
-  agentnum salesnum status address city county state zip country
+  agentnum salesnum status
+  address city county state zip country location_history
   invoice_terms
   no_censustract with_geocode with_email tax no_tax POST no_POST
   custbatch usernum
index b6be023..69bbe85 100755 (executable)
       </TD>
     </TR>
 
+    <TR>
+      <TH ALIGN="right" VALIGN="center"><% mt('Search historical addresses') %></TH>
+      <TD><INPUT TYPE="checkbox" NAME="location_history" VALUE="1"></TD>
+
   </TABLE>
   <BR>