You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcp-panel/sandbox/callforwards.pl

252 lines
8.6 KiB

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Schema;
use NGCP::Panel::Utils::Subscriber;
use NGCP::Panel::Utils::Preferences;
use Test::More;
use Data::HAL qw();
use Data::HAL::Link qw();
use Safe::Isa qw($_isa);
use NGCP::Panel::Form::CFSimpleAPI;
my $schema = NGCP::Schema->connect();
my $ql_exists = 0;
my ($ql,$ana);
if($ql_exists){
#use DBIx::Class::QueryLog;
#use DBIx::Class::QueryLog::Analyzer;
my $ql = DBIx::Class::QueryLog->new;
$schema->storage->debugobj($ql);
$schema->storage->debug(1);
my $ana = DBIx::Class::QueryLog::Analyzer->new({ querylog => $ql });
$ql->bucket('origin');
}
my $time = time();
print "start;\n";
#print Dumper($schema);
my $item_rs = $schema->resultset('voip_subscribers')->search( {
'me.status' => { '!=' => 'terminated' }
},{
prefetch => { 'provisioning_voip_subscriber'=>'voip_cf_mappings'},
#prefetch => 'provisioning_voip_subscriber',
rows => 200,
},
);
my (@arr_orig,@arr_opt);
for my $item ($item_rs->all) {
# print Dumper({$item->get_inflated_columns});
my %resource = ();
my $prov_subs = $item->provisioning_voip_subscriber;
for my $cf_type (qw/cfu cfb cft cfna cfs/) {
my $mapping = $schema->resultset('voip_cf_mappings')->search({
subscriber_id => $prov_subs->id,
type => $cf_type,
})->first;
if ($mapping) {
$resource{$cf_type} = _contents_from_cfm($mapping, $item);
} else {
$resource{$cf_type} = {};
}
}
if(keys %{$resource{cft}}){
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
$resource{cft}{ringtimeout} = $ringtimeout_preference;
}
additional_processing($item, \%resource);
push @arr_orig, \%resource;
}
print "1.time=".(time()-$time).";\n";
#exit;
if($ql_exists){
$ql->bucket('optimized');
}
$time = time();
for my $item ($item_rs->all) {
my %resource = ();
my $prov_subs = $item->provisioning_voip_subscriber;
@resource{qw/cfu cfb cft cfna cfs/} = ({}) x 5;
for my $item_cf ($item->provisioning_voip_subscriber->voip_cf_mappings->all){
$resource{$item_cf->type} = _contents_from_cfm($item_cf, $item);
}
if(keys %{$resource{cft}}){
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
$resource{cft}{ringtimeout} = $ringtimeout_preference;
}
additional_processing($item, \%resource);
push @arr_opt, \%resource;
}
print "2.time=".(time()-$time).";\n";
is_deeply(\@arr_orig, \@arr_opt, "check that arrays are equiv");
#print Dumper[\@arr_orig, \@arr_opt];
if($ql_exists){
print Dumper $ana->get_totaled_queries_by_bucket;
}
sub additional_processing{
my($item,$resource) = @_;
my $type='';
my %resource=%$resource;
my $hal = Data::HAL->new(
links => [
Data::HAL::Link->new(
relation => 'curies',
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
name => 'ngcp',
templated => 1,
),
Data::HAL::Link->new(relation => 'collection', href => sprintf("%s", '')),
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%s", '', $item->id)),
Data::HAL::Link->new(relation => "ngcp:$type", href => sprintf("/api/%s/%s", $type, $item->id)),
Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->id)),
],
relation => 'ngcp:callforwards',
);
my $form=NGCP::Panel::Form::CFSimpleAPI->new();
validate_form(
form => $form,
resource => \%resource,
run => 0,
);
$hal->resource(\%resource);
}
sub _contents_from_cfm {
my ($cfm_item, $sub) = @_;
my (@times, @destinations);
my $timeset_item = $cfm_item->time_set;
my $dset_item = $cfm_item->destination_set;
for my $time ($timeset_item ? $timeset_item->voip_cf_periods->all : () ) {
push @times, {$time->get_inflated_columns};
delete @{$times[-1]}{'time_set_id', 'id'};
}
for my $dest ($dset_item ? $dset_item->voip_cf_destinations->all : () ) {
my ($d, $duri) = NGCP::Panel::Utils::Subscriber::destination_to_field($dest->destination);
my $deflated;
if($d eq "uri") {
$deflated = NGCP::Panel::Utils::Subscriber::uri_deflate(undef, $duri,$sub) if $d eq "uri";
$d = $dest->destination;
}
push @destinations, {$dest->get_inflated_columns,
destination => $d,
$deflated ? (simple_destination => $deflated) : (),
};
delete @{$destinations[-1]}{'destination_set_id', 'id'};
}
return {times => \@times, destinations => \@destinations};
}
sub validate_form {
my (%params) = @_;
my $resource = $params{resource};
my $form = $params{form};
my $run = $params{run} // 1;
my $exceptions = $params{exceptions} // [];
my $form_params = $params{form_params} // {};
push @{ $exceptions }, "external_id";
my @normalized = ();
# move {xxx_id} into {xxx}{id} for FormHandler
foreach my $key(keys %{ $resource } ) {
my $skip_normalize = grep {/^$key$/} @{ $exceptions };
if($key =~ /^(.+)_id$/ && !$skip_normalize && !exists $resource->{$1}) {
push @normalized, $1;
$resource->{$1}{id} = delete $resource->{$key};
}
}
# remove unknown keys
my %fields = map { $_->name => $_ } $form->fields;
validate_fields($resource, \%fields, $run);
if($run) {
# check keys/vals
$form->process(params => $resource, posted => 1, %{$form_params} );
unless($form->validated) {
my $e = join '; ', map {
sprintf 'field=\'%s\', input=\'%s\', errors=\'%s\'',
($_->parent->$_isa('HTML::FormHandler::Field') ? $_->parent->name . '_' : '') . $_->name,
$_->input // '',
join('', @{ $_->errors })
} $form->error_fields;
return;
}
}
# move {xxx}{id} back into {xxx_id} for DB
foreach my $key(@normalized) {
next unless(exists $resource->{$key});
$resource->{$key . '_id'} = defined($resource->{$key}{id}) ?
int($resource->{$key}{id}) :
$resource->{$key}{id};
delete $resource->{$key};
}
return 1;
}
sub validate_fields {
my ($resource, $fields, $run) = @_;
for my $k (keys %{ $resource }) {
#if($resource->{$k}->$_isa('JSON::XS::Boolean') || $resource->{$k}->$_isa('JSON::PP::Boolean')) {
if($resource->{$k}->$_isa('JSON::PP::Boolean')) {
$resource->{$k} = $resource->{$k} ? 1 : 0;
}
unless(exists $fields->{$k}) {
delete $resource->{$k};
}
$resource->{$k} = DateTime::Format::RFC3339->format_datetime($resource->{$k})
if $resource->{$k}->$_isa('DateTime');
$resource->{$k} = $resource->{$k} + 0
if(defined $resource->{$k} && (
$fields->{$k}->$_isa('HTML::FormHandler::Field::Integer') ||
$fields->{$k}->$_isa('HTML::FormHandler::Field::Money') ||
$fields->{$k}->$_isa('HTML::FormHandler::Field::Float')) &&
(is_int($resource->{$k}) || is_decimal($resource->{$k})));
if (defined $resource->{$k} &&
$fields->{$k}->$_isa('HTML::FormHandler::Field::Repeatable') &&
"ARRAY" eq ref $resource->{$k} ) {
for my $elem (@{ $resource->{$k} }) {
my ($subfield_instance) = $fields->{$k}->fields;
my %subfields = map { $_->name => $_ } $subfield_instance->fields;
validate_fields($elem, \%subfields, $run);
}
}
# only do this for converting back from obj to hal
# otherwise it breaks db fields with the \0 and \1 notation
unless($run) {
$resource->{$k} = $resource->{$k} ? JSON::true : JSON::false
if(defined $resource->{$k} &&
$fields->{$k}->$_isa('HTML::FormHandler::Field::Boolean'));
}
}
return 1;
}
1;