--- /dev/null
+package FS::cdr::taqua62;
+
+use strict;
+use vars qw(@ISA %info $da_rewrite);
+use FS::cdr qw(_cdr_date_parser_maker);
+
+@ISA = qw(FS::cdr);
+
+%info = (
+ 'name' => 'Taqua v6.2',
+ 'weight' => 131,
+ 'header' => 1,
+ 'import_fields' => [
+
+ #0
+ '', #Key
+ '', #InsertTime, irrelevant
+ #RecordType
+ sub {
+ my($cdr, $field, $conf, $hashref) = @_;
+ $hashref->{skiprow} = 1
+ unless ($field == 0 && $cdr->disposition == 100 ) #regular CDR
+ || ($field == 1 && $cdr->lastapp eq 'acctcode'); #accountcode
+ $cdr->cdrtypenum($field);
+ },
+
+ '', #RecordVersion
+ '', #OrigShelfNumber
+ '', #OrigCardNumber
+ '', #OrigCircuit
+ '', #OrigCircuitType
+ 'uniqueid', #SequenceNumber
+ 'sessionnum', #SessionNumber
+ #10
+ 'src', #CallingPartyNumber
+ #CalledPartyNumber
+ sub {
+ my( $cdr, $field, $conf ) = @_;
+ if ( $cdr->calltypenum == 6 && $cdr->cdrtypenum == 0 ) {
+ $cdr->dst("+$field");
+ } else {
+ $cdr->dst($field);
+ }
+ },
+
+ _cdr_date_parser_maker('startdate', 'gmt' => 1), #CallArrivalTime
+ _cdr_date_parser_maker('enddate', 'gmt' => 1), #CallCompletionTime
+
+ #Disposition
+ #sub { my($cdr, $d ) = @_; $cdr->disposition( $disposition{$d}): },
+ 'disposition',
+ # -1 => '',
+ # 0 => '',
+ # 100 => '', #regular cdr
+ # 101 => '',
+ # 102 => '',
+ # 103 => '',
+ # 104 => '',
+ # 105 => '',
+ # 201 => '',
+ # 203 => '',
+ # 204 => '',
+
+ _cdr_date_parser_maker('answerdate', 'gmt' => 1), #DispositionTime
+ '', #TCAP
+ '', #OutboundCarrierConnectTime
+ '', #OutboundCarrierDisconnectTime
+
+ #TermTrunkGroup
+ #it appears channels are actually part of trunk groups, but this data
+ #is interesting and we need a source and destination place to put it
+ 'dstchannel', #TermTrunkGroup
+
+ #20
+
+ '', #TermShelfNumber
+ '', #TermCardNumber
+ '', #TermCircuit
+ '', #TermCircuitType
+ 'carrierid', #OutboundCarrierId
+
+ #BillingNumber
+ #'charged_party',
+ sub {
+ my( $cdr, $field, $conf ) = @_;
+
+ #could be more efficient for the no config case, if anyone ever needs that
+ $da_rewrite ||= $conf->config('cdr-taqua-da_rewrite');
+
+ if ( $da_rewrite && $field =~ /\d/ ) {
+ my $rewrite = $da_rewrite;
+ $rewrite =~ s/\s//g;
+ my @rewrite = split(',', $conf->config('cdr-taqua-da_rewrite') );
+ if ( grep { $field eq $_ } @rewrite ) {
+ $cdr->charged_party( $cdr->src() );
+ $cdr->calltypenum(12);
+ return;
+ }
+ }
+ if ( $cdr->is_tollfree ) { # thankfully this is already available
+ $cdr->charged_party($cdr->dst); # and this
+ } else {
+ $cdr->charged_party($field);
+ }
+ },
+
+ 'subscriber', #SubscriberName
+ 'lastapp', #ServiceName
+ '', #some weirdness #ChargeTime
+ 'lastdata', #ServiceInformation
+
+ #30
+
+ '', #FacilityInfo
+ '', #all 1900-01-01 0#CallTraceTime
+ '', #all-1#UniqueIndicator
+ '', #all-1#PresentationIndicator
+ '', #empty#Pin
+ 'calltypenum', #CallType
+
+ #nothing below is used by QIS...
+
+ '', #Balt/empty #OrigRateCenter
+ '', #Balt/empty #TermRateCenter
+
+ #OrigTrunkGroup
+ #it appears channels are actually part of trunk groups, but this data
+ #is interesting and we need a source and destination place to put it
+ 'channel', #OrigTrunkGroup
+ 'userfield', #empty#UserDefined
+
+ #40
+
+ '', #empty#PseudoDestinationNumber
+ '', #all-1#PseudoCarrierCode
+ '', #empty#PseudoANI
+ '', #all-1#PseudoFacilityInfo
+ '', #OrigDialedDigits
+ '', #all-1#OrigOutboundCarrier
+ '', #IncomingCarrierID
+ 'dcontext', #JurisdictionInfo
+ '', #OrigDestDigits
+ '', #empty#AMALineNumber
+
+ #50
+
+ '', #empty#AMAslpID
+ '', #empty#AMADigitsDialedWC
+ '', #OpxOffHook
+ '', #OpxOnHook
+ '', #OrigCalledNumber
+ '', #RedirectingNumber
+ '', #RouteAttempts
+ '', #OrigMGCPTerm
+ '', #TermMGCPTerm
+ '', #ReasonCode
+
+ #60
+
+ '', #OrigIPCallID
+ '', #ESAIPTrunkGroup
+ '', #ESAReason
+ '', #BearerlessCall
+ '', #oCodec
+ '', #tCodec
+ '', #OrigTrunkGroupNumber
+ '', #TermTrunkGroupNumber
+ '', #TermRecord
+ '', #OrigRoutingIndicator
+
+ #70
+
+ '', #TermRoutingIndicator
+
+ ],
+);
+
+1;
# set any package with FCC voice lines to the "VoIP with broadband" category
# for backward compatibility
- my $journal = 'part_pkg_fcc_voip_class';
- if (!FS::upgrade_journal->is_done($journal)) {
- @part_pkg = qsearch('part_pkg', {
- fcc_ds0s => { op => '>', value => 0 },
- fcc_voip_class => ''
- });
- foreach my $part_pkg (@part_pkg) {
- $part_pkg->set(fcc_voip_class => 2);
- my $error = $part_pkg->replace;
- die $error if $error;
+ #
+ # recover from a bad upgrade bug
+ my $upgrade = 'part_pkg_fcc_voip_class_FIX';
+ if (!FS::upgrade_journal->is_done($upgrade)) {
+ my $bad_upgrade = qsearchs('upgrade_journal',
+ { upgrade => 'part_pkg_fcc_voip_class' }
+ );
+ if ( $bad_upgrade ) {
+ my $where = 'WHERE history_date <= '.$bad_upgrade->_date.
+ ' AND history_date > '.($bad_upgrade->_date - 3600);
+ my @h_part_pkg_option = map { FS::part_pkg_option->new($_->hashref) }
+ qsearch({
+ 'select' => '*',
+ 'table' => 'h_part_pkg_option',
+ 'hashref' => {},
+ 'extra_sql' => "$where AND history_action = 'delete'",
+ 'order_by' => 'ORDER BY history_date ASC',
+ });
+ my @h_pkg_svc = map { FS::pkg_svc->new($_->hashref) }
+ qsearch({
+ 'select' => '*',
+ 'table' => 'h_pkg_svc',
+ 'hashref' => {},
+ 'extra_sql' => "$where AND history_action = 'replace_old'",
+ 'order_by' => 'ORDER BY history_date ASC',
+ });
+ my %opt;
+ foreach my $deleted (@h_part_pkg_option, @h_pkg_svc) {
+ my $pkgpart ||= $deleted->pkgpart;
+ $opt{$pkgpart} ||= {
+ options => {},
+ pkg_svc => {},
+ primary_svc => '',
+ hidden_svc => {},
+ };
+ if ( $deleted->isa('FS::part_pkg_option') ) {
+ $opt{$pkgpart}{options}{ $deleted->optionname } = $deleted->optionvalue;
+ } else { # pkg_svc
+ my $svcpart = $deleted->svcpart;
+ $opt{$pkgpart}{pkg_svc}{$svcpart} = $deleted->quantity;
+ $opt{$pkgpart}{hidden_svc}{$svcpart} ||= $deleted->hidden;
+ $opt{$pkgpart}{primary_svc} = $svcpart if $deleted->primary_svc;
+ }
+ }
+ foreach my $pkgpart (keys %opt) {
+ my $part_pkg = FS::part_pkg->by_key($pkgpart);
+ my $error = $part_pkg->replace( $part_pkg->replace_old, $opt{$pkgpart} );
+ if ( $error ) {
+ die "error recovering damaged pkgpart $pkgpart:\n$error\n";
+ }
+ }
+ } # $bad_upgrade exists
+ else { # do the original upgrade, but correctly this time
+ @part_pkg = qsearch('part_pkg', {
+ fcc_ds0s => { op => '>', value => 0 },
+ fcc_voip_class => ''
+ });
+ foreach my $part_pkg (@part_pkg) {
+ $part_pkg->set(fcc_voip_class => 2);
+ my @pkg_svc = $part_pkg->pkg_svc;
+ my %quantity = map {$_->svcpart, $_->quantity} @pkg_svc;
+ my %hidden = map {$_->svcpart, $_->hidden } @pkg_svc;
+ my $error = $part_pkg->replace(
+ $part_pkg->replace_old,
+ options => { $part_pkg->options },
+ pkg_svc => \%quantity,
+ hidden_svc => \%hidden,
+ primary_svc => ($part_pkg->svcpart || ''),
+ );
+ die $error if $error;
+ }
}
- FS::upgrade_journal->set_done($journal);
+ FS::upgrade_journal->set_done($upgrade);
}
}