summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Conf.pm7
-rw-r--r--FS/FS/cdr.pm45
-rw-r--r--FS/FS/cust_bill.pm2
-rw-r--r--FS/FS/cust_bill_pkg.pm17
-rw-r--r--FS/FS/part_pkg/voip_cdr.pm20
-rw-r--r--conf/invoice_html2
-rw-r--r--conf/invoice_latex31
7 files changed, 109 insertions, 15 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 87897c32c..4c2930719 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -1959,6 +1959,13 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'invoice-unitprice',
+ 'section' => 'billing',
+ 'description' => 'This switch enables unit pricing on the invoice.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'batch-enable',
'section' => 'billing',
'description' => 'Enable credit card and/or ACH batching - leave disabled for real-time installations.',
diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index 29bbe0e99..adde898e4 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -392,6 +392,18 @@ sub _convergent_format {
=cut
+my %export_names = (
+ 'convergent' => {},
+ 'voxlinesystems' => { 'name' => 'VoxLineSystems',
+ 'invoice_header' =>
+ "Date,Time,Name,Destination,Duration,Price",
+ },
+ 'voxlinesystems2' => { 'name' => 'VoxLineSystems with source',
+ 'invoice_header' =>
+ "Date,Time,Name,Destination,Called From,Duration,Price",
+ },
+);
+
my %export_formats = (
'convergent' => [
'carriername', #CARRIER
@@ -416,6 +428,15 @@ my %export_formats = (
sub { sprintf('%.2fm', shift->billsec / 60 ) }, #DURATION
sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
],
+ 'voxlinesystems2' => [
+ sub { time2str('%D', shift->calldate_unix ) }, #DATE
+ sub { time2str('%T', shift->calldate_unix ) }, #TIME
+ 'userfield', #USER
+ 'dst', #NUMBER_DIALED
+ 'src', #called from
+ sub { sprintf('%.2fm', shift->billsec / 60 ) }, #DURATION
+ sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
+ ],
);
sub downstream_csv {
@@ -448,6 +469,30 @@ sub downstream_csv {
=over 4
+=item invoice_formats
+
+Returns an ordered list of key value pairs containing invoice format names
+as keys (for use with part_pkg::voip_cdr) and "pretty" format names as values.
+
+=cut
+
+sub invoice_formats {
+ map { ($_ => $export_names{$_}->{'name'}) }
+ grep { $export_names{$_}->{'invoice_header'} }
+ keys %export_names;
+}
+
+=item invoice_header FORMAT
+
+Returns a scalar containing the CSV column header for invoice format FORMAT.
+
+=cut
+
+sub invoice_header {
+ my $format = shift;
+ $export_names{$format}->{'invoice_header'};
+}
+
=item import_formats
Returns an ordered list of key value pairs containing import format names
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index 7f2c18572..8e4d3f24a 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -1814,6 +1814,7 @@ sub print_latex {
'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
'balance' => $balance_due,
'ship_enable' => $conf->exists('invoice-ship_address'),
+ 'unitprices' => $conf->exists('invoice-unitprice'),
);
my $prefix = $cust_main->has_ship_address ? 'ship_' : '';
@@ -2194,6 +2195,7 @@ sub print_html {
'cid' => $cid,
'template' => $template,
'ship_enable' => $conf->exists('invoice-ship_address'),
+ 'unitprices' => $conf->exists('invoice-unitprice'),
# 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
);
diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index 7651f9046..b825b305a 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -251,8 +251,21 @@ sub details {
$format_sub = sub { my $detail = shift;
$csv->parse($detail) or return "can't parse $detail";
- join(' & ', map { '\small{'. &$escape_function($_). '}' }
- $csv->fields );
+ #join(' & ', map { '\small{'. &$escape_function($_). '}' }
+ # $csv->fields );
+ my $result = '';
+ my $column = 1;
+ foreach ($csv->fields) {
+ $result .= ' & ' if $column > 1;
+ if ($column > 6) { # KLUDGE ALERT!
+ $result .= '\multicolumn{1}{l}{\small{'.
+ &$escape_function($_). '}}';
+ }else{
+ $result .= '\small{'. &$escape_function($_). '}';
+ }
+ $column++;
+ }
+ $result;
}
if $format eq 'latex';
diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm
index 00691e30a..62c3d5459 100644
--- a/FS/FS/part_pkg/voip_cdr.pm
+++ b/FS/FS/part_pkg/voip_cdr.pm
@@ -7,6 +7,7 @@ use Tie::IxHash;
use FS::Conf;
use FS::Record qw(qsearchs qsearch);
use FS::part_pkg::flat;
+use FS::cdr;
#use FS::rate;
#use FS::rate_prefix;
@@ -78,6 +79,11 @@ tie my %rating_method, 'Tie::IxHash',
'type' => 'checkbox',
},
+ 'output_format' => { 'name' => 'Simple output format',
+ 'type' => 'select',
+ 'select_options' => { FS::cdr::invoice_formats() },
+ },
+
#XXX also have option for an external db
# 'cdr_location' => { 'name' => 'CDR database location'
# 'type' => 'select',
@@ -108,7 +114,7 @@ tie my %rating_method, 'Tie::IxHash',
default_prefix
disable_src
domestic_prefix international_prefix
- use_amaflags use_disposition
+ use_amaflags use_disposition output_format
)
],
'weight' => 40,
@@ -135,6 +141,9 @@ sub calc_recur {
my $downstream_cdr = '';
+ my $output_format = $self->option('output_format', 'Hush!')
+ || 'voxlinesystems';
+
foreach my $cust_svc (
grep { $_->part_svc->svcdb eq 'svc_phone' } $cust_pkg->cust_svc
) {
@@ -291,7 +300,7 @@ sub calc_recur {
$charge = sprintf('%.3f', $cdr->upstream_price);
$charges += $charge;
- @call_details = ( $cdr->downstream_csv( 'format' => 'voxlinesystems' ));
+ @call_details = ($cdr->downstream_csv( 'format' => $output_format ));
} else {
die "don't know how to rate CDRs using method: ".
@@ -361,7 +370,10 @@ sub calc_recur {
$call_details = join(' - ', @call_details );
}
warn " adding details on charge to invoice: $call_details"
- if $DEBUG;
+ if ( $DEBUG && !ref($call_details) );
+ warn " adding details on charge to invoice: [ ".
+ join(', ', @{$call_details} ). " ]"
+ if ( $DEBUG && ref($call_details) );
push @$details, $call_details; #\@call_details,
}
@@ -378,7 +390,7 @@ sub calc_recur {
} # $cdr
- unshift @$details, [ 'C', "Date,Time,Name,Destination,Duration,Price" ]
+ unshift @$details, [ 'C', FS::cdr::invoice_header( $output_format) ]
if (@$details && $self->option('rating_method') eq 'upstream_simple' );
} # $cust_svc
diff --git a/conf/invoice_html b/conf/invoice_html
index ddede78ce..d619c0a61 100644
--- a/conf/invoice_html
+++ b/conf/invoice_html
@@ -87,7 +87,7 @@
'</tr>'
;
if ( @{$line->{'ext_description'} } ) {
- $OUT .= '<tr class="invoice_extdesc"><td></td><td><table>';
+ $OUT .= '<tr class="invoice_extdesc"><td></td><td><table width="100%">';
foreach my $ext_desc ( @{$line->{'ext_description'} } ) {
$OUT .=
'<tr class="invoice_extdesc">'.
diff --git a/conf/invoice_latex b/conf/invoice_latex
index 19b351acc..4ea3fe643 100644
--- a/conf/invoice_latex
+++ b/conf/invoice_latex
@@ -155,16 +155,18 @@
% Commands for freeside description...
-\newcommand{\FSdesc}[3]{
+\newcommand{\FSdesc}[5]{
\multicolumn{1}{c}{\rule{0pt}{2.5ex}\textbf{#1}} &
- \multicolumn{6}{l}{\textbf{#2}} &
- \multicolumn{1}{r}{\textbf{\dollar #3}}\\
+ \multicolumn{4}{l}{\textbf{#2}} &
+ \multicolumn{1}{l}{\textbf{#3}} &
+ \multicolumn{1}{r}{\textbf{#4}} &
+ \multicolumn{1}{r}{\textbf{\dollar #5}}\\
}
% ...extended description...
\newcommand{\FSextdesc}[1]{
\multicolumn{1}{l}{\rule{0pt}{1.0ex}} &
%% \multicolumn{2}{l}{\small{~-~#1}}\\
- ~-~#1\\
+ ~~~#1\\
}
% ...and total line items.
\newcommand{\FStotaldesc}[2]{
@@ -225,16 +227,27 @@ Terms: [@-- $terms --@]\\
\hline
\rule{0pt}{2.5ex}
\makebox[1.4cm]{\textbf{Ref}} &
-\multicolumn{6}{l}{\makebox[12.8cm][l]{\textbf{Description}}} &
-\makebox[2.5cm][r]{\textbf{Amount}} \\
+\makebox[2.0cm][l]{\textbf{Description}}&
+\makebox[2.0cm][l]{}&
+\makebox[2.0cm][l]{}&
+\makebox[2.0cm][l]{}&
+\makebox[2.0cm][l]{\textbf{[@-- !$unitprices ? '~~Unit Price' : '' --@]}}&
+\makebox[2.0cm]{\textbf{[@-- !$unitprices ? '~Quantity' : '' --@]}}&
+\makebox[2.0cm][r]{\textbf{Amount}} \\
+%
\hline
\endfirsthead
\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\
\hline
\rule{0pt}{2.5ex}
\makebox[1.4cm]{\textbf{Ref}} &
-\multicolumn{6}{l}{\makebox[12.8cm][l]{\textbf{Description}}} &
-\makebox[2.5cm][r]{\textbf{Amount}} \\
+\makebox[2.0cm][l]{\textbf{Description}}&
+\makebox[2.0cm][l]{}&
+\makebox[2.0cm][l]{}&
+\makebox[2.0cm][l]{}&
+\makebox[2.0cm][l]{\textbf{[@-- !$unitprices ? '~~Unit Price' : '' --@]}}&
+\makebox[2.0cm]{\textbf{[@-- !$unitprices ? '~Quantity' : '' --@]}}&
+\makebox[2.0cm][r]{\textbf{Amount}} \\
\hline
\endhead
\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued on next page...}\\
@@ -260,6 +273,8 @@ Terms: [@-- $terms --@]\\
$OUT .= "\\hline\n";
$OUT .= '\FSdesc{' . $line->{'ref'} . '}{' . $line->{'description'} . '}' .
+ '{' . ( $unitprices ? $line->{'unit_amount'} : '' ) . '}'.
+ '{' . ( $unitprices ? $line->{'quantity'} : '' ) . '}' .
'{' . $line->{'amount'} . "}${rowbreak}\n";
foreach my $ext_desc (@$ext_description) {