X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fcdr.pm;h=1e4088162725c71a60eb2971408fb5e3bce1d33d;hp=478dcff6bfeb55e9350afa35a2de27ce921f41e4;hb=43d2e192dfed48adc33af02b2dd98d66d5813e33;hpb=c6815d4041610785099c820df097326a70c8ce41 diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm index 478dcff6b..1e4088162 100644 --- a/FS/FS/cdr.pm +++ b/FS/FS/cdr.pm @@ -130,9 +130,9 @@ following fields are currently supported: =item svcnum - Link to customer service (see L) -=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. @@ -525,6 +553,10 @@ my %export_names = ( 'invoice_header' => "Date,Time,Called From,Destination,Duration,Price", #"Date,Time,Name,Called From,Destination,Duration,Price", }, + 'basic' => { + 'name' => 'Basic', + 'invoice_header' => "Date/Time,Called Number,Min/Sec,Price", + }, 'default' => { 'name' => 'Default', 'invoice_header' => 'Date,Time,Number,Destination,Duration,Price', @@ -537,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 = (); @@ -548,23 +592,40 @@ sub export_formats { my $conf = new FS::Conf; my $date_format = $conf->config('date_format') || '%m/%d/%Y'; - # This is now smarter, and shows the call duration in the - # largest units that accurately reflect the granularity. + # call duration in the largest units that accurately reflect the granularity 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 - return sprintf("%.0fm",$sec/60); + elsif ( defined $opt{granularity} && $opt{granularity} == 60 ) {#full minutes + my $min = int($sec/60); + $min++ if $sec%60; + return $min.'m'; } else { #anything else return sprintf("%dm %ds", $sec/60, $sec%60); } }; + 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 @@ -573,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 @@ -583,7 +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, + $price_sub, ], 'default' => [ @@ -605,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'} }, ]; @@ -615,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 ) = @_; @@ -640,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; @@ -706,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; } } @@ -886,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 }, @@ -923,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 ); }