You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
7.3 KiB
278 lines
7.3 KiB
package NGCP::Panel::Utils::Phonebook;
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Sipwise::Base;
|
|
use English;
|
|
use NGCP::Panel::Utils::Generic qw(:all);
|
|
use NGCP::Panel::Utils::Message;
|
|
|
|
sub get_reseller_phonebook {
|
|
my ($c, $reseller_id) = @_;
|
|
my @pb;
|
|
|
|
my $r_pb_rs = $c->model('DB')->resultset('reseller_phonebook')->search({
|
|
reseller_id => $reseller_id,
|
|
});
|
|
|
|
for my $r ($r_pb_rs->all) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
}
|
|
|
|
return [ sort { $a->{name} cmp $b->{name} } @pb ];
|
|
}
|
|
|
|
sub get_contract_phonebook {
|
|
my ($c, $contract_id) = @_;
|
|
my @pb;
|
|
my %c_numbers;
|
|
|
|
my $contract = $c->model('DB')->resultset('contracts')->search({
|
|
id => $contract_id,
|
|
})->first;
|
|
|
|
my $r_pb_rs = $c->model('DB')->resultset('reseller_phonebook')->search({
|
|
reseller_id => $contract->contact->reseller->id,
|
|
});
|
|
|
|
my $c_pb_rs = $c->model('DB')->resultset('contract_phonebook')->search({
|
|
contract_id => $contract_id,
|
|
});
|
|
|
|
for my $r ($c_pb_rs->all) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
$c_numbers{$r->number} = $r->name;
|
|
}
|
|
|
|
for my $r ($r_pb_rs->all) {
|
|
unless (exists $c_numbers{$r->number}) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
}
|
|
}
|
|
|
|
return [ sort { $a->{name} cmp $b->{name} } @pb ];
|
|
}
|
|
|
|
sub get_subscriber_phonebook {
|
|
my ($c, $subscriber_id) = @_;
|
|
my @pb;
|
|
my %c_numbers;
|
|
|
|
my $sub = $c->model('DB')->resultset('voip_subscribers')->search({
|
|
id => $subscriber_id,
|
|
})->first;
|
|
|
|
my $r_pb_rs = $c->model('DB')->resultset('reseller_phonebook')->search({
|
|
reseller_id => $sub->contract->contact->reseller->id,
|
|
});
|
|
|
|
my $c_pb_rs = $c->model('DB')->resultset('contract_phonebook')->search({
|
|
contract_id => $sub->contract_id,
|
|
});
|
|
|
|
my $a_pb_rs = $c->model('DB')->resultset('subscriber_phonebook')->search({
|
|
shared => 1,
|
|
'contract.id' => $sub->contract_id,
|
|
},{
|
|
join => { 'subscriber' => 'contract' },
|
|
});
|
|
|
|
my $s_pb_rs = $c->model('DB')->resultset('subscriber_phonebook')->search({
|
|
subscriber_id => $subscriber_id,
|
|
});
|
|
|
|
for my $r ($s_pb_rs->all) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
$c_numbers{$r->number} = $r->name;
|
|
}
|
|
|
|
for my $r ($c_pb_rs->all) {
|
|
unless (exists $c_numbers{$r->number}) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
$c_numbers{$r->number} = $r->name;
|
|
}
|
|
}
|
|
|
|
for my $r ($a_pb_rs->all) {
|
|
unless (exists $c_numbers{$r->number}) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
$c_numbers{$r->number} = $r->name;
|
|
}
|
|
}
|
|
|
|
for my $r ($r_pb_rs->all) {
|
|
unless (exists $c_numbers{$r->number}) {
|
|
push @pb, { name => $r->name, number => $r->number };
|
|
}
|
|
}
|
|
|
|
return [ sort { $a->{name} cmp $b->{name} } @pb ];
|
|
}
|
|
|
|
sub ui_upload_csv {
|
|
my ($c, $rs, $form, $owner, $owner_id, $action, $back) = @_;
|
|
|
|
my $upload = $c->req->upload('upload_phonebook');
|
|
my $posted = $c->req->method eq 'POST';
|
|
my @params = ( upload_phonebook => $posted ? $upload : undef, );
|
|
$form->process(
|
|
posted => $posted,
|
|
params => { @params },
|
|
action => $action,
|
|
);
|
|
if($form->validated) {
|
|
unless($upload) {
|
|
NGCP::Panel::Utils::Message::error(
|
|
c => $c,
|
|
desc => $c->loc('No phonebook entries file specified!'),
|
|
);
|
|
$c->response->redirect($back);
|
|
return;
|
|
}
|
|
my $data = $upload->slurp;
|
|
my($entries, $fails, $text_success);
|
|
try {
|
|
my ($entries, $fails, $text) =
|
|
upload_csv($c, $rs, $owner, $owner_id,
|
|
$c->req->params->{purge_existing}, \$data);
|
|
NGCP::Panel::Utils::Message::info(
|
|
c => $c,
|
|
desc => $$text,
|
|
);
|
|
} catch($e) {
|
|
NGCP::Panel::Utils::Message::error(
|
|
c => $c,
|
|
error => $e,
|
|
desc => $c->loc('Failed to upload Phonebook entries'),
|
|
);
|
|
}
|
|
|
|
$c->response->redirect($back);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
sub upload_csv {
|
|
my ($c, $rs, $owner, $owner_id, $purge, $data) = @_;
|
|
|
|
my $csv = Text::CSV_XS->new({ allow_whitespace => 1, binary => 1, keep_meta_info => 1 });
|
|
|
|
my @cols = qw/name number/;
|
|
my @fields ;
|
|
my @fails = ();
|
|
my $linenum = 0;
|
|
my @entries;
|
|
|
|
$c->model('DB')->txn_do(sub {
|
|
|
|
open(my $fh, '<:encoding(utf8)', $data);
|
|
|
|
while ( my $line = <$fh> ){
|
|
++$linenum;
|
|
next unless length $line;
|
|
unless($csv->parse($line)) {
|
|
push @fails, $linenum;
|
|
next;
|
|
}
|
|
@fields = $csv->fields();
|
|
|
|
my $row = {};
|
|
# name,number
|
|
if (scalar @fields == 2) {
|
|
@{$row}{@cols} = @fields;
|
|
# name,number,reseller_id (in case of admin uploads)
|
|
} elsif ($c->user->roles eq "admin" &&
|
|
$owner eq 'reseller' && scalar @fields == 3) {
|
|
@{$row}{@cols,'reseller_id'} = @fields;
|
|
# name,number,shared
|
|
} elsif ($owner eq 'subscriber' && scalar @fields == 3) {
|
|
@{$row}{@cols,'shared'} = @fields;
|
|
# hmmm
|
|
} else {
|
|
push @fails, $linenum;
|
|
next;
|
|
}
|
|
$row->{$owner.'_id'} //= $owner_id;
|
|
push @entries, $row;
|
|
unless ($purge) {
|
|
$rs->update_or_create($row,{key=>'rel_u_idx'});
|
|
}
|
|
}
|
|
|
|
if ($purge) {
|
|
my ($start, $end);
|
|
$start = time;
|
|
$rs->delete;
|
|
$end = time;
|
|
$c->log->debug("Purging phonebook entries took " . ($end - $start) . "s");
|
|
$start = time;
|
|
$rs->populate(\@entries);
|
|
$end = time;
|
|
$c->log->debug("Populating phonebook entries took " . ($end - $start) . "s");
|
|
}
|
|
});
|
|
|
|
my $text = $c->loc('Phonebook entries successfully uploaded');
|
|
if (@fails) {
|
|
$text .= $c->loc(", but skipped the following line numbers: ") . (join ", ", @fails);
|
|
}
|
|
|
|
return ( \@entries, \@fails, \$text );
|
|
}
|
|
|
|
sub download_csv {
|
|
my ($c, $rs, $owner, $owner_id) = @_;
|
|
|
|
my @cols = qw/name number/;
|
|
|
|
if ($owner eq 'admin') {
|
|
push @cols, 'reseller_id';
|
|
} elsif ($owner eq 'subscriber') {
|
|
push @cols, 'shared';
|
|
}
|
|
|
|
my ($start, $end);
|
|
$start = time;
|
|
foreach my $row ($rs->all) {
|
|
my %entry = $row->get_inflated_columns;
|
|
delete $entry{id};
|
|
$c->res->write_fh->write(join (",", @entry{@cols}) );
|
|
$c->res->write_fh->write("\n");
|
|
}
|
|
$c->res->write_fh->close;
|
|
$end = time;
|
|
$c->log->debug("Creating phonebook entries CSV for download took " . ($end - $start) . "s");
|
|
return 1;
|
|
}
|
|
|
|
1;
|
|
|
|
=head1 NAME
|
|
|
|
NGCP::Panel::Utils::Phonebook
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
A helper to manipulate the phonebook data
|
|
|
|
=head1 METHODS
|
|
|
|
=head2 get_reseller_phonebook
|
|
|
|
=head2 get_contract_phonebook
|
|
|
|
=head2 get_subscriber_phonebook
|
|
|
|
=head1 AUTHOR
|
|
|
|
Sipwise Development Team
|
|
|
|
=head1 LICENSE
|
|
|
|
This library is free software. You can redistribute it and/or modify
|
|
it under the same terms as Perl itself.
|
|
|
|
=cut
|
|
# vim: set tabstop=4 expandtab:
|