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/lib/NGCP/Panel/Role/API/CallLists.pm

290 lines
10 KiB

package NGCP::Panel::Role::API::CallLists;
use Moose::Role;
use Sipwise::Base;
with 'NGCP::Panel::Role::API' => {
-alias =>{ item_rs => '_item_rs', },
-excludes => [ 'item_rs' ],
};
use boolean qw(true);
use TryCatch;
use Data::HAL qw();
use Data::HAL::Link qw();
use HTTP::Status qw(:constants);
use POSIX;
use DateTime::Format::Strptime;
use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::Subscriber;
use NGCP::Panel::Form::CallList::Subscriber;
sub item_rs {
my ($self, $c) = @_;
my $item_rs = $c->model('DB')->resultset('cdr');
if($c->user->roles eq "admin") {
} elsif($c->user->roles eq "reseller") {
$item_rs = $item_rs->search({
-or => [
{ source_provider_id => $c->user->reseller->contract_id },
{ destination_provider_id => $c->user->reseller->contract_id },
],
});
} elsif($c->user->roles eq "subscriberadmin") {
$item_rs = $item_rs->search({
-or => [
{ 'source_account_id' => $c->user->account_id },
{ 'destination_account_id' => $c->user->account_id },
],
});
} else {
$item_rs = $item_rs->search({
-or => [
{ 'source_subscriber.id' => $c->user->voip_subscriber->id },
{ 'destination_subscriber.id' => $c->user->voip_subscriber->id },
],
},{
join => ['source_subscriber', 'destination_subscriber'],
});
}
return $item_rs;
}
sub get_form {
my ($self, $c) = @_;
if($c->user->roles eq "admin") {
return NGCP::Panel::Form::CallList::Subscriber->new;
} elsif($c->user->roles eq "reseller") {
return NGCP::Panel::Form::CallList::Subscriber->new;
} else {
return NGCP::Panel::Form::CallList::Subscriber->new;
}
}
sub hal_from_item {
my ($self, $c, $item, $owner, $form, $href_data) = @_;
my $resource = $self->resource_from_item($c, $item, $owner, $form);
my $hal = Data::HAL->new(
links => [
Data::HAL::Link->new(
relation => 'curies',
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
name => 'ngcp',
templated => true,
),
Data::HAL::Link->new(relation => 'collection', href => sprintf("/api/%s/", $self->resource_name)),
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%d?%s", $self->dispatch_path, $item->id, $href_data)),
# todo: customer can be in source_account_id or destination_account_id
# Data::HAL::Link->new(relation => 'ngcp:customers', href => sprintf("/api/customers/%d", $item->source_customer_id)),
],
relation => 'ngcp:'.$self->resource_name,
);
$form //= $self->get_form($c);
$self->validate_form(
c => $c,
resource => $resource,
form => $form,
run => 0,
exceptions => [],
);
$resource->{id} = int($item->id);
$hal->resource($resource);
return $hal;
}
sub resource_from_item {
my ($self, $c, $item, $owner, $form) = @_;
my $sub = $owner->{subscriber};
my $cust = $owner->{customer};
my $resource = {};
my $datetime_fmt = DateTime::Format::Strptime->new(
pattern => '%F %T',
);
$resource->{call_id} = $item->call_id;
my $intra = 0;
if($item->source_user_id && $item->source_account_id == $item->destination_account_id) {
$resource->{intra_customer} = JSON::true;
$intra = 1;
} else {
$resource->{intra_customer} = JSON::false;
$intra = 0;
}
# out by default
$resource->{direction} = (defined $sub && $sub->uuid eq $item->destination_user_id) ?
"in" : "out";
my ($src_sub, $dst_sub);
if($item->source_subscriber && $item->source_subscriber->provisioning_voip_subscriber) {
$src_sub = $item->source_subscriber->provisioning_voip_subscriber;
}
if($item->destination_subscriber && $item->destination_subscriber->provisioning_voip_subscriber) {
$dst_sub = $item->destination_subscriber->provisioning_voip_subscriber;
}
my ($own_normalize, $other_normalize, $own_domain, $other_domain);
if($resource->{direction} eq "out") {
# for pbx out calls, use extension as own cli
if($src_sub && $src_sub->pbx_extension) {
$resource->{own_cli} = $src_sub->pbx_extension;
} else {
$resource->{own_cli} = $item->source_cli;
$own_normalize = 1;
}
$own_domain = $item->source_domain;
# for intra pbx out calls, use extension as other cli
if($intra && $dst_sub && $dst_sub->pbx_extension) {
$resource->{other_cli} = $dst_sub->pbx_extension;
# if there is an alias field (e.g. gpp0), use this
} elsif($item->destination_account_id && $c->req->param('alias_field')) {
my $alias = $item->get_column('destination_'.$c->req->param('alias_field'));
$resource->{other_cli} = $alias // $item->destination_user_in;
$other_normalize = 1;
} else {
$resource->{other_cli} = $item->destination_user_in;
$other_normalize = 1;
}
$other_domain = $item->destination_domain;
} else {
# for pbx in calls, use extension as own cli
if($dst_sub && $dst_sub->pbx_extension) {
$resource->{own_cli} = $dst_sub->pbx_extension;
} else {
$resource->{own_cli} = $item->destination_user_in;
$own_normalize = 1;
}
$own_domain = $item->destination_domain;
# for intra pbx in calls, use extension as other cli
if($intra && $src_sub && $src_sub->pbx_extension) {
$resource->{other_cli} = $src_sub->pbx_extension;
# if there is an alias field (e.g. gpp0), use this
} elsif($item->source_account_id && $c->req->param('alias_field')) {
my $alias = $item->get_column('source_'.$c->req->param('alias_field'));
$resource->{other_cli} = $alias // $item->source_cli;
$other_normalize = 1;
} else {
$resource->{other_cli} = $item->source_cli;
$other_normalize = 1;
}
$other_domain = $item->source_domain;
}
if($resource->{own_cli} !~ /^\d+$/) {
$resource->{own_cli} .= '@'.$own_domain;
} elsif($own_normalize) {
$resource->{own_cli} = NGCP::Panel::Utils::Subscriber::apply_rewrite(
c => $c, subscriber => $sub // $src_sub->voip_subscriber,
number => $resource->{own_cli}, direction => "caller_out"
);
}
if($resource->{direction} eq "in" && $item->source_clir) {
$resource->{other_cli} = undef;
} elsif($resource->{other_cli} !~ /^\d+$/) {
$resource->{other_cli} .= '@'.$other_domain;
} elsif($other_normalize) {
$resource->{other_cli} = NGCP::Panel::Utils::Subscriber::apply_rewrite(
c => $c, subscriber => $sub // $src_sub->voip_subscriber,
number => $resource->{other_cli}, direction => "caller_out"
);
}
$resource->{status} = $item->call_status;
$resource->{type} = $item->call_type;
$resource->{start_time} = $datetime_fmt->format_datetime($item->start_time);
$resource->{duration} = NGCP::Panel::Utils::DateTime::sec_to_hms(ceil($item->duration));
$resource->{customer_cost} = $resource->{direction} eq "out" ?
$item->source_customer_cost : $item->destination_customer_cost;
$resource->{customer_free_time} = $resource->{direction} eq "out" ?
$item->source_customer_free_time : 0;
return $resource;
}
sub item_by_id {
my ($self, $c, $id) = @_;
my $item_rs = $self->item_rs($c);
return $item_rs->find($id);
}
sub get_owner_data {
my ($self, $c, $schema) = @_;
my $ret;
if($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
if($c->req->param('subscriber_id')) {
my $sub = $schema->resultset('voip_subscribers')->find($c->req->param('subscriber_id'));
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if($c->user->roles eq "reseller" && $sub->contract->contact->reseller_id != $c->user->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
return {
subscriber => $sub,
customer => $sub->contract,
};
} elsif($c->req->param('customer_id')) {
my $cust = $schema->resultset('contracts')->find($c->req->param('customer_id'));
unless($cust && $cust->contact->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
if($c->user->roles eq "reseller" && $cust->contact->reseller_id != $c->user->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
return {
subscriber => undef,
customer => $cust,
};
} else {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Mandatory parameter 'subscriber_id' or 'customer_id' missing in request");
return;
}
} elsif($c->user->roles eq "subscriberadmin") {
if($c->req->param('subscriber_id')) {
my $sub = $schema->resultset('voip_subscribers')->find($c->req->param('subscriber_id'));
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if($sub->contract_id != $c->user->account_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
return {
subscriber => $sub,
customer => $sub->contract,
};
} else {
my $cust = $schema->resultset('contracts')->find($c->user->account_id);
unless($cust && $cust->contact->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
return {
subscriber => undef,
customer => $cust,
};
}
} else {
return {
subscriber => $c->user->voip_subscriber,
customer => $c->user->voip_subscriber->contract,
};
}
}
1;
# vim: set tabstop=4 expandtab: