diff --git a/lib/NGCP/Panel/Controller/Customer.pm b/lib/NGCP/Panel/Controller/Customer.pm new file mode 100644 index 0000000000..b617bf5e8f --- /dev/null +++ b/lib/NGCP/Panel/Controller/Customer.pm @@ -0,0 +1,204 @@ +package NGCP::Panel::Controller::Customer; +use Sipwise::Base; +use namespace::sweep; +BEGIN { extends 'Catalyst::Controller'; } +use NGCP::Panel::Form::Customer; +use NGCP::Panel::Utils; + +use Data::Printer; + +=head1 NAME + +NGCP::Panel::Controller::Reseller - Catalyst Controller + +=head1 DESCRIPTION + +Catalyst Controller. + +=head1 METHODS + +=cut + +sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { + my ($self, $c) = @_; + $c->log->debug(__PACKAGE__ . '::auto'); + return 1; +} + +sub list_customer :Chained('/') :PathPart('customer') :CaptureArgs(0) { + my ($self, $c) = @_; + + $c->stash( + customers => $c->model('billing')->resultset('contracts') + ->, + template => 'reseller/list.tt' + ); + NGCP::Panel::Utils::check_redirect_chain(c => $c); +} + +sub root :Chained('list_reseller') :PathPart('') :Args(0) { + my ($self, $c) = @_; +} + +sub ajax :Chained('list_reseller') :PathPart('ajax') :Args(0) { + my ($self, $c) = @_; + my $resellers = $c->stash->{resellers}; + $c->forward( + '/ajax_process_resultset', [ + $resellers, + [qw(id contract_id name status)], + [ 1, 2, 3 ] + ] + ); + $c->detach($c->view('JSON')); + return; +} + +sub create :Chained('list_reseller') :PathPart('create') :Args(0) { + my ($self, $c) = @_; + + # TODO: check in session if contract has just been created, and set it + # as default value + + my $posted = $c->request->method eq 'POST'; + my $form = NGCP::Panel::Form::Reseller->new; + $form->process( + posted => $posted, + params => $c->request->params, + action => $c->uri_for('create'), + ); + return if NGCP::Panel::Utils::check_form_buttons( + c => $c, + form => $form, + fields => [qw/contract.create/], + back_uri => $c->uri_for('create') + ); + # TODO: preserve the current "reseller" object for continuing editing + # when coming back from /contract/create + + if($form->validated) { + try { + delete $form->params->{save}; + $form->params->{contract_id} = delete $form->params->{contract}->{id}; + delete $form->params->{contract}; + $c->model('billing')->resultset('resellers')->create($form->params); + $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->response->redirect($c->uri_for()); + return; + } + + $c->stash(create_flag => 1); + $c->stash(close_target => $c->uri_for()); + $c->stash(form => $form); +} + +sub base :Chained('list_reseller') :PathPart('') :CaptureArgs(1) { + my ($self, $c, $reseller_id) = @_; + + unless($reseller_id && $reseller_id =~ /^\d+$/) { + $c->flash(messages => [{type => 'error', text => 'Invalid reseller id detected.'}]); + $c->response->redirect($c->uri_for()); + return; + } + + $c->stash(reseller => $c->stash->{resellers}->find({id => $reseller_id})); +} + +sub edit :Chained('base') :PathPart('edit') :Args(0) { + my ($self, $c) = @_; + + my $posted = $c->request->method eq 'POST'; + my $form = NGCP::Panel::Form::Reseller->new; + $form->process( + posted => 1, + params => $posted ? $c->request->params : {$c->stash->{reseller}->get_inflated_columns}, + action => $c->uri_for($c->stash->{reseller}->get_column('id'), 'edit'), + ); + return if NGCP::Panel::Utils::check_form_buttons( + c => $c, form => $form, fields => [qw/contract.create/], + back_uri => $c->uri_for($c->stash->{reseller}->get_column('id'), 'edit') + ); + + if($posted && $form->validated) { + try { + my $form_values = $form->value; + $form_values->{contract_id} = delete $form_values->{contract}{id}; + delete $form_values->{contract}; + $c->stash->{reseller}->update($form_values); + $c->flash(messages => [{type => 'success', text => 'Reseller successfully changed.'}]); + delete $c->session->{contract_id}; + } catch($e) { + $c->log->error($e); + $c->flash(messages => [{type => 'error', text => 'Updating reseller failed.'}]); + } + $c->response->redirect($c->uri_for()); + } + + $c->stash(close_target => $c->uri_for()); + $c->stash(form => $form); + $c->stash(edit_flag => 1); + + $c->session(contract_id => $c->stash->{reseller}->get_column('contract_id')); + + return; +} + +sub delete :Chained('base') :PathPart('delete') :Args(0) { + my ($self, $c) = @_; + + try { + $c->stash->{reseller}->delete; + $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->response->redirect($c->uri_for()); +} + +sub ajax_contract :Chained('list_reseller') :PathPart('ajax_contract') :Args(0) { + my ($self, $c) = @_; + + my $contract_id = $c->session->{contract_id}; + + my @used_contracts = map { + $_->get_column('contract_id') unless( + $contract_id && + $contract_id == $_->get_column('contract_id') + ) + } $c->stash->{resellers}->all; + my $free_contracts = $c->model('billing') + ->resultset('contracts') + ->search_rs({ + id => { 'not in' => \@used_contracts } + }); + + $c->forward("/ajax_process_resultset", [ + $free_contracts, + ["id","contact_id","external_id","status"], + [1,2,3] + ]); + + $c->detach( $c->view("JSON") ); +} + +=head1 AUTHOR + +Andreas Granig,,, + +=head1 LICENSE + +This library is free software. You can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + +__PACKAGE__->meta->make_immutable; + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Field/CustomerContract.pm b/lib/NGCP/Panel/Field/CustomerContract.pm new file mode 100644 index 0000000000..f6c11bbc35 --- /dev/null +++ b/lib/NGCP/Panel/Field/CustomerContract.pm @@ -0,0 +1,26 @@ +package NGCP::Panel::Field::CustomerContract; +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler::Field::Compound'; + +has_field 'id' => ( + type => '+NGCP::Panel::Field::DataTable', + label => 'Contract', + do_label => 0, + do_wrapper => 0, + required => 1, + template => 'share/templates/helpers/datatables_field.tt', + ajax_src => '/customer/ajax_contract', + table_titles => ['#', 'Contact #', 'External #', 'Status'], + table_fields => ['id', 'contact.id', 'external_id', 'status'], +); + +has_field 'create' => ( + type => 'Button', + label => 'or', + value => 'Create Contract', + element_class => [qw/btn btn-tertiary/], +); + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Field/CustomerStatusSelect.pm b/lib/NGCP/Panel/Field/CustomerStatusSelect.pm new file mode 100644 index 0000000000..d35daaff51 --- /dev/null +++ b/lib/NGCP/Panel/Field/CustomerStatusSelect.pm @@ -0,0 +1,18 @@ +package NGCP::Panel::Field::CustomerStatusSelect; +use Moose; +extends 'HTML::FormHandler::Field::Select'; + +sub build_options { + my ($self) = @_; + + return [ + { label => 'Select...', value => '' }, + { label => 'active', value => 'active' }, + { label => 'locked', value => 'locked' }, + { label => 'terminated', value => 'terminated' }, + ]; +} + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/Customer.pm b/lib/NGCP/Panel/Form/Customer.pm new file mode 100644 index 0000000000..370ca04f08 --- /dev/null +++ b/lib/NGCP/Panel/Form/Customer.pm @@ -0,0 +1,55 @@ +package NGCP::Panel::Form::Customer; + +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +has '+widget_wrapper' => ( default => 'Bootstrap' ); +#sub build_render_list {[qw/submitid fields actions/]} +sub build_render_list {[qw/fields actions/]} +sub build_form_element_class { [qw/form-horizontal/] } + +#has_field 'submitid' => ( +# type => 'Hidden' +#); + +has_field 'contract' => ( + type => '+NGCP::Panel::Field::CustomerContract', + label => 'Contract', + not_nullable => 1, +); + +has_field 'name' => ( + type => 'Text', + required => 1, +); + + +has_field 'status' => ( + type => '+NGCP::Panel::Field::CustomerStatusSelect', + required => 1, +); + +has_field 'save' => ( + type => 'Submit', + value => 'Save', + element_class => [qw/btn btn-primary/], + label => '', +); + +has_block 'fields' => ( + tag => 'div', + class => [qw/modal-body/], + render_list => [qw/contract name status/], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +1; +# vim: set tabstop=4 expandtab: diff --git a/share/templates/customer/list.tt b/share/templates/customer/list.tt new file mode 100644 index 0000000000..c31834b8fb --- /dev/null +++ b/share/templates/customer/list.tt @@ -0,0 +1,18 @@ +[% META title = 'Customers' -%] +[% + helper.name = 'Customers'; + helper.data = customers; + helper.messages = messages; + helper.column_titles = [ '#', 'Contract #', 'Name', 'Status' ]; + helper.column_fields = [ 'id', 'contract_id', 'name', 'status' ]; + + 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( c.controller.action_for('ajax') ); + helper.base_uri = c.uri_for( c.controller.action_for("") ); + + PROCESS 'helpers/datatables.tt'; +-%] +