diff --git a/lib/NGCP/BulkProcessor/Dao/Trunk/provisioning/voip_cf_mappings.pm b/lib/NGCP/BulkProcessor/Dao/Trunk/provisioning/voip_cf_mappings.pm index be212dd..f1aa690 100644 --- a/lib/NGCP/BulkProcessor/Dao/Trunk/provisioning/voip_cf_mappings.pm +++ b/lib/NGCP/BulkProcessor/Dao/Trunk/provisioning/voip_cf_mappings.pm @@ -3,6 +3,12 @@ use strict; ## no critic +use NGCP::BulkProcessor::Logging qw( + getlogger + rowinserted + rowsdeleted +); + use NGCP::BulkProcessor::ConnectorPool qw( get_provisioning_db @@ -28,6 +34,7 @@ our @EXPORT_OK = qw( $CFNA_TYPE insert_row + delete_cfmappings ); my $tablename = 'voip_cf_mappings'; @@ -89,6 +96,37 @@ sub countby_subscriberid_type { } +sub delete_cfmappings { + + my ($xa_db,$subscriber_id,$types) = @_; + + check_table(); + my $db = &$get_db(); + $xa_db //= $db; + my $table = $db->tableidentifier($tablename); + + my $stmt = 'DELETE FROM ' . $table . ' WHERE ' . + $db->columnidentifier('subscriber_id') . ' = ?'; + my @params = ($subscriber_id); + if (defined $types and 'HASH' eq ref $types) { + foreach my $in (keys %$types) { + my @values = (defined $types->{$in} and 'ARRAY' eq ref $types->{$in} ? @{$types->{$in}} : ($types->{$in})); + $stmt .= ' AND ' . $db->columnidentifier('type') . ' ' . $in . ' (' . substr(',?' x scalar @values,1) . ')'; + push(@params,@values); + } + } + + my $count; + if ($count = $xa_db->db_do($stmt,@params)) { + rowsdeleted($db,$tablename,$count,$count,getlogger(__PACKAGE__)); + return 1; + } else { + rowsdeleted($db,$tablename,0,0,getlogger(__PACKAGE__)); + return 0; + } + +} + sub insert_row { my $db = &$get_db(); diff --git a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Provisioning.pm b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Provisioning.pm index 03a3fa6..a98ce1a 100644 --- a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Provisioning.pm +++ b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Provisioning.pm @@ -36,6 +36,10 @@ use NGCP::BulkProcessor::Projects::Migration::UPCAT::Settings qw( $ccs_sippassword_length @css_trusted_source_ips + + $cf_default_priority + $cf_default_timeout + $cft_default_ringtimeout ); use NGCP::BulkProcessor::Logging qw ( @@ -72,9 +76,9 @@ use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_dbaliases qw(); use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_subscribers qw(); use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences qw(); use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_usr_preferences qw(); -#use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings qw(); -#use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destination_sets qw(); -#use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destinations qw(); +use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings qw(); +use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destination_sets qw(); +use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destinations qw(); use NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_trusted_sources qw(); use NGCP::BulkProcessor::Dao::Trunk::kamailio::voicemail_users qw(); @@ -111,6 +115,7 @@ our @EXPORT_OK = qw( provision_mta_subscribers provision_ccs_subscribers $UPDATE_CCS_PREFERENCES_MODE + $SET_CCS_CF_MODE ); my $split_ipnets_pattern = join('|',( @@ -127,6 +132,12 @@ my $default_barring = 'default'; my $ccs_contact_identifier_field = 'gpp9'; our $UPDATE_CCS_PREFERENCES_MODE = 'update_ccs_preferences'; +our $SET_CCS_CF_MODE = 'set_ccs_cf'; + +my $cf_types_pattern = '^' . $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFB_TYPE . '|' + . $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFT_TYPE . '|' + . $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFU_TYPE . '|' + . $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::CFNA_TYPE . '$'; sub provision_mta_subscribers { @@ -1126,7 +1137,7 @@ sub _provision_ccs_susbcriber { #} _update_ccs_preferences($context); _set_registrations($context); - ##_set_callforwards($context); + _set_callforwards($context); ##todo: additional prefs, AllowedIPs, NCOS, Callforwards. still thinking wether to integrate it ##in this main provisioning loop, or align it in separate run-modes, according to the files given. } else { @@ -1140,6 +1151,8 @@ sub _provision_ccs_susbcriber { if (defined $context->{prov_subscriber}) { if ($update_mode eq $UPDATE_CCS_PREFERENCES_MODE) { _update_ccs_preferences($context); + } elsif ($update_mode eq $SET_CCS_CF_MODE) { + _set_callforwards($context); } else { _warn($context,$context->{prov_subscriber}->{username} . ': ' . (scalar @$existing_billing_voip_subscribers) . ' existing billing subscribers found, skipping'); } @@ -1334,6 +1347,28 @@ sub _provision_ccs_subscribers_checks { processing_info(threadid(),"shared_buddylist_visibility attribute found",getlogger(__PACKAGE__)); } + foreach my $cf_attribute (@NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::CF_ATTRIBUTES) { + eval { + $context->{attributes}->{$cf_attribute} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute($cf_attribute); + }; + if ($@ or not defined $context->{attributes}->{$cf_attribute}) { + rowprocessingerror(threadid(),"cannot find $cf_attribute attribute",getlogger(__PACKAGE__)); + $result = 0; #even in skip-error mode.. + } else { + processing_info(threadid(),"$cf_attribute attribute found",getlogger(__PACKAGE__)); + } + } + + eval { + $context->{attributes}->{ringtimeout} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::findby_attribute( + $NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_preferences::RINGTIMEOUT_ATTRIBUTE); + }; + if ($@ or not defined $context->{attributes}->{ringtimeout}) { + rowprocessingerror(threadid(),'cannot find ringtimeout attribute',getlogger(__PACKAGE__)); + $result = 0; #even in skip-error mode.. + } else { + processing_info(threadid(),"ringtimeout attribute found",getlogger(__PACKAGE__)); + } return $result; } @@ -1531,6 +1566,52 @@ sub _provision_ccs_susbcriber_init_context { $context->{registrations} = \@registrations; $context->{trusted_sources} = \@trusted_sources; + $context->{ringtimeout} = undef; + my %cfsimple = (); + my @callforwards = (); + push(@callforwards,{ + type => 'cfu', + destination => $first->{target_number}, + }) if $first->{routing_type} eq '1:1'; + if ((scalar @callforwards) > 0) { + my %vmcf = (); + my %maxpriority = (); + foreach my $callforward (@callforwards) { + my $type = lc($callforward->{type}); + if ($type =~ /$cf_types_pattern/) { + unless (defined $callforward->{destination} and length($callforward->{destination}) > 0) { + _warn($context,"empty callforward destination, ignoring"); + next; + } + if ($callforward->{destination} =~ /voicemail/i) { + $callforward->{destination} = 'sip:vm' . ('cfb' eq $type ? 'b' : 'u') . $context->{numbers}->{primary}->{number} . '@voicebox.local'; + $vmcf{$type} = 1 unless $vmcf{$type}; + } elsif ($callforward->{destination} !~ /^\d+$/i) { + _warn($context,"invalid callforward destination '$callforward->{destination}', ignoring"); + next; + } else { #todo: allow sip uri destinations + $callforward->{destination} = 'sip:' . $callforward->{destination} .'@' . $context->{domain}->{domain}; + } + $callforward->{priority} //= $cf_default_priority; + $callforward->{timeout} //= $cf_default_timeout; + $callforward->{ringtimeout} //= $cft_default_ringtimeout if 'cft' eq $type; + $context->{ringtimeout} = $callforward->{ringtimeout} if ('cft' eq $type and (not defined $context->{ringtimeout} or $callforward->{ringtimeout} > $context->{ringtimeout})); + + $cfsimple{$type} = [] unless exists $cfsimple{$type}; + push(@{$cfsimple{$type}},{ + destination => $callforward->{destination}, + priority => $callforward->{priority}, + timeout => $callforward->{timeout}, + }); + #$vmcf{$type} = ($callforward->{destination} =~ /voicemail/i) unless $vmcf{$type}; + $maxpriority{$type} = $callforward->{priority} if (not defined $maxpriority{$type} or $callforward->{priority} > $maxpriority{$type}); + } else { + _warn($context,"invalid callforward type '$type', ignoring"); + } + } + } + $context->{callforwards} = \%cfsimple; + #$context->{preferences} = {}; #$context->{preferences}->{gpp} = [ @@ -1677,6 +1758,56 @@ sub _set_registrations { } +sub _set_callforwards { + + my ($context) = @_; + my $result = 1; + foreach my $type (keys %{$context->{callforwards}}) { + NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::delete_cfmappings($context->{db}, + $context->{prov_subscriber}->{id},{ '=' => $type }); + + my $destination_set_id = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destination_sets::insert_row($context->{db},{ + subscriber_id => $context->{prov_subscriber}->{id}, + name => "quickset_$type", + }); + foreach my $callforward (@{$context->{callforwards}->{$type}}) { + $callforward->{id} = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_destinations::insert_row($context->{db},{ + %$callforward, + destination_set_id => $destination_set_id, + }); + } + my $cf_mapping_id = NGCP::BulkProcessor::Dao::Trunk::provisioning::voip_cf_mappings::insert_row($context->{db},{ + subscriber_id => $context->{prov_subscriber}->{id}, + type => $type, + destination_set_id => $destination_set_id, + #time_set_id + }); + + $context->{preferences}->{$type} = { id => set_subscriber_preference($context, + $context->{prov_subscriber}->{id}, + $context->{attributes}->{$type}, + $cf_mapping_id), value => $cf_mapping_id }; + + if (defined $context->{ringtimeout}) { + $context->{preferences}->{ringtimeout} = { id => set_subscriber_preference($context, + $context->{prov_subscriber}->{id}, + $context->{attributes}->{ringtimeout}, + $context->{ringtimeout}), value => $context->{ringtimeout} }; + } + _info($context,"$type created (destination(s) " . join(', ',(map { $_->{destination}; } @{$context->{callforwards}->{$type}})) . ")",1); + + $context->{callforwards}->{$type} = { + destination_set => { + destinations => $context->{callforwards}->{$type}, + id => $destination_set_id, + }, + id => $cf_mapping_id, + }; + } + return $result; + +} + sub _error { my ($context,$message) = @_; diff --git a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Settings.pm b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Settings.pm index 3e1e93b..f5aed7e 100644 --- a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Settings.pm +++ b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/Settings.pm @@ -92,6 +92,10 @@ our @EXPORT_OK = qw( $ccs_sippassword_length @css_trusted_source_ips + + $cf_default_priority + $cf_default_timeout + $cft_default_ringtimeout ); #$default_channels_map @@ -150,6 +154,10 @@ our $ccs_sippassword_length = 16; our @css_trusted_source_ips = (); +our $cf_default_priority = 1; +our $cf_default_timeout = 300; +our $cft_default_ringtimeout = 20; + sub update_settings { my ($data,$configfile) = @_; @@ -238,6 +246,10 @@ sub update_settings { } } + $cf_default_priority = $data->{cf_default_priority} if exists $data->{cf_default_priority}; + $cf_default_timeout = $data->{cf_default_timeout} if exists $data->{cf_default_timeout}; + $cft_default_ringtimeout = $data->{cft_default_ringtimeout} if exists $data->{cft_default_ringtimeout}; + return $result; } diff --git a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/process.pl b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/process.pl index 5b30ffc..462918b 100644 --- a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/process.pl +++ b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/process.pl @@ -94,6 +94,7 @@ use NGCP::BulkProcessor::Projects::Migration::UPCAT::Provisioning qw( provision_mta_subscribers provision_ccs_subscribers $UPDATE_CCS_PREFERENCES_MODE + $SET_CCS_CF_MODE ); scripterror(getscriptpath() . ' already running',getlogger(getscriptpath())) unless flock DATA, LOCK_EX | LOCK_NB; # not tested on windows yet @@ -129,6 +130,9 @@ push(@TASK_OPTS,$create_ccs_subscriber_task_opt); my $update_ccs_subscriber_preferences_task_opt = 'update_ccs_subscriber_preferences'; push(@TASK_OPTS,$update_ccs_subscriber_preferences_task_opt); +my $set_ccs_subscriber_cf_task_opt = 'set_ccs_subscriber_cf'; +push(@TASK_OPTS,$set_ccs_subscriber_cf_task_opt); + if (init()) { main(); @@ -213,6 +217,13 @@ sub main() { $completion |= 1; } + } elsif (lc($set_ccs_subscriber_cf_task_opt) eq lc($task)) { + if (taskinfo($set_ccs_subscriber_cf_task_opt,$result,1)) { + next unless check_dry(); + $result &= set_ccs_subscriber_cf_task(\@messages); + $completion |= 1; + } + } else { $result = 0; scripterror("unknow task option '" . $task . "', must be one of " . join(', ',@TASK_OPTS),getlogger(getscriptpath())); @@ -523,6 +534,29 @@ sub update_ccs_subscriber_preferences_task { return $result; } +sub set_ccs_subscriber_cf_task { + my ($messages) = @_; + my ($result,$warning_count) = (0,0); + eval { + ($result,$warning_count) = provision_ccs_subscribers($SET_CCS_CF_MODE); + }; + my $err = $@; + my $stats = ": $warning_count warnings"; + eval { + $stats .= "\n total contracts: " . + NGCP::BulkProcessor::Dao::Trunk::billing::contracts::countby_status_resellerid(undef,undef) . ' rows'; + $stats .= "\n total subscribers: " . + NGCP::BulkProcessor::Dao::Trunk::billing::voip_subscribers::countby_status_resellerid(undef,undef) . ' rows'; + }; + if ($err or !$result) { + push(@$messages,"set ccs subscriber callforwards INCOMPLETE$stats"); + } else { + push(@$messages,"set ccs subscribers callforwards completed$stats"); + } + destroy_all_dbs(); + return $result; +} + #END { # # this should not be required explicitly, but prevents Log4Perl's # # "rootlogger not initialized error upon exit.. diff --git a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.cfg b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.cfg index e3f1398..3bba221 100644 --- a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.cfg +++ b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.cfg @@ -39,4 +39,8 @@ ccs_reseller_name = UPC ccs_billing_profile_name = Default Billing UPC ccs_domain = in-ivr.upc.at ccs_sippassword_length = 16 -css_trusted_source_ips = 80.110.2.228,80.110.2.229 \ No newline at end of file +css_trusted_source_ips = 80.110.2.228,80.110.2.229 + +cf_default_priority: 1 +cf_default_timeout: 300 +cft_default_ringtimeout: 20 \ No newline at end of file diff --git a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.debug.cfg b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.debug.cfg index 61a7caf..79f674e 100644 --- a/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.debug.cfg +++ b/lib/NGCP/BulkProcessor/Projects/Migration/UPCAT/settings.debug.cfg @@ -37,8 +37,13 @@ provision_ccs_subscriber_multithreading = 1 provision_ccs_subscriber_numofthreads = 2 ccs_reseller_name = default ccs_billing_profile_name = Default Billing Profile -ccs_domain = 10.15.19.193 +ccs_domain = 192.168.0.29 +#10.15.19.193 #d20.upc.at #in-ivr.upc.at ccs_sippassword_length = 16 -css_trusted_source_ips = 80.110.2.228,80.110.2.229 \ No newline at end of file +css_trusted_source_ips = 80.110.2.228,80.110.2.229 + +cf_default_priority: 1 +cf_default_timeout: 300 +cft_default_ringtimeout: 20 \ No newline at end of file