From 914722e348a6a2c2a016b326782309a7c607f699 Mon Sep 17 00:00:00 2001 From: Kirill Solomko Date: Sun, 4 Aug 2019 23:55:10 +0200 Subject: [PATCH] TT#63545 rework /api/customerfraudevents support cdr_period_costs * /api/customerfraudevents now support cdr_period_costs * add PATCH support to be able to change notify_status and notified_at * item id is now compound from contract_id,period,period_date * now all locked contracts are returned (was only for current day/month before) * interval query param is not mandatory anymore and multiple entries per contract can be returned Change-Id: I9faa911d260f3e3cd386fb1470663a82edb2850c --- .gitignore | 2 + .../Controller/API/CustomerFraudEvents.pm | 8 ++- .../Controller/API/CustomerFraudEventsItem.pm | 56 +++++++++++++++++-- .../Form/CustomerFraudEvents/Reseller.pm | 38 ++++++++++++- .../Panel/Role/API/CustomerFraudEvents.pm | 52 ++++++++++++++--- 5 files changed, 140 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 1fdff604d0..055888c572 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ NGCP-Panel-* ngcp_panel_local.conf api-rest.pretty nytprof +.tags +.remote-sync.json diff --git a/lib/NGCP/Panel/Controller/API/CustomerFraudEvents.pm b/lib/NGCP/Panel/Controller/API/CustomerFraudEvents.pm index ff0c2a879d..1b74bd1074 100644 --- a/lib/NGCP/Panel/Controller/API/CustomerFraudEvents.pm +++ b/lib/NGCP/Panel/Controller/API/CustomerFraudEvents.pm @@ -32,7 +32,11 @@ sub query_params { }, { param => 'interval', - description => 'Interval filter. values: day, month. default: month', + description => 'Interval filter. values: ["day", "month"].', + }, + { + param => 'notify_status', + description => 'Notify status filter. values: ["new", "notified"].', }, ]; } @@ -69,7 +73,7 @@ sub GET :Allow { push @embedded, $self->hal_from_item($c, $item, $form); push @links, Data::HAL::Link->new( relation => 'ngcp:'.$self->resource_name, - href => sprintf('/%s%d', $c->request->path, $item->id), + href => sprintf('/%s%d-%s-%s', $c->request->path, $item->id, $item->interval, $item->interval_date), ); } push @links, diff --git a/lib/NGCP/Panel/Controller/API/CustomerFraudEventsItem.pm b/lib/NGCP/Panel/Controller/API/CustomerFraudEventsItem.pm index 4024c4cd4e..ef088a79b5 100644 --- a/lib/NGCP/Panel/Controller/API/CustomerFraudEventsItem.pm +++ b/lib/NGCP/Panel/Controller/API/CustomerFraudEventsItem.pm @@ -11,7 +11,7 @@ require NGCP::Panel::Role::HTTPMethods; require Catalyst::ActionRole::RequireSSL; sub allowed_methods{ - return [qw/GET OPTIONS HEAD/]; + return [qw/GET OPTIONS HEAD PATCH/]; } use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::CustomerFraudEvents/; @@ -31,12 +31,15 @@ sub query_params { return [ { param => 'interval', - description => 'Interval filter. values: day, month. default: month', + description => 'Interval filter. values: ["day", "month"].', + }, + { + param => 'notify_status', + description => 'Notify status filter. values: ["new", "notified"].', }, ]; } - __PACKAGE__->set_config({ allowed_roles => [qw/admin reseller/], }); @@ -44,7 +47,6 @@ __PACKAGE__->set_config({ sub GET :Allow { my ($self, $c, $id) = @_; { - last unless $self->valid_id($c, $id); my $item = $self->item_by_id($c, $id); last unless $self->resource_exists($c, customerfraudevent => $item); @@ -63,6 +65,52 @@ sub GET :Allow { return; } +sub PATCH :Allow { + my ($self, $c, $id) = @_; + my $schema = $c->model('DB'); + my $guard = $schema->txn_scope_guard; + { + my $preference = $self->require_preference($c); + last unless $preference; + + my $item = $self->item_by_id($c, $id); + my $json = $self->get_valid_patch_data( + c => $c, + id => 1, # TODO: allow non int ids in PATCH + media_type => 'application/json-patch+json', + ops => ["replace"], + ); + last unless $json; + + my $form = $self->get_form($c); + my $old_resource = $self->hal_from_item($c, $item)->resource; + my $resource = $self->apply_patch($c, $old_resource, $json); + last unless $resource; + + $item = $self->update_item($c, $item, undef, $resource, $form); + last unless $item; + + my $hal = $self->hal_from_item($c, $item); + last unless $hal; + + $guard->commit; + + if ('minimal' eq $preference) { + $c->response->status(HTTP_NO_CONTENT); + $c->response->header(Preference_Applied => 'return=minimal'); + $c->response->body(q()); + } else { + my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new( + $hal->http_headers, + ), $hal->as_json); + $c->response->headers($response->headers); + $c->response->header(Preference_Applied => 'return=representation'); + $c->response->body($response->content); + } + } + return; +} + 1; # vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/CustomerFraudEvents/Reseller.pm b/lib/NGCP/Panel/Form/CustomerFraudEvents/Reseller.pm index 387a351b17..1a89505d30 100644 --- a/lib/NGCP/Panel/Form/CustomerFraudEvents/Reseller.pm +++ b/lib/NGCP/Panel/Form/CustomerFraudEvents/Reseller.pm @@ -23,6 +23,16 @@ has_field 'interval' => ( }, ); +has_field 'interval_date' => ( + type => 'Text', + label => 'Interval Date', + required => 1, + element_attr => { + rel => ['tooltip'], + title => ['Interval date of the fraud events.'] + }, +); + has_field 'type' => ( type => 'Text', label => 'Type', @@ -36,6 +46,7 @@ has_field 'type' => ( has_field 'interval_cost' => ( type => 'Float', label => 'Interval cost', + precision => '3', required => 1, element_attr => { rel => ['tooltip'], @@ -63,6 +74,16 @@ has_field 'interval_lock' => ( }, ); +has_field 'interval_notify' => ( + type => 'Text', + label => 'Notify Email', + required => 1, + element_attr => { + rel => ['tooltip'], + title => ['Email used for this notification.'] + }, +); + has_field 'use_reseller_rates' => ( type => 'Integer', label => 'Use reseller rates', @@ -73,16 +94,27 @@ has_field 'use_reseller_rates' => ( }, ); -has_field 'interval_notify' => ( +has_field 'notify_status' => ( + type => 'Text', + label => 'Notify Status', + required => 1, + element_attr => { + rel => ['tooltip'], + title => ['Status of the notification.'] + }, +); + +has_field 'notified_at' => ( type => 'Text', - label => 'Interval Notify', + label => 'Notified at', required => 1, element_attr => { rel => ['tooltip'], - title => ['A list of emails to send the notify to.'] + title => ['When the last related notification was sent.'] }, ); + 1; =head1 NAME diff --git a/lib/NGCP/Panel/Role/API/CustomerFraudEvents.pm b/lib/NGCP/Panel/Role/API/CustomerFraudEvents.pm index 6f3c5939c5..8224fc6c0c 100644 --- a/lib/NGCP/Panel/Role/API/CustomerFraudEvents.pm +++ b/lib/NGCP/Panel/Role/API/CustomerFraudEvents.pm @@ -12,12 +12,15 @@ use HTTP::Status qw(:constants); sub _item_rs { my ($self, $c) = @_; - my $item_rs = $c->model('DB')->resultset('contract_fraud_events')->search( - undef, - { - bind => [ $c->request->param('interval') || 'month' ] - } - ); + my $item_rs = $c->model('DB')->resultset('contract_fraud_events')->search({ + }); + + if (my $interval = $c->request->param('interval')) { + $item_rs = $item_rs->search({ interval => $interval }); + } + if (my $notify_status = $c->request->param('notify_status')) { + $item_rs = $item_rs->search({ notify_status => $notify_status }); + } if($c->user->roles eq "admin") { # @@ -73,7 +76,42 @@ sub hal_from_item { sub item_by_id { my ($self, $c, $id) = @_; my $item_rs = $self->item_rs($c); - return $item_rs->find($id); + my ($contract_id, $period, $period_date) = split(/-/, $id, 3); + + return $item_rs->search_rs({ + id => $contract_id, + interval => $period, + interval_date => $period_date + })->first; +} + +sub update_item { + my ($self, $c, $item, $old_resource, $resource, $form) = @_; + + $form //= $self->get_form($c); + return unless $self->validate_form( + c => $c, + form => $form, + resource => $resource, + ); + + my $cpc_rs = $c->model('DB')->resultset('cdr_period_costs')->search({ + contract_id => $item->id, + period => $item->interval, + period_date => $item->interval_date + }); + my $cpc = $cpc_rs->first; + unless ($cpc) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Customer fraud event does not exist"); + return; + } + + # only update r/w fields + $cpc->update({ + map { $_ => $resource->{$_} } qw(notify_status notified_at) + }); + + return $item; } 1;