diff --git a/lib/NGCP/Panel/Controller/API/Invoices.pm b/lib/NGCP/Panel/Controller/API/Invoices.pm
index ce8e9051e5..984b2639fd 100644
--- a/lib/NGCP/Panel/Controller/API/Invoices.pm
+++ b/lib/NGCP/Panel/Controller/API/Invoices.pm
@@ -82,7 +82,7 @@ sub create_item {
my $period = $form->values->{period};
my $item;
try {
- my($contract_id,$customer,$tmpl,$stime,$etime,$invoice_data) = NGCP::Panel::Utils::Invoice::check_invoice_data($c, {
+ my ($contract,$tmpl,$stime,$etime,$invoice_data) = NGCP::Panel::Utils::Invoice::check_invoice_data($c, {
contract_id => $contract_id,
tmpl_id => $tmpl_id,
period_start => $period_start,
@@ -90,8 +90,7 @@ sub create_item {
period => $period,
});
$item = NGCP::Panel::Utils::Invoice::create_invoice($c,{
- contract_id => $contract_id,
- customer => $customer,
+ contract => $contract,
stime => $stime,
etime => $etime,
tmpl => $tmpl,
diff --git a/lib/NGCP/Panel/Controller/Contract.pm b/lib/NGCP/Panel/Controller/Contract.pm
index 9b1d6c4110..93cfe7a38e 100644
--- a/lib/NGCP/Panel/Controller/Contract.pm
+++ b/lib/NGCP/Panel/Controller/Contract.pm
@@ -586,6 +586,48 @@ sub is_valid_noreseller_contact {
}
}
+sub all_contracts_list :Chained('contract_list') :PathPart('all_contracts') :CaptureArgs(0) {
+ my ($self, $c) = @_;
+
+ my $now = NGCP::Panel::Utils::DateTime::current_local;
+ $c->stash->{contract_dt_columnsX} = NGCP::Panel::Utils::Datatables::set_columns($c, [
+ { name => "id", search => 1, title => $c->loc("#") },
+ { name => "external_id", search => 1, title => $c->loc("External #") },
+ { name => "contact.email", search => 1, title => $c->loc("Contact Email") },
+ #{ name => 'billing_profile_name', accessor => "billing_profile_name", search => 0, title => $c->loc('Billing Profile'),
+ # literal_sql => NGCP::Panel::Utils::BillingMappings::get_actual_billing_mapping_stmt(c => $c, now => $now, projection => 'billing_profile.name' ) },
+ { name => "status", search => 1, title => $c->loc("Status") },
+ { name => "product.name", search => 0, title => $c->loc("Product") },
+ ]);
+
+ my $rs_all_contracts = NGCP::Panel::Utils::Contract::get_contract_rs(
+ schema => $c->model('DB'),
+ now => $now,
+ include_terminated => 0,
+ );
+
+ $c->stash(rs_all_contracts => $rs_all_contracts);
+
+ #my @product_ids = map { $_->id; } $c->model('DB')->resultset('products')->search_rs({ 'class' => ['sippeering'] })->all;
+ #my $base_rs = $c->stash->{contract_select_rs};
+ #$c->stash->{peering_rs} = $base_rs->search({
+ # 'product_id' => { -in => [ @product_ids ] },
+ #});
+
+ $c->stash(ajax_uri => $c->uri_for_action("/contract/all_contracts_ajax"));
+}
+
+sub all_contracts_root :Chained('all_contracts_list') :PathPart('') :Args(0) {
+
+}
+
+sub all_contracts_ajax :Chained('all_contracts_list') :PathPart('ajax') :Args(0) {
+ my ($self, $c) = @_;
+
+ my $rs = $c->stash->{rs_all_contracts};
+ NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{contract_dt_columnsX});
+ $c->detach( $c->view("JSON") );
+}
1;
diff --git a/lib/NGCP/Panel/Controller/Invoice.pm b/lib/NGCP/Panel/Controller/Invoice.pm
index 2908880bd4..2453cfcf3e 100644
--- a/lib/NGCP/Panel/Controller/Invoice.pm
+++ b/lib/NGCP/Panel/Controller/Invoice.pm
@@ -41,8 +41,9 @@ sub inv_list :Chained('/') :PathPart('invoice') :CaptureArgs(0) :Does(ACL) :ACLD
$c->stash->{inv_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
{ name => 'id', search => 1, title => $c->loc('#') },
- { name => 'contract.id', search => 1, title => $c->loc('Customer #') },
- { name => 'contract.contact.email', search => 1, title => $c->loc('Customer Email') },
+ { name => 'contract.id', search => 1, title => $c->loc('Contract #') },
+ { name => 'contract.contact.email', search => 1, title => $c->loc('Contract Email') },
+ { name => 'contract.product.name', search => 1, title => $c->loc('Product #') },
{ name => 'serial', search => 1, title => $c->loc('Serial') },
]);
@@ -169,9 +170,9 @@ sub create :Chained('inv_list') :PathPart('create') :Args() :Does(ACL) :ACLDetac
my $tmpl_id = $form->values->{template}{id};
delete $form->values->{template};
my $period = delete $form->values->{period};
- my($customer,$tmpl,$stime,$etime,$invoice_data);
+ my($contract,$tmpl,$stime,$etime,$invoice_data);
- ($contract_id,$customer,$tmpl,$stime,$etime,$invoice_data) = NGCP::Panel::Utils::Invoice::check_invoice_data($c, {
+ ($contract,$tmpl,$stime,$etime,$invoice_data) = NGCP::Panel::Utils::Invoice::check_invoice_data($c, {
contract_id => $contract_id,
tmpl_id => $tmpl_id,
period_start => undef,
@@ -182,8 +183,7 @@ sub create :Chained('inv_list') :PathPart('create') :Args() :Does(ACL) :ACLDetac
$schema->set_transaction_isolation('READ COMMITTED');
$schema->txn_do(sub {
NGCP::Panel::Utils::Invoice::create_invoice($c,{
- contract_id => $contract_id,
- customer => $customer,
+ contract => $contract,
stime => $stime,
etime => $etime,
tmpl => $tmpl,
diff --git a/lib/NGCP/Panel/Controller/InvoiceTemplate.pm b/lib/NGCP/Panel/Controller/InvoiceTemplate.pm
index b8d8dde61d..b1c6fcb8b3 100644
--- a/lib/NGCP/Panel/Controller/InvoiceTemplate.pm
+++ b/lib/NGCP/Panel/Controller/InvoiceTemplate.pm
@@ -33,6 +33,7 @@ sub template_list :Chained('/') :PathPart('invoicetemplate') :CaptureArgs(0) :Do
{ name => 'reseller.name', search => 1, title => $c->loc('Reseller') },
{ name => 'name', search => 1, title => $c->loc('Name') },
{ name => 'type', search => 1, title => $c->loc('Type') },
+ { name => 'category', search => 1, title => $c->loc('Category') },
]);
$c->stash(template => 'invoice/template_list.tt');
@@ -119,6 +120,7 @@ sub create :Chained('template_list_restricted') :PathPart('create') :Args() {
}
}
}
+
$form->process(
posted => $posted,
params => $c->request->params,
@@ -142,6 +144,8 @@ sub create :Chained('template_list_restricted') :PathPart('create') :Args() {
$form->values->{reseller_id} = $c->user->reseller_id;
}
delete $form->values->{reseller};
+
+ $c->log->debug("roles: " . $c->user->roles);
my $dup_item = $schema->resultset('invoice_templates')->find({
reseller_id => $form->values->{reseller_id},
@@ -152,7 +156,7 @@ sub create :Chained('template_list_restricted') :PathPart('create') :Args() {
}
my $tmpl_params = $form->values;
- $tmpl_params->{data} //= NGCP::Panel::Utils::InvoiceTemplate::svg_content($c, $tmpl_params->{data});
+ $tmpl_params->{data} //= NGCP::Panel::Utils::InvoiceTemplate::svg_content($c, $tmpl_params->{category}, $tmpl_params->{data});
my $tmpl = $c->stash->{tmpl_rs}->create($tmpl_params);
delete $c->session->{created_objects}->{reseller};
@@ -287,7 +291,7 @@ sub get_content_ajax :Chained('base') :PathPart('editcontent/get/ajax') :Args(0)
my ($self, $c) = @_;
my $tmpl = $c->stash->{tmpl};
- my $content = NGCP::Panel::Utils::InvoiceTemplate::svg_content($c, $tmpl->data);
+ my $content = NGCP::Panel::Utils::InvoiceTemplate::svg_content($c, $tmpl->category, $tmpl->data);
$c->response->content_type('text/html');
$c->response->body($content);
diff --git a/lib/NGCP/Panel/Field/AllContracts.pm b/lib/NGCP/Panel/Field/AllContracts.pm
new file mode 100644
index 0000000000..76c25078b6
--- /dev/null
+++ b/lib/NGCP/Panel/Field/AllContracts.pm
@@ -0,0 +1,20 @@
+package NGCP::Panel::Field::AllContracts;
+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 => 'helpers/datatables_field.tt',
+ ajax_src => '/contract/all_contracts/ajax',
+ table_titles => ['#', 'Status', 'Contact Email', 'Product'],
+ table_fields => ['id', 'status', 'contact_email', 'product_name'],
+);
+
+no Moose;
+1;
+
+# vim: set tabstop=4 expandtab:
diff --git a/lib/NGCP/Panel/Field/InvoiceTemplate.pm b/lib/NGCP/Panel/Field/InvoiceTemplate.pm
index 10c6d62674..d2166d062a 100644
--- a/lib/NGCP/Panel/Field/InvoiceTemplate.pm
+++ b/lib/NGCP/Panel/Field/InvoiceTemplate.pm
@@ -10,8 +10,8 @@ has_field 'id' => (
required => 1,
ajax_src => '/invoicetemplate/ajax',
template => 'helpers/datatables_field.tt',
- table_titles => ['#', 'Reseller', 'Name'],
- table_fields => ['id', 'reseller_name', 'name'],
+ table_titles => ['#', 'Reseller', 'Name', 'Category'],
+ table_fields => ['id', 'reseller_name', 'name', 'category'],
);
no Moose;
diff --git a/lib/NGCP/Panel/Form/Invoice/Invoice.pm b/lib/NGCP/Panel/Form/Invoice/Invoice.pm
index 6c6a5fc839..2dfa5b4859 100644
--- a/lib/NGCP/Panel/Form/Invoice/Invoice.pm
+++ b/lib/NGCP/Panel/Form/Invoice/Invoice.pm
@@ -21,8 +21,8 @@ has_field 'template' => (
);
has_field 'contract' => (
- type => '+NGCP::Panel::Field::CustomerContract',
- label => 'Customer',
+ type => '+NGCP::Panel::Field::AllContracts',
+ label => 'Contract',
validate_when_empty => 1,
element_attr => {
rel => ['tooltip'],
diff --git a/lib/NGCP/Panel/Form/Invoice/TemplateAdmin.pm b/lib/NGCP/Panel/Form/Invoice/TemplateAdmin.pm
index 110751a6d1..e250b4b973 100644
--- a/lib/NGCP/Panel/Form/Invoice/TemplateAdmin.pm
+++ b/lib/NGCP/Panel/Form/Invoice/TemplateAdmin.pm
@@ -6,7 +6,6 @@ extends 'NGCP::Panel::Form::Invoice::TemplateReseller';
has_field 'reseller' => (
type => '+NGCP::Panel::Field::Reseller',
label => 'Reseller',
- validate_when_empty => 1,
element_attr => {
rel => ['tooltip'],
title => ['The reseller id to assign this invoice template to.']
@@ -16,9 +15,31 @@ has_field 'reseller' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
- render_list => [qw/reseller name type call_direction/],
+ render_list => [qw/reseller name type call_direction category/],
);
+sub validate {
+ my ($self) = @_;
+
+ my $c = $self->ctx;
+ return unless $c;
+
+ my $category = $self->field('category')->value;
+ my $reseller_id = $self->field('reseller')->value;
+ $reseller_id = $reseller_id->{id} if $reseller_id;
+
+ if (($category eq 'customer'
+ or $category eq 'did')
+ and not $reseller_id) {
+ $self->field('reseller')->fields->[0]->add_error($c->loc("Reseller is required for category 'customer' or 'did'"));
+ } elsif (($category eq 'peer'
+ or $category eq 'reseller')
+ and $reseller_id) {
+ $self->field('reseller')->fields->[0]->add_error($c->loc("Reseller is must be empty for category 'peer' or 'reseller'"));
+ }
+
+}
+
1;
# vim: set tabstop=4 expandtab:
diff --git a/lib/NGCP/Panel/Form/Invoice/TemplateReseller.pm b/lib/NGCP/Panel/Form/Invoice/TemplateReseller.pm
index d761a03e87..3eefc958b5 100644
--- a/lib/NGCP/Panel/Form/Invoice/TemplateReseller.pm
+++ b/lib/NGCP/Panel/Form/Invoice/TemplateReseller.pm
@@ -49,6 +49,23 @@ has_field 'call_direction' => (
},
);
+has_field 'category' => (
+ type => 'Select',
+ label => 'Category',
+ required => 1,
+ options => [
+ { label => 'customer', value => 'customer' },
+ { label => 'peer', value => 'peer' },
+ { label => 'reseller', value => 'reseller' },
+ { label => 'did', value => 'did' },
+ ],
+ default => 'customer',
+ element_attr => {
+ rel => ['tooltip'],
+ title => ['The category of the invoice.'],
+ },
+);
+
has_field 'save' => (
type => 'Submit',
value => 'Save',
@@ -59,7 +76,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
- render_list => [qw/name type call_direction/],
+ render_list => [qw/name type call_direction category/],
);
has_block 'actions' => (
diff --git a/lib/NGCP/Panel/Utils/Contract.pm b/lib/NGCP/Panel/Utils/Contract.pm
index b1e395afa2..0455e166e4 100644
--- a/lib/NGCP/Panel/Utils/Contract.pm
+++ b/lib/NGCP/Panel/Utils/Contract.pm
@@ -174,69 +174,112 @@ sub get_contract_zonesfees_rs {
my $contract_id = $params{contract_id};
my $subscriber_uuid = $params{subscriber_uuid};
my $group_detail = $params{group_by_detail};
-
- my $zonecalls_rs_out = $c->model('DB')->resultset('cdr')->search( {
- 'call_status' => 'ok',
- 'source_user_id' => ($subscriber_uuid || { '!=' => '0' }),
+ my $category = $params{category};
+
+ my $q = {
+ call_status => 'ok',
start_time =>
[ -and =>
{ '>=' => $stime->epoch},
{ '<=' => $etime->epoch},
],
- source_account_id => $contract_id,
- },{
+ };
+
+ my $q_out = { %$q };
+ my $q_in = { %$q };
+ #my $q_intra = { %$q };
+
+ my $contract = $c->model('DB')->resultset('contracts')->find({ id => $contract_id });
+ my $class;
+ $class = $contract->product()->class() if $contract;
+ if ($class) {
+ if ($class eq 'sippeering' or $class eq 'pstnpeering') {
+ $category = 'carrier' unless $category;
+ $q_out->{source_provider_id} = $contract_id;
+ $q_out->{destination_provider_id} = { '!=' => $contract_id };
+ #$q_out->{source_user_id} = { '=' => '0' };
+ $q_in->{destination_provider_id} = $contract_id;
+ $q_in->{source_provider_id} = { '!=' => $contract_id };
+ #$q_in->{destination_user_id} = { '=' => '0' };
+ #$q_intra->{source_provider_id} = $contract_id;
+ #$q_intra->{destination_provider_id} = $contract_id;
+ } elsif ($class eq 'reseller') {
+ $category = 'reseller' unless $category;
+ $q_out->{source_provider_id} = $contract_id;
+ $q_out->{destination_provider_id} = { '!=' => $contract_id }; #no intra reseller calls
+ #$q_out->{source_user_id} = { '!=' => '0' };
+ $q_in->{destination_provider_id} = $contract_id;
+ $q_in->{source_provider_id} = { '!=' => $contract_id }; #no intra reseller calls
+ #$q_in->{destination_user_id} = { '!=' => '0' };
+ #$q_intra->{source_provider_id} = $contract_id;
+ #$q_intra->{destination_provider_id} = $contract_id;
+ } elsif ($class eq 'sipaccount' or $class eq 'pbxaccount') {
+ $category = 'customer' unless $category;
+ if ($subscriber_uuid) {
+ $q_out->{source_user_id} = $subscriber_uuid;
+ $q_out->{destination_account_id} = { '!=' => $contract_id };
+
+ $q_in->{destination_user_id} = $subscriber_uuid;
+ $q_in->{source_account_id} = { '!=' => $contract_id };
+ } else {
+ $q_out->{source_account_id} = $contract_id;
+ $q_out->{destination_account_id} = { '!=' => $contract_id }; #no intra contract calls
+ #$q_out->{source_user_id} = { '!=' => '0' };
+ $q_in->{destination_account_id} = $contract_id;
+ $q_in->{source_account_id} = { '!=' => $contract_id }; #no intra contract calls
+ #$q_in->{destination_user_id} = { '!=' => '0' };
+ #$q_intra->{source_account_id} = $contract_id;
+ #$q_intra->{destination_account_id} = $contract_id;
+ }
+ }
+ }
+ $category = 'carrier' if $category eq 'peer';
+ $category = 'customer' if $category eq 'did';
+
+ my $zonecalls_rs_out = $c->model('DB')->resultset('cdr')->search($q_out,{
'select' => [
{ sum => 'me.source_customer_cost', -as => 'customercost' },
{ sum => 'me.source_carrier_cost', -as => 'carriercost' },
{ sum => 'me.source_reseller_cost', -as => 'resellercost' },
- { sum => 'me.source_customer_free_time', -as => 'free_time' },
+ { sum => "me.source_" . $category . "_free_time", -as => 'free_time' },
{ sum => 'me.duration', -as => 'duration' },
{ count => '*', -as => 'number' },
- 'source_customer_billing_zones_history.zone',
- $group_detail ? 'source_customer_billing_zones_history.detail' : (),
+ "source_" . $category . "_billing_zones_history.zone",
+ $group_detail ? "source_" . $category . "_billing_zones_history.detail" : (),
],
'as' => [
qw/customercost carriercost resellercost free_time duration number zone/,
$group_detail ? 'zone_detail' : (),
],
- join => 'source_customer_billing_zones_history',
+ join => "source_" . $category . "_billing_zones_history",
group_by => [
- 'source_customer_billing_zones_history.zone',
- $group_detail ? 'source_customer_billing_zones_history.detail' : (),
+ "source_" . $category . "_billing_zones_history.zone",
+ $group_detail ? "source_" . $category . "_billing_zones_history.detail" : (),
],
- order_by => 'source_customer_billing_zones_history.zone',
+ order_by => "source_" . $category . "_billing_zones_history.zone",
} );
- my $zonecalls_rs_in = $c->model('DB')->resultset('cdr')->search( {
- 'call_status' => 'ok',
- 'destination_user_id' => ($subscriber_uuid || { '!=' => '0' }),
- start_time =>
- [ -and =>
- { '>=' => $stime->epoch},
- { '<=' => $etime->epoch},
- ],
- destination_account_id => $contract_id,
- },{
+ my $zonecalls_rs_in = $c->model('DB')->resultset('cdr')->search($q_in,{
'select' => [
{ sum => 'me.destination_customer_cost', -as => 'customercost' },
{ sum => 'me.destination_carrier_cost', -as => 'carriercost' },
{ sum => 'me.destination_reseller_cost', -as => 'resellercost' },
- { sum => 'me.destination_customer_free_time', -as => 'free_time' },
+ { sum => "me.destination_" . $category . "_free_time", -as => 'free_time' },
{ sum => 'me.duration', -as => 'duration' },
{ count => '*', -as => 'number' },
- 'destination_customer_billing_zones_history.zone',
- $group_detail ? 'destination_customer_billing_zones_history.detail' : (),
+ "destination_" . $category . "_billing_zones_history.zone",
+ $group_detail ? "destination_" . $category . "_billing_zones_history.detail" : (),
],
'as' => [
qw/customercost carriercost resellercost free_time duration number zone/,
$group_detail ? 'zone_detail' : (),
],
- join => 'destination_customer_billing_zones_history',
+ join => "destination_" . $category . "_billing_zones_history",
group_by => [
- 'destination_customer_billing_zones_history.zone',
- $group_detail ? 'destination_customer_billing_zones_history.detail' : (),
+ "destination_" . $category . "_billing_zones_history.zone",
+ $group_detail ? "destination_" . $category . "_billing_zones_history.detail" : (),
],
- order_by => 'destination_customer_billing_zones_history.zone',
+ order_by => "destination_" . $category . "_billing_zones_history.zone",
} );
return ($zonecalls_rs_in, $zonecalls_rs_out);
@@ -285,32 +328,60 @@ sub get_contract_zonesfees {
return \%allzones;
}
-sub get_contract_calls_rs{
+sub get_contract_calls_rs {
my %params = @_;
- (my($c,$customer_contract_id,$stime,$etime,$call_direction)) = @params{qw/c customer_contract_id stime etime call_direction/};
+ my($c,$contract_id,$stime,$etime,$call_direction,$category) = @params{qw/c contract_id stime etime call_direction category/};
$stime ||= NGCP::Panel::Utils::DateTime::current_local()->truncate( to => 'month' );
$etime ||= $stime->clone->add( months => 1 );
-
- my @cols = ();
- push(@cols,qw/source_user source_domain source_cli destination_user_in/);
- #push(@cols,NGCP::Panel::Utils::CallList::get_suppression_id_colnames());
- push(@cols,qw/start_time duration call_type source_customer_cost/);
- my @colnames = @cols;
- push(@cols,qw/source_customer_billing_zones_history.zone source_customer_billing_zones_history.detail/);
- push(@colnames,qw/zone zone_detail/);
- my $calls_rs = $c->model('DB')->resultset('cdr')->search({
+ my $q = {
'call_status' => 'ok',
'start_time' =>
[ -and =>
{ '>=' => $stime->epoch},
{ '<=' => $etime->epoch},
],
- },{
+ };
+
+ my $contract = $c->model('DB')->resultset('contracts')->find({ id => $contract_id });
+ my $class;
+ $class = $contract->product()->class() if $contract;
+ my $contract_type;
+ if ($class) {
+ if ($class eq 'sippeering' or $class eq 'pstnpeering') {
+ $category = 'carrier' unless $category;
+ $contract_type = 'provider';
+ #if ($call_direction eq 'in') {
+ # $call_direction = 'out';
+ #} elsif ($call_direction eq 'out') {
+ # $call_direction = 'in';
+ #}
+ } elsif ($class eq 'reseller') {
+ $category = 'reseller' unless $category;
+ $contract_type = 'provider';
+ } elsif ($class eq 'sipaccount' or $class eq 'pbxaccount') {
+ $category = 'customer' unless $category;
+ $contract_type = 'account';
+ }
+ }
+ $category = 'carrier' if $category eq 'peer';
+ $category = 'customer' if $category eq 'did';
+
+ my @cols = ();
+ push(@cols,qw/source_user source_domain source_cli destination_user_in/);
+ #push(@cols,NGCP::Panel::Utils::CallList::get_suppression_id_colnames());
+ push(@cols,qw/start_time duration call_type/);
+ push(@cols,'source_' . $category . '_cost');
+ my @colnames = @cols;
+ push(@cols,'source_' . $category . '_billing_zones_history.zone');
+ push(@cols,'source_' . $category . '_billing_zones_history.detail');
+ push(@colnames,qw/zone zone_detail/);
+
+ my $calls_rs = $c->model('DB')->resultset('cdr')->search($q,{
select => \@cols,
as => \@colnames,
- 'join' => 'source_customer_billing_zones_history',
+ 'join' => 'source_' . $category . '_billing_zones_history',
'order_by' => 'start_time',
}
);
@@ -318,21 +389,21 @@ sub get_contract_calls_rs{
if ($call_direction) {
if ($call_direction eq "in") {
$calls_rs = $calls_rs->search({
- destination_account_id => $customer_contract_id,
+ 'destination_' . $contract_type . '_id' => $contract_id,
});
#suppression rs decoration at last, after any "select =>"
return NGCP::Panel::Utils::CallList::call_list_suppressions_rs($c,$calls_rs,NGCP::Panel::Utils::CallList::SUPPRESS_IN);
} elsif ($call_direction eq "out") {
$calls_rs = $calls_rs->search({
- source_account_id => $customer_contract_id,
+ 'source_' . $contract_type . '_id' => $contract_id,
});
#suppression rs decoration at last, after any "select =>"
return NGCP::Panel::Utils::CallList::call_list_suppressions_rs($c,$calls_rs,NGCP::Panel::Utils::CallList::SUPPRESS_OUT);
} elsif ($call_direction eq "in_out") {
$calls_rs = $calls_rs->search({
-or => [
- { source_account_id => $customer_contract_id },
- { destination_account_id => $customer_contract_id },
+ { 'source_' . $contract_type . '_id' => $contract_id },
+ { 'destination_' . $contract_type . '_id' => $contract_id },
],
});
#suppression rs decoration at last, after any "select =>"
diff --git a/lib/NGCP/Panel/Utils/Invoice.pm b/lib/NGCP/Panel/Utils/Invoice.pm
index 2cd67cbf22..07547bc267 100644
--- a/lib/NGCP/Panel/Utils/Invoice.pm
+++ b/lib/NGCP/Panel/Utils/Invoice.pm
@@ -11,15 +11,23 @@ use HTML::Entities;
use Geography::Countries qw/country/;
use HTTP::Status qw(:constants);
-sub get_invoice_amounts{
+sub get_invoice_amounts {
my(%params) = @_;
- my($customer_contract,$billing_profile,$contract_balance,$zonecalls) = @params{qw/customer_contract billing_profile contract_balance zonecalls/};
+ my($customer_contract,$billing_profile,$contract_balance,$zonecalls,$category) = @params{qw/customer_contract billing_profile contract_balance zonecalls category/};
my $invoice = {};
$billing_profile->{interval_charge} //= 0.0;
$customer_contract->{vat_rate} //= 0.0;
if ($zonecalls) {
$invoice->{amount_net} = 0.0;
- map { $invoice->{amount_net} += $_->{customercost}; } values %$zonecalls;
+ map {
+ if ($category eq 'customer' or $category eq 'did') {
+ $invoice->{amount_net} += $_->{customercost};
+ } elsif ($category eq 'reseller') {
+ $invoice->{amount_net} += $_->{resellercost};
+ } elsif ($category eq 'peer') {
+ $invoice->{amount_net} += $_->{carriercost};
+ }
+ } values %$zonecalls;
} else {
$contract_balance->{cash_balance_interval} //= 0.0;
#use Data::Dumper;
@@ -51,9 +59,9 @@ sub prepare_contact_data{
#return $contact;
}
-sub create_invoice{
+sub create_invoice {
my($c,$params) = @_;
- my($contract_id,$customer,$stime,$etime,$tmpl,$invoice_data) = @$params{qw/contract_id customer stime etime tmpl invoice_data/};
+ my($contract,$stime,$etime,$tmpl,$invoice_data) = @$params{qw/contract stime etime tmpl invoice_data/};
my $invoice;
@@ -62,64 +70,87 @@ sub create_invoice{
#this has to be refactored - select a contract balance instead of a "period"
my $balance = NGCP::Panel::Utils::ProfilePackages::get_contract_balance(
c => $c,
- contract => $customer,
+ contract => $contract,
stime => $stime,
etime => $etime,);
$stime = $balance->start;
$etime = $balance->end;
my $bm_actual = NGCP::Panel::Utils::BillingMappings::get_actual_billing_mapping(
c => $c,
- contract => $customer,
+ contract => $contract,
now => $balance->start);
my $billing_profile = $bm_actual->billing_profile;
- my $zonecalls = NGCP::Panel::Utils::Contract::get_contract_zonesfees(
+ my $zonecalls = {};
+ my $did_zonecalls = [];
+ if ($tmpl->category eq 'did') {
+ foreach my $subs ($schema->resultset('voip_subscribers')->search({
+ contract_id => $contract->id,
+ #status => { '!=' => 'terminated' },
+ #'provisioning_voip_subscriber.is_pbx_group' => 0,
+ }, #{
+ #join => 'provisioning_voip_subscriber',
+ #}
+ )->all) {
+ my $zc = NGCP::Panel::Utils::Contract::get_contract_zonesfees(
+ c => $c,
+ contract_id => $contract->id,
+ stime => $stime,
+ etime => $etime,
+ call_direction => $tmpl->call_direction,
+ group_by_detail => 1,
+ category => $tmpl->category,
+ subscriber_uuid => $subs->uuid,
+ );
+ my $s = { $subs->get_inflated_columns };
+ $s->{primary_number} = { $subs->primary_number->get_inflated_columns } if $subs->primary_number;
+ $s->{prov_subscriber} = { $subs->provisioning_voip_subscriber->get_inflated_columns } if $subs->provisioning_voip_subscriber;
+ push(@$did_zonecalls,{
+ subscriber => $s,
+ zonecalls => $zc,
+ totalcost => 0.0,
+ totalduration => 0.0,
+ }) if scalar keys %$zc;
+ }
+ }
+ $zonecalls = NGCP::Panel::Utils::Contract::get_contract_zonesfees(
c => $c,
- contract_id => $contract_id,
+ contract_id => $contract->id,
stime => $stime,
etime => $etime,
call_direction => $tmpl->call_direction,
group_by_detail => 1,
- );
- my $calllist_rs = NGCP::Panel::Utils::Contract::get_contract_calls_rs(
- c => $c,
- customer_contract_id => $contract_id,
- stime => $stime,
- etime => $etime,
- call_direction => $tmpl->call_direction,
- );
- my $calllist = [ map {
- my $call = {$_->get_inflated_columns};
- $call->{start_time} = $call->{start_time}->epoch;
- $call->{destination_user_in} =~s/%23/#/g;
- #$call->{destination_user_in} = encode_entities($call->{destination_user_in}, '<>&"#');
- $call->{source_customer_cost} += 0.0; # make sure it's a number
- NGCP::Panel::Utils::CallList::suppress_cdr_fields($c,$call,$_);
- } $calllist_rs->all ];
-
- #my $billing_mapping = $customer->billing_mappings->find($customer->get_column('bmid'));
- #my $billing_profile = $billing_mapping->billing_profile;
- #try {
- # $balance = NGCP::Panel::Utils::Contract::get_contract_balance(
- # c => $c,
- # profile => $billing_profile,
- # contract => $customer,
- # stime => $stime,
- # etime => $etime
- # );
- #} catch($e) {
- # NGCP::Panel::Utils::Message::error(
- # c => $c,
- # error => $e,
- # desc => $c->loc('Failed to get contract balance.'),
- # );
- # die;
- #}
+ category => $tmpl->category,
+ );
+
+ my $calllist = [];
+ if ($tmpl->category eq 'customer') {
+ my $calllist_rs = NGCP::Panel::Utils::Contract::get_contract_calls_rs(
+ c => $c,
+ contract_id => $contract->id,
+ stime => $stime,
+ etime => $etime,
+ call_direction => $tmpl->call_direction,
+ category => $tmpl->category,
+ );
+ $calllist = [ map {
+ my $call = {$_->get_inflated_columns};
+ $call->{start_time} = $call->{start_time}->epoch;
+ $call->{destination_user_in} =~s/%23/#/g;
+ #$call->{destination_user_in} = encode_entities($call->{destination_user_in}, '<>&"#');
+ $call->{source_customer_cost} += 0.0; # make sure it's a number
+ $call->{source_reseller_cost} += 0.0 if exists $call->{source_reseller_cost};
+ $call->{source_carrier_cost} += 0.0 if exists $call->{source_carrier_cost};
+ NGCP::Panel::Utils::CallList::suppress_cdr_fields($c,$call,$_);
+ } $calllist_rs->all ];
+ }
my $invoice_amounts = get_invoice_amounts(
- customer_contract => {$customer->get_inflated_columns},
+ customer_contract => {$contract->get_inflated_columns}, #support legacy
+ contract => {$contract->get_inflated_columns},
billing_profile => {$billing_profile->get_inflated_columns},
contract_balance => {$balance->get_inflated_columns},
zonecalls => $zonecalls,
+ category => $tmpl->category,
);
@{$invoice_data}{qw/amount_net amount_vat amount_total/} = @$invoice_amounts{qw/amount_net amount_vat amount_total/};
@@ -156,13 +187,16 @@ sub create_invoice{
# TODO: index 170 seems the upper limit here, then the calllist breaks
- $vars->{rescontact} = { $customer->contact->reseller->contract->contact->get_inflated_columns };
- $vars->{customer} = { $customer->get_inflated_columns };
- $vars->{custcontact} = { $customer->contact->get_inflated_columns };
+ $vars->{rescontact} = { $contract->contact->reseller->contract->contact->get_inflated_columns } if $contract->contact->reseller;
+ $vars->{customer} = { $contract->get_inflated_columns };
+ $vars->{contract} = { $contract->get_inflated_columns };
+ $vars->{custcontact} = { $contract->contact->get_inflated_columns };
+ $vars->{contact} = { $contract->contact->get_inflated_columns };
$vars->{billprof} = { $billing_profile->get_inflated_columns };
prepare_contact_data($vars->{billprof});
prepare_contact_data($vars->{custcontact});
+ prepare_contact_data($vars->{contact});
prepare_contact_data($vars->{rescontact});
$vars->{invoice} = {
@@ -173,6 +207,7 @@ sub create_invoice{
amount_vat => $invoice_data->{amount_vat},
amount_total => $invoice_data->{amount_total},
contract_balance => { $balance->get_inflated_columns },
+ call_direction => ($tmpl->call_direction eq 'in' ? 'from' : ($tmpl->call_direction eq 'out' ? 'to' : ($tmpl->call_direction eq 'in_out' ? 'from/to' : ''))),
};
$vars->{calls} = $calllist;
$vars->{zones} = {
@@ -181,9 +216,35 @@ sub create_invoice{
data => [ values(%{ $zonecalls }) ],
};
map {
- $vars->{zones}->{totalcost} += $_->{customercost};
+ if ($tmpl->category eq 'customer' or $tmpl->category eq 'did') {
+ $vars->{zones}->{totalcost} += $_->{customercost};
+ } elsif ($tmpl->category eq 'reseller') {
+ $vars->{zones}->{totalcost} += $_->{resellercost};
+ } elsif ($tmpl->category eq 'peer') {
+ $vars->{zones}->{totalcost} += $_->{carriercost};
+ }
$vars->{zones}->{totalduration} += $_->{duration};
} values %$zonecalls;
+
+ map {
+ my $did_zc = $_;
+ map {
+ if ($tmpl->category eq 'customer' or $tmpl->category eq 'did') {
+ $did_zc->{totalcost} += $_->{customercost};
+ } elsif ($tmpl->category eq 'reseller') {
+ $did_zc->{totalcost} += $_->{resellercost};
+ } elsif ($tmpl->category eq 'peer') {
+ $did_zc->{totalcost} += $_->{carriercost};
+ }
+ $did_zc->{totalduration} += $_->{duration};
+ $did_zc->{data} = [ values(%{ delete $did_zc->{zonecalls} }) ];
+ } values %{$did_zc->{zonecalls}};
+ } @$did_zonecalls;
+ $vars->{did_zones} = $did_zonecalls;
+
+ #use Data::Dumper;
+ #$c->log->debug(Dumper($did_zonecalls));
+
$t->process(\$svg, $vars, \$out) || do {
my $error = $t->error();
my $error_msg = "error processing template, type=".$error->type.", info='".$error->info."'";
@@ -213,56 +274,80 @@ sub create_invoice{
}
sub check_invoice_data{
- my($c,$params) = @_;
- my($contract_id,$tmpl_id,$period,$period_start,$period_end) = @$params{qw/contract_id tmpl_id period period_start period_end/};
+ my ($c,$params) = @_;
+ my ($contract_id,$tmpl_id,$period,$period_start,$period_end) = @$params{qw/contract_id tmpl_id period period_start period_end/};
my $invoice_data = {};
my $schema = $c->model('DB');
- my $customer = NGCP::Panel::Utils::Contract::get_customer_rs(c => $c)->find({ 'me.id' => $contract_id });
- unless($customer) {
- die {
- showdetails => $c->loc('Customer not found'),
- error => "invalid contract_id $contract_id",
- httpcode => HTTP_UNPROCESSABLE_ENTITY,
- };
- }
- $invoice_data->{contract_id} = $contract_id;
-
+
my $tmpl = $schema->resultset('invoice_templates')->search({
id => $tmpl_id,
});
- if($c->user->roles eq "admin") {
- } elsif($c->user->roles eq "reseller") {
+ if ($c->user->roles eq "admin") {
+ } elsif ($c->user->roles eq "reseller") {
$tmpl = $tmpl->search({
reseller_id => $c->user->reseller_id,
});
}
$tmpl = $tmpl->first;
- unless($tmpl) {
+ unless ($tmpl) {
die {
showdetails => $c->loc('Invoice template not found'),
error => "invalid template id $tmpl_id",
httpcode => HTTP_UNPROCESSABLE_ENTITY,
};
}
- unless($tmpl->data) {
+ unless ($tmpl->data) {
die {
showdetails => $c->loc('Invoice template does not have an SVG stored yet'),
error => "invalid template id $tmpl_id, data is empty",
httpcode => HTTP_UNPROCESSABLE_ENTITY,
};
}
+
+ my $contract;
+ if ('customer' eq $tmpl->category or 'did' eq $tmpl->category) {
+ $contract = NGCP::Panel::Utils::Contract::get_customer_rs(c => $c)->find({ 'me.id' => $contract_id });
+ unless($contract) {
+ die {
+ showdetails => $c->loc('Customer not found'),
+ error => "invalid contract_id $contract_id",
+ httpcode => HTTP_UNPROCESSABLE_ENTITY,
+ };
+ }
+
+ unless($contract->contact->reseller_id == $tmpl->reseller_id) {
+ die {
+ showdetails => $c->loc('Template and customer must belong to same reseller'),
+ error => "template id ".$tmpl->id." has different reseller than contract id $contract_id",
+ httpcode => HTTP_UNPROCESSABLE_ENTITY,
+ };
+ }
+ } else {
+
+ my @product_ids = map { $_->id; } $schema->resultset('products')->search_rs({ 'class' => ['pstnpeering','sippeering','reseller'] })->all;
+ $contract = NGCP::Panel::Utils::Contract::get_contract_rs(c => $c)->search_rs({
+ 'me.id' => $contract_id,
+ 'product_id' => { -in => [ @product_ids ] },
+ },{
+ join => 'contact',
+ })->first;
+
+ unless($contract) {
+ die {
+ showdetails => $c->loc('Contract not found'),
+ error => "invalid contract_id $contract_id",
+ httpcode => HTTP_UNPROCESSABLE_ENTITY,
+ };
+ }
- unless($customer->contact->reseller_id == $tmpl->reseller_id) {
- die {
- showdetails => $c->loc('Template and customer must belong to same reseller'),
- error => "template id ".$tmpl->id." has different reseller than contract id $contract_id",
- httpcode => HTTP_UNPROCESSABLE_ENTITY,
- };
}
+
+ $invoice_data->{contract_id} = $contract_id;
+ #$invoice_data->{category} = $tmpl->category;
my $stime = $period_start ? NGCP::Panel::Utils::DateTime::from_string(
$period_start
@@ -273,7 +358,8 @@ sub check_invoice_data{
$period_end
) : $stime->clone->add(months => 1)->subtract(seconds => 1);
- return($contract_id,$customer,$tmpl,$stime,$etime,$invoice_data);
+ return ($contract,$tmpl,$stime,$etime,$invoice_data);
+
}
-1;
-# vim: set tabstop=4 expandtab:
+
+1;
\ No newline at end of file
diff --git a/lib/NGCP/Panel/Utils/InvoiceTemplate.pm b/lib/NGCP/Panel/Utils/InvoiceTemplate.pm
index 41262f2faa..8cd0d3333f 100644
--- a/lib/NGCP/Panel/Utils/InvoiceTemplate.pm
+++ b/lib/NGCP/Panel/Utils/InvoiceTemplate.pm
@@ -159,18 +159,20 @@ sub get_tt {
}
sub svg_content{
- my ($c, $content) = @_;
+ my ($c, $category, $content) = @_;
unless ($content) {
#default is the same for all - I would like to move it as something constant to itils
- my $default = 'invoice/default/invoice_template_svg.tt';
+ my $default = 'invoice/default/' . $category . '_invoice_template_svg.tt';
my $t = NGCP::Panel::Utils::InvoiceTemplate::get_tt();
try {
$content = $t->context->insert($default);
} catch($e) {
# TODO: handle error!
- $c and $c->log->error("failed to load default invoice template: $e");
+ my $msg = "failed to load default $category invoice template: $e";
+ $c and $c->log->error($msg);
+ die($msg);
return;
}
}
diff --git a/share/templates/invoice/default/invoice_template_svg.tt b/share/templates/invoice/default/customer_invoice_template_svg.tt
similarity index 97%
rename from share/templates/invoice/default/invoice_template_svg.tt
rename to share/templates/invoice/default/customer_invoice_template_svg.tt
index 3997545e97..93950b65fe 100644
--- a/share/templates/invoice/default/invoice_template_svg.tt
+++ b/share/templates/invoice/default/customer_invoice_template_svg.tt
@@ -6,11 +6,11 @@
# money_signs = 3;
PROCESS "invoice/default/invoice_template_aux.tt";
- money_format(amount=(billprof.interval_charge * 100), comma='.'); fixfee = aux.val;
+ money_format(amount=(billprof.interval_charge), comma='.'); fixfee = aux.val;
money_format(amount=(zones.totalcost), comma='.'); zonefee = aux.val;
- money_format(amount=(invoice.amount_net * 100), comma='.'); netfee = aux.val;
- money_format(amount=(invoice.amount_vat * 100), comma='.'); vatfee = aux.val;
- money_format(amount=(invoice.amount_total * 100), comma='.'); allfee = aux.val;
+ money_format(amount=(invoice.amount_net), comma='.'); netfee = aux.val;
+ money_format(amount=(invoice.amount_vat), comma='.'); vatfee = aux.val;
+ money_format(amount=(invoice.amount_total), comma='.'); allfee = aux.val;
cur = billprof.currency;
p_start = date_format(thedate=invoice.period_start, format='%Y-%m-%d');
p_end = date_format(thedate=invoice.period_end, format='%Y-%m-%d');
@@ -25,7 +25,7 @@
[% rescontact.company %]
[% rescontact.street %]
- [% rescontact.postcode %] [% custcontact.city %]
+ [% rescontact.postcode %] [% rescontact.city %]
[% rescontact.country %]
Company Reg.Nr.: [% rescontact.comregnum %]
@@ -82,7 +82,7 @@
- Call Summary
+ Calls [% invoice.call_direction %] other Customers and Subscribers
Zone
Quantity
diff --git a/share/templates/invoice/default/did_invoice_template_svg.tt b/share/templates/invoice/default/did_invoice_template_svg.tt
new file mode 100644
index 0000000000..19fc45061b
--- /dev/null
+++ b/share/templates/invoice/default/did_invoice_template_svg.tt
@@ -0,0 +1,159 @@
+
+
+
diff --git a/share/templates/invoice/default/invoice_template_aux.tt b/share/templates/invoice/default/invoice_template_aux.tt
index ddcab3ba13..70739b2268 100644
--- a/share/templates/invoice/default/invoice_template_aux.tt
+++ b/share/templates/invoice/default/invoice_template_aux.tt
@@ -67,6 +67,7 @@
END;
aux.lasty = y;
END;
+
MACRO apply_units(item) BLOCK;
IF server_process_units == 'none';
'';
diff --git a/share/templates/invoice/default/peer_invoice_template_svg.tt b/share/templates/invoice/default/peer_invoice_template_svg.tt
new file mode 100644
index 0000000000..b4369ebf83
--- /dev/null
+++ b/share/templates/invoice/default/peer_invoice_template_svg.tt
@@ -0,0 +1,129 @@
+
+
+
diff --git a/share/templates/invoice/default/reseller_invoice_template_svg.tt b/share/templates/invoice/default/reseller_invoice_template_svg.tt
new file mode 100644
index 0000000000..186f9b798a
--- /dev/null
+++ b/share/templates/invoice/default/reseller_invoice_template_svg.tt
@@ -0,0 +1,129 @@
+
+
+