Support downloading documents in reports #1606

This commit is contained in:
Hillel Coren 2017-10-19 11:18:32 +03:00
parent 14902baf28
commit 131f3706b0
9 changed files with 111 additions and 21 deletions

View File

@ -72,6 +72,7 @@ class ReportController extends BaseController
'activity', 'activity',
'aging', 'aging',
'client', 'client',
'document',
'expense', 'expense',
'invoice', 'invoice',
'payment', 'payment',
@ -98,6 +99,8 @@ class ReportController extends BaseController
'date_field' => $dateField, 'date_field' => $dateField,
'invoice_status' => request()->invoice_status, 'invoice_status' => request()->invoice_status,
'group_dates_by' => request()->group_dates_by, 'group_dates_by' => request()->group_dates_by,
'document_filter' => request()->document_filter,
'export_format' => $format,
]; ];
$report = new $reportClass($startDate, $endDate, $isExport, $options); $report = new $reportClass($startDate, $endDate, $isExport, $options);
if (Input::get('report_type')) { if (Input::get('report_type')) {
@ -138,8 +141,8 @@ class ReportController extends BaseController
$filename = "{$params['startDate']}-{$params['endDate']}_invoiceninja-".strtolower(Utils::normalizeChars(trans("texts.$reportType")))."-report"; $filename = "{$params['startDate']}-{$params['endDate']}_invoiceninja-".strtolower(Utils::normalizeChars(trans("texts.$reportType")))."-report";
$formats = ['csv', 'pdf', 'xlsx']; $formats = ['csv', 'pdf', 'xlsx', 'zip'];
if(!in_array($format, $formats)) { if (! in_array($format, $formats)) {
throw new \Exception("Invalid format request to export report"); throw new \Exception("Invalid format request to export report");
} }

View File

@ -46,7 +46,7 @@ class DownloadInvoices extends Job
*/ */
public function handle(UserMailer $userMailer) public function handle(UserMailer $userMailer)
{ {
$zip = Archive::instance_by_useragent(date('Y-m-d') . '-Invoice_PDFs'); $zip = Archive::instance_by_useragent(date('Y-m-d') . '_' . str_replace(' ', '_', trans('texts.invoice_pdfs')));
foreach ($this->invoices as $invoice) { foreach ($this->invoices as $invoice) {
$zip->add_file($invoice->getFileName(), $invoice->getPDFString()); $zip->add_file($invoice->getFileName(), $invoice->getPDFString());

View File

@ -84,7 +84,7 @@ class EntityPresenter extends Presenter
$entity = $this->entity; $entity = $this->entity;
$entityType = $entity->getEntityType(); $entityType = $entity->getEntityType();
return sprintf('%s: %s', trans('texts.' . $entityType), $entity->getDisplayName()); return sprintf('%s %s', trans('texts.' . $entityType), $entity->getDisplayName());
} }
public function calendarEvent($subColors = false) public function calendarEvent($subColors = false)

View File

@ -2,6 +2,7 @@
namespace App\Ninja\Reports; namespace App\Ninja\Reports;
use Barracuda\ArchiveStream\Archive;
use App\Models\Expense; use App\Models\Expense;
use Auth; use Auth;
use Utils; use Utils;
@ -19,6 +20,12 @@ class ExpenseReport extends AbstractReport
public function run() public function run()
{ {
$account = Auth::user()->account; $account = Auth::user()->account;
$exportFormat = $this->options['export_format'];
$with = ['client.contacts', 'vendor'];
if ($exportFormat == 'zip') {
$with[] = ['documents'];
}
$expenses = Expense::scope() $expenses = Expense::scope()
->orderBy('expense_date', 'desc') ->orderBy('expense_date', 'desc')
@ -27,6 +34,19 @@ class ExpenseReport extends AbstractReport
->where('expense_date', '>=', $this->startDate) ->where('expense_date', '>=', $this->startDate)
->where('expense_date', '<=', $this->endDate); ->where('expense_date', '<=', $this->endDate);
if ($this->isExport && $exportFormat == 'zip') {
$zip = Archive::instance_by_useragent(date('Y-m-d') . '_' . str_replace(' ', '_', trans('texts.expense_documents')));
foreach ($expenses->get() as $expense) {
foreach ($expense->documents as $document) {
$name = sprintf('%s_%s_%s_%s', date('Y-m-d'), trans('texts.expense'), $expense->public_id, $document->name);
$name = str_replace(' ', '_', $name);
$zip->add_file($name, $document->getRaw());
}
}
$zip->finish();
exit;
}
foreach ($expenses->get() as $expense) { foreach ($expenses->get() as $expense) {
$amount = $expense->amountWithTax(); $amount = $expense->amountWithTax();

View File

@ -4,6 +4,7 @@ namespace App\Ninja\Reports;
use App\Models\Client; use App\Models\Client;
use Auth; use Auth;
use Barracuda\ArchiveStream\Archive;
class InvoiceReport extends AbstractReport class InvoiceReport extends AbstractReport
{ {
@ -22,6 +23,7 @@ class InvoiceReport extends AbstractReport
{ {
$account = Auth::user()->account; $account = Auth::user()->account;
$status = $this->options['invoice_status']; $status = $this->options['invoice_status'];
$exportFormat = $this->options['export_format'];
$clients = Client::scope() $clients = Client::scope()
->orderBy('name') ->orderBy('name')
@ -44,6 +46,21 @@ class InvoiceReport extends AbstractReport
}, 'invoice_items']); }, 'invoice_items']);
}]); }]);
if ($this->isExport && $exportFormat == 'zip') {
$zip = Archive::instance_by_useragent(date('Y-m-d') . '_' . str_replace(' ', '_', trans('texts.invoice_documents')));
foreach ($clients->get() as $client) {
foreach ($client->invoices as $invoice) {
foreach ($invoice->documents as $document) {
$name = sprintf('%s_%s_%s', date('Y-m-d'), $invoice->present()->titledName, $document->name);
$zip->add_file($name, $document->getRaw());
}
}
}
$zip->finish();
exit;
}
foreach ($clients->get() as $client) { foreach ($clients->get() as $client) {
foreach ($client->invoices as $invoice) { foreach ($client->invoices as $invoice) {
$payments = count($invoice->payments) ? $invoice->payments : [false]; $payments = count($invoice->payments) ? $invoice->payments : [false];

View File

@ -4,6 +4,7 @@ namespace App\Ninja\Reports;
use App\Models\Client; use App\Models\Client;
use Auth; use Auth;
use Barracuda\ArchiveStream\Archive;
class QuoteReport extends AbstractReport class QuoteReport extends AbstractReport
{ {
@ -19,6 +20,7 @@ class QuoteReport extends AbstractReport
{ {
$account = Auth::user()->account; $account = Auth::user()->account;
$status = $this->options['invoice_status']; $status = $this->options['invoice_status'];
$exportFormat = $this->options['export_format'];
$clients = Client::scope() $clients = Client::scope()
->orderBy('name') ->orderBy('name')
@ -35,6 +37,21 @@ class QuoteReport extends AbstractReport
->with(['invoice_items']); ->with(['invoice_items']);
}]); }]);
if ($this->isExport && $exportFormat == 'zip') {
$zip = Archive::instance_by_useragent(date('Y-m-d') . '_' . str_replace(' ', '_', trans('texts.quote_documents')));
foreach ($clients->get() as $client) {
foreach ($client->invoices as $invoice) {
foreach ($invoice->documents as $document) {
$name = sprintf('%s_%s_%s', date('Y-m-d'), $invoice->present()->titledName, $document->name);
$name = str_replace(' ', '_', $name);
$zip->add_file($name, $document->getRaw());
}
}
}
$zip->finish();
exit;
}
foreach ($clients->get() as $client) { foreach ($clients->get() as $client) {
foreach ($client->invoices as $invoice) { foreach ($client->invoices as $invoice) {
$this->data[] = [ $this->data[] = [

View File

@ -1099,8 +1099,9 @@ $LANG = array(
'email_documents_header' => 'Documents:', 'email_documents_header' => 'Documents:',
'email_documents_example_1' => 'Widgets Receipt.pdf', 'email_documents_example_1' => 'Widgets Receipt.pdf',
'email_documents_example_2' => 'Final Deliverable.zip', 'email_documents_example_2' => 'Final Deliverable.zip',
'invoice_documents' => 'Documents', 'quote_documents' => 'Quote Documents',
'expense_documents' => 'Attached Documents', 'invoice_documents' => 'Invoice Documents',
'expense_documents' => 'Expense Documents',
'invoice_embed_documents' => 'Embed Documents', 'invoice_embed_documents' => 'Embed Documents',
'invoice_embed_documents_help' => 'Include attached images in the invoice.', 'invoice_embed_documents_help' => 'Include attached images in the invoice.',
'document_email_attachment' => 'Attach Documents', 'document_email_attachment' => 'Attach Documents',
@ -2488,6 +2489,9 @@ $LANG = array(
'task_rate' => 'Task Rate', 'task_rate' => 'Task Rate',
'task_rate_help' => 'Set the default <b>rate for invoiced tasks</b>.', 'task_rate_help' => 'Set the default <b>rate for invoiced tasks</b>.',
'past_due' => 'Past Due', 'past_due' => 'Past Due',
'document' => 'Document',
'invoice_or_expense' => 'Invoice/Expense',
'invoice_pdfs' => 'Invoice PDFs',
); );

View File

@ -288,7 +288,7 @@
<li role="presentation"><a href="#footer" aria-controls="footer" role="tab" data-toggle="tab">{{ trans("texts.footer") }}</a></li> <li role="presentation"><a href="#footer" aria-controls="footer" role="tab" data-toggle="tab">{{ trans("texts.footer") }}</a></li>
@if ($account->hasFeature(FEATURE_DOCUMENTS)) @if ($account->hasFeature(FEATURE_DOCUMENTS))
<li role="presentation"><a href="#attached-documents" aria-controls="attached-documents" role="tab" data-toggle="tab"> <li role="presentation"><a href="#attached-documents" aria-controls="attached-documents" role="tab" data-toggle="tab">
{{ trans("texts.invoice_documents") }} {{ trans("texts.documents") }}
@if ($count = ($invoice->countDocuments($expenses))) @if ($count = ($invoice->countDocuments($expenses)))
({{ $count }}) ({{ $count }})
@endif @endif

View File

@ -141,6 +141,13 @@
->addOption(trans('texts.payment_date'), FILTER_PAYMENT_DATE) !!} ->addOption(trans('texts.payment_date'), FILTER_PAYMENT_DATE) !!}
</div> </div>
<div id="invoiceOrExpenseField" style="display:none">
{!! Former::select('document_filter')->label('filter')
->addOption(trans('texts.all'), '')
->addOption(trans('texts.invoice'), 'invoice')
->addOption(trans('texts.expense'), 'expense') !!}
</div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
@ -167,6 +174,7 @@
<center> <center>
{!! DropdownButton::primary(trans('texts.export')) {!! DropdownButton::primary(trans('texts.export'))
->large() ->large()
->withAttributes(array('id' => 'export-button'))
->withContents([ ->withContents([
['url' => 'javascript:onExportClick("csv")', 'label' => 'CSV'], ['url' => 'javascript:onExportClick("csv")', 'label' => 'CSV'],
['url' => 'javascript:onExportClick("xlsx")', 'label' => 'XLSX'], ['url' => 'javascript:onExportClick("xlsx")', 'label' => 'XLSX'],
@ -268,20 +276,25 @@
$('#action').val('export'); $('#action').val('export');
$('#format').val(format); $('#format').val(format);
$('#submitButton').click(); $('#submitButton').click();
$('#action').val(''); $('#action').val('');
} }
function setFiltersShown() { function setFiltersShown() {
var val = $('#report_type').val(); var val = $('#report_type').val();
if (val == '{{ ENTITY_TAX_RATE }}') { $('#dateField').toggle(val == '{{ ENTITY_TAX_RATE }}');
$('#dateField').show(); $('#statusField').toggle(val == '{{ ENTITY_INVOICE }}' || val == '{{ ENTITY_PRODUCT }}');
} else { $('#invoiceOrExpenseField').toggle(val == '{{ ENTITY_DOCUMENT }}');
$('#dateField').hide(); }
}
if (val == '{{ ENTITY_INVOICE }}' || val == '{{ ENTITY_PRODUCT }}') { function setDocumentZipShown() {
$('#statusField').show(); var $ul = $('#export-button').next();
} else { var val = $('#report_type').val();
$('#statusField').hide(); var showOption = ['invoice', 'quote', 'expense', 'document'].indexOf(val) >= 0;
var numOptions = $ul.children().length;
if (showOption && numOptions == 3) {
$ul.append('<li><a href="javascript:onExportClick(\'zip\')">ZIP - {{ trans('texts.documents') }}</a></li>');
} else if (! showOption && numOptions == 4) {
$ul.find('li:last-child').remove();
} }
} }
@ -298,9 +311,17 @@
toggleDatePicker('end_date'); toggleDatePicker('end_date');
}); });
$('#document_filter').change(function() {
var val = $('#document_filter').val();
if (isStorageSupported()) {
localStorage.setItem('last:document_filter', val);
}
});
$('#report_type').change(function() { $('#report_type').change(function() {
var val = $('#report_type').val(); var val = $('#report_type').val();
setFiltersShown(); setFiltersShown();
setDocumentZipShown();
if (isStorageSupported()) { if (isStorageSupported()) {
localStorage.setItem('last:report_type', val); localStorage.setItem('last:report_type', val);
} }
@ -361,11 +382,19 @@
widgets: ['zebra', 'uitheme'], widgets: ['zebra', 'uitheme'],
}).show(); }).show();
var lastReportType = localStorage.getItem('last:report_type'); if (isStorageSupported()) {
if (lastReportType) { var lastReportType = localStorage.getItem('last:report_type');
$('#report_type').val(lastReportType); if (lastReportType) {
$('#report_type').val(lastReportType);
}
var lastDocumentFilter = localStorage.getItem('last:document_filter');
if (lastDocumentFilter) {
$('#document_filter').val(lastDocumentFilter);
}
} }
setFiltersShown(); setFiltersShown();
setDocumentZipShown();
}); });
}) })