typeset CDRs into 5 columns on invoices
authorjeff <jeff>
Fri, 16 May 2008 19:26:40 +0000 (19:26 +0000)
committerjeff <jeff>
Fri, 16 May 2008 19:26:40 +0000 (19:26 +0000)
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/voip_cdr.pm
conf/invoice_html
conf/invoice_latex

index f8dd38b..457e5c8 100644 (file)
@@ -499,6 +499,7 @@ sub tables_hashref {
         'detailnum', 'serial', '', '', '', '', 
         'pkgnum',  'int', '', '', '', '', 
         'invnum',  'int', '', '', '', '', 
+        'format',  'char', 'NULL', 1, '', '',
         'detail',  'varchar', '', $char_d, '', '', 
       ],
       'primary_key' => 'detailnum',
index c10eec0..29bbe0e 100644 (file)
@@ -408,6 +408,14 @@ my %export_formats = (
     sub { shift->rated_price ? 'Y' : 'N' }, #RATED
     '', #OTHER_INFO
   ],
+  'voxlinesystems' => [
+    sub { time2str('%D', shift->calldate_unix ) },   #DATE
+    sub { time2str('%T', shift->calldate_unix ) },   #TIME
+    'userfield',                                     #USER
+    'dst',                                           #NUMBER_DIALED
+    sub { sprintf('%.2fm', shift->billsec / 60 ) },  #DURATION
+    sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
+  ],
 );
 
 sub downstream_csv {
index f470813..9b7c4ad 100644 (file)
@@ -2000,6 +2000,7 @@ sub print_generic {
 
     my %options = ();
     $options{'section'} = $section if $multisection;
+    $options{'format'} = $format;
 
     foreach my $line_item ( $self->_items_pkg(%options) ) {
       my $detail = {
@@ -2010,9 +2011,7 @@ sub print_generic {
       $detail->{'section'} = $section;
       $detail->{'description'} = &$escape_function($line_item->{'description'});
       if ( exists $line_item->{'ext_description'} ) {
-        @{$detail->{'ext_description'}} = map {
-          &$escape_function($_);
-        } @{$line_item->{'ext_description'}};
+        @{$detail->{'ext_description'}} = @{$line_item->{'ext_description'}};
       }
       {
         my $money = $old_latex ? '' : $money_char;
@@ -2528,6 +2527,9 @@ sub _items_tax {
 sub _items_cust_bill_pkg {
   my $self = shift;
   my $cust_bill_pkg = shift;
+  my %opt = @_;
+  my $format = $opt{format} || '';
+  my $escape_function = $opt{escape_function} || sub { shift };
 
   my @b = ();
   foreach my $cust_bill_pkg ( @$cust_bill_pkg ) {
@@ -2542,7 +2544,10 @@ sub _items_cust_bill_pkg {
         my $description = $desc;
         $description .= ' Setup' if $cust_bill_pkg->recur != 0;
         my @d = $cust_pkg->h_labels_short($self->_date);
-        push @d, $cust_bill_pkg->details if $cust_bill_pkg->recur == 0;
+        push @d, $cust_bill_pkg->details( 'format'          => $format,
+                                          'escape_function' => $escape_function,
+                                        )
+          if $cust_bill_pkg->recur == 0;
         push @b, {
           description     => $description,
           #pkgpart         => $part_pkg->pkgpart,
@@ -2569,7 +2574,8 @@ sub _items_cust_bill_pkg {
             [ $cust_pkg->h_labels_short( $self->_date ),
                                          #$cust_bill_pkg->edate,
                                          #$cust_bill_pkg->sdate),
-              $cust_bill_pkg->details,
+              $cust_bill_pkg->details( 'format'          => $format,
+                                       'escape_function' => $escape_function),
             ],
         };
       }
index 1cb9826..5d60311 100644 (file)
@@ -112,7 +112,8 @@ sub insert {
     my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail {
       'pkgnum' => $self->pkgnum,
       'invnum' => $self->invnum,
-      'detail' => $detail,
+      'format' => (ref($detail) ? $detail->[0] : '' ),
+      'detail' => (ref($detail) ? $detail->[1] : $detail ),
     };
     $error = $cust_bill_pkg_detail->insert;
     if ( $error ) {
@@ -220,18 +221,62 @@ sub cust_bill {
   qsearchs( 'cust_bill', { 'invnum' => $self->invnum } );
 }
 
-=item details
+=item details [ OPTION => VALUE ... ]
 
 Returns an array of detail information for the invoice line item.
 
+Currently available options are: I<format> I<escape_function>
+
+If I<format> is set to html or latex then the array members are improved
+for tabular appearance in those environments if possible.
+
+If I<escape_function> is set then the array members are processed by this
+function before being returned.
+
 =cut
 
 sub details {
-  my $self = shift;
+  my ( $self, %opt ) = @_;
+  my $format = $opt{format} || '';
+  my $escape_function = $opt{escape_function} || sub { shift };
   return () unless defined dbdef->table('cust_bill_pkg_detail');
-  map { $_->detail }
-    qsearch ( 'cust_bill_pkg_detail', { 'pkgnum' => $self->pkgnum,
-                                        'invnum' => $self->invnum, } );
+
+  eval "use Text::CSV_XS;";
+  die $@ if $@;
+  my $csv = new Text::CSV_XS;
+
+  my $format_sub = sub { my $detail = shift;
+                         $csv->parse($detail) or return "can't parse $detail";
+                         join(' - ', map { &$escape_function($_) }
+                                     $csv->fields
+                             );
+                       };
+
+  $format_sub = sub { my $detail = shift;
+                      $csv->parse($detail) or return "can't parse $detail";
+                      join('</TD><TD>', map { &$escape_function($_) }
+                                        $csv->fields
+                          );
+                    }
+    if $format eq 'html';
+
+  $format_sub = sub { my $detail = shift;
+                      $csv->parse($detail) or return "can't parse $detail";
+                      join(' & ', map { &$escape_function($_) } $csv->fields );
+                    }
+    if $format eq 'latex';
+
+  map { ( $_->format eq 'C'
+          ? &{$format_sub}( $_->detail )
+          : &{$escape_function}( $_->detail )
+        )
+      }
+    qsearch ({ 'table'    => 'cust_bill_pkg_detail',
+               'hashref'  => { 'pkgnum' => $self->pkgnum,
+                               'invnum' => $self->invnum,
+                             },
+               'order_by' => 'ORDER BY detailnum',
+            });
     #qsearch ( 'cust_bill_pkg_detail', { 'lineitemnum' => $self->lineitemnum });
 }
 
index 4156816..a69998a 100644 (file)
@@ -104,6 +104,7 @@ sub check {
   $self->ut_numbern('detailnum')
     || $self->ut_foreign_key('pkgnum', 'cust_pkg', 'pkgnum')
     || $self->ut_foreign_key('invnum', 'cust_bill', 'invnum')
+    || $self->ut_enum('format', [ '', 'C' ] )
     || $self->ut_text('detail')
     || $self->SUPER::check
     ;
index c4827c9..0f25e15 100644 (file)
@@ -292,15 +292,7 @@ sub calc_recur {
         $charge = sprintf('%.3f', $cdr->upstream_price);
         $charges += $charge;
 
-        @call_details = (
-          #time2str("%Y %b %d - %r", $cdr->calldate_unix ),
-          time2str("%c", $cdr->calldate_unix),  #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot
-          sprintf('%.2f', $cdr->billsec / 60 ).'m',
-          '$'.$charge, #XXX $money_char
-          #$pretty_destnum,
-          $cdr->userfield, #$rate_region->regionname,
-          $cdr->dst,
-        );
+        @call_details = ( $cdr->downstream_csv( 'format' => 'voxlinesystems' ));
 
       } else {
         die "don't know how to rate CDRs using method: ".
@@ -363,7 +355,12 @@ sub calc_recur {
         }
 
         if ( $charge > 0 ) {
-          my $call_details = join(' - ', @call_details );
+          my $call_details;
+          if ( $self->option('rating_method') eq 'upstream_simple' ) {
+            $call_details = [ 'C', $call_details[0] ];
+          }else{
+            $call_details = join(' - ', @call_details );
+          }
           warn "  adding details on charge to invoice: $call_details"
             if $DEBUG;
           push @$details, $call_details; #\@call_details,
@@ -382,6 +379,9 @@ sub calc_recur {
 
     } # $cdr
 
+    unshift @$details, [ 'C', "Date,Time,Name,Destination,Duration,Price" ]
+      if (@$details && $self->option('rating_method') eq 'upstream_simple' );
+
   } # $cust_svc
 
   if ( $spool_cdr && length($downstream_cdr) ) {
index 9d97243..14b25c6 100644 (file)
               '<td align="right">'. $line->{'amount'}. '</td>'.
             '</tr>'
           ;
-          foreach my $ext_desc ( @{$line->{'ext_description'} } ) {
-            $OUT .=
-              '<tr class="invoice_extdesc">'.
-                '<td></td>'.
-                '<td align="left">-&nbsp;'. $ext_desc. '</td>'.
-                '<td></td>'.
-              '</tr>'
+          if ( @{$line->{'ext_description'} } ) {
+            $OUT .= '<tr class="invoice_extdesc"><td></td><td><table>';
+            foreach my $ext_desc ( @{$line->{'ext_description'} } ) {
+              $OUT .=
+                '<tr class="invoice_extdesc">'.
+                  '<td align="left">-&nbsp;'. $ext_desc. '</td>'.
+                '</tr>'
+            }
+            $OUT .= '</table></td><td></td></tr>';
           }
         }
 
index 6a81c4c..e43fc3e 100644 (file)
@@ -242,10 +242,15 @@ Terms: [@-- $terms --@]\\
       $OUT .= '\FSdesc{' . $line->{'ref'} . '}{' . $line->{'description'} . '}' .\r
               '{' . $line->{'amount'} . "}${rowbreak}\n";\r
 \r
-      foreach my $ext_desc (@$ext_description) {\r
-        $ext_desc = substr($ext_desc, 0, 80) . '...'\r
-          if (length($ext_desc) > 80);\r
-        $OUT .= '\FSextdesc{' . $ext_desc . '}' . "${rowbreak}\n";\r
+      if (@$ext_description) {\r
+        $OUT .= '\multicolumn{1}{l}{\rule{0pt}{1.0ex}} &';\r
+        $OUT .= '\multicolumn{2}{l}{\begin{tabular}{lllll}'; %%cheating at 5\r
+        foreach my $ext_desc (@$ext_description) {\r
+          $ext_desc = substr($ext_desc, 0, 80) . '...'\r
+            if (length($ext_desc) > 80);\r
+          $OUT .= '\small{' . $ext_desc . '}' . "\\\\${rowbreak}\n";\r
+        }\r
+        $OUT .="\\end{tabular}}\\\\${rowbreak}\n";\r
       }\r
 \r
     }\r