From bee006efcd60689bd428c914b85019533199cd33 Mon Sep 17 00:00:00 2001 From: Andreas Granig Date: Tue, 30 Jul 2013 16:03:52 +0200 Subject: [PATCH] Rework reseller handling. --- lib/NGCP/Panel/Controller/Billing.pm | 32 +++- lib/NGCP/Panel/Controller/Contact.pm | 17 +- lib/NGCP/Panel/Controller/Contract.pm | 105 ++++++------ lib/NGCP/Panel/Controller/Customer.pm | 9 ++ lib/NGCP/Panel/Controller/Dashboard.pm | 1 - lib/NGCP/Panel/Controller/Peering.pm | 48 +++--- lib/NGCP/Panel/Controller/Reseller.pm | 149 ++++++++++-------- lib/NGCP/Panel/Controller/Root.pm | 3 + lib/NGCP/Panel/Field/Contact.pm | 4 +- lib/NGCP/Panel/Field/ResellerContract.pm | 4 +- .../Admin.pm} | 4 +- .../Reseller.pm} | 2 +- share/templates/customer/list.tt | 27 ++-- share/templates/reseller/details.tt | 74 +++++---- 14 files changed, 276 insertions(+), 203 deletions(-) rename lib/NGCP/Panel/Form/{BillingProfile_admin.pm => BillingProfile/Admin.pm} (83%) rename lib/NGCP/Panel/Form/{BillingProfile_reseller.pm => BillingProfile/Reseller.pm} (98%) diff --git a/lib/NGCP/Panel/Controller/Billing.pm b/lib/NGCP/Panel/Controller/Billing.pm index c8bce3163c..6e0caa86ee 100644 --- a/lib/NGCP/Panel/Controller/Billing.pm +++ b/lib/NGCP/Panel/Controller/Billing.pm @@ -7,8 +7,8 @@ use DateTime::Format::ISO8601; BEGIN { extends 'Catalyst::Controller'; } -use NGCP::Panel::Form::BillingProfile_admin; -use NGCP::Panel::Form::BillingProfile_reseller; +use NGCP::Panel::Form::BillingProfile::Admin; +use NGCP::Panel::Form::BillingProfile::Reseller; use NGCP::Panel::Form::BillingFee; use NGCP::Panel::Form::BillingZone; use NGCP::Panel::Form::BillingPeaktimeWeekdays; @@ -111,15 +111,22 @@ sub edit :Chained('base') :PathPart('edit') { } sub create :Chained('profile_list') :PathPart('create') :Args(0) { - my ($self, $c) = @_; + my ($self, $c, $no_reseller) = @_; - my $posted = ($c->request->method eq 'POST'), - my $dispatch_to = 'NGCP::Panel::Form::BillingProfile_' . $c->user->auth_realm; - my $form = $dispatch_to->new; + my $posted = ($c->request->method eq 'POST'); + my $form; + my $params = {}; + if($c->user->is_superuser && $no_reseller) { + $form = NGCP::Panel::Form::BillingProfile::Reseller->new; + } elsif($c->user->is_superuser) { + $form = NGCP::Panel::Form::BillingProfile::Admin->new; + } else { + $form = NGCP::Panel::Form::BillingProfile::Reseller->new; + } $form->process( posted => $posted, params => $c->request->params, - action => $c->uri_for('create'), + item => $params, ); NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, @@ -129,7 +136,9 @@ sub create :Chained('profile_list') :PathPart('create') :Args(0) { ); if($posted && $form->validated) { try { - if($c->user->is_superuser) { + if($c->user->is_superuser && $no_reseller) { + $form->values->{reseller_id} = $c->user->reseller_id; + } elsif($c->user->is_superuser) { $form->values->{reseller_id} = $form->values->{reseller}{id}; } else { $form->values->{reseller_id} = $c->user->reseller_id; @@ -152,6 +161,13 @@ sub create :Chained('profile_list') :PathPart('create') :Args(0) { $c->stash(form => $form); } +sub create_without_reseller :Chained('profile_list') :PathPart('create/noreseller') :Args(0) { + my ($self, $c) = @_; + + $self->create($c, 1); +} + + sub fees_list :Chained('base') :PathPart('fees') :CaptureArgs(0) { my ($self, $c) = @_; diff --git a/lib/NGCP/Panel/Controller/Contact.pm b/lib/NGCP/Panel/Controller/Contact.pm index 6ef68b8f02..f616f69fe3 100644 --- a/lib/NGCP/Panel/Controller/Contact.pm +++ b/lib/NGCP/Panel/Controller/Contact.pm @@ -40,12 +40,16 @@ sub root :Chained('list_contact') :PathPart('') :Args(0) { } sub create :Chained('list_contact') :PathPart('create') :Args(0) { - my ($self, $c) = @_; + my ($self, $c, $no_reseller) = @_; my $posted = ($c->request->method eq 'POST'); my $form; my $params = {}; - if($c->user->is_superuser) { + if($c->user->is_superuser && $no_reseller) { + $form = NGCP::Panel::Form::Contact::Reseller->new; + $params->{reseller}{id} = $c->user->reseller_id; + # we'll delete this after validation, as we don't need the reseller in this case + } elsif($c->user->is_superuser) { $form = NGCP::Panel::Form::Contact::Admin->new; } else { $form = NGCP::Panel::Form::Contact::Reseller->new; @@ -63,6 +67,9 @@ sub create :Chained('list_contact') :PathPart('create') :Args(0) { ); if($posted && $form->validated) { try { + if($c->user->is_superuser && $no_reseller) { + delete $form->values->{reseller}; + } my $contact = $c->stash->{contacts}->create($form->values); $c->session->{created_objects}->{contact} = { id => $contact->id }; $c->flash(messages => [{type => 'success', text => 'Contact successfully created'}]); @@ -78,6 +85,12 @@ sub create :Chained('list_contact') :PathPart('create') :Args(0) { $c->stash(form => $form); } +sub create_without_reseller :Chained('list_contact') :PathPart('create/noreseller') :Args(0) { + my ($self, $c) = @_; + + $self->create($c, 1); +} + sub base :Chained('list_contact') :PathPart('') :CaptureArgs(1) { my ($self, $c, $contact_id) = @_; diff --git a/lib/NGCP/Panel/Controller/Contract.pm b/lib/NGCP/Panel/Controller/Contract.pm index dce083d2e6..8532201c3b 100644 --- a/lib/NGCP/Panel/Controller/Contract.pm +++ b/lib/NGCP/Panel/Controller/Contract.pm @@ -21,6 +21,7 @@ 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" }, @@ -77,7 +78,7 @@ sub root :Chained('contract_list') :PathPart('') :Args(0) { } sub create :Chained('contract_list') :PathPart('create') :Args(0) { - my ($self, $c) = @_; + my ($self, $c, $no_reseller) = @_; my $posted = ($c->request->method eq 'POST'); my $params = {}; @@ -89,11 +90,16 @@ sub create :Chained('contract_list') :PathPart('create') :Args(0) { params => $c->request->params, item => $params ); + + my $suffix = ''; + if($c->user->is_superuser && $no_reseller) { + $suffix = '/noreseller'; + } NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, - fields => {'contact.create' => $c->uri_for('/contact/create'), - 'billing_profile.create' => $c->uri_for('/billing/create')}, + fields => {'contact.create' => $c->uri_for('/contact/create'.$suffix), + 'billing_profile.create' => $c->uri_for('/billing/create'.$suffix)}, back_uri => $c->req->uri, ); if($posted && $form->validated) { @@ -132,6 +138,11 @@ sub create :Chained('contract_list') :PathPart('create') :Args(0) { $c->stash(form => $form); } +sub create_without_reseller :Chained('contract_list') :PathPart('create/noreseller') :Args(0) { + my ($self, $c) = @_; + $self->create($c, 1); +} + sub base :Chained('contract_list') :PathPart('') :CaptureArgs(1) { my ($self, $c, $contract_id) = @_; @@ -192,7 +203,6 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { my $schema = $c->model('DB'); $schema->txn_do(sub { if($form->values->{billing_profile}{id} != $billing_mapping->billing_profile->id) { - say ">>>>>>>> billing profile changed, update mapping"; $contract->billing_mappings->create({ start_date => DateTime->now(), billing_profile_id => $form->values->{billing_profile}{id}, @@ -287,9 +297,6 @@ sub peering_create :Chained('peering_list') :PathPart('create') :Args(0) { my $posted = ($c->request->method eq 'POST'); my $params = {}; $params = Hash::Merge->new('RIGHT_PRECEDENT')->merge($params, $c->session->{created_objects}); - # TODO: where to store created contact and billing profile? - say ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "; - use Data::Printer; p $params; my $form = NGCP::Panel::Form::Contract->new; $form->process( posted => $posted, @@ -299,8 +306,8 @@ sub peering_create :Chained('peering_list') :PathPart('create') :Args(0) { NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, - fields => {'contact.create' => $c->uri_for('/contact/create'), - 'billing_profile.create' => $c->uri_for('/billing/create')}, + fields => {'contact.create' => $c->uri_for('/contact/create/noreseller'), + 'billing_profile.create' => $c->uri_for('/billing/create/noreseller')}, back_uri => $c->req->uri, ); if($posted && $form->validated) { @@ -358,55 +365,63 @@ sub customer_ajax :Chained('customer_list') :PathPart('ajax') :Args(0) { my $rs = $base_rs->search({ 'product_id' => undef, }, { - 'join' => { - 'billing_mappings' => 'product', - }, + 'join' => {'billing_mappings' => 'product'}, }); - - $c->forward( "/ajax_process_resultset", [$rs, - ["id","contact_id", "external_id", "billing_profile_id", "billing_profile_name","status"], - ["external_id", "billing_profile.name", "status"]]); - + + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{contract_dt_columns}); $c->detach( $c->view("JSON") ); } sub customer_create :Chained('customer_list') :PathPart('create') :Args(0) { my ($self, $c) = @_; - - my $item = $c->model('DB')->resultset('billing_mappings')->new_result({}); - $item->product(undef); + my $posted = ($c->request->method eq 'POST'); + my $params = {}; + $params = Hash::Merge->new('RIGHT_PRECEDENT')->merge($params, $c->session->{created_objects}); my $form = NGCP::Panel::Form::Contract->new; - if($form->process( - posted => ($c->request->method eq 'POST'), + $form->process( + posted => $posted, params => $c->request->params, - item => $item, - )) { - # insert ok, populate contract_balance table - try { - NGCP::Panel::Utils::Contract::create_contract_balance( - c => $c, - profile => $item->billing_profile, - contract => $item->contract, - ); - } catch($e) { - # TODO: roll back contract and billing_mappings creation and - # redirect to correct entry point - $c->log->error($e); - $c->flash(messages => [{type => 'error', text => 'Failed to create contract balance!'}]); - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/customer')); - } - } + item => $params + ); NGCP::Panel::Utils::Navigation::check_form_buttons( - c => $c, form => $form, - fields => {'contract.contact.create' => $c->uri_for('/contact/create'), + c => $c, + form => $form, + fields => {'contact.create' => $c->uri_for('/contact/create'), 'billing_profile.create' => $c->uri_for('/billing/create')}, back_uri => $c->req->uri, ); - if($form->validated) { - $c->flash(messages => [{type => 'success', text => 'Contract successfully created!'}]); - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/customer/details', [$item->contract->id])); - } + if($posted && $form->validated) { + try { + my $schema = $c->model('DB'); + $schema->txn_do(sub { + $form->params->{contact_id} = $form->params->{contact}{id}; + delete $form->params->{contract}; + my $bprof_id = $form->params->{billing_profile}{id}; + delete $form->params->{billing_profile}; + my $contract = $schema->resultset('contracts')->create($form->params); + my $billing_profile = $schema->resultset('billing_profiles')->find($bprof_id); + $contract->billing_mappings->create({ + billing_profile_id => $bprof_id, + }); + + NGCP::Panel::Utils::Contract::create_contract_balance( + c => $c, + profile => $billing_profile, + contract => $contract, + ); + $c->session->{created_objects}->{contract} = { id => $contract->id }; + delete $c->session->{created_objects}->{contact}; + delete $c->session->{created_objects}->{billing_profile}; + $c->flash(messages => [{type => 'success', text => 'Contract successfully created'}]); + }); + } catch($e) { + $c->log->error("Failed to create contract: $e"); + $c->flash(messages => [{type => 'error', text => 'Failed to create contract'}]); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contract/root')); + } + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contract/root')); + } $c->stash(create_flag => 1); $c->stash(form => $form); diff --git a/lib/NGCP/Panel/Controller/Customer.pm b/lib/NGCP/Panel/Controller/Customer.pm index 73909657b7..e2cbc122d4 100644 --- a/lib/NGCP/Panel/Controller/Customer.pm +++ b/lib/NGCP/Panel/Controller/Customer.pm @@ -32,6 +32,15 @@ sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRol sub list_customer :Chained('/') :PathPart('customer') :CaptureArgs(0) { my ($self, $c) = @_; + $c->stash->{contract_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "id", search => 1, title => "#" }, + { name => "external_id", search => 1, title => "External #" }, + { 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" }, + ]); + $c->stash( template => 'customer/list.tt' ); diff --git a/lib/NGCP/Panel/Controller/Dashboard.pm b/lib/NGCP/Panel/Controller/Dashboard.pm index 867ba54bdb..7eb5754af0 100644 --- a/lib/NGCP/Panel/Controller/Dashboard.pm +++ b/lib/NGCP/Panel/Controller/Dashboard.pm @@ -36,7 +36,6 @@ sub index :Path :Args(0) { $c->stash(template => 'dashboard.tt'); delete $c->session->{redirect_targets}; - delete $c->session->{created_objects}; } =head1 AUTHOR diff --git a/lib/NGCP/Panel/Controller/Peering.pm b/lib/NGCP/Panel/Controller/Peering.pm index 73c2372fc3..899b0ccccf 100644 --- a/lib/NGCP/Panel/Controller/Peering.pm +++ b/lib/NGCP/Panel/Controller/Peering.pm @@ -81,7 +81,7 @@ sub edit :Chained('base') :PathPart('edit') { ); NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, - fields => {'contract.create' => $c->uri_for('/contract/peering/create')}, + fields => {'contract.create' => $c->uri_for('/contract/peering/create/noreseller')}, back_uri => $c->req->uri, ); if($posted && $form->validated) { @@ -89,9 +89,9 @@ sub edit :Chained('base') :PathPart('edit') { $c->stash->{group_result}->update($form->custom_get_values); $self->_sip_lcr_reload; delete $c->session->{created_objects}->{contract}; - $c->flash(messages => [{type => 'success', text => 'Peering Group successfully changed!'}]); + $c->flash(messages => [{type => 'success', text => 'Peering group successfully updated'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(messages => [{type => 'error', text => 'Update of peering group failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to update peering group'}]); $c->log->info("Update failed: " . $e); }; $c->response->redirect($c->uri_for()); @@ -108,9 +108,9 @@ sub delete :Chained('base') :PathPart('delete') { try { $c->stash->{group_result}->delete; $self->_sip_lcr_reload; - $c->flash(messages => [{type => 'success', text => 'Peering Group successfully deleted!'}]); + $c->flash(messages => [{type => 'success', text => 'Peering Group successfully deleted'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(messages => [{type => 'error', text => 'Delete failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to delete peering group'}]); $c->log->info("Delete failed: " . $e); }; $c->response->redirect($c->uri_for()); @@ -123,8 +123,6 @@ sub create :Chained('group_list') :PathPart('create') :Args(0) { my $form = NGCP::Panel::Form::PeeringGroup->new; my $params = {}; $params = Hash::Merge->new('RIGHT_PRECEDENT')->merge($params, $c->session->{created_objects}); - say ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> got new contract:"; - use Data::Printer; p $params; $form->process( posted => $posted, params => $c->request->params, @@ -142,9 +140,9 @@ sub create :Chained('group_list') :PathPart('create') :Args(0) { $formdata ); $self->_sip_lcr_reload; delete $c->session->{created_objects}->{contract}; - $c->flash(messages => [{type => 'success', text => 'Peering group successfully created!'}]); + $c->flash(messages => [{type => 'success', text => 'Peering group successfully created'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(rules_messages => [{type => 'error', text => 'Creation of peering group failed.'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Failed to create peering group'}]); $c->log->info("Create failed: " . $e); }; $c->response->redirect($c->uri_for_action('/peering/root')); @@ -194,9 +192,9 @@ sub servers_create :Chained('servers_list') :PathPart('create') :Args(0) { try { $c->stash->{group_result}->voip_peer_hosts->create( $form->fif ); $self->_sip_lcr_reload; - $c->flash(messages => [{type => 'success', text => 'Peering server successfully created!'}]); + $c->flash(messages => [{type => 'success', text => 'Peering server successfully created'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(messages => [{type => 'error', text => 'Creation of Peering server failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to create peering server'}]); $c->log->info("Create failed: " . $e); }; $c->response->redirect($c->stash->{sr_list_uri}); @@ -212,7 +210,7 @@ sub servers_base :Chained('servers_list') :PathPart('') :CaptureArgs(1) { my ($self, $c, $server_id) = @_; unless($server_id && $server_id->is_integer) { - $c->flash(messages => [{type => 'error', text => 'Invalid peering sever (host) id detected!'}]); + $c->flash(messages => [{type => 'error', text => 'Invalid peering server id'}]); $c->response->redirect($c->stash->{sr_list_uri}); $c->detach; return; @@ -220,7 +218,7 @@ sub servers_base :Chained('servers_list') :PathPart('') :CaptureArgs(1) { my $res = $c->stash->{group_result}->voip_peer_hosts->find($server_id); unless(defined($res)) { - $c->flash(messages => [{type => 'error', text => 'Peering Server does not exist!'}]); + $c->flash(messages => [{type => 'error', text => 'Peering server does not exist'}]); $c->response->redirect($c->stash->{sr_list_uri}); $c->detach; return; @@ -243,9 +241,9 @@ sub servers_edit :Chained('servers_base') :PathPart('edit') :Args(0) { try { $c->stash->{server_result}->update($form->fif); $self->_sip_lcr_reload; - $c->flash(messages => [{type => 'success', text => 'Peering Server successfully changed!'}]); + $c->flash(messages => [{type => 'success', text => 'Peering server successfully updated'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(messages => [{type => 'error', text => 'Updating of Peering server failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to update peering server'}]); $c->log->info("Update failed: " . $e); }; @@ -264,9 +262,9 @@ sub servers_delete :Chained('servers_base') :PathPart('delete') :Args(0) { try { $c->stash->{server_result}->delete; $self->_sip_lcr_reload; - $c->flash(messages => [{type => 'success', text => 'Peering Server successfully deleted!'}]); + $c->flash(messages => [{type => 'success', text => 'Peering server successfully deleted'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(rules_messages => [{type => 'error', text => 'Delete failed.'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Failed to delete peering server'}]); $c->log->info("Delete failed: " . $e); }; $c->response->redirect($c->stash->{sr_list_uri}); @@ -386,9 +384,9 @@ sub rules_create :Chained('rules_list') :PathPart('create') :Args(0) { try { $c->stash->{group_result}->voip_peer_rules->create( $form->fif ); $self->_sip_lcr_reload; - $c->flash(rules_messages => [{type => 'success', text => 'Peering rule successfully created!'}]); + $c->flash(rules_messages => [{type => 'success', text => 'Peering rule successfully created'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(rules_messages => [{type => 'error', text => 'Create failed.'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Failed to create peering rule'}]); $c->log->info("Create failed: " . $e); }; $c->response->redirect($c->stash->{sr_list_uri}); @@ -404,7 +402,7 @@ sub rules_base :Chained('rules_list') :PathPart('') :CaptureArgs(1) { my ($self, $c, $rule_id) = @_; unless($rule_id && $rule_id->is_integer) { - $c->flash(rules_messages => [{type => 'error', text => 'Invalid peering rule id detected!'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Invalid peering rule id detected'}]); $c->response->redirect($c->stash->{sr_list_uri}); $c->detach; return; @@ -412,7 +410,7 @@ sub rules_base :Chained('rules_list') :PathPart('') :CaptureArgs(1) { my $res = $c->stash->{group_result}->voip_peer_rules->find($rule_id); unless(defined($res)) { - $c->flash(rules_messages => [{type => 'error', text => 'Peering Rule does not exist!'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Peering Rule does not exist'}]); $c->response->redirect($c->stash->{sr_list_uri}); $c->detach; return; @@ -435,9 +433,9 @@ sub rules_edit :Chained('rules_base') :PathPart('edit') :Args(0) { try { $c->stash->{rule_result}->update($form->fif); $self->_sip_lcr_reload; - $c->flash(rules_messages => [{type => 'success', text => 'Peering Rule successfully changed!'}]); + $c->flash(rules_messages => [{type => 'success', text => 'Peering rule successfully changed'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(rules_messages => [{type => 'error', text => 'Edit failed.'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Failed to update peering rule'}]); $c->log->info("Update failed: " . $e); }; $c->response->redirect($c->stash->{sr_list_uri}); @@ -455,9 +453,9 @@ sub rules_delete :Chained('rules_base') :PathPart('delete') :Args(0) { try { $c->stash->{rule_result}->delete; $self->_sip_lcr_reload; - $c->flash(rules_messages => [{type => 'success', text => 'Peering Rule successfully deleted!'}]); + $c->flash(rules_messages => [{type => 'success', text => 'Peering rule successfully deleted'}]); } catch (DBIx::Class::Exception $e) { - $c->flash(rules_messages => [{type => 'error', text => 'Delete failed.'}]); + $c->flash(rules_messages => [{type => 'error', text => 'Failed to delete peering rule'}]); $c->log->info("Delete failed: " . $e); }; $c->response->redirect($c->stash->{sr_list_uri}); diff --git a/lib/NGCP/Panel/Controller/Reseller.pm b/lib/NGCP/Panel/Controller/Reseller.pm index 90345a8298..883cde0136 100644 --- a/lib/NGCP/Panel/Controller/Reseller.pm +++ b/lib/NGCP/Panel/Controller/Reseller.pm @@ -30,6 +30,15 @@ sub list_reseller :Chained('/') :PathPart('reseller') :CaptureArgs(0) { { name => "name", search => 1, title => "Name" }, { name => "status", search => 1, title => "Status" }, ]); + + # we need this in ajax_contracts also + $c->stash->{contract_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "id", search => 1, title => "#" }, + { name => "external_id", search => 1, title => "External #" }, + { 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" }, + ]); } sub root :Chained('list_reseller') :PathPart('') :Args(0) { @@ -63,7 +72,7 @@ sub create :Chained('list_reseller') :PathPart('create') :Args(0) { NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, - fields => [qw/contract.create/], + fields => {'contract.create' => $c->uri_for('/contract/create/noreseller') }, back_uri => $c->req->uri, ); @@ -71,13 +80,13 @@ sub create :Chained('list_reseller') :PathPart('create') :Args(0) { try { $form->params->{contract_id} = delete $form->params->{contract}->{id}; delete $form->params->{contract}; - $c->model('DB')->resultset('resellers')->create($form->params); + my $reseller = $c->model('DB')->resultset('resellers')->create($form->params); delete $c->session->{created_objects}->{contract}; - $c->flash(messages => [{type => 'success', text => 'Reseller successfully created.'}]); + $c->flash(messages => [{type => 'success', text => 'Reseller successfully created'}]); } catch($e) { $c->log->error($e); - $c->flash(messages => [{type => 'error', text => 'Creating reseller failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to create reseller'}]); } $c->response->redirect($c->uri_for()); return; @@ -91,40 +100,56 @@ sub create :Chained('list_reseller') :PathPart('create') :Args(0) { sub base :Chained('list_reseller') :PathPart('') :CaptureArgs(1) { my ($self, $c, $reseller_id) = @_; - $c->detach('/denied_page') - if($c->user->read_only); - unless($reseller_id && $reseller_id =~ /^\d+$/) { - $c->flash(messages => [{type => 'error', text => 'Invalid reseller id detected.'}]); + $c->flash(messages => [{type => 'error', text => 'Invalid reseller id detected'}]); $c->response->redirect($c->uri_for()); return; } + $c->stash->{contact_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "id", search => 1, title => "#" }, + { name => "firstname", search => 1, title => "First Name" }, + { name => "lastname", search => 1, title => "Last Name" }, + { name => "company", search => 1, title => "Company" }, + { name => "email", search => 1, title => "Email" }, + ]); + $c->stash->{reseller_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "id", search => 1, title => "#" }, + { name => "name", search => 1, title => "Name" }, + { name => "status", search => 1, title => "Status" }, + ]); + $c->stash->{admin_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "id", search => 1, title => "#" }, + { name => "login", search => 1, title => "Name" }, + { name => "is_master", title => "Master" }, + { name => "is_active", title => "Active" }, + { name => "read_only", title => "Read-Only" }, + { name => "show_passwords", title => "Show Passwords" }, + { name => "call_data", title => "Show CDRs" }, + ]); + $c->stash->{customer_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "id", search => 1, title => "#" }, + { name => "external_id", search => 1, title => "External #" }, + { name => "contact.email", search => 1, title => "Contact Email" }, + { name => "status", search => 1, title => "Status" }, + ]); $c->stash(reseller => $c->stash->{resellers}->search_rs({ id => $reseller_id })); } sub reseller_contacts :Chained('base') :PathPart('contacts') :Args(0) { my ($self, $c) = @_; - $c->forward( - '/ajax_process_resultset', [ - $c->stash->{reseller}->first->contract->search_related_rs('contact'), - [qw(id firstname lastname email create_timestamp)], - [ "firstname", "lastname", "email" ] - ] - ); + use Data::Printer; + p $c->stash->{contact_dt_columns}; + my $rs = $c->stash->{reseller}->first->contract->search_related_rs('contact'); + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{contact_dt_columns}); $c->detach($c->view('JSON')); return; } sub reseller_contracts :Chained('base') :PathPart('contracts') :Args(0) { my ($self, $c) = @_; - $c->forward( - '/ajax_process_resultset', [ - $c->stash->{reseller}->first->search_related_rs('contract'), - [qw(id contact_id)], - [ "contact_id" ] - ] - ); + my $rs = $c->stash->{reseller}->first->search_related_rs('contract'); + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{contract_dt_columns}); $c->detach($c->view('JSON')); return; } @@ -132,42 +157,28 @@ sub reseller_contracts :Chained('base') :PathPart('contracts') :Args(0) { sub reseller_single :Chained('base') :PathPart('single') :Args(0) { my ($self, $c) = @_; - $c->forward( - '/ajax_process_resultset', [ - $c->stash->{reseller}, - [qw(id contract_id name status)], - [ "contract_id", "name", "status" ] - ] - ); + NGCP::Panel::Utils::Datatables::process($c, $c->stash->{reseller}, $c->stash->{reseller_dt_columns}); $c->detach($c->view('JSON')); return; } sub reseller_admin :Chained('base') :PathPart('admins') :Args(0) { my ($self, $c) = @_; - $c->forward( - '/ajax_process_resultset', [ - $c->stash->{reseller}->first->search_related_rs('admins'), - [qw(id reseller_id login)], - [ "reseller_id", "login" ] - ] - ); + my $rs = $c->stash->{reseller}->first->search_related_rs('admins'); + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{admin_dt_columns}); $c->detach($c->view('JSON')); return; } -sub reseller_customers :Chained('base') :PathPart('customers') :Args(0) -{ +sub reseller_customers :Chained('base') :PathPart('customers') :Args(0) { my ($self, $c) = @_; - $c->forward( - '/ajax_process_resultset', [ - $c->stash->{reseller}->first->search_related_rs('contracts'), - # TODO: also external_id (same in Customer list) - [qw(id contact_id status)], - [ "contact_id", "status" ] - ] - ); + my $rs = $c->model('DB')->resultset('contracts')->search({ + 'contact.reseller_id' => $c->stash->{reseller}->first->id + }, { + join => 'contact' + }); + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{customer_dt_columns}); $c->detach($c->view('JSON')); return; } @@ -175,8 +186,15 @@ sub reseller_customers :Chained('base') :PathPart('customers') :Args(0) sub edit :Chained('base') :PathPart('edit') :Args(0) { my ($self, $c) = @_; + $c->detach('/denied_page') + if($c->user->read_only); + my $posted = $c->request->method eq 'POST'; my $form = NGCP::Panel::Form::Reseller->new; + + # we need this in the ajax call to not filter it as used contract + $c->session->{edit_contract_id} = $c->stash->{reseller}->first->contract_id; + my $params = { $c->stash->{reseller}->first->get_inflated_columns }; $params->{contract}{id} = delete $params->{contract_id}; $params = Hash::Merge->new('RIGHT_PRECEDENT')->merge($params, $c->session->{created_objects}); @@ -196,10 +214,11 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { delete $form->params->{contract}; $c->stash->{reseller}->first->update($form->params); delete $c->session->{created_objects}->{contract}; - $c->flash(messages => [{type => 'success', text => 'Reseller successfully changed.'}]); + delete $c->session->{edit_contract_id}; + $c->flash(messages => [{type => 'success', text => 'Reseller successfully updated'}]); } catch($e) { $c->log->error($e); - $c->flash(messages => [{type => 'error', text => 'Updating reseller failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to update reseller'}]); } $c->response->redirect($c->uri_for()); } @@ -208,20 +227,21 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { $c->stash(form => $form); $c->stash(edit_flag => 1); - $c->session(contract_id => $c->stash->{reseller}->first->get_column('contract_id')); - return; } sub delete :Chained('base') :PathPart('delete') :Args(0) { my ($self, $c) = @_; + $c->detach('/denied_page') + if($c->user->read_only); + try { $c->stash->{reseller}->first->delete; - $c->flash(messages => [{type => 'success', text => 'Reseller successfully deleted.'}]); + $c->flash(messages => [{type => 'success', text => 'Reseller successfully deleted'}]); } catch($e) { $c->log->error($e); - $c->flash(messages => [{type => 'error', text => 'Deleting reseller failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to delete reseller'}]); } $c->response->redirect($c->uri_for()); } @@ -234,27 +254,18 @@ sub details :Chained('base') :PathPart('details') :Args(0) { sub ajax_contract :Chained('list_reseller') :PathPart('ajax_contract') :Args(0) { my ($self, $c) = @_; - - my $contract_id = $c->session->{contract_id}; - + + my $edit_contract_id = $c->session->{edit_contract_id}; my @used_contracts = map { - $_->get_column('contract_id') unless( - $contract_id && - $contract_id == $_->get_column('contract_id') - ) + $_->get_column('contract_id') + unless($edit_contract_id && $edit_contract_id == $_->get_column('contract_id')) } $c->stash->{resellers}->all; my $free_contracts = $c->model('DB') ->resultset('contracts') ->search_rs({ - id => { 'not in' => \@used_contracts } + 'me.id' => { 'not in' => \@used_contracts } }); - - $c->forward("/ajax_process_resultset", [ - $free_contracts, - ["id", "contact_id", "external_id", "status"], - ["contact_id", "external_id", "status"] - ]); - + NGCP::Panel::Utils::Datatables::process($c, $free_contracts, $c->stash->{contract_dt_columns}); $c->detach( $c->view("JSON") ); } @@ -323,9 +334,9 @@ sub create_defaults :Path('create_defaults') :Args(0) { }); } catch($e) { $c->log->error($e); - $c->flash(messages => [{type => 'error', text => 'Creating reseller failed.'}]); + $c->flash(messages => [{type => 'error', text => 'Failed to create reseller'}]); }; - $c->flash(messages => [{type => 'success', text => "Reseller successfully created with login ".$defaults{admins}->{login}." and password ".$defaults{admins}->{md5pass}.", please review your settings below!" }]); + $c->flash(messages => [{type => 'success', text => "Reseller successfully created with login ".$defaults{admins}->{login}." and password ".$defaults{admins}->{md5pass}.", please review your settings below" }]); $c->res->redirect(sprintf('/reseller/%d/details', $r{resellers}->id), HTTP_SEE_OTHER); $c->detach; return; diff --git a/lib/NGCP/Panel/Controller/Root.pm b/lib/NGCP/Panel/Controller/Root.pm index a048a025e9..aba7793e17 100644 --- a/lib/NGCP/Panel/Controller/Root.pm +++ b/lib/NGCP/Panel/Controller/Root.pm @@ -61,6 +61,9 @@ sub auto :Private { } $c->stash(topmenu => $topmenu_templates); + + $c->session->{created_objects} = {} unless(defined $c->session->{created_objects}); + return 1; } diff --git a/lib/NGCP/Panel/Field/Contact.pm b/lib/NGCP/Panel/Field/Contact.pm index 981ed7da12..3c89412ad6 100644 --- a/lib/NGCP/Panel/Field/Contact.pm +++ b/lib/NGCP/Panel/Field/Contact.pm @@ -10,8 +10,8 @@ has_field 'id' => ( required => 1, template => 'share/templates/helpers/datatables_field.tt', ajax_src => '/contact/ajax', - table_titles => ['#', 'First Name', 'Last Name', 'Email'], - table_fields => ['id', 'firstname', 'lastname', 'email'], + table_titles => ['#', 'Reseller', 'First Name', 'Last Name', 'Email'], + table_fields => ['id', 'reseller_name', 'firstname', 'lastname', 'email'], ); has_field 'create' => ( diff --git a/lib/NGCP/Panel/Field/ResellerContract.pm b/lib/NGCP/Panel/Field/ResellerContract.pm index 91ac281fba..2e05bc84c6 100644 --- a/lib/NGCP/Panel/Field/ResellerContract.pm +++ b/lib/NGCP/Panel/Field/ResellerContract.pm @@ -10,8 +10,8 @@ has_field 'id' => ( required => 1, template => 'share/templates/helpers/datatables_field.tt', ajax_src => '/reseller/ajax_contract', - table_titles => ['#', 'Contact #', 'External #', 'Status'], - table_fields => ['id', 'contact_id', 'external_id', 'status'], + table_titles => ['#', 'Contact Email', 'External #', 'Status'], + table_fields => ['id', 'contact_email', 'external_id', 'status'], ); has_field 'create' => ( diff --git a/lib/NGCP/Panel/Form/BillingProfile_admin.pm b/lib/NGCP/Panel/Form/BillingProfile/Admin.pm similarity index 83% rename from lib/NGCP/Panel/Form/BillingProfile_admin.pm rename to lib/NGCP/Panel/Form/BillingProfile/Admin.pm index 22c7d23b74..0791a924c8 100644 --- a/lib/NGCP/Panel/Form/BillingProfile_admin.pm +++ b/lib/NGCP/Panel/Form/BillingProfile/Admin.pm @@ -1,7 +1,7 @@ -package NGCP::Panel::Form::BillingProfile_admin; +package NGCP::Panel::Form::BillingProfile::Admin; use HTML::FormHandler::Moose; -extends 'NGCP::Panel::Form::BillingProfile_reseller'; +extends 'NGCP::Panel::Form::BillingProfile::Reseller'; has_field 'reseller' => ( type => '+NGCP::Panel::Field::Reseller', diff --git a/lib/NGCP/Panel/Form/BillingProfile_reseller.pm b/lib/NGCP/Panel/Form/BillingProfile/Reseller.pm similarity index 98% rename from lib/NGCP/Panel/Form/BillingProfile_reseller.pm rename to lib/NGCP/Panel/Form/BillingProfile/Reseller.pm index 31b1491064..3e0316632e 100644 --- a/lib/NGCP/Panel/Form/BillingProfile_reseller.pm +++ b/lib/NGCP/Panel/Form/BillingProfile/Reseller.pm @@ -1,4 +1,4 @@ -package NGCP::Panel::Form::BillingProfile_reseller; +package NGCP::Panel::Form::BillingProfile::Reseller; use HTML::FormHandler::Moose; extends 'HTML::FormHandler'; diff --git a/share/templates/customer/list.tt b/share/templates/customer/list.tt index 6fb1c3aed8..2fd1622efd 100644 --- a/share/templates/customer/list.tt +++ b/share/templates/customer/list.tt @@ -3,8 +3,7 @@ helper.name = 'Customers'; helper.data = contracts; helper.messages = messages; - helper.column_titles = [ '#', 'Contact #', 'Billing Profile', 'Status' ]; - helper.column_fields = [ 'id', 'contact_id', 'billing_profile_name', 'status' ]; + helper.dt_columns = contract_dt_columns; helper.close_target = close_target; helper.create_flag = create_flag; @@ -12,15 +11,21 @@ helper.form_object = form; helper.ajax_uri = c.uri_for('/contract/customer/ajax'); - helper.dt_buttons = [ - { name = 'Edit', uri = "/contract/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, - { name = 'Delete', uri = "/contract/'+full[\"id\"]+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, - { name = 'Details', uri = "/customer/'+full[\"id\"]+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' }, - ]; - helper.top_buttons = [ - { name = 'Create Customer', uri = c.uri_for_action('/contract/customer_create'), icon = 'icon-star' }, - ]; + UNLESS c.user.read_only; + helper.dt_buttons = [ + { name = 'Edit', uri = "/contract/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, + { name = 'Delete', uri = "/contract/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, + { name = 'Details', uri = "/customer/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' }, + ]; + helper.top_buttons = [ + { name = 'Create Customer', uri = c.uri_for_action('/contract/customer_create'), icon = 'icon-star' }, + ]; + ELSE; + helper.dt_buttons = [ + { name = 'Details', uri = "/customer/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' }, + ]; + END; PROCESS 'helpers/datatables.tt'; -%] - +[% # vim: set tabstop=4 syntax=html expandtab: -%] diff --git a/share/templates/reseller/details.tt b/share/templates/reseller/details.tt index da3670ba3d..f91add303d 100644 --- a/share/templates/reseller/details.tt +++ b/share/templates/reseller/details.tt @@ -15,48 +15,48 @@
+
-
+
[% - helper.name = 'Contact'; + helper.name = 'Reseller'; helper.messages = messages; - helper.column_titles = [ '#', 'First name', 'Last name', 'Email address', 'created' ]; - helper.column_fields = [ 'id', 'firstname', 'lastname', 'email', 'create_timestamp' ]; + helper.dt_columns = reseller_dt_columns; helper.paginate = 'false'; helper.filter = 'false'; - helper.close_target = c.uri_for(''); + helper.close_target = close_target; helper.create_flag = create_flag; helper.edit_flag = edit_flag; helper.form_object = form; - helper.ajax_uri = c.uri_for_action('/reseller/reseller_contacts', c.req.captures ); - helper.base_uri = c.uri_for_action('/contact/root'); + helper.ajax_uri = c.uri_for_action('/reseller/reseller_single', c.req.captures ); + helper.base_uri = c.uri_for_action('/reseller/root'); PROCESS 'helpers/datatables.tt'; -%]
+
[% helper.name = 'Contract'; helper.messages = messages; - helper.column_titles = [ '#', 'Contact #']; - helper.column_fields = [ 'id', 'contact_id']; - helper.paginate = 'false'; - helper.filter = 'false'; + helper.dt_columns = contract_dt_columns; helper.close_target = close_target; helper.create_flag = create_flag; helper.edit_flag = edit_flag; helper.form_object = form; + helper.paginate = 'false'; + helper.filter = 'false'; helper.ajax_uri = c.uri_for_action('/reseller/reseller_contracts', c.req.captures ); helper.base_uri = c.uri_for_action('/contract/root'); @@ -65,44 +65,42 @@
+
-
+
[% - helper.name = 'Reseller'; + helper.name = 'Contact'; helper.messages = messages; - helper.column_titles = [ '#', 'Contract #', 'Name', 'Status' ]; - helper.column_fields = [ 'id', 'contract_id', 'name', 'status' ]; - helper.paginate = 'false'; - helper.filter = 'false'; - helper.close_target = close_target; + helper.dt_columns = contact_dt_columns; + helper.close_target = c.uri_for(''); helper.create_flag = create_flag; helper.edit_flag = edit_flag; helper.form_object = form; - helper.ajax_uri = c.uri_for_action('/reseller/reseller_single', c.req.captures ); - helper.base_uri = c.uri_for_action('/reseller/root'); + helper.paginate = 'false'; + helper.filter = 'false'; + helper.ajax_uri = c.uri_for_action('/reseller/reseller_contacts', c.req.captures ); + helper.base_uri = c.uri_for_action('/contact/root'); PROCESS 'helpers/datatables.tt'; -%]
+
[% helper.name = 'Administrator'; helper.messages = messages; - helper.column_titles = [ '#', 'Reseller #', 'Login' ]; - helper.column_fields = [ 'id', 'reseller_id', 'login' ]; - helper.paginate = 'false'; - helper.filter = 'false'; + helper.dt_columns = admin_dt_columns; helper.close_target = close_target; helper.create_flag = create_flag; helper.edit_flag = edit_flag; @@ -124,8 +122,7 @@ [% helper.name = 'Customer'; helper.messages = messages; - helper.column_titles = [ '#', 'Contact #', 'Status' ]; - helper.column_fields = [ 'id', 'contact_id', 'status' ]; + helper.dt_columns = customer_dt_columns; helper.paginate = 'true'; helper.filter = 'true'; helper.close_target = close_target; @@ -134,11 +131,17 @@ helper.form_object = form; helper.ajax_uri = c.uri_for_action('/reseller/reseller_customers', c.req.captures ); - helper.dt_buttons = [ - { name = 'Edit', uri = "/contract/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, - { name = 'Delete', uri = "/contract/'+full[\"id\"]+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, - { name = 'Details', uri = "/customer/'+full[\"id\"]+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' }, - ]; + UNLESS c.user.read_only; + helper.dt_buttons = [ + { name = 'Edit', uri = "/contract/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, + { name = 'Delete', uri = "/contract/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, + { name = 'Details', uri = "/customer/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' }, + ]; + ELSE; + helper.dt_buttons = [ + { name = 'Details', uri = "/customer/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' }, + ]; + END; PROCESS 'helpers/datatables.tt'; -%] @@ -146,3 +149,4 @@
+[% # vim: set tabstop=4 syntax=html expandtab: -%]