mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Support downloading documents in reports #1606
This commit is contained in:
parent
14902baf28
commit
131f3706b0
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
@ -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[] = [
|
||||||
@ -46,7 +63,7 @@ class QuoteReport extends AbstractReport
|
|||||||
];
|
];
|
||||||
|
|
||||||
$this->addToTotals($client->currency_id, 'amount', $invoice->amount);
|
$this->addToTotals($client->currency_id, 'amount', $invoice->amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user