Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Sat, 10 Feb 2018 03:10:00 +0000 (19:10 -0800)
committerIvan Kohler <ivan@freeside.biz>
Sat, 10 Feb 2018 03:10:00 +0000 (19:10 -0800)
21 files changed:
FS/FS/Schema.pm
FS/FS/cdr.pm
FS/FS/cust_bill.pm
FS/FS/cust_bill_pkg.pm
FS/FS/cust_bill_pkg_detail.pm
FS/FS/part_pkg/prorate_Mixin.pm
FS/FS/quotation.pm
FS/bin/freeside-passwd [new file with mode: 0755]
bin/update-rates [new file with mode: 0644]
debian/control
debian/freeside-webui.postinst [new file with mode: 0644]
debian/freeside.postinst [new file with mode: 0644]
debian/postinst [deleted file]
debian/rules
httemplate/docs/about.html
httemplate/edit/access_user.html
httemplate/edit/process/access_user.html
httemplate/elements/menu.html
httemplate/misc/process/void-cust_bill.html
httemplate/misc/void-cust_bill.html
httemplate/view/prospect_main.html

index 65eadad..edecb7f 100644 (file)
@@ -5661,9 +5661,6 @@ sub tables_hashref {
         'sessionnum',       'int',    'NULL',      '', '', '',
         'subscriber',   'varchar',    'NULL', $char_d, '', '',
 
-        #old
-        'cdrbatch',     'varchar',    'NULL',     255, '', '',
-        #new
         'cdrbatchnum',      'int',    'NULL',      '', '', '',
 
         # FK to cust_bill_pkg_detail; having a value here absolutely means
index 331ac0f..3de0224 100644 (file)
@@ -170,7 +170,7 @@ following fields are currently supported:
 
 =item freesiderewritestatus - NULL, done, skipped
 
-=item cdrbatch
+=item cdrbatchnum
 
 =item detailnum - Link to invoice detail (L<FS::cust_bill_pkg_detail>)
 
@@ -240,7 +240,6 @@ sub table_info {
         'svcnum'                => 'Freeside service',
         'freesidestatus'        => 'Freeside status',
         'freesiderewritestatus' => 'Freeside rewrite status',
-        'cdrbatch'              => 'Legacy batch',
         'cdrbatchnum'           => 'Batch',
         'detailnum'             => 'Freeside invoice detail line',
     },
@@ -1659,7 +1658,12 @@ foreach my $INC ( @INC ) {
 
 tie my %import_formats, 'Tie::IxHash',
   map  { $_ => $cdr_info{$_}->{'name'} }
-  sort { $cdr_info{$a}->{'weight'} <=> $cdr_info{$b}->{'weight'} }
+  
+  #this is not doing anything useful anymore
+  #sort { $cdr_info{$a}->{'weight'} <=> $cdr_info{$b}->{'weight'} }
+  #so just sort alpha
+  sort { lc($cdr_info{$a}->{'name'}) cmp lc($cdr_info{$b}->{'name'}) }
+
   grep { exists($cdr_info{$_}->{'import_fields'}) }
   keys %cdr_info;
 
@@ -1868,41 +1872,6 @@ sub process_batch_import {
 #    @columns = map { s/^ +//; $_; } @columns;
 #  }
 
-# _ upgrade_data
-#
-# Used by FS::Upgrade to migrate to a new database.
-
-sub _upgrade_data {
-  my ($class, %opts) = @_;
-
-  warn "$me upgrading $class\n" if $DEBUG;
-
-  my $sth = dbh->prepare(
-    'SELECT DISTINCT(cdrbatch) FROM cdr WHERE cdrbatch IS NOT NULL'
-  ) or die dbh->errstr;
-
-  $sth->execute or die $sth->errstr;
-
-  my %cdrbatchnum = ();
-  while (my $row = $sth->fetchrow_arrayref) {
-
-    my $cdr_batch = qsearchs( 'cdr_batch', { 'cdrbatch' => $row->[0] } );
-    unless ( $cdr_batch ) {
-      $cdr_batch = new FS::cdr_batch { 'cdrbatch' => $row->[0] };
-      my $error = $cdr_batch->insert;
-      die $error if $error;
-    }
-
-    $cdrbatchnum{$row->[0]} = $cdr_batch->cdrbatchnum;
-  }
-
-  $sth = dbh->prepare('UPDATE cdr SET cdrbatch = NULL, cdrbatchnum = ? WHERE cdrbatch IS NOT NULL AND cdrbatch = ?') or die dbh->errstr;
-
-  foreach my $cdrbatch (keys %cdrbatchnum) {
-    $sth->execute($cdrbatchnum{$cdrbatch}, $cdrbatch) or die $sth->errstr;
-  }
-
-}
 
 =item ip_addr_sql FIELD RANGE
 
index 8b94dcc..bd1b8bb 100644 (file)
@@ -215,7 +215,7 @@ sub insert {
 
 }
 
-=item void [ REASON ]
+=item void [ REASON [ , REPROCESS_CDRS ] ]
 
 Voids this invoice: deletes the invoice and adds a record of the voided invoice
 to the FS::cust_bill_void table (and related tables starting from
@@ -226,6 +226,7 @@ FS::cust_bill_pkg_void).
 sub void {
   my $self = shift;
   my $reason = scalar(@_) ? shift : '';
+  my $reprocess_cdrs = scalar(@_) ? shift : '';
 
   unless (ref($reason) || !$reason) {
     $reason = FS::reason->new_or_existing(
@@ -257,7 +258,7 @@ sub void {
   }
 
   foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
-    my $error = $cust_bill_pkg->void($reason);
+    my $error = $cust_bill_pkg->void($reason, $reprocess_cdrs);
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
       return $error;
@@ -3541,6 +3542,23 @@ sub _items_aging_balances {
   return map{ sprintf('%.2f',$_) } @aging_balances;
 }
 
+=item has_call_details
+
+Returns true if this invoice has call details.
+
+=cut
+
+sub has_call_details {
+  my $self = shift;
+  $self->scalar_sql("
+    SELECT 1 FROM cust_bill_pkg_detail
+             LEFT JOIN cust_bill_pkg USING (billpkgnum)
+      WHERE cust_bill_pkg_detail.format = 'C'
+        AND cust_bill_pkg.invnum = ?
+      LIMIT 1
+  ", $self->invnum);
+}
+
 =item call_details [ OPTION => VALUE ... ]
 
 Returns an array of CSV strings representing the call details for this invoice
index e44a847..77dce24 100644 (file)
@@ -324,7 +324,7 @@ sub insert {
 
 }
 
-=item void [ REASON ]
+=item void [ REASON [ , REPROCESS_CDRS ] ]
 
 Voids this line item: deletes the line item and adds a record of the voided
 line item to the FS::cust_bill_pkg_void table (and related tables).
@@ -334,6 +334,7 @@ line item to the FS::cust_bill_pkg_void table (and related tables).
 sub void {
   my $self = shift;
   my $reason = scalar(@_) ? shift : '';
+  my $reprocess_cdrs = scalar(@_) ? shift : '';
 
   unless (ref($reason) || !$reason) {
     $reason = FS::reason->new_or_existing(
@@ -373,6 +374,9 @@ sub void {
     cust_tax_exempt_pkg
     cust_bill_pkg_fee
   )) {
+    my %delete_args = ();
+    $delete_args{'reprocess_cdrs'} = $reprocess_cdrs
+      if $table eq 'cust_bill_pkg_detail';
 
     foreach my $linked ( qsearch($table, { billpkgnum=>$self->billpkgnum }) ) {
 
@@ -380,7 +384,7 @@ sub void {
       my $void = $vclass->new( {
         map { $_ => $linked->get($_) } $linked->fields
       });
-      my $error = $void->insert || $linked->delete;
+      my $error = $void->insert || $linked->delete(%delete_args);
       if ( $error ) {
         $dbh->rollback if $oldAutoCommit;
         return $error;
@@ -863,7 +867,7 @@ sub _item_discount {
   # show introductory rate as a pseudo-discount
   if (!$d) { # this will conflict with showing real discounts
     my $part_pkg = $self->part_pkg;
-    if ( $part_pkg and $part_pkg->option('show_as_discount') ) {
+    if ( $part_pkg and $part_pkg->option('show_as_discount',1) ) {
       my $cust_pkg = $self->cust_pkg;
       my $intro_end = $part_pkg->intro_end($cust_pkg);
       my $_date = $self->cust_bill->_date;
index dd118c1..19b15f7 100644 (file)
@@ -106,21 +106,37 @@ sub insert {
   '';
 }
 
-=item delete
+=item delete [ ARG => VALUE ... ]
 
 Delete this record from the database.
 
+If the "reprocess_cdrs" argument is set to true, resets the status of any
+related CDRs (and deletes their associated cdr_termination records, if any).
+
 =cut
 
 sub delete {
-  my $self = shift;
+  my( $self, %args ) = @_;
+
   my $error = $self->SUPER::delete;
   return $error if $error;
+
   foreach my $cdr (qsearch('cdr', { detailnum => $self->detailnum })) {
+
     $cdr->set('detailnum', '');
+    $cdr->set('freesidestatus', '') if $args{'reprocess_cdrs'};
     $error = $cdr->replace;
     return "error unlinking CDR #" . $cdr->acctid . ": $error" if $error;
+
+    #well, technically this could have been on other invoices / termination
+    # partners... separate flag?
+    $self->scalar_sql( 'DELETE FROM cdr_termination WHERE acctid = ?',
+                       $cdr->acctid )
+      if $args{'reprocess_cdrs'};
+
   }
+
+  '';
 }
 
 =item replace OLD_RECORD
index 1a7b1ef..9e97cc5 100644 (file)
@@ -205,7 +205,7 @@ sub prorate_setup {
         # For some reason (probably user override), the bill date has been set even
         # though the package isn't billing yet. Start billing as though that was the
         # start date.
-        $sdate = $cust_pkg->bill;
+        $$sdate = $cust_pkg->bill;
         $cust_pkg->setup($cust_pkg->bill);
       }
       # Now figure the start and end of the period that contains the start date.
index 6b0c914..a3f0612 100644 (file)
@@ -716,7 +716,10 @@ sub estimate {
     my $cust_main;
     if ( $cust_or_prospect->isa('FS::prospect_main') ) {
       $cust_main = $cust_or_prospect->convert_cust_main;
-      die "$cust_main (simulating customer signup)\n" unless ref $cust_main;
+      unless ( ref($cust_main) ) {
+        $temp_dbh->rollback;
+        die "$cust_main (simulating customer signup)\n";
+      }
       $fake_self->set('prospectnum', '');
       $fake_self->set('custnum', $cust_main->custnum);
     } else {
@@ -726,7 +729,10 @@ sub estimate {
     # order packages
     local($FS::cust_pkg::disable_start_on_hold) = 1;
     $error = $fake_self->order(\%pkgnum_of);
-    die "$error (simulating package order)\n" if $error;
+    if ( $error ) {
+      $temp_dbh->rollback;
+      die "$error (simulating package order)\n";
+    }
 
     my @new_pkgs = map { FS::cust_pkg->by_key($_) } values(%pkgnum_of);
 
@@ -739,7 +745,10 @@ sub estimate {
       'no_usage_reset'  => 1,
     );
     $error = $cust_main->bill(%bill_opt);
-    die "$error (simulating initial billing)\n" if $error;
+    if ( $error ) {
+      $temp_dbh->rollback;
+      die "$error (simulating initial billing)\n" if $error;
+    }
 
     # pick dates for future bills
     my %next_bill_pkgs;
@@ -755,7 +764,10 @@ sub estimate {
       $bill_opt{'return_bill'} = $return_bill[$i] = [];
       $bill_opt{'pkg_list'} = $next_bill_pkgs{$next_bill};
       $error = $cust_main->bill(%bill_opt);
-      die "$error (simulating recurring billing cycle $i)\n" if $error;
+      if ( $error ) {
+        $temp_dbh->rollback;
+        die "$error (simulating recurring billing cycle $i)\n";
+      }
       $i++;
     }
 
diff --git a/FS/bin/freeside-passwd b/FS/bin/freeside-passwd
new file mode 100755 (executable)
index 0000000..dbd566e
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my $user = shift or die &usage;
+my $password = shift or die &usage;
+
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw( qsearchs );
+use FS::access_user;
+
+adminsuidsetup $user;
+
+my $access_user = qsearchs('access_user', {'username'=>$user})
+  or die "unknown username $user\n";
+my $error = $access_user->change_password($password);
+die $error if $error;
+
+1;
diff --git a/bin/update-rates b/bin/update-rates
new file mode 100644 (file)
index 0000000..b16fc7f
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+
+use FS::UID 'adminsuidsetup';
+use FS::Record qw(dbh qsearch qsearchs);
+use FS::tax_class;
+use FS::tax_rate;
+use strict;
+
+adminsuidsetup('ivan');
+$FS::UID::AutoCommit = 0;
+my @location = ( geocode => { op => 'like', value => '24%' } );
+
+# convert TELECOMM RELAY SYSTEMS SURCHARGE:CENTREX LINES
+# to      TELECOMM RELAY SYSTEMS SURCHARGE:TELECOMMUNICATIONS
+my $old_taxclassnum = qsearchs('tax_class', { 'taxclass' => '09:35' })->taxclassnum;
+my $new_taxclassnum = qsearchs('tax_class', { 'taxclass' => '09:00' })->taxclassnum;
+my $error;
+
+my @bindings = qsearch('part_pkg_taxrate', {
+  'taxclassnum' => $old_taxclassnum,
+  @location
+});
+print "remapping ".scalar(@bindings)." tax rate bindings.\n";
+foreach my $part_pkg_taxrate (@bindings) {
+  $part_pkg_taxrate->set('taxclassnum', $new_taxclassnum);
+  $error = $part_pkg_taxrate->replace;
+  die $part_pkg_taxrate->pkgtaxratenum .": $error" if $error;
+}
+
+# change the fee to 0.05.
+my @tax_rates = qsearch('tax_rate', {
+  taxclassnum => $new_taxclassnum,
+  @location
+});
+print "changing rate on ".scalar(@tax_rates)." tax rate definitions.\n";
+foreach my $tax_rate (@tax_rates) {
+  $tax_rate->set('fee', 0.05);
+  my $error = $tax_rate->replace;
+  die $tax_rate->taxnum . ": $error\n" if $error;
+}
+
+dbh->commit;
index fc3bae1..2391f73 100644 (file)
@@ -175,7 +175,7 @@ Description: Self-service portal html/cgi filesfor Freeside billing and trouble
 
 Package: freeside-ng-selfservice
 Architecture: all
-Depends: libapache2-mod-php5,php5-xmlrpc,apache2
+Depends: libapache2-mod-php|libapache2-mod-php5,php5-xmlrpc,apache2
 Recommends:
 Description: Next Generation Self-service portal for Freeside billing and trouble ticketing
  Freeside is a web-based billing and trouble ticketing application.
diff --git a/debian/freeside-webui.postinst b/debian/freeside-webui.postinst
new file mode 100644 (file)
index 0000000..8dd2baa
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+chown -R freeside /usr/local/etc/freeside
+rm -fr  /usr/local/etc/freeside/masondata/*
+
+#XXX systemd equivalent (start apache after postgres)
+/sbin/insserv -d
+
+exit 0
+
diff --git a/debian/freeside.postinst b/debian/freeside.postinst
new file mode 100644 (file)
index 0000000..3e7dc25
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+#probably not needed with systemd
+/usr/sbin/update-rc.d freeside defaults 23 01
+
+chown -R freeside /usr/local/etc/freeside
+rm -fr  /usr/local/etc/freeside/masondata/*
+
+exit 0
+
diff --git a/debian/postinst b/debian/postinst
deleted file mode 100644 (file)
index 09f9dae..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-chown -R freeside /usr/local/etc/freeside
-/usr/sbin/update-rc.d freeside defaults 23 01
-/sbin/insserv -d
-rm -fr  /usr/local/etc/freeside/masondata/*
-
-exit 0
-
index 1eb312b..041c895 100755 (executable)
@@ -228,8 +228,9 @@ install-stamp: build-stamp
 
        # Torrus 
        
-       install -d ${TORRUS_CONF}
-       install -o root -m 755 htetc/freeside-torrus.conf $(TORRUS_CONF)/
+       #in freeside-webui package
+       #install -d ${TORRUS_CONF}
+       #install -o root -m 755 htetc/freeside-torrus.conf $(TORRUS_CONF)/
 
        ( cd torrus; \
        torrus_user=freeside var_user=freeside var_group=freeside ./configure; \
index bc3c1b3..29a9fe0 100644 (file)
@@ -28,7 +28,7 @@
 % } else {
   <FONT SIZE="-1">
 % }
-&copy; 2017 Freeside Internet Services, Inc.<BR>
+&copy; 2018 Freeside Internet Services, Inc.<BR>
 All rights reserved.<BR>
 Licensed under the terms of the<BR>
 GNU <b>Affero</b> General Public License.<BR>
@@ -56,7 +56,7 @@ GNU <b>Affero</b> General Public License.<BR>
 
 % unless ( $agentnum ) {
   <CENTER>
-  <FONT SIZE="-3">"I've heard it too many times to ignore it / Its's something that I'm supposed to be" - K. Frog</FONT>
+  <FONT SIZE="-3">"Then, when all seemed to be lost, a small glimmer of light appeared in the distance.  Could it be...  back from the great beyond..." - D. 3030</FONT>
   </CENTER>
 % }
 
index 9d25853..f40575c 100644 (file)
                    sub {
                      my $access_user = shift;
 
-                     '<BR>Employee Groups<BR>'.
-                     ntable("#cccccc",2).
+                     '<BR>'.
+                     '<FONT CLASS="fsinnerbox-title">Employee Groups</FONT>'.
+                     '<BR>'.
+                     '<TABLE CLASS="fsinnerbox">'.
                      '<TR><TD>'.
                      include( '/elements/checkboxes-table.html',
                                 'source_obj'   => $access_user,
@@ -49,6 +51,7 @@
                    },
                  'onsubmit'  => 'check_user_custnum_search',
                  'html_foot' => $check_user_custnum_search,
+                 'html_table_class' => 'fsinnerbox',
            )
 %>
 <%init>
index 54d2b03..fcd210f 100644 (file)
@@ -11,7 +11,7 @@
                                        'target_table' => 'access_group',
                                      },
                  'precheck_callback'        => \&precheck_callback,
-                 'post_new_object_callback' => \&post_new_object_callback,
+                 #'post_new_object_callback' => \&post_new_object_callback,
                  'noerror_callback'         => \&noerror_callback,
              )
 %>
@@ -38,20 +38,24 @@ sub precheck_callback {
   return '';
 }
 
-sub post_new_object_callback {
+#sub post_new_object_callback {
+#  my( $cgi, $access_user ) = @_;
+#
+#  if ( length($cgi->param('_password')) ) {
+#    my $password = scalar($cgi->param('_password'));
+#    my $error = $access_user->is_password_allowed($password);
+#    #XXX and then bubble the error back up to the UI
+#  }
+#}
+
+sub noerror_callback {
   my( $cgi, $access_user ) = @_;
 
   if ( length($cgi->param('_password')) ) {
     my $password = scalar($cgi->param('_password'));
-    my $error = $access_user->is_password_allowed($password)
-             || $access_user->change_password($password);
+    $access_user->change_password($password);
   }
 
-}
-
-sub noerror_callback {
-  my( $cgi, $access_user ) = @_;
-
   #handle installer checkbox
   my @sched_item = $access_user->sched_item;
   my $sched_item = $sched_item[0];
index 9b8b2cd..eb065b6 100644 (file)
@@ -518,8 +518,9 @@ tie my %tools_importing, 'Tie::IxHash',
   'Customers'            => [ $fsurl.'misc/cust_main-import.cgi', '' ],
   'Package definitions'  => [ $fsurl.'misc/part_pkg-import.html', '' ],
   'Customer packages'    => [ $fsurl.'misc/cust_pkg-import.html', '' ],
+#  'Customer broadband services' => [ $fsurl.'misc/svc_broadband-import.html', '' ],
   'Customer notes'       => [ $fsurl.'misc/cust_main_note-import.html', '' ],
-  'Customer Contacts'    => [ $fsurl.'misc/contact-import.cgi', '' ],
+  'Customer contacts'    => [ $fsurl.'misc/contact-import.cgi', '' ],
   'One-time charges'     => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ],
   'Payments'             => [ $fsurl.'misc/cust_pay-import.cgi', '' ],
   'Credits'              => [ $fsurl.'misc/cust_credit-import.html', '' ],
index 32a2fc5..49dda18 100755 (executable)
@@ -19,8 +19,8 @@ my $invnum = $1;
 
 my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
 
-my $custnum = $cust_bill->custnum;
-
-my $error = $cust_bill->void( scalar($cgi->param('reason')) );
+my $error = $cust_bill->void( scalar($cgi->param('reason')),
+                              scalar($cgi->param('reprocess_cdrs')),
+                            );
 
 </%init>
index e4e4705..e5fbdc6 100755 (executable)
              'cgi'            => $cgi
 &>
 
+% if ( $cust_bill->has_call_details ) {
+  <& /elements/tr-checkbox.html,
+       label => 'Reprocess CDRs',
+       field => 'reprocess_cdrs',
+       value => '1',
+  &>
+% }
+
 </TABLE>
 
 <BR>
index 2fde797..f4dd414 100644 (file)
@@ -108,8 +108,7 @@ my $prospect_main = qsearchs( {
 });
 die "Prospect not found!" unless $prospect_main;
 
-my $title = encode_entities($prospect_main->name);
-$title = mt("Prospect"). ": $title";
+my $title = mt("Prospect"). ': '. $prospect_main->name;
 $title .= ' ('.mt('DISABLED').')'
   if $prospect_main->disabled;