Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Mon, 2 Jun 2014 22:56:11 +0000 (15:56 -0700)
committerIvan Kohler <ivan@freeside.biz>
Mon, 2 Jun 2014 22:56:11 +0000 (15:56 -0700)
19 files changed:
FS/FS/Schema.pm
FS/FS/TicketSystem.pm
FS/FS/cust_main/Credit_Limit.pm
FS/FS/part_event/Action/pkg_sales_credit_pkg.pm [new file with mode: 0644]
FS/FS/rate_detail.pm
FS/FS/tower_sector.pm
FS/FS/vend_main.pm
FS/bin/freeside-upgrade
httemplate/browse/rate_region.html
httemplate/edit/elements/rate_detail.html
httemplate/edit/process/rate_region.cgi
httemplate/edit/process/tower.html
httemplate/edit/rate_detail.html
httemplate/edit/tower.html
httemplate/elements/menu.html
httemplate/elements/tower_sector.html
httemplate/misc/process/copy-rate_detail.html
httemplate/search/report_vend_main.html [new file with mode: 0644]
httemplate/search/vend_main.html [new file with mode: 0644]

index 12064af..4e67cf7 100644 (file)
@@ -4548,16 +4548,16 @@ sub tables_hashref {
 
     'tower_sector' => {
       'columns' => [
-        'sectornum',   'serial',     '',      '', '', '',
-        'towernum',       'int',     '',      '', '', '',
-        'sectorname', 'varchar',     '', $char_d, '', '',
-        'ip_addr',    'varchar', 'NULL',      15, '', '',
-        'height',     'decimal', 'NULL',      '', '', '', 
-        'freq_mhz',       'int', 'NULL',      '', '', '',
-        'direction',      'int', 'NULL',      '', '', '',
-        'width',          'int', 'NULL',      '', '', '',
+        'sectornum',     'serial',     '',      '', '', '',
+        'towernum',         'int',     '',      '', '', '',
+        'sectorname',   'varchar',     '', $char_d, '', '',
+        'ip_addr',      'varchar', 'NULL',      15, '', '',
+        'height',       'decimal', 'NULL',      '', '', '', 
+        'freq_mhz',         'int', 'NULL',      '', '', '',
+        'direction',        'int', 'NULL',      '', '', '',
+        'width',            'int', 'NULL',      '', '', '',
         #downtilt etc? rfpath has profile files for devices/antennas you upload?
-        'range',      'decimal', 'NULL',      '', '', '',  #?
+        'sector_range', 'decimal', 'NULL',      '', '', '',  #?
       ],
       'primary_key'  => 'sectornum',
       'unique'       => [ [ 'towernum', 'sectorname' ], [ 'ip_addr' ], ],
@@ -4772,13 +4772,15 @@ sub tables_hashref {
         'dest_regionnum',  'int',     '',     '',      '', '', 
         'min_included',    'int',     '',     '',      '', '', 
         'conn_charge',     'decimal', '', '10,4', '0.0000', '',
+        'conn_cost',       'decimal', '', '10,4', '0.0000', '',
         'conn_sec',        'int',     '',     '',      '0', '',
         'min_charge',      'decimal', '', '10,5',       '', '',
+        'min_cost',        'decimal', '', '10,5','0.00000', '',
         'sec_granularity', 'int',     '',     '',       '', '', 
         'ratetimenum',     'int', 'NULL',     '',       '', '',
         'classnum',        'int', 'NULL',     '',       '', '', 
         'cdrtypenum',      'int', 'NULL',     '',       '', '',
-        'region_group', 'char', 'NULL',        1,       '', '', 
+        'region_group',   'char', 'NULL',      1,       '', '', 
       ],
       'primary_key'  => 'ratedetailnum',
       'unique'       => [ [ 'ratenum', 'orig_regionnum', 'dest_regionnum' ] ],
index 3c972d0..7339d74 100644 (file)
@@ -331,16 +331,24 @@ sub _upgrade_data {
     }
   }
 
-  #Pg-specific 
-  my $cve_2013_3373_sql = q(
-    UPDATE Tickets SET Subject = REPLACE(Subject,E'\n','')
-  );
-  #need this for mysql
-  #UPDATE Tickets SET Subject = REPLACE(Subject,'\n','');
-
-  my $cve_2013_3373_sth = $dbh->prepare( $cve_2013_3373_sql)
-    or die $dbh->errstr;
-  $cve_2013_3373_sth->execute or die $cve_2013_3373_sth->errstr;
+  my $cve_2013_3373_sql = '';
+  if ( driver_name =~ /^Pg/i ) {
+    $cve_2013_3373_sql = q(
+      UPDATE Tickets SET Subject = REPLACE(Subject,E'\n','')
+    );
+  } elsif ( driver_name =~ /^mysql/i ) {
+    $cve_2013_3373_sql = q(
+      UPDATE Tickets SET Subject = REPLACE(Subject,'\n','');
+    );
+  } else {
+    warn "WARNING: Don't know how to update RT Ticket Subjects for your database driver for CVE-2013-3373";
+  }
+  if ( $cve_2013_3373_sql ) {
+    my $cve_2013_3373_sth = $dbh->prepare($cve_2013_3373_sql)
+      or die $dbh->errstr;
+    $cve_2013_3373_sth->execute
+      or die $cve_2013_3373_sth->errstr;
+  }
 
   # Remove dangling customer links, if any
   my %target_pkey = ('cust_main' => 'custnum', 'cust_svc' => 'svcnum');
index 238d885..4b2fbdf 100644 (file)
@@ -42,13 +42,10 @@ sub check_credit_limit {
 
   #false laziness  w/svc_phone->sum_cdrs / psearch_cdrs
   my $sum = qsearchs( {
-    'select'  => 'SUM(rated_price) AS rated_price',
-    'table'   => 'cdr',
-    'hashref' => { 'status' => 'rated',
-                   'svcnum' => { op    => 'IN',
-                                 value => '('. join(',',@svcnum). ')',
-                               },
-                 },
+    'select'    => 'SUM(rated_price) AS rated_price',
+    'table'     => 'cdr',
+    'hashref'   => { 'status' => 'rated', },
+    'extra_sql' => ' AND svcnum IN ('. join(',',@svcnum). ') ',
   } );
 
   return '' unless $sum->rated_price > $credit_limit;
diff --git a/FS/FS/part_event/Action/pkg_sales_credit_pkg.pm b/FS/FS/part_event/Action/pkg_sales_credit_pkg.pm
new file mode 100644 (file)
index 0000000..1e3c2b3
--- /dev/null
@@ -0,0 +1,9 @@
+package FS::part_event::Action::pkg_sales_credit_pkg;
+
+use strict;
+use base qw( FS::part_event::Action::Mixin::credit_pkg
+             FS::part_event::Action::pkg_sales_credit );
+
+sub description { 'Credit the package sales person an amount based on the referred package'; }
+
+1;
index 66c5c97..d81d9db 100644 (file)
@@ -129,7 +129,10 @@ sub check {
 
     #|| $self->ut_money('min_charge')
     #good enough for now...
+    || $self->ut_floatn('conn_charge')
+    || $self->ut_floatn('conn_cost')
     || $self->ut_float('min_charge')
+    || $self->ut_floatn('min_cost')
 
     || $self->ut_number('sec_granularity')
 
index 7e6819a..4fbd89c 100644 (file)
@@ -109,7 +109,7 @@ sub check {
     || $self->ut_numbern('freq_mhz')
     || $self->ut_numbern('direction')
     || $self->ut_numbern('width')
-    || $self->ut_floatn('range')
+    || $self->ut_floatn('sector_range')
   ;
   return $error if $error;
 
index 2e5e150..22ac0bf 100644 (file)
@@ -101,6 +101,66 @@ sub check {
 
 =item vend_class
 
+=item search
+
+=cut
+
+sub search {
+  my ($class, $param) = @_;
+
+  my @where = ();
+  my $addl_from = '';
+
+  #_date
+  if ( $param->{_date} ) {
+    my($beginning, $ending) = @{$param->{_date}};
+
+    push @where, "vend_bill._date >= $beginning",
+                 "vend_bill._date <  $ending";
+  }
+
+  #payment_date
+  if ( $param->{payment_date} ) {
+    my($beginning, $ending) = @{$param->{payment_date}};
+
+    push @where, "vend_pay._date >= $beginning",
+                 "vend_pay._date <  $ending";
+  }
+
+  if ( $param->{'classnum'} =~ /^(\d+)$/ ) {
+    push @where, "vend_main.classnum = $1";
+  }
+
+  my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : '';
+
+  my $group_by = ' GROUP BY vend_main.vendnum ';
+
+  my $addl_from_vend_bill = ' LEFT JOIN vend_bill_pay USING (vendbillnum) '.
+                            ' LEFT JOIN vend_pay      USING (vendpaynum)  ';
+
+  $addl_from .= " LEFT JOIN vend_bill USING ( vendnum ) $addl_from_vend_bill";
+
+  #simplistic, but how we are for now
+
+  my $count_query = "
+    SELECT COUNT(*),
+           ( SELECT SUM(charged) from vend_bill $addl_from_vend_bill $extra_sql
+           ) AS sum_charged
+      FROM vend_main "; #XXX classnum, sum_charged > 0
+
+  +{
+    'table'         => 'vend_main',
+    'select'        => 'vend_main.*, sum(vend_bill.charged) as sum_charged',
+    'addl_from'     => $addl_from,
+    'hashref'       => {},
+    'extra_sql'     => "$extra_sql $group_by",
+    'order_by'      => 'ORDER BY sum_charged desc',
+    'count_query'   => $count_query,
+    #'extra_headers' => \@extra_headers,
+    #'extra_fields'  => \@extra_fields,
+  };
+}
+
 =back
 
 =head1 BUGS
index b2cd3db..5b94c47 100755 (executable)
@@ -94,10 +94,18 @@ if ( dbdef->table('areacode') and
 }
 
 if ( dbdef->table('upgrade_journal') ) {
-  push @bugfix, "SELECT SETVAL( 'upgrade_journal_upgradenum_seq',
-                                ( SELECT MAX(upgradenum) FROM upgrade_journal )
-                              )
-                ";
+  if ( driver_name =~ /^Pg/i ) {
+    push @bugfix, "
+      SELECT SETVAL( 'upgrade_journal_upgradenum_seq',
+                     ( SELECT MAX(upgradenum) FROM upgrade_journal )
+                   )
+    ";
+  } elsif ( driver_name =~ /^mysql/i ) {
+    push @bugfix, "
+       ALTER TABLE upgrade_journal AUTO_INCREMENT =
+                   ( ( SELECT MAX(upgradenum) FROM upgrade_journal ) + 1 )
+    ";
+  }
 }
 
 if ( $DRY_RUN ) {
index b0ce467..962841d 100644 (file)
@@ -96,8 +96,9 @@ sub _rate_detail_factory {
   my( $rate, $field ) = @_;
   return sub {
     my $rate_detail = $rate->dest_detail(shift)
-                      || new FS::rate_region { 'min_included'    => 0,
+                      || new FS::rate_detail { 'min_included'    => 0,
                                                'min_charge'      => 0,
+                                               'min_cost'        => 0,
                                                'sec_granularity' => 0,
                                              };
     my $value = $rate_detail->$field();
index 1b597fb..14b5211 100644 (file)
@@ -52,6 +52,9 @@ with row headers showing the region name and prefixes.
       <TABLE CLASS="inv" STYLE="border:none">
       <TR><TD><% edit_link($detail) %><% $money_char.$detail->min_charge %>
               <% $detail->sec_granularity ? ' / minute':' / call' %>
+%             if ( $detail->min_cost ) {
+                (<% $money_char.$detail->min_cost %> cost)
+%             }
       <% $edit_hint %></A>
       </TD></TR>
       <% granularity_detail($detail) %>
@@ -92,7 +95,7 @@ sub edit_link {
   include( '/elements/popup_link_onclick.html',
              'action'      => "${p}edit/rate_detail.html?$ratedetailnum",
              'actionlabel' => 'Edit rate',
-             'height'      => 420,
+             'height'      => 460,
              #default# 'width'       => 540,
              #default# 'color'       => '#333399',
          ) . '">'
@@ -110,7 +113,7 @@ sub add_link {
                                  ($rate_time ? $rate_time->ratetimenum : '').
                                ";cdrtypenum=$cdrtypenum",
              'actionlabel' => 'Add rate',
-             'height'      => 420,
+             'height'      => 460,
              ).'">'.small('(add)').'</A>'
 }
 
@@ -157,7 +160,11 @@ sub conn_charge_detail {
   #return '' unless $rate_detail->conn_charge > 0 || $rate_detail->conn_sec;
     '<TR><TD>'.
     small( $money_char. $rate_detail->conn_charge.
-      ' for '.$conn_secs{$rate_detail->conn_sec}
+             ( $rate_detail->conn_cost
+                 ? ' ('. $money_char.$rate_detail->conn_cost. ' cost)'
+                 : ''
+             ).
+           ' for '. $conn_secs{$rate_detail->conn_sec}
     ).
     '</TD></TR>'
   }
index d342e60..87d634a 100755 (executable)
@@ -2,7 +2,7 @@
 %  $cgi->param('error', $error);
 <% $cgi->redirect(popurl(2). "rate_region.cgi?". $cgi->query_string ) %>
 %} elsif ( $action eq 'Add' ) {
-<% $cgi->redirect(popurl(2). "rate_region.cgi?$regionnum") %>
+<% $cgi->redirect(popurl(2). "rate_region.cgi?regionnum=$regionnum") %>
 %} else { 
 <% $cgi->redirect(popurl(3). "browse/rate_region.html") %>
 %}
index bbfc1a6..02362db 100644 (file)
@@ -2,6 +2,9 @@
     table       => 'tower',
     viewall_dir => 'browse',
     process_o2m => { 'table'  => 'tower_sector',
-                     'fields' => [qw( sectorname ip_addr height freq_mhz direction width range )],
+                     'fields' => [qw(
+                       sectorname ip_addr height freq_mhz direction width
+                       sector_range
+                     )],
                    },
 &>
index 0e40689..0de6ecc 100644 (file)
@@ -8,10 +8,12 @@
                    'rate_time_name'      => 'Time period',
                    'min_included'        => 'Included minutes/calls',
                    'region_group'        => 'Region Group',
-                   'conn_charge'         => 'Connection charge',
+                   'conn_charge'         => 'Retail connection charge',
                    'conn_sec'            => 'For',
-                   'min_charge'          => 'Charge per minute/call',
+                   'min_charge'          => 'Retail charge per minute/call',
                    'sec_granularity'     => 'Granularity',
+                   'conn_cost'           => 'Wholesale connection cost',
+                   'min_cost'            => 'Wholesale cost per minute/call',
                    'classnum'            => 'Usage class',
                  },
      'fields' => [
@@ -29,6 +31,7 @@
                    },
                    { field=>'min_included',        type=>'text',  size=>5 },
                    { field=>'conn_charge',         type=>'money', size=>4 },
+                   { field=>'conn_cost',         type=>'money', size=>4 },
                    { field          =>'conn_sec',
                       type          =>'select',
                       options       => [ keys %conn_secs ],
@@ -36,6 +39,7 @@
                       disable_empty => 1,
                    },
                    { field=>'min_charge',          type=>'money', size=>4 },
+                   { field=>'min_cost',          type=>'money', size=>4 },
                    { field         =>'sec_granularity',
                      type          =>'select',
                      options       => [ keys %granularity ],
index 00c9add..fa3838d 100644 (file)
 my $m2_error_callback = sub { # reconstruct the list
   my ($cgi, $object) = @_;
 
-  my @fields = qw( sectorname ip_addr height freq_mhz direction width range );
+  my @fields = qw(
+    sectorname ip_addr height freq_mhz direction width sector_range
+  );
+
   map {
     my $k = $_;
     new FS::tower_sector {
index 7df2448..fdd4962 100644 (file)
@@ -377,7 +377,8 @@ if( $curuser->access_right('Financial reports') ) {
 } # else $report_financial contains nothing.
 
 tie my %report_payable, 'Tie::IxHash',
-  'Payables' => [ $fsurl. 'search/report_vend_bill.html' ],
+  'Payables summary' => [ $fsurl. 'search/report_vend_main.html', 'Payables summary by vendor' ],
+  'Payables detail' => [ $fsurl. 'search/report_vend_bill.html' ],
 ;
 
 tie my %report_logs, 'Tie::IxHash';
index 406895e..151d3ba 100644 (file)
@@ -51,13 +51,13 @@ if ( $curr_value ) {
 my %size = ( 'title' => 12 );
 
 tie my %label, 'Tie::IxHash',
-  'sectorname' => 'Name',
-  'ip_addr'    => 'IP Address',
-  'height'     => 'Height',
-  'freq_mhz'   => 'Freq. (MHz)',
-  'direction'  => 'Direction', # or a button to set these to 0 for omni
-  'width'      => 'Width',     #
-  'range'      => 'Range',
+  'sectorname'   => 'Name',
+  'ip_addr'      => 'IP Address',
+  'height'       => 'Height',
+  'freq_mhz'     => 'Freq. (MHz)',
+  'direction'    => 'Direction', # or a button to set these to 0 for omni
+  'width'        => 'Width',     #
+  'sector_range' => 'Range',
 ;
 
 my @fields = keys %label;
index 60b2aeb..94acce0 100644 (file)
@@ -47,7 +47,8 @@ foreach my $countrycode ( @countrycodes ) {
                           || new FS::rate_detail   \%hash;
 
     $dst_rate_detail->$_( $src_rate_detail->get($_) )
-      foreach qw( min_included conn_charge conn_sec min_charge sec_granularity classnum );
+      foreach qw( min_included conn_charge conn_sec min_charge sec_granularity
+                  conn_cost min_cost classnum );
 
     my $method = $dst_rate_detail->ratedetailnum ? 'replace' : 'insert';
 
diff --git a/httemplate/search/report_vend_main.html b/httemplate/search/report_vend_main.html
new file mode 100644 (file)
index 0000000..c7fbb2b
--- /dev/null
@@ -0,0 +1,48 @@
+<& /elements/header.html, mt('Payables summary by vendor') &>
+
+<FORM ACTION="vend_main.html" METHOD="GET">
+
+  <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+    <TR>
+        <TD ALIGN="right" VALIGN="center"><% mt('Date') |h %></TD>
+        <TD>
+          <TABLE>
+              <& /elements/tr-input-beginning_ending.html,
+                        prefix   => '_date',
+                        layout   => 'horiz',
+              &>
+          </TABLE>
+        </TD>
+    </TR>
+
+    <TR>
+        <TD ALIGN="right" VALIGN="center"><% mt('Payment date') |h %></TD>
+        <TD>
+          <TABLE>
+              <& /elements/tr-input-beginning_ending.html,
+                        prefix   => 'payment_date',
+                        layout   => 'horiz',
+              &>
+          </TABLE>
+        </TD>
+    </TR>
+
+    <& /elements/tr-select-vend_class.html,
+    &>
+
+  </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="<% mt('Get Report') |h %>">
+
+</FORM>
+
+<& /elements/footer.html &>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
+
diff --git a/httemplate/search/vend_main.html b/httemplate/search/vend_main.html
new file mode 100644 (file)
index 0000000..41917a5
--- /dev/null
@@ -0,0 +1,40 @@
+<& elements/search.html,
+     'title'       => 'Payables summary by vendor',
+     'name'        => 'vendors',
+     'query'       => $query,
+     'count_query' => $count_query,
+     'count_addl'  => [ '$%.2f total', ],
+     'header'      => [
+                        'Vendor',
+                        'Class',
+                        'Amount',
+                        '',
+                      ],
+     'fields'      => [
+                        sub { shift->vendname },
+                        sub { shift->vend_class->classname },
+                        'sum_charged',
+                      ],
+
+&>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my %search = ();
+
+# begin/end/beginning/ending
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, '_date');
+$search{'_date'} = [ $beginning, $ending ];
+
+($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, 'payment_date');
+$search{'payment_date'} = [ $beginning, $ending ];
+
+$search{'classnum'} = $cgi->param('classnum');
+
+my $query = FS::vend_main->search( \%search );
+my $count_query = delete( $query->{'count_query'} );
+
+</%init>
+