From 6d384428763b2a69505550750f42f43b6c97b663 Mon Sep 17 00:00:00 2001 From: Andreas Granig Date: Fri, 2 Aug 2013 11:08:03 +0200 Subject: [PATCH] Filter terminated elements; visual cleanups. Don't show terminated resellers and contracts. Wrap customer details into accordion. --- lib/NGCP/Panel/Controller/Contract.pm | 2 +- lib/NGCP/Panel/Controller/Customer.pm | 9 + lib/NGCP/Panel/Controller/Subscriber.pm | 52 ++- lib/NGCP/Panel/Field/CustomerContract.pm | 4 +- lib/NGCP/Panel/Form/Subscriber.pm | 8 +- share/templates/customer/details.tt | 392 ++++++++++++++--------- share/templates/subscriber/list.tt | 2 +- 7 files changed, 273 insertions(+), 196 deletions(-) diff --git a/lib/NGCP/Panel/Controller/Contract.pm b/lib/NGCP/Panel/Controller/Contract.pm index ae6116c0cc..a9e14e78a5 100644 --- a/lib/NGCP/Panel/Controller/Contract.pm +++ b/lib/NGCP/Panel/Controller/Contract.pm @@ -21,7 +21,6 @@ sub contract_list :Chained('/') :PathPart('contract') :CaptureArgs(0) { { name => "id", search => 1, title => "#" }, { name => "external_id", search => 1, title => "External #" }, { name => "contact.reseller.name", search => 1, title => "Reseller" }, - { name => "contact.reseller.name", search => 1, title => "Reseller" }, { name => "contact.email", search => 1, title => "Contact Email" }, { name => "billing_mappings.billing_profile.name", search => 1, title => "Billing Profile" }, { name => "status", search => 1, title => "Status" }, @@ -30,6 +29,7 @@ sub contract_list :Chained('/') :PathPart('contract') :CaptureArgs(0) { my $mapping_rs = $c->model('DB')->resultset('billing_mappings'); my $rs = $c->model('DB')->resultset('contracts') ->search({ + 'me.status' => { '!=' => 'terminated' }, 'billing_mappings.id' => { '=' => $mapping_rs->search({ contract_id => { -ident => 'me.id' }, diff --git a/lib/NGCP/Panel/Controller/Customer.pm b/lib/NGCP/Panel/Controller/Customer.pm index 529871ea03..4e71e78623 100644 --- a/lib/NGCP/Panel/Controller/Customer.pm +++ b/lib/NGCP/Panel/Controller/Customer.pm @@ -61,6 +61,13 @@ sub base :Chained('list_customer') :PathPart('') :CaptureArgs(1) { my $contract = $c->model('DB')->resultset('contracts') ->search_rs(id => $contract_id); + unless($c->user->is_superuser) { + $contract = $contract->search({ + 'contact.reseller_id' => $c->user->reseller_id, + }, { + join => 'contact', + }); + } my $stime = DateTime->now->truncate(to => 'month'); my $etime = $stime->clone->add(months => 1); @@ -126,6 +133,8 @@ sub base :Chained('list_customer') :PathPart('') :CaptureArgs(1) { sub details :Chained('base') :PathPart('details') :Args(0) { my ($self, $c) = @_; + + $c->stash->{contact_hash} = { $c->stash->{contract}->contact->get_inflated_columns }; } sub subscriber_create :Chained('base') :PathPart('subscriber/create') :Args(0) { diff --git a/lib/NGCP/Panel/Controller/Subscriber.pm b/lib/NGCP/Panel/Controller/Subscriber.pm index 2def6a4a1a..c9447caa1e 100644 --- a/lib/NGCP/Panel/Controller/Subscriber.pm +++ b/lib/NGCP/Panel/Controller/Subscriber.pm @@ -61,12 +61,24 @@ sub sub_list :Chained('/') :PathPart('subscriber') :CaptureArgs(0) { template => 'subscriber/list.tt', ); + $c->stash->{subscribers_rs} = $c->model('DB')->resultset('voip_subscribers')->search({ + 'me.status' => { '!=' => 'terminated' }, + }); + unless($c->user->is_superuser) { + $c->stash->{subscribers_rs} = $c->stash->{subscribers_rs}->search({ + 'contact.reseller_id' => $c->user->reseller_id, + },{ + join => { 'contract' => 'contact'}, + }); + } + $c->stash->{dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ { name => "id", search => 1, title => "#" }, + { name => "contract_id", search => 1, title => "Contract #"}, + { name => "contract.contact.email", search => 1, title => "Contact Email" }, { name => "username", search => 1, title => "Username" }, { name => "domain.domain", search => 1, title => "Domain" }, { name => "status", search => 1, title => "Status" }, - { name => "contract_id", search => 1, title => "Contract #"}, ]); } @@ -105,20 +117,20 @@ sub create_list :Chained('sub_list') :PathPart('create') :Args(0) { UUID::generate($uuid_bin); UUID::unparse($uuid_bin, $uuid_string); - # TODO: check if we find a reseller and contract and domains - my $reseller = $schema->resultset('resellers') - ->find($c->request->params->{'reseller.id'}); my $contract = $schema->resultset('contracts') - ->find($c->request->params->{'contract.id'}); + ->find($form->params->{contract}{id}); my $billing_domain = $schema->resultset('domains') - ->find($c->request->params->{'domain.id'}); + ->find($form->params->{domain}{id}); my $prov_domain = $schema->resultset('voip_domains') ->find({domain => $billing_domain->domain}); + my $reseller = $contract->contact->reseller; + my $number; if(defined $c->request->params->{'e164.cc'} && $c->request->params->{'e164.cc'} ne '') { + $number = $reseller->voip_numbers->create({ cc => $c->request->params->{'e164.cc'}, ac => $c->request->params->{'e164.ac'} || '', @@ -224,16 +236,14 @@ sub base :Chained('/subscriber/sub_list') :PathPart('') :CaptureArgs(1) { my ($self, $c, $subscriber_id) = @_; unless($subscriber_id && $subscriber_id->is_integer) { - $c->flash(messages => [{type => 'error', text => 'Invalid subscriber id detected!'}]); - $c->response->redirect($c->uri_for()); - return; + $c->flash(messages => [{type => 'error', text => 'Invalid subscriber id detected'}]); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriber')); } - my $res = $c->model('DB')->resultset('voip_subscribers')->find({ id => $subscriber_id }); + my $res = $c->stash->{subscribers_rs}->find({ id => $subscriber_id }); unless(defined $res) { - $c->flash(messages => [{type => 'error', text => 'Subscriber does not exist!'}]); - $c->response->redirect($c->uri_for('/subscriber')); - $c->detach; + $c->flash(messages => [{type => 'error', text => 'Subscriber does not exist'}]); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriber')); } $c->stash(subscriber => $res); @@ -247,26 +257,12 @@ sub base :Chained('/subscriber/sub_list') :PathPart('') :CaptureArgs(1) { sub ajax :Chained('sub_list') :PathPart('ajax') :Args(0) { my ($self, $c) = @_; - my $dispatch_to = '_ajax_resultset_' . $c->user->auth_realm; - my $resultset = $self->$dispatch_to($c); + my $resultset = $c->stash->{subscribers_rs}; NGCP::Panel::Utils::Datatables::process($c, $resultset, $c->stash->{dt_columns}); - $c->detach( $c->view("JSON") ); } -sub _ajax_resultset_admin { - my ($self, $c) = @_; - return $c->model('DB')->resultset('voip_subscribers')->search; -} - -sub _ajax_resultset_reseller { - my ($self, $c) = @_; - - # TODO: filter for reseller - return $c->model('DB')->resultset('voip_subscribers'); -} - sub terminate :Chained('base') :PathPart('terminate') :Args(0) { my ($self, $c) = @_; diff --git a/lib/NGCP/Panel/Field/CustomerContract.pm b/lib/NGCP/Panel/Field/CustomerContract.pm index 0feecf2d11..3a7f23e33e 100644 --- a/lib/NGCP/Panel/Field/CustomerContract.pm +++ b/lib/NGCP/Panel/Field/CustomerContract.pm @@ -10,8 +10,8 @@ has_field 'id' => ( required => 1, template => 'share/templates/helpers/datatables_field.tt', ajax_src => '/contract/customer/ajax', - table_titles => ['#', 'Contact Email', 'External #', 'Status'], - table_fields => ['id', 'contact_email', 'external_id', 'status'], + table_titles => ['#', 'Reseller', 'Contact Email', 'External #', 'Status'], + table_fields => ['id', 'contact_reseller_name', 'contact_email', 'external_id', 'status'], ); has_field 'create' => ( diff --git a/lib/NGCP/Panel/Form/Subscriber.pm b/lib/NGCP/Panel/Form/Subscriber.pm index 6174a01fce..b2f1933b8c 100644 --- a/lib/NGCP/Panel/Form/Subscriber.pm +++ b/lib/NGCP/Panel/Form/Subscriber.pm @@ -15,12 +15,6 @@ has_field 'submitid' => ( type => 'Hidden' ); sub build_render_list {[qw/submitid fields actions/]} sub build_form_element_class {[qw(form-horizontal)]} -has_field 'reseller' => ( - type => '+NGCP::Panel::Field::Reseller', - label => 'Reseller', - not_nullable => 1, -); - has_field 'contract' => ( type => '+NGCP::Panel::Field::CustomerContract', label => 'Customer', @@ -157,7 +151,7 @@ has_field 'save' => ( has_block 'fields' => ( tag => 'div', class => [qw/modal-body/], - render_list => [qw/reseller contract webusername webpassword e164 username domain password status external_id administrative/ ], + render_list => [qw/contract webusername webpassword e164 username domain password status external_id administrative/ ], ); has_block 'actions' => ( diff --git a/share/templates/customer/details.tt b/share/templates/customer/details.tt index d3f513e166..ff8670855c 100644 --- a/share/templates/customer/details.tt +++ b/share/templates/customer/details.tt @@ -26,169 +26,247 @@
-

Billing Profiles

+
- - - - - - - - - [% FOR mapping IN contract.billing_mappings.all -%] - [% bprof = mapping.billing_profile -%] - - - - - [% END -%] - -
DateBilling Profile Name
- [% bprof.start_date ? bprof.start_date : 'NULL' %] - [% bprof.end_date ? bprof.end_date : 'NULL' %] - [% bprof.name %]
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameValue
Email[% contact_hash.email%]
Name[% contact_hash.firstname %] [% contact_hash.lastname %]
Company[% contact_hash.company%]
Address + [% contact_hash.street %]
+ [% contact_hash.postcode %] [% contact_hash.city %]
+ [% contact_hash.country %] +
Phone/Fax + Mobile: [% contact_hash.mobilenumber %]
+ Fixed: [% contact_hash.phonenumber %]
+ Fax: [% contact_hash.faxnumber %]
+
+
+
+
-

Subscribers

+
+ +
+
+ + + + + + + + + [% FOR mapping IN contract.billing_mappings.all -%] + [% bprof = mapping.billing_profile -%] + + + + + [% END -%] + +
DateBilling Profile Name
+ [% bprof.start_date ? bprof.start_date : 'NULL' %] - [% bprof.end_date ? bprof.end_date : 'NULL' %] + [% bprof.name %]
+
+
+
- Create Subscriber -
- - - - - - - - - - - [% FOR subscriber IN subscribers -%] - - - - - - - [% END -%] - -
SIP URIPrimary NumberRegistered Devices
[% subscriber.username %]@[% subscriber.domain %][% subscriber.primary_number.cc %] [% subscriber.primary_number.ac %] [% subscriber.primary_number.sn %] - [% FOR location IN subscriber.locations -%] - [% location.user_agent %]
- [% END -%] -
- -
- -

Contract Balance

+
+ +
+
+ Create Subscriber +
+ + + + + + + + + + + [% FOR subscriber IN subscribers -%] + + + + + + + [% END -%] + +
SIP URIPrimary NumberRegistered Devices
[% subscriber.username %]@[% subscriber.domain %][% subscriber.primary_number.cc %] [% subscriber.primary_number.ac %] [% subscriber.primary_number.sn %] + [% FOR location IN subscriber.locations -%] + [% location.user_agent %]
+ [% END -%] +
+ +
+
+
+
- - - - - - - - - - - - - - - - - - - - - - - -
CashFree time
Current totals[% balance.cash_balance %][% balance.free_time_balance %] - -
Spent this interval[% balance.cash_balance_interval %][% balance.free_time_balance_interval %]
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
CashFree time
Current totals[% balance.cash_balance %][% balance.free_time_balance %] + +
Spent this interval[% balance.cash_balance_interval %][% balance.free_time_balance_interval %]
+
+
+
-

Fraud Limits

+
+ +
+
+ + + + + + + + + + + + + + [% fraud_def_message = (fraud.fraud_interval_limit.defined ? "none" : "billing profile default") %] + + + + + + + + [% fraud_def_message = (fraud.fraud_daily_limit.defined ? "none" : "billing profile default") %] + + + + + + +
LimitLock LevelNotify
Monthly Settings[% fraud.fraud_interval_limit.defined ? fraud.fraud_interval_limit : fraud_def_message %] + [% IF fraud.fraud_interval_lock.defined -%] + + [% ELSE -%] + [% fraud_def_message %] + [% END -%] + [% fraud.fraud_interval_notify.defined ? fraud.fraud_interval_notify : fraud_def_message %] + +
Daily Settings[% fraud.fraud_daily_limit.defined ? fraud.fraud_daily_limit : fraud_def_message %] + [% IF fraud.fraud_daily_lock.defined -%] + + [% ELSE -%] + [% fraud_def_message %] + [% END -%] + [% fraud.fraud_daily_notify.defined ? fraud.fraud_daily_notify : fraud_def_message %] + +
+
+
+
+
- - - - - - - - - - - - - - [% fraud_def_message = (fraud.fraud_interval_limit.defined ? "none" : "billing profile default") %] - - - - - - - - [% fraud_def_message = (fraud.fraud_daily_limit.defined ? "none" : "billing profile default") %] - - - - - - -
LimitLock LevelNotify
Monthly Settings[% fraud.fraud_interval_limit.defined ? fraud.fraud_interval_limit : fraud_def_message %] - [% IF fraud.fraud_interval_lock.defined -%] - - [% ELSE -%] - [% fraud_def_message %] - [% END -%] - [% fraud.fraud_interval_notify.defined ? fraud.fraud_interval_notify : fraud_def_message %] - -
Daily Settings[% fraud.fraud_daily_limit.defined ? fraud.fraud_daily_limit : fraud_def_message %] - [% IF fraud.fraud_daily_lock.defined -%] - - [% ELSE -%] - [% fraud_def_message %] - [% END -%] - [% fraud.fraud_daily_notify.defined ? fraud.fraud_daily_notify : fraud_def_message %] - -
[% IF create_flag == 1 -%] [% PROCESS "helpers/modal.tt"; diff --git a/share/templates/subscriber/list.tt b/share/templates/subscriber/list.tt index 1d2a4b3e01..7922ba3b9e 100644 --- a/share/templates/subscriber/list.tt +++ b/share/templates/subscriber/list.tt @@ -14,7 +14,7 @@ UNLESS c.user.read_only; helper.dt_buttons = [ - { name = 'Terminate', uri = "/subscriber/'+full.id+'/terminate", class = 'btn-small btn-secondary', icon = 'icon-trash', condition = 'full.status != "terminated"' }, + { name = 'Terminate', uri = "/subscriber/'+full.id+'/terminate", class = 'btn-small btn-secondary', icon = 'icon-remove', condition = 'full.status != "terminated"' }, { name = 'Details', uri = "/subscriber/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-th-list', condition = 'full.status != "terminated"' }, { name = 'Customer', uri = "/customer/'+full.contract_id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-user' }, ];