From 2fbc3dd85fcf7ee340179134193cd7bb4e814046 Mon Sep 17 00:00:00 2001 From: Irina Peshinskaya Date: Mon, 5 May 2014 03:26:23 +0300 Subject: [PATCH] MT#5879 Save state before adding from-to search to invoices. --- lib/NGCP/Panel/Controller/Invoice.pm | 22 ++++++- lib/NGCP/Panel/Model/DB/InvoiceTemplate.pm | 31 ++++++++-- lib/NGCP/Panel/Utils/Datatables.pm | 72 ++++++++++++---------- share/templates/helpers/datatables.tt | 6 +- share/templates/invoice/list.tt | 37 ++++++++++- 5 files changed, 127 insertions(+), 41 deletions(-) diff --git a/lib/NGCP/Panel/Controller/Invoice.pm b/lib/NGCP/Panel/Controller/Invoice.pm index 0bcc0dc4f5..38537b9f09 100644 --- a/lib/NGCP/Panel/Controller/Invoice.pm +++ b/lib/NGCP/Panel/Controller/Invoice.pm @@ -155,6 +155,7 @@ sub invoice_details_calls :Chained('invoice_details_zones') :PathPart('') :Captu sub invoice_list :Chained('invoice_details_calls') :PathPart('list') :Args(0) { my ($self, $c) = @_; my $backend = NGCP::Panel::Model::DB::InvoiceTemplate->new( schema => $c->model('DB') ); + $c->log->debug('invoice_list'); $c->forward( 'template_list_data' ); my $provider_id = $c->stash->{provider}->id; my $invoice_list = $backend->getProviderInvoiceList( @@ -162,19 +163,36 @@ sub invoice_list :Chained('invoice_details_calls') :PathPart('list') :Args(0) { ); $c->stash( client_contacts_list => $backend->getInvoiceProviderClients( provider_id => $provider_id ), - invoice_list => [$invoice_list->all], - template => 'invoice/list.tt', + invoice_list => [$invoice_list->all], + #invoice_list_ajax => $invoice_list, + template => 'invoice/list.tt', ); #$c->detach( $c->view() ); } +sub invoice_list_data :Chained('invoice') :PathPart('list') :Args(0) { + my ($self, $c) = @_; + my $backend = NGCP::Panel::Model::DB::InvoiceTemplate->new( schema => $c->model('DB') ); + $c->log->debug('invoice_list_data'); + my $provider_id = $c->stash->{provider}->id; + my $invoice_list_ajax = $backend->getProviderInvoiceListAjax( + provider_id => $provider_id, + ); + $c->stash( + invoice_list_data_ajax => $invoice_list_ajax, + ); + #$c->detach( $c->view() ); +} + sub invoice_data :Chained('invoice') :PathPart('data') :Args(1) { my ($self, $c) = @_; my ($invoice_id) = pop; + $c->log->debug('invoice_data'); my $backend = NGCP::Panel::Model::DB::InvoiceTemplate->new( schema => $c->model('DB') ); my $invoice = $backend->getInvoice(invoice_id => $invoice_id); $c->response->content_type('application/pdf'); $c->response->body( $invoice->first->get_column('data') ); + return; } sub template_base :Chained('base') :PathPart('template') :CaptureArgs(0) { diff --git a/lib/NGCP/Panel/Model/DB/InvoiceTemplate.pm b/lib/NGCP/Panel/Model/DB/InvoiceTemplate.pm index 20304a1b8c..be14eee15e 100644 --- a/lib/NGCP/Panel/Model/DB/InvoiceTemplate.pm +++ b/lib/NGCP/Panel/Model/DB/InvoiceTemplate.pm @@ -239,12 +239,35 @@ sub getProviderInvoiceList{ 'contact.reseller_id' => $provider_reseller_id, #$client_contract_id - contract of the client ], },{ - '+select' => ['contract_balances.invoice_id','contract_balances.start','contract_balances.end','contract_balances.cash_balance','contract_balances.free_time_balance','reseller.id','reseller.name','contact.id',], - '+as' => ['invoice_id','contract_balance_start','contract_balance_end','cash_balance','free_time_balance', 'reseller_id', 'reseller_name',,'client_contact_id' ], - 'prefetch' => [ {'contract_balances' => { 'contract' => { 'contact' => 'reseller' } } } ], - 'order_by' => [ { '-desc' => 'contract_balances.start' },{ '-asc' => 'contract_balances.end' }, ] + 'select' => [ 'contract_balances.invoice_id','contract_balances.start','contract_balances.end','contract_balances.cash_balance','contract_balances.free_time_balance','reseller.id','reseller.name','contact.id',], + 'as' => [ 'invoice_id','contract_balance_start','contract_balance_end','cash_balance','free_time_balance', 'reseller_id', 'reseller_name','client_contact_id' ], + 'prefetch' => [ {'contract_balances' => { 'contract' => { 'contact' => 'reseller' } } } ], + #'collapse' => 1, + 'order_by' => [ { '-desc' => 'contract_balances.start' },{ '-asc' => 'contract_balances.end' }, ], + 'alias' => 'me', }); } +sub getProviderInvoiceListAjax{ + my $self = shift; + my (%params) = @_; + my ($provider_reseller_id,$stime,$etime) = @params{qw/provider_id stime etime/}; + $stime ||= NGCP::Panel::Utils::DateTime::current_local()->truncate( to => 'month' ); + $etime ||= $stime->clone->add( months => 1); + $self->schema->resultset('invoices')->search({ + '-and' => + [ + 'contact.reseller_id' => $provider_reseller_id, #$client_contract_id - contract of the client + ], + },{ + #'select' => [ 'contract_balances.invoice_id','contract_balances.start','contract_balances.end','contract_balances.cash_balance','contract_balances.free_time_balance','reseller.id','reseller.name','contact.id',], + #'as' => [ 'invoice_id','contract_balance_start','contract_balance_end','cash_balance','free_time_balance', 'reseller_id', 'reseller_name','client_contact_id' ], + #'prefetch' => [ {'contract_balances' => { 'contract' => { 'contact' => 'reseller' } } } ], + ##'collapse' => 1, + #'order_by' => [ { '-desc' => 'contract_balances.start' },{ '-asc' => 'contract_balances.end' }, ], + #'alias' => 'me', + }); +} + sub getInvoice{ my $self = shift; my (%params) = @_; diff --git a/lib/NGCP/Panel/Utils/Datatables.pm b/lib/NGCP/Panel/Utils/Datatables.pm index 697f063916..c912f134f7 100644 --- a/lib/NGCP/Panel/Utils/Datatables.pm +++ b/lib/NGCP/Panel/Utils/Datatables.pm @@ -8,7 +8,7 @@ use Scalar::Util qw/blessed/; use DateTime::Format::Strptime; sub process { - my ($c, $rs, $cols, $row_func) = @_; + my ($c_, $rs, $cols, $row_func) = @_; my $use_rs_cb = ('CODE' eq (ref $rs)); my $aaData = []; @@ -18,43 +18,33 @@ sub process { # check if we need to join more tables # TODO: can we nest it deeper than once level? - set_columns($c, $cols); + set_columns($c_, $cols); for my $c(@{ $cols }) { my @parts = split /\./, $c->{name}; if($c->{literal_sql}) { - $rs = $rs->search_rs(undef, { + $rs = $rs->search_rs(undef, { '+select' => [ \[$c->{literal_sql}] ], '+as' => [ $c->{accessor} ], }); - } elsif(@parts == 2) { - $rs = $rs->search_rs(undef, { - join => $parts[0], - '+select' => [ $c->{name} ], - '+as' => [ $c->{accessor} ], - }); - } elsif(@parts == 3) { - $rs = $rs->search_rs(undef, { - join => { $parts[0] => $parts[1] }, - '+select' => [ $parts[1].'.'.$parts[2] ], - '+as' => [ $c->{accessor} ], - }); - } elsif(@parts == 4) { + } elsif( @parts > 1 ) { + my $join = $parts[$#parts-1]; + foreach my $table(reverse @parts[0..($#parts-2)]){ + $join = { $table => $join }; + } $rs = $rs->search_rs(undef, { - join => { $parts[0] => { $parts[1] => $parts[2] } }, - '+select' => [ $parts[2].'.'.$parts[3] ], + join => $join, + '+select' => [ $parts[($#parts-1)].'.'.$parts[$#parts] ], '+as' => [ $c->{accessor} ], }); - } elsif(@parts > 4) { - # TODO throw an error for now as we only support up to 3 levels } } # generic searching my @searchColumns = (); - my $searchString = $c->request->params->{sSearch} // ""; + my $searchString = $c_->request->params->{sSearch} // ""; foreach my $col(@{ $cols }) { # avoid amigious column names if we have the same column in different joined tables - my $name = _get_joined_column_name($col->{name}); + my $name = _get_joined_column_name_($col->{name}); my $stmt = { $name => { like => '%'.$searchString.'%' } }; $stmt = \[$col->{literal_sql} . " LIKE ?", [ {} => '%'.$searchString.'%'] ] if $col->{literal_sql}; @@ -65,8 +55,8 @@ sub process { } # data-range searching - my $from_date = $c->request->params->{sSearch_0} // ""; - my $to_date = $c->request->params->{sSearch_1} // ""; + my $from_date = $c_->request->params->{sSearch_0} // ""; + my $to_date = $c_->request->params->{sSearch_1} // ""; my $parser = DateTime::Format::Strptime->new( #pattern => '%Y-%m-%d %H:%M', pattern => '%Y-%m-%d', @@ -80,7 +70,7 @@ sub process { @searchColumns = (); foreach my $c(@{ $cols }) { # avoid amigious column names if we have the same column in different joined tables - my $name = _get_joined_column_name($c->{name}); + my $name = _get_joined_column_name_($c->{name}); if($c->{search_from_epoch} && $from_date) { $rs = $rs->search({ @@ -97,7 +87,7 @@ sub process { $displayRecords = $use_rs_cb ? 0 : $rs->count; # show specific row on top (e.g. if we come back from a newly created entry) - my $topId = $c->request->params->{iIdOnTop}; + my $topId = $c_->request->params->{iIdOnTop}; if(defined $topId) { if(defined(my $row = $rs->find($topId))) { push @{ $aaData }, _prune_row($cols, $row->get_inflated_columns); @@ -109,8 +99,8 @@ sub process { } # sorting - my $sortColumn = $c->request->params->{iSortCol_0}; - my $sortDirection = $c->request->params->{sSortDir_0} || 'asc'; + my $sortColumn = $c_->request->params->{iSortCol_0}; + my $sortDirection = $c_->request->params->{sSortDir_0} || 'asc'; if(defined $sortColumn && defined $sortDirection && ! $use_rs_cb) { if('desc' eq lc $sortDirection) { $sortDirection = 'desc'; @@ -122,7 +112,7 @@ sub process { my @displayedFields = (); for my $c(@{ $cols }) { next unless $c->{title}; - my $name = _get_joined_column_name($c->{name}); + my $name = _get_joined_column_name_($c->{name}); push @displayedFields, $name; } # ... and pick the name defined by the dt index @@ -136,8 +126,7 @@ sub process { } # pagination - my $pageStart = $c->request->params->{iDisplayStart}; - my $pageSize = $c->request->params->{iDisplayLength}; + my $pageSize = $c_->request->params->{iDisplayLength}; if ($use_rs_cb) { ($rs, $totalRecords, $displayRecords) = $rs->( offset => $pageStart || 0, @@ -160,11 +149,11 @@ sub process { } } - $c->stash( + $c_->stash( aaData => $aaData, iTotalRecords => $totalRecords, iTotalDisplayRecords => $displayRecords, - sEcho => int($c->request->params->{sEcho} // 1), + sEcho => int($c_->request->params->{sEcho} // 1), ); } @@ -206,14 +195,31 @@ sub _get_joined_column_name { } elsif(@parts == 3) { $name = $parts[1].'.'.$parts[2]; } elsif(@parts == 4) { + #I can suggest that in this case parts[1]may be schema name. If it isn't, then it will be incorrect sql for example for order (and in other cases too). But I didn't see schema names usage in tt (at least accounting or billing). So, switched to new sub. $name = $parts[1].'.'.$parts[2].'.'.$parts[3]; } else { # TODO throw an error for now as we only support one and two level + $name = join('.',@parts[1 .. $#parts]); } } return $name; } +sub _get_joined_column_name_{ + my $cname = shift; + my $name; + if($cname !~ /\./) { + $name = 'me.'.$cname; + } else { + my @parts = split /\./, $cname; + if(@parts == 2){ + $name = $cname; + }else{ + $name = join('.',@parts[($#parts-1) .. $#parts]); + } + } + return $name; +} 1; diff --git a/share/templates/helpers/datatables.tt b/share/templates/helpers/datatables.tt index e572590786..f36f2ad8a8 100644 --- a/share/templates/helpers/datatables.tt +++ b/share/templates/helpers/datatables.tt @@ -94,11 +94,15 @@ $(document).ready(function() { [% FOR button IN helper.dt_buttons -%] [% confirm_delete = button.name == "Delete" ? 'data-confirm="Delete"' : '' -%] [% confirm_delete = button.name == "Terminate" ? 'data-confirm="Terminate"' : confirm_delete -%] + [%IF !( button.uri.search('[\?\&]back=|^javascript:') ); %] + [% backuri = backuri | uri%] + [% button.uri = button.uri _ '?back=' _ backuri %] + [%END%] [% IF button.condition -%] if([% button.condition %]) { [% END -%] html += - '' + + '' + ' [% button.name %]' + ''; [% IF button.condition -%] diff --git a/share/templates/invoice/list.tt b/share/templates/invoice/list.tt index 4e8f614f08..8a500b5162 100644 --- a/share/templates/invoice/list.tt +++ b/share/templates/invoice/list.tt @@ -37,7 +37,42 @@
-[%PROCESS 'invoice/invoice_list.tt' %] + +[%# [%IF 0 && c.user.roles == 'admin' %] +[%# { name => 'reseller_id', title => c.loc('Reseller Id')}, +[%# { name => 'reseller_name', title => c.loc('Reseller Name')}, +[%# [%END%] +[%# { name => 'client_contact_id', title => c.loc('Client')}, +[%# { name => 'contract_balance_start', title => c.loc('Period Start')}, +[%# { name => 'contract_balance_end', title => c.loc('Period End')}, +[%# { name => 'cash_balance', title => c.loc('Cash balance')}, +[%# { name => 'free_time_balance', title => c.loc('Free time balance')},%] +[%#, title => c.loc('Reseller #')%] +[%#, title => c.loc('Reseller name')%] +[%#Dumper.dump_html(invoice_list_ajax)%] +[% + clearHelper(); + helper.name_single = c.loc('Invoices'); + helper.name = c.loc('Invoices'); + helper.dt_columns = [ + { name => 'contract_balances.contract.contact.reseller_id'}, + { name => 'contract_balances.contract.contact.reseller.name'}, + { name => 'contract_balances.contract.contact.id', title => c.loc('Client')}, + { name => 'contract_balances.invoice_id', title => c.loc('Invoice #')}, + { name => 'contract_balances.start', title => c.loc('Period Start')}, + { name => 'contract_balances.end', title => c.loc('Period End')}, + { name => 'contract_balances.cash_balance', title => c.loc('Cash balance')}, + { name => 'contract_balances.free_time_balance', title => c.loc('Free Time balance')}, + ]; + helper.dt_buttons = [ + { name = c.loc('View PDF'), uri = "javascript:window.open(\\'/invoice/data/' + full.contract_balances_invoice_id + '\\',\\'_blank\\');void(0);", class = 'btn-small btn-primary', icon = 'icon-edit' }, + ]; + helper.identifier = 'invoice_list_data_ajax'; + helper.ajax_uri = c.uri_for_action( '/invoice/ajax_datatables_data', [ provider.id, 'invoice_list_data' ] ) ; + initHelperAuto(); + PROCESS 'helpers/datatables.tt'; +-%] +[%#PROCESS 'invoice/invoice_list.tt' %]