'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' ], ],
'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' ] ],
}
}
- #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');
#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;
--- /dev/null
+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;
#|| $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')
|| $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;
=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
}
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 ) {
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();
<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) %>
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',
) . '">'
($rate_time ? $rate_time->ratetimenum : '').
";cdrtypenum=$cdrtypenum",
'actionlabel' => 'Add rate',
- 'height' => 420,
+ 'height' => 460,
).'">'.small('(add)').'</A>'
}
#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>'
}
% $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") %>
%}
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
+ )],
},
&>
'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' => [
},
{ 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 ],
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 ],
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 {
} # 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';
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;
|| 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';
--- /dev/null
+<& /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>
+
--- /dev/null
+<& 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>
+