Propagate reseller and contract status to children

Properly terminate/lock/unlock sub-contracts and subscribers if the
parent contract status changes.
agranig/1_0_subfix
Andreas Granig 13 years ago
parent 3494c02e27
commit 08e5a2a3a8

@ -6,6 +6,7 @@ use Hash::Merge;
use NGCP::Panel::Form::Contract;
use NGCP::Panel::Utils::Navigation;
use NGCP::Panel::Utils::Contract;
use NGCP::Panel::Utils::Subscriber;
sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) {
my ($self, $c) = @_;
@ -208,21 +209,20 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
billing_profile_id => $form->values->{billing_profile}{id},
});
}
my $old_status = $contract->status;
delete $form->values->{billing_profile};
$form->values->{contact_id} = $form->values->{contact}{id};
delete $form->values->{contact};
$contract->update($form->values);
# terminate all voip subscribers if contract is terminated
if($contract->status eq "terminated") {
for my $subscriber($contract->voip_subscribers->all) {
$subscriber->update({ status => 'terminated' });
$subscriber->provisioning_voip_subscriber->delete;
}
# if status changed, populate it down the chain
if($contract->status ne $old_status) {
NGCP::Panel::Utils::Contract::recursively_lock_contract(
c => $c,
contract => $contract,
);
}
# TODO: what about terminating a peering contract?
delete $c->session->{created_objects}->{contact};
delete $c->session->{created_objects}->{billing_profile};
});
@ -243,7 +243,16 @@ sub terminate :Chained('base') :PathPart('terminate') :Args(0) {
my ($self, $c) = @_;
try {
$c->stash->{contract_result}->update({ status => 'terminated' });
my $contract = $c->stash->{contract_result};
my $old_status = $contract->status;
$contract->update({ status => 'terminated' });
# if status changed, populate it down the chain
if($contract->status ne $old_status) {
NGCP::Panel::Utils::Contract::recursively_lock_contract(
c => $c,
contract => $contract,
);
}
$c->flash(messages => [{type => 'success', text => 'Contract successfully terminated'}]);
} catch (DBIx::Class::Exception $e) {
$c->log->info("failed to terminate contract: $e");
@ -252,29 +261,11 @@ sub terminate :Chained('base') :PathPart('terminate') :Args(0) {
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'}]);
} catch (DBIx::Class::Exception $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);
}
sub ajax :Chained('contract_list') :PathPart('ajax') :Args(0) {
my ($self, $c) = @_;
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->detach( $c->view("JSON") );
}

@ -7,6 +7,7 @@ use Hash::Merge;
use HTTP::Status qw(HTTP_SEE_OTHER);
use NGCP::Panel::Form::Reseller;
use NGCP::Panel::Utils::Navigation;
use NGCP::Panel::Utils::Contract;
sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) {
my ($self, $c) = @_;
@ -210,21 +211,21 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
if($posted && $form->validated) {
try {
$form->params->{contract_id} = delete $form->params->{contract}{id};
delete $form->params->{contract};
$c->stash->{reseller}->first->update($form->params);
# if a reseller is terminated, we need to terminate all customers
# and subscribers
if($c->stash->{reseller}->first->status eq "terminated") {
for my $customer($c->stash->{reseller}->first->contracts->all) {
$customer->update({ status => 'terminated' });
for my $subscriber($customer->voip_subscribers->all) {
$subscriber->update({ status => 'terminated' });
$subscriber->provisioning_voip_subscriber->delete;
}
$c->model('DB')->txn_do(sub {
$form->params->{contract_id} = delete $form->params->{contract}{id};
delete $form->params->{contract};
my $old_status = $c->stash->{reseller}->first->status;
$c->stash->{reseller}->first->update($form->params);
if($c->stash->{reseller}->first->status ne $old_status) {
my $contract = $c->stash->{reseller}->first->contract;
$contract->update({ status => $c->stash->{reseller}->first->status });
NGCP::Panel::Utils::Contract::recursively_lock_contract(
c => $c,
contract => $contract,
);
}
}
});
delete $c->session->{created_objects}->{contract};
delete $c->session->{edit_contract_id};
@ -233,7 +234,7 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
$c->log->error($e);
$c->flash(messages => [{type => 'error', text => 'Failed to update reseller'}]);
}
$c->response->redirect($c->uri_for());
NGCP::Utils::Navigation::back_or($c, $c->uri_for);
}
$c->stash(close_target => $c->uri_for());
@ -243,6 +244,32 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) {
return;
}
sub terminate :Chained('base') :PathPart('terminate') :Args(0) {
my ($self, $c) = @_;
try {
$c->model('DB')->txn_do(sub {
my $reseller = $c->stash->{reseller}->first;
my $old_status = $reseller->status;
$reseller->update({ status => 'terminated' });
if($reseller->status ne $old_status) {
my $contract = $reseller->contract;
$contract->update({ status => $c->stash->{reseller}->first->status });
NGCP::Panel::Utils::Contract::recursively_lock_contract(
c => $c,
contract => $contract,
);
}
});
$c->flash(messages => [{type => 'success', text => 'Successfully terminated reseller'}]);
} catch($e) {
$c->log->error("failed to terminate reseller: $e");
$c->flash(messages => [{type => 'error', text => 'Failed to terminate reseller'}]);
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for);
}
sub details :Chained('base') :PathPart('details') :Args(0) {
my ($self, $c) = @_;
$c->stash(template => 'reseller/details.tt');

@ -55,6 +55,77 @@ sub create_contract_balance {
}
}
sub recursively_lock_contract {
my %params = @_;
my $c = $params{c};
my $contract = $params{contract};
my $status = $contract->status;
# first, change all voip subscribers, in case there are any
for my $subscriber($contract->voip_subscribers->all) {
$subscriber->update({ status => $status });
if($status eq 'terminated') {
$subscriber->provisioning_voip_subscriber->delete;
} elsif($status eq 'locked') {
NGCP::Panel::Utils::Subscriber::lock_provisoning_voip_subscriber(
c => $c,
prov_subscriber => $subscriber->provisioning_voip_subscriber,
level => 4,
);
} elsif($status eq 'active') {
NGCP::Panel::Utils::Subscriber::lock_provisoning_voip_subscriber(
c => $c,
prov_subscriber => $subscriber->provisioning_voip_subscriber,
level => 0,
);
}
}
# then, check all child contracts in case of reseller
my $resellers = $c->model('DB')->resultset('resellers')->search({
contract_id => $contract->id
});
for my $reseller($resellers->all) {
# remove domains in case of reseller termination
if($status eq 'terminated') {
for my $domain($reseller->domain_resellers->all) {
$domain->delete;
}
}
# fetch sub-contracts of this contract
my $customers = $c->model('DB')->resultset('contracts')->search({
'contact.reseller_id' => $reseller->id,
}, {
join => 'contact',
}
);
for my $customer($customers->all) {
$customer->update({ status => $status });
for my $subscriber($customer->voip_subscribers->all) {
$subscriber->update({ status => $status });
if($status eq 'terminated') {
$subscriber->provisioning_voip_subscriber->delete;
} elsif($status eq 'locked') {
NGCP::Panel::Utils::Subscriber::lock_provisoning_voip_subscriber(
c => $c,
prov_subscriber => $subscriber->provisioning_voip_subscriber,
level => 4,
);
} elsif($status eq 'active') {
NGCP::Panel::Utils::Subscriber::lock_provisoning_voip_subscriber(
c => $c,
prov_subscriber => $subscriber->provisioning_voip_subscriber,
level => 0,
);
}
}
}
}
}
1;
=head1 NAME

@ -79,6 +79,36 @@ sub destination_as_string {
}
}
sub lock_provisoning_voip_subscriber {
my %params = @_;
my $c = $params{c};
my $prov_subscriber= $params{prov_subscriber};
my $level = $params{level};
return unless $prov_subscriber;
my $rs = get_usr_preference_rs(
c => $c,
prov_subscriber => $prov_subscriber,
attribute => 'lock'
);
try {
if($rs->first) {
if($level == 0) {
$rs->first->delete;
} else {
$rs->first->update({ value => $level });
}
} elsif($level > 0) { # nothing to do for level 0, if no lock is set yet
$rs->create({ value => $level });
}
} catch($e) {
$c->log->error("failed to set provisioning_voip_subscriber lock: $e");
$e->rethrow;
}
}
1;
=head1 NAME

@ -15,7 +15,6 @@
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' },

@ -14,7 +14,7 @@
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 = 'Terminate', uri = "/contract/'+full.id+'/terminate", class = 'btn-small btn-secondary', icon = 'icon-remove' },
{ name = 'Details', uri = "/customer/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' },
];
helper.top_buttons = [

@ -134,7 +134,7 @@
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 = 'Terminate', uri = "/contract/'+full.id+'/terminate", class = 'btn-small btn-secondary', icon = 'icon-remove' },
{ name = 'Details', uri = "/customer/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' },
];
ELSE;

@ -13,14 +13,18 @@
UNLESS c.user.read_only;
helper.dt_buttons = [
{ name = 'Edit', uri = "/reseller/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = 'Delete', uri = "/reseller/'+full[\"id\"]+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },
{ name = 'Details', uri = "/reseller/'+full[\"id\"]+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' },
{ name = 'Edit', uri = "/reseller/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = 'Terminate', uri = "/reseller/'+full.id+'/terminate", class = 'btn-small btn-secondary', icon = 'icon-remove' },
{ name = 'Details', uri = "/reseller/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' },
];
helper.top_buttons = [
{ name = 'Create Reseller', uri = c.uri_for('/reseller/create'), icon = 'icon-star' },
{ name = 'Create Reseller with default values', uri = c.uri_for('/reseller/create_defaults'), icon = 'icon-star', method = 'post' },
];
ELSE;
helper.dt_buttons = [
{ name = 'Details', uri = "/reseller/'+full.id+'/details", class = 'btn-small btn-tertiary', icon = 'icon-list' },
];
END;
PROCESS 'helpers/datatables.tt';

Loading…
Cancel
Save