use detail formats to show CDRs in selfservice, #14923
[freeside.git] / FS / FS / cdr.pm
index 65ca50b..1e40881 100644 (file)
@@ -130,9 +130,9 @@ following fields are currently supported:
 
 =item svcnum - Link to customer service (see L<FS::cust_svc>)
 
-=item freesidestatus - NULL, done (or something)
+=item freesidestatus - NULL, processing-tiered, done
 
-=item freesiderewritestatus - NULL, done (or something)
+=item freesiderewritestatus - NULL, done, skipped
 
 =item cdrbatch
 
@@ -401,13 +401,12 @@ error, otherwise returns false.
 
 sub set_status_and_rated_price {
   my($self, $status, $rated_price, $svcnum, %opt) = @_;
-  if($opt{'inbound'}) {
-    my $term = qsearchs('cdr_termination', {
-        acctid   => $self->acctid, 
-        termpart => 1 # inbound
-    });
+
+  if ($opt{'inbound'}) {
+
+    my $term = $self->cdr_termination( 1 ); #1: inbound
     my $error;
-    if($term) {
+    if ( $term ) {
       warn "replacing existing cdr status (".$self->acctid.")\n" if $term;
       $error = $term->delete;
       return $error if $error;
@@ -417,18 +416,47 @@ sub set_status_and_rated_price {
         termpart    => 1,
         rated_price => $rated_price,
         status      => $status,
-        svcnum      => $svcnum,
     });
+    $term->rated_seconds($opt{rated_seconds}) if exists($opt{rated_seconds});
+    $term->rated_minutes($opt{rated_minutes}) if exists($opt{rated_minutes});
+    $term->svcnum($svcnum) if $svcnum;
     return $term->insert;
-  }
-  else {
+
+  } else {
+
     $self->freesidestatus($status);
     $self->rated_price($rated_price);
+    $self->rated_seconds($opt{rated_seconds}) if exists($opt{rated_seconds});
+    $self->rated_minutes($opt{rated_minutes}) if exists($opt{rated_minutes});
     $self->svcnum($svcnum) if $svcnum;
     return $self->replace();
+
   }
 }
 
+=item cdr_termination [ TERMPART ]
+
+=cut
+
+sub cdr_termination {
+  my $self = shift;
+
+  if ( scalar(@_) && $_[0] ) {
+    my $termpart = shift;
+
+    qsearchs('cdr_termination', { acctid   => $self->acctid,
+                                  termpart => $termpart,
+                                }
+            );
+
+  } else {
+
+    qsearch('cdr_termination', { acctid => $self->acctid, } );
+
+  }
+
+}
+
 =item calldate_unix 
 
 Parses the calldate in SQL string format and returns a UNIX timestamp.
@@ -541,6 +569,18 @@ my %export_names = (
     'name'           => 'Default plus accountcode',
     'invoice_header' => 'Date,Time,Account,Number,Destination,Duration,Price',
   },
+  'description_default' => {
+    'name'           => 'Default with description field as destination',
+    'invoice_header' => 'Caller,Date,Time,Number,Destination,Duration,Price',
+  },
+  'sum_duration' => {
+    'name'           => 'Summary (one line per service, with duration)',
+    'invoice_header' => 'Caller,Calls,Minutes,Price',
+  },
+  'sum_count' => {
+    'name'           => 'Summary (one line per service, with count)',
+    'invoice_header' => 'Caller,Messages,Price',
+  },
 );
 
 my %export_formats = ();
@@ -556,11 +596,11 @@ sub export_formats {
   my $duration_sub = sub {
     my($cdr, %opt) = @_;
     my $sec = $opt{seconds} || $cdr->billsec;
-    if ( length($opt{granularity}) && 
+    if ( defined $opt{granularity} && 
          $opt{granularity} == 0 ) { #per call
       return '1 call';
     }
-    elsif ( $opt{granularity} == 60 ) {#full minutes
+    elsif ( defined $opt{granularity} && $opt{granularity} == 60 ) {#full minutes
       my $min = int($sec/60);
       $min++ if $sec%60;
       return $min.'m';
@@ -570,6 +610,22 @@ sub export_formats {
     }
   };
 
+  my $price_sub = sub {
+    my ($cdr, %opt) = @_;
+    my $price;
+    if ( defined($opt{charge}) ) {
+      $price = $opt{charge};
+    }
+    elsif ( $opt{inbound} ) {
+      my $term = $cdr->cdr_termination(1); # 1 = inbound
+      $price = $term->rated_price if defined $term;
+    }
+    else {
+      $price = $cdr->rated_price;
+    }
+    length($price) ? ($opt{money_char} . $price) : '';
+  };
+
   %export_formats = (
     'simple' => [
       sub { time2str($date_format, shift->calldate_unix ) },   #DATE
@@ -578,7 +634,7 @@ sub export_formats {
       'dst',                                           #NUMBER_DIALED
       $duration_sub,                                   #DURATION
       #sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
-      sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE
+      $price_sub,
     ],
     'simple2' => [
       sub { time2str($date_format, shift->calldate_unix ) },   #DATE
@@ -588,13 +644,26 @@ sub export_formats {
       'dst',                                           #NUMBER_DIALED
       $duration_sub,                                   #DURATION
       #sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
-      sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE
+      $price_sub,
+    ],
+    'sum_duration' => [ 
+      # for summary formats, the CDR is a fictitious object containing the 
+      # total billsec and the phone number of the service
+      'src',
+      sub { my($cdr, %opt) = @_; $opt{count} },
+      sub { my($cdr, %opt) = @_; int($opt{seconds}/60).'m' },
+      $price_sub,
+    ],
+    'sum_count' => [
+      'src',
+      sub { my($cdr, %opt) = @_; $opt{count} },
+      $price_sub,
     ],
     'basic' => [
       sub { time2str('%d %b - %I:%M %p', shift->calldate_unix) },
       'dst',
       $duration_sub,
-      sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE
+      $price_sub,
     ],
     'default' => [
 
@@ -616,8 +685,7 @@ sub export_formats {
       $duration_sub,
 
       #PRICE
-      sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; },
-
+      $price_sub,
     ],
   );
   $export_formats{'source_default'} = [ 'src', @{ $export_formats{'default'} }, ];
@@ -626,10 +694,31 @@ sub export_formats {
       'accountcode',
       @{ $export_formats{'default'} }[2..5],
     ];
+  my @default = @{ $export_formats{'default'} };
+  $export_formats{'description_default'} = 
+    [ 'src', @default[0..2], 
+      sub { my($cdr, %opt) = @_; $cdr->description },
+      @default[4,5] ];
 
-  %export_formats
+  return %export_formats;
 }
 
+=item downstream_csv OPTION => VALUE ...
+
+Returns a string of formatted call details for display on an invoice.
+
+Options:
+
+format
+
+charge
+
+seconds
+
+granularity
+
+=cut
+
 sub downstream_csv {
   my( $self, %opt ) = @_;
 
@@ -651,6 +740,8 @@ sub downstream_csv {
         }
     @{ $formats{$format} };
 
+  return @columns if defined $opt{'keeparray'};
+
   my $status = $csv->combine(@columns);
   die "FS::CDR: error combining ". $csv->error_input(). "into downstream CSV"
     unless $status;
@@ -717,14 +808,13 @@ sub clear_status {
     return $error;
   } 
 
-  my @cdr_termination = qsearch('cdr_termination', 
-                               { 'acctid' => $self->acctid } );
-  foreach my $cdr_termination ( @cdr_termination ) {
-      $cdr_termination->status('');
-      $error = $cdr_termination->replace;
+  foreach my $cdr_termination ( $self->cdr_termination ) {
+      #$cdr_termination->status('');
+      #$error = $cdr_termination->replace;
+      $error = $cdr_termination->delete;
       if ( $error ) {
-       $dbh->rollback if $oldAutoCommit;
-       return $error;
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
       } 
   }
   
@@ -897,7 +987,7 @@ my %import_options = (
                },
 
                           #drop the || 'csv' to allow auto xls for csv types?
-  'format_types' => { map { $_ => ( lc($cdr_info{$_}->{'type'}) || 'csv' ); }
+  'format_types' => { map { $_ => lc($cdr_info{$_}->{'type'} || 'csv'); }
                           keys %cdr_info
                     },
 
@@ -934,6 +1024,14 @@ sub batch_import {
   my $iopt = _import_options;
   $opt->{$_} = $iopt->{$_} foreach keys %$iopt;
 
+  if ( defined $opt->{'cdrtypenum'} ) {
+        $opt->{'preinsert_callback'} = sub {
+                my($record,$param) = (shift,shift);
+                $record->cdrtypenum($opt->{'cdrtypenum'});
+                '';
+        };
+  }
+
   FS::Record::batch_import( $opt );
 
 }