diff --git a/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr.pm b/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr.pm index 4c90f726..5b3204f1 100644 --- a/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr.pm +++ b/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr.pm @@ -43,6 +43,7 @@ our @EXPORT_OK = qw( process_fromto get_callidprefix + findby_callid $OK_CALL_STATUS @@ -247,6 +248,27 @@ sub findby_callidprefix { } +sub findby_callid { + + my ($xa_db,$call_id,$joins,$conditions,$load_recursive) = @_; + + check_table(); + my $db = &$get_db(); + $xa_db //= $db; + my $table = $db->tableidentifier($tablename); + + my @conditions = @{$conditions // []}; + push(@conditions,{ $table . '.call_id' => { '=' => '?' } }); + my $stmt = 'SELECT ' . join(',', map { $table . '.' . $db->columnidentifier($_); } @$expected_fieldnames) . ' ' . + _get_export_stmt($db,undef,$joins,\@conditions) . + ' ORDER BY ' . $table . '.start_time ASC'; + my @params = ($call_id); + my $rows = $xa_db->db_get_all_arrayref($stmt,@params); + + return buildrecords_fromrows($rows,$load_recursive); + +} + sub update_row { my ($xa_db,$data) = @_; diff --git a/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr_group.pm b/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr_group.pm new file mode 100644 index 00000000..5beba9d6 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Dao/Trunk/accounting/cdr_group.pm @@ -0,0 +1,131 @@ +package NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_group; +use strict; + +## no critic + +use NGCP::BulkProcessor::Logging qw( + getlogger +); + +use NGCP::BulkProcessor::ConnectorPool qw( + get_accounting_db + destroy_dbs +); + +use NGCP::BulkProcessor::SqlProcessor qw( + checktableinfo + copy_row + +); +use NGCP::BulkProcessor::SqlRecord qw(); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::SqlRecord); +our @EXPORT_OK = qw( + gettablename + check_table + + findby_cdrid + findby_callid + +); +#findby_callid + +my $tablename = 'cdr_group'; +my $get_db = \&get_accounting_db; + +my $expected_fieldnames = [ +"cdr_id", +"call_id", +"cdr_start_time", +]; + +my $indexes = {}; + +my $insert_unique_fields = []; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::SqlRecord->new($class,$get_db, + $tablename,$expected_fieldnames,$indexes); + + copy_row($self,shift,$expected_fieldnames); + + return $self; + +} + +sub findby_cdrid { + + my ($xa_db,$cdrid,$load_recursive) = @_; + + check_table(); + my $db = &$get_db(); + $xa_db //= $db; + my $table = $db->tableidentifier($tablename); + + my $stmt = 'SELECT * FROM ' . $table . ' WHERE ' . + $db->columnidentifier('cdr_id') . ' = ?'; + my @params = ($cdrid); + my $rows = $xa_db->db_get_all_arrayref($stmt,@params); + + return buildrecords_fromrows($rows,$load_recursive); + +} + +sub findby_callid { + + my ($xa_db,$callid,$load_recursive) = @_; + + check_table(); + my $db = &$get_db(); + $xa_db //= $db; + my $table = $db->tableidentifier($tablename); + + my $stmt = 'SELECT * FROM ' . $table . ' WHERE ' . + $db->columnidentifier('call_id') . ' = ?'; + my @params = ($callid); + my $rows = $xa_db->db_get_all_arrayref($stmt,@params); + + return buildrecords_fromrows($rows,$load_recursive); + +} + +sub buildrecords_fromrows { + + my ($rows,$load_recursive) = @_; + + my @records = (); + my $record; + + if (defined $rows and ref $rows eq 'ARRAY') { + foreach my $row (@$rows) { + $record = __PACKAGE__->new($row); + + # transformations go here ... + + push @records,$record; + } + } + + return \@records; + +} + +sub gettablename { + + return $tablename; + +} + +sub check_table { + + return checktableinfo($get_db, + __PACKAGE__,$tablename, + $expected_fieldnames, + $indexes); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/CDR.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/CDR.pm index 13d1acfa..296c3b44 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/CDR.pm +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/CDR.pm @@ -24,6 +24,9 @@ use NGCP::BulkProcessor::Projects::Export::Ama::Ccs::Settings qw( $ama_outgoing_trunk_group_number $ama_originating_digits_cdr_field $ama_terminating_digits_cdr_field + + $ivr_duration_limit + $primary_alias_pattern ); use NGCP::BulkProcessor::Logging qw ( @@ -40,6 +43,7 @@ use NGCP::BulkProcessor::LogError qw( use NGCP::BulkProcessor::Dao::Trunk::accounting::cdr qw(); use NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status qw(); use NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data qw(); +use NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_group qw(); use NGCP::BulkProcessor::Dao::Trunk::accounting::mark qw(); use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers qw(); @@ -86,7 +90,12 @@ our @EXPORT_OK = qw( reset_export_status ); -my $DIRECT_FORWARDER_SCENARIO = 1; +my $BLIND_TRANSFER_NO_IVR = 1; +my $BLIND_TRANSFER = 2; +my $NO_TRANSFER_NO_IVR = 3; +my $NO_TRANSFER = 4; +my $ATTN_TRANSFER_NO_IVR = 5; +my $ATTN_TRANSFER = 6; my $file_sequence_number : shared = 0; my $rowcount : shared = 0; @@ -165,7 +174,9 @@ sub export_cdrs { static_context => $static_context, process_code => sub { my ($context,$records,$row_offset) = @_; + # we only want to export a call scenario of eg. 4 cdrs, if the block (eg. 1000 cdrs) contains all 4. $context->{block_call_id_map} = {}; + my $cdr_id_map = {}; foreach my $record (@$records) { my ($id,$call_id) = @$record; my $call_id_prefix = NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::get_callidprefix($call_id); @@ -174,6 +185,14 @@ sub export_cdrs { } else { $context->{block_call_id_map}->{$call_id_prefix} = 1; } + $cdr_id_map->{$id} = 1; + } + $context->{correlated_cdrs_map} = {}; + foreach my $record (@$records) { + my ($id,$call_id) = @$record; + $context->{correlated_cdrs_map}->{$id} = _find_child_cdrs($context,$id); + my $call_id_prefix = NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::get_callidprefix($call_id); + map { $context->{block_call_id_map}->{$call_id_prefix} += 1 if exists $cdr_id_map->{$_->{id}}; } @{$context->{correlated_cdrs_map}->{$id}}; } foreach my $record (@$records) { if (defined $export_cdr_limit) { @@ -278,70 +297,256 @@ sub export_cdrs { return ($result,$warning_count,\@ama_files); } +sub _find_child_cdrs { + my ($context,$id) = @_; + my @correlated_cdrs = (); + foreach my $correlated_group_cdr (@{NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_group::findby_cdrid($context->{db},$id)}) { + foreach my $correlated_cdr (@{NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::findby_callid($context->{db},$correlated_group_cdr->{call_id})}) { + push(@correlated_cdrs,$correlated_cdr); + } + } + return \@correlated_cdrs; +} sub _export_cdrs_init_context { my ($context,$cdr_id,$call_id) = @_; my $result = 0; - $context->{cdrs} = []; + my $parent_cdrs; $context->{call_id} = $call_id; - my $scenario = { code => 0, }; + my $scenario = { code => 0, ama => [], }; $context->{scenario} = $scenario; - if (not exists $context->{file_cdr_id_map}->{$cdr_id}) { + if (not exists $context->{file_cdr_id_map}->{$cdr_id}) { #skip if processed for a file already my $call_id_prefix = NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::get_callidprefix($call_id); - if (exists $context->{block_call_id_map}->{$call_id_prefix}) { - $context->{cdrs} = NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::findby_callidprefix($context->{db}, - $call_id,$export_cdr_joins,$export_cdr_conditions); #already sorted - my $cdrs_in_block = delete $context->{block_call_id_map}->{$call_id_prefix}; - if ((scalar @{$context->{cdrs}}) == $cdrs_in_block) { - my $malformed = 0; - if ((scalar @{$context->{cdrs}}) == 2 - and not $context->{cdrs}->[0]->is_xfer() - and $context->{cdrs}->[1]->is_xfer() - and ($scenario->{ccs_subscriber} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers::findby_uuid(undef,$context->{cdrs}->[0]->{destination_user_id})) - and ($scenario->{ccs_subscriber}->{primary_alias} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::findby_subscriberidisprimary($scenario->{ccs_subscriber}->{id},1)->[0]) - ) { - if ($context->{cdrs}->[0]->{$ama_originating_digits_cdr_field} =~ /^[0-9]+$/ - and $context->{cdrs}->[1]->{$ama_terminating_digits_cdr_field} =~ /^[0-9]+$/ - ) { - $scenario->{code} = $DIRECT_FORWARDER_SCENARIO; - $result = 1; + if (exists $context->{block_call_id_map}->{$call_id_prefix}) { #skip if this callid form parent calls that have already been processed + if ((scalar @{NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_group::findby_callid($context->{db},$call_id)}) == 0) { #skip if this is a correlated (child) cdr + $parent_cdrs = NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::findby_callidprefix($context->{db}, + $call_id,$export_cdr_joins,$export_cdr_conditions); #already sorted + my @scenario_cdrs = @$parent_cdrs; + foreach my $cdr (@$parent_cdrs) { + my @correlated_cdrs; + if (exists $context->{correlated_cdrs_map}->{$cdr->{id}}) { + @correlated_cdrs = @{$context->{correlated_cdrs_map}->{$cdr->{id}}}; } else { - $malformed = 1; + @correlated_cdrs = @{_find_child_cdrs($context,$cdr->{id})}; } - #} else { - # print "blah"; + $cdr->{_correlated_cdrs} = \@correlated_cdrs; + push(@scenario_cdrs,@correlated_cdrs); } - foreach my $cdr (@{$context->{cdrs}}) { - if ($result) { - $cdr->{_extended_export_status} = $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data::OK; - } elsif ($malformed) { - $cdr->{_extended_export_status} = $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data::FAILED; - } else { - $cdr->{_extended_export_status} = $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data::SKIPPED; + $scenario->{parent_cdrs} = $parent_cdrs; + $scenario->{all_cdrs} = \@scenario_cdrs; + my $cdrs_in_block = delete $context->{block_call_id_map}->{$call_id_prefix}; + if ((scalar @scenario_cdrs) == $cdrs_in_block) { + my $malformed = 0; + + #blind xfer: + if ((scalar @$parent_cdrs) == 2 + and not $parent_cdrs->[0]->is_xfer() + and $parent_cdrs->[1]->is_xfer() + and (scalar @{$parent_cdrs->[0]->{_correlated_cdrs}}) == 0 + and (scalar @{$parent_cdrs->[1]->{_correlated_cdrs}}) == 0 + and ($scenario->{ccs_subscriber} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers::findby_uuid(undef,$parent_cdrs->[0]->{destination_user_id})) + and ($scenario->{ccs_subscriber}->{primary_alias} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::findby_subscriberidisprimary($scenario->{ccs_subscriber}->{id},1)->[0]) + and (not defined $primary_alias_pattern or $scenario->{ccs_subscriber}->{primary_alias}->{username} =~ $primary_alias_pattern) + ) { + my $ivr_duration = abs($parent_cdrs->[0]->{start_time} - $parent_cdrs->[1]->{init_time}); + if ($ivr_duration < $ivr_duration_limit) { + $scenario->{code} = $BLIND_TRANSFER_NO_IVR; + } else { + $scenario->{code} = $BLIND_TRANSFER; + } + $result = 1; + #no transfer: + } elsif ((scalar @$parent_cdrs) == 1 + and not $parent_cdrs->[0]->is_xfer() + and not $parent_cdrs->[0]->is_pbx() + and (scalar @{$parent_cdrs->[0]->{_correlated_cdrs}}) == 0 + and ($scenario->{ccs_subscriber} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers::findby_uuid(undef,$parent_cdrs->[0]->{destination_user_id})) + and ($scenario->{ccs_subscriber}->{primary_alias} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::findby_subscriberidisprimary($scenario->{ccs_subscriber}->{id},1)->[0]) + and (not defined $primary_alias_pattern or $scenario->{ccs_subscriber}->{primary_alias}->{username} =~ $primary_alias_pattern) + ) { + my $ivr_duration = $parent_cdrs->[0]->{duration}; + if ($ivr_duration < $ivr_duration_limit) { + $scenario->{code} = $NO_TRANSFER_NO_IVR; + } else { + $scenario->{code} = $NO_TRANSFER; + } + $result = 1; + #attn transfer: + } elsif ((scalar @$parent_cdrs) == 2 + and not $parent_cdrs->[0]->is_pbx() + and $parent_cdrs->[1]->is_pbx() + and (scalar @{$parent_cdrs->[0]->{_correlated_cdrs}}) == 0 + and (scalar @{$parent_cdrs->[1]->{_correlated_cdrs}}) == 1 + and ($scenario->{ccs_subscriber} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers::findby_uuid(undef,$parent_cdrs->[0]->{destination_user_id})) + and ($scenario->{ccs_subscriber}->{primary_alias} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases::findby_subscriberidisprimary($scenario->{ccs_subscriber}->{id},1)->[0]) + and (not defined $primary_alias_pattern or $scenario->{ccs_subscriber}->{primary_alias}->{username} =~ $primary_alias_pattern) + ) { + my $correlated_cdr = $parent_cdrs->[1]->{_correlated_cdrs}->[0]; + my $ivr_duration = abs($correlated_cdr->{start_time} - $parent_cdrs->[1]->{init_time}); + if ($ivr_duration < $ivr_duration_limit) { + $scenario->{code} = $ATTN_TRANSFER_NO_IVR; + } else { + $scenario->{code} = $ATTN_TRANSFER; + } + $result = 1; + } #elsif (... + # + #} + + foreach my $cdr (@scenario_cdrs) { + if ($result) { + $cdr->{_extended_export_status} = $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data::OK; + } elsif ($malformed) { + $cdr->{_extended_export_status} = $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data::FAILED; + } else { + $cdr->{_extended_export_status} = $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr_export_status_data::SKIPPED; + } + $context->{file_cdr_id_map}->{$cdr->{id}} = $cdr; #->{start_time}; + lock $rowcount; + $rowcount += 1; } - $context->{file_cdr_id_map}->{$cdr->{id}} = $cdr; #->{start_time}; - lock $rowcount; - $rowcount += 1; } } } } - if ($scenario->{code} == $DIRECT_FORWARDER_SCENARIO) { - $scenario->{start_time} = $context->{cdrs}->[0]->{start_time}; - $scenario->{duration} = $context->{cdrs}->[0]->{duration}; - $scenario->{originating} = $context->{cdrs}->[0]->{$ama_originating_digits_cdr_field}; - $scenario->{terminating} = $context->{cdrs}->[1]->{$ama_terminating_digits_cdr_field}; - $scenario->{unanswered} = ($context->{cdrs}->[1]->{call_status} ne $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::OK_CALL_STATUS ? 1 : 0); - $scenario->{correlation_id} = substr($context->{cdrs}->[0]->{id},-7); - $scenario->{nod} = { - originating_digits => $scenario->{originating}, - switch_number_digits => $scenario->{ccs_subscriber}->{primary_alias}->{username}, - mode => '0001', - }; + if ($scenario->{code} == $BLIND_TRANSFER_NO_IVR) { + my $originating = $parent_cdrs->[0]->{$ama_originating_digits_cdr_field}; + my $terminating = $parent_cdrs->[1]->{$ama_terminating_digits_cdr_field}; + push(@{$scenario->{ama}},{ + start_time => $parent_cdrs->[1]->{start_time}, #? + duration => $parent_cdrs->[1]->{duration}, + originating => $originating, + terminating => $terminating, + unanswered => ($parent_cdrs->[1]->{call_status} ne $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::OK_CALL_STATUS ? 1 : 0), + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '0001', + }, + }); + } elsif ($scenario->{code} == $BLIND_TRANSFER) { + my $originating = $parent_cdrs->[0]->{$ama_originating_digits_cdr_field}; + my $terminating = $parent_cdrs->[1]->{$ama_terminating_digits_cdr_field}; + push(@{$scenario->{ama}},{ + start_time => $parent_cdrs->[0]->{start_time}, #? + duration => abs($parent_cdrs->[0]->{start_time} - $parent_cdrs->[1]->{init_time}), + originating => $originating, + terminating => $terminating, + unanswered => 0, + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '6001', + }, + },{ + start_time => $parent_cdrs->[1]->{start_time}, + duration => $parent_cdrs->[1]->{duration}, + originating => $originating, + terminating => $terminating, + unanswered => ($parent_cdrs->[1]->{call_status} ne $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::OK_CALL_STATUS ? 1 : 0), + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '2002', + }, + }); + } elsif ($scenario->{code} == $NO_TRANSFER_NO_IVR) { + my $originating = $parent_cdrs->[0]->{$ama_originating_digits_cdr_field}; + my $terminating = $parent_cdrs->[0]->{$ama_terminating_digits_cdr_field}; + push(@{$scenario->{ama}},{ + start_time => $parent_cdrs->[0]->{start_time}, #? + duration => 0, + originating => $originating, + terminating => $terminating, + unanswered => 1, + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '0001', + }, + }); + } elsif ($scenario->{code} == $NO_TRANSFER) { + my $originating = $parent_cdrs->[0]->{$ama_originating_digits_cdr_field}; + my $terminating = $parent_cdrs->[0]->{$ama_terminating_digits_cdr_field}; + push(@{$scenario->{ama}},{ + start_time => $parent_cdrs->[0]->{start_time}, #? + duration => $parent_cdrs->[0]->{duration}, + originating => $originating, + terminating => $terminating, + unanswered => 0, + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '6001', + }, + },{ + start_time => $parent_cdrs->[0]->{start_time}, #? + duration => 0, + originating => $originating, + terminating => $terminating, + unanswered => 1, + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '2002', + }, + }); + } elsif ($scenario->{code} == $ATTN_TRANSFER_NO_IVR) { + my $correlated_cdr = $parent_cdrs->[1]->{_correlated_cdrs}->[0]; + my $originating = $correlated_cdr->{$ama_originating_digits_cdr_field}; + my $terminating = $parent_cdrs->[1]->{$ama_terminating_digits_cdr_field}; + push(@{$scenario->{ama}},{ + start_time => $parent_cdrs->[1]->{start_time}, #? + duration => $correlated_cdr->{duration} - abs($correlated_cdr->{start_time} - $parent_cdrs->[1]->{start_time}), + originating => $originating, + terminating => $terminating, + unanswered => ($correlated_cdr->{call_status} ne $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::OK_CALL_STATUS ? 1 : 0), + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '0001', + }, + }); + } elsif ($scenario->{code} == $ATTN_TRANSFER) { + my $correlated_cdr = $parent_cdrs->[1]->{_correlated_cdrs}->[0]; + my $originating = $correlated_cdr->{$ama_originating_digits_cdr_field}; + my $terminating = $parent_cdrs->[1]->{$ama_terminating_digits_cdr_field}; + push(@{$scenario->{ama}},{ + start_time => $parent_cdrs->[1]->{start_time}, #? + duration => abs($correlated_cdr->{start_time} - $parent_cdrs->[1]->{init_time}), + originating => $originating, + terminating => $terminating, + unanswered => 0, + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '6001', + }, + },{ + start_time => $parent_cdrs->[1]->{start_time}, #? + duration => $correlated_cdr->{duration} - abs($correlated_cdr->{start_time} - $parent_cdrs->[1]->{start_time}), + originating => $originating, + terminating => $terminating, + unanswered => ($correlated_cdr->{call_status} ne $NGCP::BulkProcessor::Dao::Trunk::accounting::cdr::OK_CALL_STATUS ? 1 : 0), + correlation_id => substr($parent_cdrs->[0]->{id},-7), + nod => { + originating_digits => $originating, + switch_number_digits => $terminating, #$scenario->{ccs_subscriber}->{primary_alias}->{username}, + mode => '2002', + }, + }); } return $result; @@ -432,6 +637,76 @@ sub _get_transfer_in { } +sub _create_ama_record { + my ($context,$ama) = @_; + $context->{file}->update_start_end_time($ama->{start_time},$ama->{start_time} + $ama->{duration}); + return NGCP::BulkProcessor::Projects::Export::Ama::Format::Record->new( + NGCP::BulkProcessor::Projects::Export::Ama::Format::Structures::Structure0510->new( + call_type => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallType::STATION_PAID, + + rewritten => 0, + sensor_id => $ama_sensor_id, + + padding => 0, + recording_office_id => $ama_recording_office_id, + + call_type => '970', + #timing ind 000 + #seervice observed 0c + + unanswered => $ama->{unanswered}, #called party off-hook setzen + + date => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date::get_ama_date(from_epoch($ama->{start_time})), + + service_feature => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature::OTHER, + + originating_significant_digits => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_length($ama->{originating}), + originating_open_digits_1 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_1($ama->{originating}), + originating_open_digits_2 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_2($ama->{originating}), + + domestic_international => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational::INTERNATIONAL, #get_number_domestic_international($context->{destination}), + + terminating_significant_digits => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_length($ama->{terminating}), + terminating_open_digits_1 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_1($ama->{terminating}), + terminating_open_digits_2 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_2($ama->{terminating}), + + connect_time => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime::get_connect_time(from_epoch($ama->{start_time})), + elapsed_time => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime::get_elapsed_time($ama->{duration}), + ), + NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module611->new( + generic_context_identifier => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::GenericContextIdentifier::IN_CORRELATION_ID, + parsing_rules => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::GenericContextIdentifier::IN_CORRELATION_ID_PARSING_RULES, + additional_digits_dialed => $ama->{correlation_id}, + ), + NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module199->new( + network_operator_data => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::NetworkOperatorData::get_network_operator_data( + $ama->{nod}->{originating_digits}, + $ama->{nod}->{switch_number_digits}, + $ama->{nod}->{mode}, + ), + ), + NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module104->new( + direction => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TrunkIdentification::INCOMING, + trunk_group_number => $ama_incoming_trunk_group_number, + trunk_member_number => '0000', + ), + NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module104->new( + direction => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TrunkIdentification::OUTGOING, + trunk_group_number => $ama_outgoing_trunk_group_number, + trunk_member_number => '0000', + ), + NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module000->new( + ), + ); +} + +sub _create_ama_records { + my ($context,$scenario_name) = @_; + my $records = [ map { _create_ama_record($context,$_); } @{$context->{scenario}->{ama}} ]; + _info($context,"$scenario_name - cdr ids " . join(', ', map { $_->{id}; } @{$context->{scenario}->{all_cdrs}}) . ':' . join("\n", map { $_->to_string(); } @$records),1); + return $records; +} + sub _get_record { my %params = @_; @@ -441,70 +716,20 @@ sub _get_record { context /}; - if ($context->{scenario}->{code} == $DIRECT_FORWARDER_SCENARIO) { - $context->{file}->update_start_end_time($context->{scenario}->{start_time},$context->{scenario}->{start_time} + $context->{scenario}->{duration}); - my $record = NGCP::BulkProcessor::Projects::Export::Ama::Format::Record->new( - NGCP::BulkProcessor::Projects::Export::Ama::Format::Structures::Structure0510->new( - call_type => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallType::STATION_PAID, - - rewritten => 0, - sensor_id => $ama_sensor_id, - - padding => 0, - recording_office_id => $ama_recording_office_id, - - call_type => '970', - #timing ind 000 - #seervice observed 0c - - unanswered => $context->{scenario}->{unanswered}, #called party off-hook setzen - - date => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date::get_ama_date(from_epoch($context->{scenario}->{start_time})), - - service_feature => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature::OTHER, - - originating_significant_digits => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_length($context->{scenario}->{originating}), - originating_open_digits_1 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_1($context->{scenario}->{originating}), - originating_open_digits_2 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_2($context->{scenario}->{originating}), - - domestic_international => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational::INTERNATIONAL, #get_number_domestic_international($context->{destination}), - - terminating_significant_digits => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_length($context->{scenario}->{terminating}), - terminating_open_digits_1 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_1($context->{scenario}->{terminating}), - terminating_open_digits_2 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_2($context->{scenario}->{terminating}), - - connect_time => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime::get_connect_time(from_epoch($context->{scenario}->{start_time})), - elapsed_time => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime::get_elapsed_time($context->{scenario}->{duration}), - ), - NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module611->new( - generic_context_identifier => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::GenericContextIdentifier::IN_CORRELATION_ID, - parsing_rules => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::GenericContextIdentifier::IN_CORRELATION_ID_PARSING_RULES, - additional_digits_dialed => $context->{scenario}->{correlation_id}, - ), - NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module199->new( - network_operator_data => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::NetworkOperatorData::get_network_operator_data( - $context->{scenario}->{nod}->{originating_digits}, - $context->{scenario}->{nod}->{switch_number_digits}, - $context->{scenario}->{nod}->{mode}, - ), - ), - NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module104->new( - direction => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TrunkIdentification::INCOMING, - trunk_group_number => $ama_incoming_trunk_group_number, - trunk_member_number => '0000', - ), - NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module104->new( - direction => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TrunkIdentification::OUTGOING, - trunk_group_number => $ama_outgoing_trunk_group_number, - trunk_member_number => '0000', - ), - NGCP::BulkProcessor::Projects::Export::Ama::Format::Modules::Module000->new( - ), - ); - _info($context,"ama record from cdr ids " . join(', ',map { $_->{id}; } @{$context->{cdrs}}) . ':' . $record->to_string(),1); - return $record; + if ($context->{scenario}->{code} == $BLIND_TRANSFER_NO_IVR) { + return _create_ama_records($context,'BLIND_TRANSFER_NO_IVR'); + } elsif ($context->{scenario}->{code} == $BLIND_TRANSFER) { + return _create_ama_records($context,'BLIND_TRANSFER'); + } elsif ($context->{scenario}->{code} == $NO_TRANSFER_NO_IVR) { + return _create_ama_records($context,'NO_TRANSFER_NO_IVR'); + } elsif ($context->{scenario}->{code} == $NO_TRANSFER) { + return _create_ama_records($context,'NO_TRANSFER'); + } elsif ($context->{scenario}->{code} == $ATTN_TRANSFER_NO_IVR) { + return _create_ama_records($context,'ATTN_TRANSFER_NO_IVR'); + } elsif ($context->{scenario}->{code} == $ATTN_TRANSFER) { + return _create_ama_records($context,'ATTN_TRANSFER'); } else { - _error($context,"unknown scenario $context->{scenario}->{code} for cdr ids " . join(', ',map { $_->{id}; } @{$context->{cdrs}}) ); + _error($context,"unknown scenario $context->{scenario}->{code} for cdr ids " . join(', ',map { $_->{id}; } @{$context->{scenario}->{all_cdrs}}) ); } } diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/Settings.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/Settings.pm index 2e58983f..340c5e4f 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/Settings.pm +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/Settings.pm @@ -61,6 +61,8 @@ our @EXPORT_OK = qw( $ama_originating_digits_cdr_field $ama_terminating_digits_cdr_field + $ivr_duration_limit + $primary_alias_pattern ); our $defaultconfig = 'config.cfg'; @@ -88,6 +90,9 @@ our $ama_outgoing_trunk_group_number; our $ama_originating_digits_cdr_field; our $ama_terminating_digits_cdr_field; +our $ivr_duration_limit = 5; +our $primary_alias_pattern = undef; + sub update_settings { my ($data,$configfile) = @_; @@ -128,6 +133,13 @@ sub update_settings { configurationerror($configfile,'unknown ama_terminating_digits_cdr_field',getlogger(__PACKAGE__)); } + $ivr_duration_limit = $data->{ivr_duration_limit} if exists $data->{ivr_duration_limit}; + + my $regexp_result; + $primary_alias_pattern = $data->{primary_alias_pattern} if exists $data->{primary_alias_pattern}; + ($regexp_result,$primary_alias_pattern) = parse_regexp($primary_alias_pattern,$configfile); + $result &= $regexp_result; + return $result; } diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/config.debug.cfg b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/config.debug.cfg index 9419038c..f4fd7160 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/config.debug.cfg +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/config.debug.cfg @@ -59,6 +59,6 @@ doneemailrecipient = ##logging: fileloglevel = DEBUG #DEBUG -screenloglevel = INFO +screenloglevel = DEBUG #INFO emailloglevel = OFF diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.cfg b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.cfg index d8f5f0d8..da2cb7c0 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.cfg +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.cfg @@ -27,3 +27,6 @@ ama_incoming_trunk_group_number = 2999 ama_outgoing_trunk_group_number = 2014 ama_originating_digits_cdr_field = source_cli ama_terminating_digits_cdr_field = destination_user_in + +ivr_duration_limit = 5 +primary_alias_pattern = 431976 \ No newline at end of file diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.debug.cfg b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.debug.cfg index b956387d..03043dca 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.debug.cfg +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Ccs/settings.debug.cfg @@ -12,6 +12,7 @@ export_cdr_rollover_fsn = 1 #, { 'accounting.cdr.rating_status' => { '=' => '"ok"' } } #{ 'accounting.cdr.call_status' => { '=' => '"ok"' } } #export_cdr_joins = { 'accounting.cdr_export_status_data esd' => { 'esd.cdr_id' => 'accounting.cdr.id' } }, { 'accounting.cdr_export_status es' => { 'es.id' => 'esd.status_id' } } +export_cdr_conditions = { 'accounting.cdr.id' => { '>=' => '51' } } use_tempfiles = 1 make_dir = 1 @@ -27,4 +28,7 @@ ama_recording_office_id = 438716 ama_incoming_trunk_group_number = 2999 ama_outgoing_trunk_group_number = 2014 ama_originating_digits_cdr_field = source_cli -ama_terminating_digits_cdr_field = destination_user_in \ No newline at end of file +ama_terminating_digits_cdr_field = destination_user_in + +ivr_duration_limit = 5 +#primary_alias_pattern = 431976 \ No newline at end of file diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/File.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/File.pm index e9cf7d50..1aba8f77 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/File.pm +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/File.pm @@ -294,23 +294,26 @@ sub write_record { ) unless $self->{record_count} > 0; my $result = 0; - my $record = &$get_record(@_); - if (not $self->add_record($record)) { - $result |= $self->close( - get_transfer_out => $get_transfer_out, - commit_cb => $commit_cb, - @_ - ); - $self->add_record( - $self->_save_transfer_in(&$get_transfer_in( - - #file_sequence_number => 1, + my $records = &$get_record(@_); + $records = [ $records ] unless 'ARRAY' eq ref $records; + foreach my $record (@$records) { + if (not $self->add_record($record)) { + $result |= $self->close( + get_transfer_out => $get_transfer_out, + commit_cb => $commit_cb, @_ - )), - 1 - ); + ); + $self->add_record( + $self->_save_transfer_in(&$get_transfer_in( - $self->add_record($record); + #file_sequence_number => 1, + @_ + )), + 1 + ); + + $self->add_record($record); + } } return $result;