voxline invoice formatting
authorjeff <jeff>
Wed, 4 Jun 2008 17:59:42 +0000 (17:59 +0000)
committerjeff <jeff>
Wed, 4 Jun 2008 17:59:42 +0000 (17:59 +0000)
FS/FS/Conf.pm
FS/FS/Conf_compat17.pm
FS/FS/cdr.pm
FS/FS/cust_bill_pkg.pm
FS/FS/part_pkg/voip_cdr.pm
conf/invoice_html
conf/invoice_latex

index 16305bf..1506dde 100644 (file)
@@ -1875,6 +1875,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.',
index 8286431..693c02f 100644 (file)
@@ -1947,6 +1947,13 @@ httemplate/docs/config.html
   },
 
   {
+    '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.',
index 29bbe0e..adde898 100644 (file)
@@ -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
index d15200e..e92c05d 100644 (file)
@@ -268,8 +268,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';
 
index 0f25e15..6a3a2ac 100644 (file)
@@ -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;
 
@@ -79,6 +80,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',
@@ -109,7 +115,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,
@@ -136,6 +142,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
   ) {
@@ -292,7 +301,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: ".
@@ -362,7 +371,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,
         }
 
@@ -379,7 +391,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
index ae6910d..a3ab6c0 100644 (file)
             '</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">'.
index d17ff8f..2acd710 100644 (file)
 \r
 \r
 % Commands for freeside description...\r
-\newcommand{\FSdesc}[3]{\r
+\newcommand{\FSdesc}[5]{\r
   \multicolumn{1}{c}{\rule{0pt}{2.5ex}\textbf{#1}} &\r
-  \multicolumn{6}{l}{\textbf{#2}} &\r
-  \multicolumn{1}{r}{\textbf{\dollar #3}}\\\r
+  \multicolumn{4}{l}{\textbf{#2}} &\r
+  \multicolumn{1}{l}{\textbf{#3}} &\r
+  \multicolumn{1}{r}{\textbf{#4}} &\r
+  \multicolumn{1}{r}{\textbf{\dollar #5}}\\\r
 }\r
 % ...extended description...\r
 \newcommand{\FSextdesc}[1]{\r
   \multicolumn{1}{l}{\rule{0pt}{1.0ex}} &\r
 %%  \multicolumn{2}{l}{\small{~-~#1}}\\\r
-  ~-~#1\\\r
+  ~~~#1\\\r
 }\r
 % ...and total line items.\r
 \newcommand{\FStotaldesc}[2]{\r
@@ -238,16 +240,26 @@ Terms: [@-- $terms --@]\\
     $OUT .= '\hline';\r
     $OUT .= '\rule{0pt}{2.5ex}';\r
     $OUT .= '\makebox[1.4cm]{\textbf{Ref}} & ';\r
-    $OUT .= '\multicolumn{6}{l}{\makebox[12.8cm][l]{\textbf{Description}}} & ';\r
-    $OUT .= '\makebox[2.5cm][r]{\textbf{Amount}} \\\\';\r
+    $OUT .= '\makebox[2.0cm][l]{\textbf{Description}}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{\textbf{'. ($unitprices ? '~~Unit Price' : ''). '}&';\r
+    $OUT .= '\makebox[2.0cm]{\textbf{'. ($unitprices ? '~Quantity' : ''). '}&';\r
+    $OUT .= '\makebox[2.0cm][r]{\textbf{Amount}} \\\\';\r
     $OUT .= '\hline';\r
     $OUT .= '\endfirsthead';\r
     $OUT .= '\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\\\';\r
     $OUT .= '\hline';\r
     $OUT .= '\rule{0pt}{2.5ex}';\r
     $OUT .= '\makebox[1.4cm]{\textbf{Ref}} & ';\r
-    $OUT .= '\multicolumn{6}{l}{\makebox[12.8cm][l]{\textbf{Description}}} & ';\r
-    $OUT .= '\makebox[2.5cm][r]{\textbf{Amount}} \\\\';\r
+    $OUT .= '\makebox[2.0cm][l]{\textbf{Description}}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{}& ';\r
+    $OUT .= '\makebox[2.0cm][l]{\textbf{'. ($unitprices ? '~~Unit Price' : ''). '}&';\r
+    $OUT .= '\makebox[2.0cm]{\textbf{'. ($unitprices ? '~Quantity' : ''). '}&';\r
+    $OUT .= '\makebox[2.0cm][r]{\textbf{Amount}} \\\\';\r
     $OUT .= '\hline';\r
     $OUT .= '\endhead';\r
     $OUT .= '\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued on next page...}\\\\';\r
@@ -283,6 +295,8 @@ Terms: [@-- $terms --@]\\
   \r
       $OUT .= "\\hline\n";\r
       $OUT .= '\FSdesc{' . $line->{'ref'} . '}{' . $line->{'description'} . '}' .\r
+              '{' . ( $unitprices ? $line->{'unit_amount'} : '' ) . '}'.\r
+              '{' . ( $unitprices ? $line->{'quantity'} : ''  ) . '}' .\r
               '{' . $line->{'amount'} . "}${rowbreak}\n";\r
 \r
       foreach my $ext_desc (@$ext_description) {\r