First part of reworking reseller handling.

agranig/1_0_subfix
Andreas Granig 13 years ago
parent 55b79ae3d6
commit 04296de4c4

@ -95,7 +95,6 @@ sub create :Chained('list_admin') :PathPart('create') :Args(0) {
try {
$form->params->{reseller_id} = delete $form->params->{reseller}{id};
delete $form->params->{reseller};
delete $form->params->{save};
delete $form->params->{id};
$c->model('DB')->resultset('admins')->create($form->params);
$c->flash(messages => [{type => 'success', text => 'Administrator created.'}]);
@ -131,7 +130,7 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
my ($self, $c) = @_;
my $posted = $c->request->method eq 'POST';
my $form;
if($c->user->auth_realm eq "admin") {
if($c->user->is_superuser) {
$form = NGCP::Panel::Form::Administrator::Admin->new;
$c->stash->{administrator}->{reseller}{id} =
delete $c->stash->{administrator}->{reseller_id};
@ -145,7 +144,11 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
params => $posted ? $c->request->params : $c->stash->{administrator},
action => $c->uri_for($c->stash->{administrator}->{id}, 'edit'),
);
# TODO: if pass is empty, don't update it
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
);
if ($posted && $form->validated) {
try {
my $form_values = $form->value;

@ -15,6 +15,7 @@ use NGCP::Panel::Form::BillingPeaktimeWeekdays;
use NGCP::Panel::Form::BillingPeaktimeSpecial;
use NGCP::Panel::Form::BillingFeeUpload;
use NGCP::Panel::Utils::Navigation;
use NGCP::Panel::Utils::Datatables;
my @WEEKDAYS = map { langinfo($_) } (DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7, DAY_1);
#Monday Tuesday Wednesday Thursday Friday Saturday Sunday
@ -32,6 +33,11 @@ sub profile_list :Chained('/') :PathPart('billing') :CaptureArgs(0) {
my $dispatch_to = '_profile_resultset_' . $c->user->auth_realm;
my $profiles_rs = $self->$dispatch_to($c);
$c->stash(profiles_rs => $profiles_rs);
$c->stash->{profile_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
{ name => "id", "search" => 1, "title" => "#" },
{ name => "name", "search" => 1, "title" => "Name" },
{ name => "reseller.name", "search" => 1, "title" => "Reseller" },
]);
$c->stash(template => 'billing/list.tt');
}
@ -57,10 +63,7 @@ sub ajax :Chained('profile_list') :PathPart('ajax') :Args(0) {
my ($self, $c) = @_;
my $resultset = $c->stash->{profiles_rs};
$c->forward( "/ajax_process_resultset", [$resultset,
["id", "name"],
["id", "name"]]);
NGCP::Panel::Utils::Datatables::process($c, $resultset, $c->stash->{profile_dt_columns});
$c->detach( $c->view("JSON") );
}
@ -110,18 +113,36 @@ sub edit :Chained('base') :PathPart('edit') {
sub create :Chained('profile_list') :PathPart('create') :Args(0) {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST'),
my $dispatch_to = 'NGCP::Panel::Form::BillingProfile_' . $c->user->auth_realm;
my $form = $dispatch_to->new;
$form->process(
posted => ($c->request->method eq 'POST'),
posted => $posted,
params => $c->request->params,
action => $c->uri_for('create'),
item => $c->stash->{profiles_rs}->new_result({}),
);
if($form->validated) {
$c->flash(messages => [{type => 'success', text => 'Billing profile successfully created!'}]);
$c->response->redirect($c->uri_for());
return;
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
back_uri => $c->req->uri,
);
if($posted && $form->validated) {
try {
if($c->user->is_superuser) {
$form->values->{reseller_id} = $form->values->{reseller}{id};
} else {
$form->values->{reseller_id} = $c->user->reseller_id;
}
delete $form->values->{reseller};
$c->model('DB')->resultset('billing_profiles')->create($form->values);
$c->flash(messages => [{type => 'success', text => 'Billing profile successfully created'}]);
} catch($e) {
$c->log->error("failed to create billing profile: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to create billing profile'}]);
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
$c->stash(close_target => $c->uri_for());

@ -3,7 +3,8 @@ use Sipwise::Base;
use namespace::sweep;
BEGIN { extends 'Catalyst::Controller'; }
use NGCP::Panel::Form::Contact;
use NGCP::Panel::Form::Contact::Reseller;
use NGCP::Panel::Form::Contact::Admin;
use NGCP::Panel::Utils::Navigation;
sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) {
@ -16,35 +17,22 @@ sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRol
sub list_contact :Chained('/') :PathPart('contact') :CaptureArgs(0) {
my ($self, $c) = @_;
my $contacts;
if($c->user->auth_realm eq "reseller") {
$contacts = $c->model('DB')->resultset('contracts')->search({
reseller_id => $c->user->reseller_id
})->search_related_rs('contact');
} else {
$contacts = $c->model('DB')->resultset('contacts');
my $contacts = $c->model('DB')->resultset('contacts');
unless($c->user->is_superuser) {
$contacts = $contacts->search({ reseller_id => $c->user->reseller_id });
}
$c->stash(contacts => $contacts);
$c->stash(template => 'contact/list.tt');
$c->stash->{contact_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
{ name => "id", search => 1, title => "#" },
{ name => "reseller.name", search => 1, title => "Reseller" },
{ 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" },
]);
# TODO: wtf?
if($c->session->{redirect_targets} && @{ $c->session->{redirect_targets} }) {
my $target = ${ $c->session->{redirect_targets} }[0];
if('/'.$c->request->path eq $target->path) {
shift @{$c->session->{redirect_targets}};
} else {
$c->stash(close_target => $target);
}
}
}
sub root :Chained('list_contact') :PathPart('') :Args(0) {
@ -54,35 +42,36 @@ sub root :Chained('list_contact') :PathPart('') :Args(0) {
sub create :Chained('list_contact') :PathPart('create') :Args(0) {
my ($self, $c) = @_;
my $form = NGCP::Panel::Form::Contact->new;
my $posted = ($c->request->method eq 'POST');
my $form;
my $params = {};
if($c->user->is_superuser) {
$form = NGCP::Panel::Form::Contact::Admin->new;
} else {
$form = NGCP::Panel::Form::Contact::Reseller->new;
$params->{reseller}{id} = $c->user->reseller_id;
}
$form->process(
posted => ($c->request->method eq 'POST'),
posted => $posted,
params => $c->request->params,
action => $c->uri_for('create'),
item => $params,
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
);
if($form->validated) {
if($posted && $form->validated) {
try {
delete $form->params->{submitid};
delete $form->params->{save};
my $contact = $c->stash->{contacts}->create($form->params);
if($c->stash->{close_target}) {
$c->session->{created_object} = { contact => { id => $contact->id } };
$c->response->redirect($c->stash->{close_target});
return;
}
my $contact = $c->stash->{contacts}->create($form->values);
$c->session->{created_object} = { contact => { id => $contact->id } };
$c->flash(messages => [{type => 'success', text => 'Contact successfully created'}]);
$c->response->redirect($c->uri_for_action('/contact/root'));
return;
} catch($e) {
$c->log->error("failed to create contact: $e");
if($c->stash->{close_target}) {
$c->response->redirect($c->stash->{close_target});
return;
}
$c->flash(messages => [{type => 'error', text => 'Failed to create contact'}]);
$c->response->redirect($c->uri_for_action('/contact/root'));
return;
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contact/root'));
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contact/root'));
}
$c->stash(create_flag => 1);
@ -94,11 +83,10 @@ sub base :Chained('list_contact') :PathPart('') :CaptureArgs(1) {
unless($contact_id && $contact_id =~ /^\d+$/) {
$c->flash(messages => [{type => 'error', text => 'Invalid contact id detected!'}]);
$c->response->redirect($c->uri_for());
return;
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for());
}
$c->stash(contact => $c->stash->{contacts}->find($contact_id));
my $res = $c->stash->{contacts};
$c->stash(contact => $res->find($contact_id));
}
sub edit :Chained('base') :PathPart('edit') :Args(0) {
@ -118,13 +106,11 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
delete $form->params->{save};
$c->stash->{contact}->update($form->params);
$c->flash(messages => [{type => 'success', text => 'Contact successfully changed'}]);
$c->response->redirect($c->uri_for_action('/contact/root'));
return;
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contact/root'));
} catch($e) {
$c->log->error("failed to update contact: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to update contact'}]);
$c->response->redirect($c->uri_for_action('/contact/root'));
return;
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contact/root'));
}
}
@ -137,33 +123,24 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
sub delete :Chained('base') :PathPart('delete') :Args(0) {
my ($self, $c) = @_;
$c->stash->{contact}->delete;
$c->flash(messages => [{type => 'success', text => 'Contact successfully deleted'}]);
$c->response->redirect($c->uri_for());
try {
$c->stash->{contact}->delete;
$c->flash(messages => [{type => 'success', text => 'Contact successfully deleted'}]);
} catch($e) {
$c->log->error("failed to delete contact: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to delete contact'}]);
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
sub ajax :Chained('list_contact') :PathPart('ajax') :Args(0) {
my ($self, $c) = @_;
#TODO: when user is not logged in, this gets forwarded to login page
my $contacts = $c->model('DB')->resultset('contacts')->search_rs({});
NGCP::Panel::Utils::Datatables::process($c, $c->stash->{contacts}, $c->stash->{contact_dt_columns});
$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;

@ -2,6 +2,7 @@ package NGCP::Panel::Controller::Contract;
use Sipwise::Base;
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller'; }
use Hash::Merge;
use NGCP::Panel::Form::Contract;
use NGCP::Panel::Utils::Navigation;
use NGCP::Panel::Utils::Contract;
@ -15,8 +16,20 @@ sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRol
sub contract_list :Chained('/') :PathPart('contract') :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" },
]);
my $mapping_rs = $c->model('DB')->resultset('billing_mappings');
# TODO: also order by end_date desc (also in rate-o-mat etc?)
# leave it as is currently to preserve backwards-compatibility
my $rs = $c->model('DB')->resultset('contracts')
->search({
'billing_mappings.id' => {
@ -37,20 +50,24 @@ sub contract_list :Chained('/') :PathPart('contract') :CaptureArgs(0) {
})->get_column('id')->as_query,
},
},{
'join' => {
'billing_mappings' => 'billing_profile',
},
'join' => 'billing_mappings',
'+select' => [
'billing_mappings.billing_profile_id',
'billing_profile.name',
'billing_mappings.id',
],
'+as' => [
'billing_profile_id',
'billing_profile_name',
'billing_mapping_id',
],
});
unless($c->user->is_superuser) {
$rs = $rs->search({
'contact.reseller_id' => $c->user->reseller_id,
}, {
join => 'contact',
});
}
$c->stash(contract_select_rs => $rs);
$c->stash(ajax_uri => $c->uri_for_action("/contract/ajax"));
$c->stash(template => 'contract/list.tt');
}
@ -62,43 +79,52 @@ sub root :Chained('contract_list') :PathPart('') :Args(0) {
sub create :Chained('contract_list') :PathPart('create') :Args(0) {
my ($self, $c) = @_;
my $item = $c->model('DB')->resultset('billing_mappings')->new_result({});
my $params = delete $c->session->{created_object} || {};
my $posted = ($c->request->method eq 'POST');
my $params = {};
Hash::Merge->new('RIGHT_PRECEDENT')->merge($params, delete $c->session->{created_object});
# TODO: where to store created contact and billing profile?
my $form = NGCP::Panel::Form::Contract->new;
if($form->process(
posted => ($c->request->method eq 'POST'),
my $form;
$form = NGCP::Panel::Form::Contract->new;
$form->process(
posted => $posted,
params => $c->request->params,
action => $c->uri_for('create'),
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,
);
$c->session->{created_object} = { contract => { id => $item->contract->id } };
} catch($e) {
# TODO: roll back contract and billing_mappings creation and
# redirect to correct entry point
$c->log->error("Failed to create contract balance: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to create contract balance!'}]);
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/contract/root'));
}
}
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!'}]);
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->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);
@ -112,15 +138,15 @@ sub base :Chained('contract_list') :PathPart('') :CaptureArgs(1) {
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
my $res = $c->stash->{contract_select_rs}
->search(undef, {
my $res = $c->stash->{contract_select_rs};
$res = $res->search(undef, {
'+select' => 'billing_mappings.id',
'+as' => 'bmid',
})
->find($contract_id);
unless(defined($res)) {
$c->flash(messages => [{type => 'error', text => 'Contract does not exist!'}]);
$c->flash(messages => [{type => 'error', text => 'Contract does not exist'}]);
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
@ -134,22 +160,23 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
my $posted = ($c->request->method eq 'POST');
my $contr = $c->stash->{contract_result};
my $item = $contr->billing_mappings->find($contr->get_column('bmid'));
if ($posted && $item->billing_profile_id) {
if($item->billing_profile_id != $c->req->params->{'billing_profile.id'}) {
$item = $c->stash->{contract_result}->billing_mappings->new_result({});
$item->start_date(time);
}
} else {
my $contract = $c->stash->{contract_result};
my $billing_mapping = $contract->billing_mappings->find($contract->get_column('bmid'));
my $params = {};
unless($posted) {
$params->{billing_profile}{id} = $billing_mapping->billing_profile->id;
$params->{contact}{id} = $contract->contact_id;
$params->{external_id} = $contract->external_id;
$params->{status} = $contract->status;
}
# TODO: handle created contact/bilprof
my $form = NGCP::Panel::Form::Contract->new;
$form->process(
posted => $posted,
params => $c->req->params,
item => $item,
action => $c->uri_for($c->stash->{contract}->{id}, 'edit'),
item => $params,
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c, form => $form,
@ -158,7 +185,27 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
back_uri => $c->req->uri,
);
if($posted && $form->validated) {
$c->flash(messages => [{type => 'success', text => 'Contract successfully changed!'}]);
try {
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},
});
}
delete $form->values->{billing_profile};
$form->values->{contact_id} = $form->values->{contact}{id};
delete $form->values->{contact};
$contract->update($form->values);
});
$c->flash(messages => [{type => 'success', text => 'Contract successfully changed!'}]);
} catch($e) {
$c->log->error("failed to update contract: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to update contract'}]);
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
@ -166,15 +213,28 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
$c->stash(edit_flag => 1);
}
sub terminate :Chained('base') :PathPart('terminate') :Args(0) {
my ($self, $c) = @_;
try {
$c->stash->{contract_result}->update({ status => 'terminated' });
$c->flash(messages => [{type => 'success', text => 'Contract successfully terminated'}]);
} catch (DBIx::Class::Exception $e) {
$c->log->info("failed to terminate contract: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to terminate contract'}]);
};
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
sub delete :Chained('base') :PathPart('delete') :Args(0) {
my ($self, $c) = @_;
try {
$c->stash->{contract_result}->delete;
$c->flash(messages => [{type => 'success', text => 'Contract successfully deleted!'}]);
$c->flash(messages => [{type => 'success', text => 'Contract successfully deleted'}]);
} catch (DBIx::Class::Exception $e) {
$c->flash(messages => [{type => 'error', text => 'Delete failed.'}]);
$c->log->info("Delete failed: " . $e);
$c->log->info("failed to delete contract: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to delete contract'}]);
};
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
@ -182,11 +242,12 @@ sub delete :Chained('base') :PathPart('delete') :Args(0) {
sub ajax :Chained('contract_list') :PathPart('ajax') :Args(0) {
my ($self, $c) = @_;
my $rs = $c->stash->{contract_select_rs};
my $res = $c->stash->{contract_select_rs};
NGCP::Panel::Utils::Datatables::process($c, $res, $c->stash->{contract_dt_columns});
$c->forward( "/ajax_process_resultset", [$rs,
["id", "contact_id", "billing_profile_name", "billing_profile_id", "status"],
["billing_profile.name", "status"]]);
# $c->forward( "/ajax_process_resultset", [$rs,
# ["id", "contact_id", "billing_profile_name", "billing_profile_id", "status"],
# ["billing_profile.name", "status"]]);
$c->detach( $c->view("JSON") );
}

@ -3,6 +3,7 @@ use Sipwise::Base;
use namespace::sweep;
BEGIN { extends 'Catalyst::Controller'; }
use DateTime qw();
use Hash::Merge;
use HTTP::Status qw(HTTP_SEE_OTHER);
use NGCP::Panel::Form::Reseller;
use NGCP::Panel::Utils::Navigation;
@ -178,7 +179,6 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
my $params = { $c->stash->{reseller}->first->get_inflated_columns };
$params->{contract}{id} = delete $params->{contract_id};
if($c->session->{created_object}) { # got a contract id from next step
use Hash::Merge;
$params = Hash::Merge->new('RIGHT_PRECEDENT')->merge($params, delete $c->session->{created_object});
}
$form->process(

@ -5,15 +5,16 @@ extends 'NGCP::Panel::Form::BillingProfile_reseller';
has_field 'reseller' => (
type => '+NGCP::Panel::Field::Reseller',
not_nullable => 1,
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/handle name interval_charge interval_free_time interval_free_cash
render_list => [qw/reseller handle name prepaid interval_charge interval_free_time interval_free_cash
fraud_interval_limit fraud_interval_lock fraud_interval_notify
fraud_daily_limit fraud_daily_lock fraud_daily_notify
currency vat_rate vat_included reseller id/],
currency vat_rate vat_included id/],
);

@ -1,7 +1,7 @@
package NGCP::Panel::Form::BillingProfile_reseller;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Model::DBIC';
extends 'HTML::FormHandler';
use Moose::Util::TypeConstraints;
use HTML::FormHandler::Widget::Block::Bootstrap;
@ -34,12 +34,18 @@ has_field 'handle' => (
},
);
has_field 'prepaid' => (
type => 'Boolean',
default => 0,
);
has_field 'interval_charge' => (
type => 'Money',
element_attr => {
rel => ['tooltip'],
title => ['base fee charged per billing interval, float, specifying Euro']
},
default => '0',
);
has_field 'interval_free_time' => (
@ -48,6 +54,7 @@ has_field 'interval_free_time' => (
rel => ['tooltip'],
title => ['included time per billing interval, integer, specifying seconds']
},
default => '0',
);
has_field 'interval_free_cash' => (
@ -56,6 +63,7 @@ has_field 'interval_free_cash' => (
rel => ['tooltip'],
title => ['included money per billing interval, float, specifying EUR, USD, etc.']
},
default => '0',
);
has_field 'fraud_interval_limit' => (
@ -99,6 +107,8 @@ has_field 'fraud_daily_limit' => (
rel => ['tooltip'],
title => ['fraud detection threshold, per day, float, specifying EUR, USD, etc.']
},
required => 0,
default => undef,
);
has_field 'fraud_daily_lock' => (
@ -152,6 +162,7 @@ has_field 'vat_included' => (
rel => ['tooltip'],
title => ['check if fees are inclusive VAT']
},
default => 0,
);
has_field 'save' => (
@ -164,7 +175,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/handle name interval_charge interval_free_time interval_free_cash
render_list => [qw/handle name prepaid interval_charge interval_free_time interval_free_cash
fraud_interval_limit fraud_interval_lock fraud_interval_notify
fraud_daily_limit fraud_daily_lock fraud_daily_notify
currency vat_rate vat_included id/],
@ -176,12 +187,5 @@ has_block 'actions' => (
render_list => [qw/save/],
);
before 'update_model' => sub {
my $self = shift;
foreach my $val(values $self->value) {
$val = '' unless defined($val);
}
};
1;
# vim: set tabstop=4 expandtab:

@ -0,0 +1,19 @@
package NGCP::Panel::Form::Contact::Admin;
use HTML::FormHandler::Moose;
extends 'NGCP::Panel::Form::Contact::Reseller';
use Moose::Util::TypeConstraints;
has_field 'reseller' => (
type => '+NGCP::Panel::Field::Reseller',
not_nullable => 1,
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/reseller firstname lastname email company/],
);
1;
# vim: set tabstop=4 expandtab:

@ -1,4 +1,4 @@
package NGCP::Panel::Form::Contact;
package NGCP::Panel::Form::Contact::Reseller;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler';
@ -14,15 +14,17 @@ sub build_form_element_class { [qw/form-horizontal/] }
has_field 'firstname' => (
type => 'Text',
label => 'First Name',
required => 1,
);
has_field 'lastname' => (
type => 'Text',
label => 'Last Name',
required => 1,
);
has_field 'company' => (
type => 'Text',
label => 'Company',
);
has_field 'email' => (
type => 'Email',
@ -39,7 +41,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/firstname lastname email/],
render_list => [qw/firstname lastname email company/],
);
has_block 'actions' => (

@ -1,7 +1,7 @@
package NGCP::Panel::Form::Contract;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Model::DBIC';
extends 'HTML::FormHandler';
use Moose::Util::TypeConstraints;
use HTML::FormHandler::Widget::Block::Bootstrap;
@ -11,11 +11,7 @@ has_field 'submitid' => ( type => 'Hidden' );
sub build_render_list {[qw/submitid fields actions/]}
sub build_form_element_class { [qw/form-horizontal/] }
has_field 'contract' => (
type => 'Compound',
);
has_field 'contract.contact' => (
has_field 'contact' => (
type => '+NGCP::Panel::Field::Contact',
label => 'Contact',
not_nullable => 1,
@ -26,12 +22,17 @@ has_field 'billing_profile' => (
not_nullable => 1,
);
has_field 'contract.status' => (
has_field 'status' => (
type => '+NGCP::Panel::Field::ContractStatusSelect',
not_nullable => 1,
);
has_field 'external_id' => (
type => 'Text',
label => 'External #',
required => 0,
);
has_field 'save' => (
type => 'Submit',
value => 'Save',
@ -42,7 +43,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/contract.contact billing_profile contract.status/],
render_list => [qw/contact billing_profile status external_id/],
);
has_block 'actions' => (

@ -37,14 +37,17 @@ sub create_contract_balance {
}
try {
$c->model('DB')->resultset('contract_balances')->create({
contract_id => $contract->id,
cash_balance => $cash_balance,
cash_balance_interval => $cash_balance_interval,
free_time_balance => $free_time_balance,
free_time_balance_interval => $free_time_balance_interval,
start => $stime,
end => $etime,
my $schema = $c->model('DB');
$schema->txn_do(sub {
$schema->resultset('contract_balances')->create({
contract_id => $contract->id,
cash_balance => $cash_balance,
cash_balance_interval => $cash_balance_interval,
free_time_balance => $free_time_balance,
free_time_balance_interval => $free_time_balance_interval,
start => $stime,
end => $etime,
});
});
} catch($e) {
$c->log->error("Creating contract balance failed: " . $e);

@ -36,10 +36,12 @@ sub check_form_buttons {
my $posted = ($c->request->method eq 'POST');
delete $form->params->{save} if $posted;
delete $form->values->{save} if $posted;
if($posted && $form->field('submitid')) {
my $val = $form->value->{submitid};
delete $form->params->{submitid};
delete $form->values->{submitid};
if(defined $val and exists($fields->{$val}) ) {
my $target;
if (defined $fields->{$val}) {
@ -55,7 +57,7 @@ sub check_form_buttons {
$c->session->{redirect_targets} = [ $back_uri ];
}
$c->response->redirect($target);
$c->detach();
$c->detach;
}
}
}
@ -64,7 +66,7 @@ sub back_or {
my ($c, $alternative_target) = @_;
my $target = $c->stash->{close_target} || $alternative_target || $c->req->uri;
$c->response->redirect($target);
$c->detach();
$c->detach;
}
1;

@ -1,25 +1,25 @@
[% META title = 'Billing Profiles' -%]
[%
helper.name = 'Billing Profiles';
helper.show_create_button = 1;
helper.messages = messages;
helper.column_titles = [ '#', 'Profile' ];
helper.column_fields = [ 'id', 'name' ];
helper.dt_columns = profile_dt_columns;
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.dt_buttons = [
{ name = 'Edit', uri = "/billing/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = 'Fees', uri = "/billing/'+full[\"id\"]+'/fees", class = 'btn-small btn-tertiary', icon = 'icon-shopping-cart' },
{ name = 'Peaktimes', uri = "/billing/'+full[\"id\"]+'/peaktimes", class = 'btn-small btn-tertiary', icon = 'icon-time' },
];
helper.top_buttons = [
{ name = 'Create Billing Profile', uri = c.uri_for('/billing/create'), icon = 'icon-star' },
];
UNLESS c.user.read_only;
helper.dt_buttons = [
{ name = 'Edit', uri = "/billing/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = 'Fees', uri = "/billing/'+full[\"id\"]+'/fees", class = 'btn-small btn-tertiary', icon = 'icon-shopping-cart' },
{ name = 'Peaktimes', uri = "/billing/'+full[\"id\"]+'/peaktimes", class = 'btn-small btn-tertiary', icon = 'icon-time' },
];
helper.top_buttons = [
{ name = 'Create Billing Profile', uri = c.uri_for('/billing/create'), icon = 'icon-star' },
];
END;
PROCESS 'helpers/datatables.tt';
-%]

@ -1,11 +1,9 @@
[% META title = 'Contracts' -%]
[%
helper.name = 'Contract';
helper.show_create_button = 1;
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;
@ -13,13 +11,16 @@
helper.form_object = form;
helper.ajax_uri = ajax_uri;
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' },
];
helper.top_buttons = [
{ name = 'Create Contract', uri = c.uri_for('/contract/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 = 'Terminate', uri = "/contract/'+full.id+'/terminate", class = 'btn-small btn-primary', icon = 'icon-remove' },
{ name = 'Delete', uri = "/contract/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },
];
helper.top_buttons = [
{ name = 'Create Contract', uri = c.uri_for('/contract/create'), icon = 'icon-star' },
];
END;
PROCESS 'helpers/datatables.tt';
-%]

Loading…
Cancel
Save