mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Working on scheduled reports
This commit is contained in:
parent
7336cd4234
commit
0b99e44907
@ -2,12 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Carbon;
|
||||||
|
use Str;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Ninja\Mailers\ContactMailer as Mailer;
|
use App\Ninja\Mailers\ContactMailer as Mailer;
|
||||||
|
use App\Ninja\Mailers\UserMailer;
|
||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
use App\Ninja\Repositories\InvoiceRepository;
|
use App\Ninja\Repositories\InvoiceRepository;
|
||||||
|
use App\Models\ScheduledReport;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use App\Jobs\ExportReportResults;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SendReminders.
|
* Class SendReminders.
|
||||||
@ -46,13 +51,14 @@ class SendReminders extends Command
|
|||||||
* @param InvoiceRepository $invoiceRepo
|
* @param InvoiceRepository $invoiceRepo
|
||||||
* @param accountRepository $accountRepo
|
* @param accountRepository $accountRepo
|
||||||
*/
|
*/
|
||||||
public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, AccountRepository $accountRepo)
|
public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, AccountRepository $accountRepo, UserMailer $userMailer)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->mailer = $mailer;
|
$this->mailer = $mailer;
|
||||||
$this->invoiceRepo = $invoiceRepo;
|
$this->invoiceRepo = $invoiceRepo;
|
||||||
$this->accountRepo = $accountRepo;
|
$this->accountRepo = $accountRepo;
|
||||||
|
$this->userMailer = $userMailer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fire()
|
public function fire()
|
||||||
@ -63,6 +69,28 @@ class SendReminders extends Command
|
|||||||
config(['database.default' => $database]);
|
config(['database.default' => $database]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->chargeLateFees();
|
||||||
|
$this->setReminderEmails();
|
||||||
|
$this->sendScheduledReports();
|
||||||
|
|
||||||
|
$this->info('Done');
|
||||||
|
|
||||||
|
if (\Utils::isNinjaDev()) {
|
||||||
|
$this->info('Stopping early on ninja dev');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($errorEmail = env('ERROR_EMAIL')) {
|
||||||
|
\Mail::raw('EOM', function ($message) use ($errorEmail, $database) {
|
||||||
|
$message->to($errorEmail)
|
||||||
|
->from(CONTACT_EMAIL)
|
||||||
|
->subject("SendReminders [{$database}]: Finished successfully");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function chargeLateFees()
|
||||||
|
{
|
||||||
$accounts = $this->accountRepo->findWithFees();
|
$accounts = $this->accountRepo->findWithFees();
|
||||||
$this->info(count($accounts) . ' accounts found with fees');
|
$this->info(count($accounts) . ' accounts found with fees');
|
||||||
|
|
||||||
@ -84,11 +112,13 @@ class SendReminders extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setReminderEmails()
|
||||||
|
{
|
||||||
$accounts = $this->accountRepo->findWithReminders();
|
$accounts = $this->accountRepo->findWithReminders();
|
||||||
$this->info(count($accounts) . ' accounts found with reminders');
|
$this->info(count($accounts) . ' accounts found with reminders');
|
||||||
|
|
||||||
/** @var \App\Models\Account $account */
|
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
if (! $account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
|
if (! $account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
|
||||||
continue;
|
continue;
|
||||||
@ -97,7 +127,6 @@ class SendReminders extends Command
|
|||||||
$invoices = $this->invoiceRepo->findNeedingReminding($account);
|
$invoices = $this->invoiceRepo->findNeedingReminding($account);
|
||||||
$this->info($account->name . ': ' . count($invoices) . ' invoices found');
|
$this->info($account->name . ': ' . count($invoices) . ' invoices found');
|
||||||
|
|
||||||
/** @var Invoice $invoice */
|
|
||||||
foreach ($invoices as $invoice) {
|
foreach ($invoices as $invoice) {
|
||||||
if ($reminder = $account->getInvoiceReminder($invoice)) {
|
if ($reminder = $account->getInvoiceReminder($invoice)) {
|
||||||
$this->info('Send email: ' . $invoice->id);
|
$this->info('Send email: ' . $invoice->id);
|
||||||
@ -105,15 +134,56 @@ class SendReminders extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->info('Done');
|
private function sendScheduledReports()
|
||||||
|
{
|
||||||
|
$scheduledReports = ScheduledReport::where('send_date', '=', date('Y-m-d'))->get();
|
||||||
|
$this->info(count($scheduledReports) . ' scheduled reports');
|
||||||
|
|
||||||
if ($errorEmail = env('ERROR_EMAIL')) {
|
foreach ($scheduledReports as $scheduledReport) {
|
||||||
\Mail::raw('EOM', function ($message) use ($errorEmail, $database) {
|
$config = json_decode($scheduledReport->config);
|
||||||
$message->to($errorEmail)
|
$reportType = $config->report_type;
|
||||||
->from(CONTACT_EMAIL)
|
$reportClass = '\\App\\Ninja\\Reports\\' . Str::studly($reportType) . 'Report';
|
||||||
->subject("SendReminders [{$database}]: Finished successfully");
|
|
||||||
});
|
if ($config->range) {
|
||||||
|
switch ($config->range) {
|
||||||
|
case 'this_month':
|
||||||
|
$startDate = Carbon::now()->firstOfMonth()->toDateString();
|
||||||
|
$endDate = Carbon::now()->lastOfMonth()->toDateString();
|
||||||
|
break;
|
||||||
|
case 'last_month':
|
||||||
|
$startDate = Carbon::now()->subMonth()->firstOfMonth()->toDateString();
|
||||||
|
$endDate = Carbon::now()->subMonth()->lastOfMonth()->toDateString();
|
||||||
|
break;
|
||||||
|
case 'this_year':
|
||||||
|
$startDate = Carbon::now()->firstOfYear()->toDateString();
|
||||||
|
$endDate = Carbon::now()->lastOfYear()->toDateString();
|
||||||
|
break;
|
||||||
|
case 'last_year':
|
||||||
|
$startDate = Carbon::now()->subYear()->firstOfYear()->toDateString();
|
||||||
|
$endDate = Carbon::now()->subYear()->lastOfYear()->toDateString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$startDate = Carbon::now()->subDays($config->start_date)->toDateString();
|
||||||
|
$endDate = Carbon::now()->subDays($config->end_date)->toDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
$report = new $reportClass($startDate, $endDate, true, (array) $config);
|
||||||
|
$params = [
|
||||||
|
'startDate' => $startDate,
|
||||||
|
'endDate' => $endDate,
|
||||||
|
'report' => $report,
|
||||||
|
];
|
||||||
|
|
||||||
|
$report->run();
|
||||||
|
$params = array_merge($params, $report->results());
|
||||||
|
$file = dispatch(new ExportReportResults($scheduledReport->user, $config->export_format, $reportType, $params));
|
||||||
|
|
||||||
|
if ($file) {
|
||||||
|
$this->userMailer->sendScheduledReport($scheduledReport, $file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Jobs\ExportReportResults;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Models\ScheduledReport;
|
use App\Models\ScheduledReport;
|
||||||
use Auth;
|
use Auth;
|
||||||
@ -9,7 +10,7 @@ use Input;
|
|||||||
use Str;
|
use Str;
|
||||||
use Utils;
|
use Utils;
|
||||||
use View;
|
use View;
|
||||||
use Excel;
|
use Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ReportController.
|
* Class ReportController.
|
||||||
@ -112,7 +113,7 @@ class ReportController extends BaseController
|
|||||||
$params = array_merge($params, $report->results());
|
$params = array_merge($params, $report->results());
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
case 'export':
|
case 'export':
|
||||||
return self::export($format, $reportType, $params);
|
return dispatch(new ExportReportResults(auth()->user(), $format, $reportType, $params))->export($format);
|
||||||
break;
|
break;
|
||||||
case 'schedule':
|
case 'schedule':
|
||||||
self::schedule($params, $options);
|
self::schedule($params, $options);
|
||||||
@ -136,11 +137,17 @@ class ReportController extends BaseController
|
|||||||
private function schedule($params, $options)
|
private function schedule($params, $options)
|
||||||
{
|
{
|
||||||
$options['report_type'] = $params['reportType'];
|
$options['report_type'] = $params['reportType'];
|
||||||
|
$options['range'] = request('range');
|
||||||
|
$options['start_date'] = $options['range'] ? '' : Carbon::parse($params['startDate'])->diffInDays(null, false); // null,false to get the relative/non-absolute diff
|
||||||
|
$options['end_date'] = $options['range'] ? '' : Carbon::parse($params['endDate'])->diffInDays(null, false);
|
||||||
|
|
||||||
$schedule = ScheduledReport::createNew();
|
$schedule = ScheduledReport::createNew();
|
||||||
$schedule->config = json_encode($options);
|
$schedule->config = json_encode($options);
|
||||||
$schedule->frequency = request('frequency');
|
$schedule->frequency = request('frequency');
|
||||||
|
$schedule->send_date = Utils::toSqlDate(request('send_date'));
|
||||||
$schedule->save();
|
$schedule->save();
|
||||||
|
|
||||||
|
session()->now('message', trans('texts.created_scheduled_report'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function cancelSchdule()
|
private function cancelSchdule()
|
||||||
@ -149,109 +156,7 @@ class ReportController extends BaseController
|
|||||||
->whereUserId(auth()->user()->id)
|
->whereUserId(auth()->user()->id)
|
||||||
->wherePublicId(request('scheduled_report_id'))
|
->wherePublicId(request('scheduled_report_id'))
|
||||||
->delete();
|
->delete();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
session()->now('message', trans('texts.deleted_scheduled_report'));
|
||||||
* @param $format
|
|
||||||
* @param $reportType
|
|
||||||
* @param $params
|
|
||||||
* @todo: Add summary to export
|
|
||||||
*/
|
|
||||||
private function export($format, $reportType, $params)
|
|
||||||
{
|
|
||||||
if (! Auth::user()->hasPermission('view_all')) {
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$format = strtolower($format);
|
|
||||||
$data = $params['displayData'];
|
|
||||||
$columns = $params['columns'];
|
|
||||||
$totals = $params['reportTotals'];
|
|
||||||
$report = $params['report'];
|
|
||||||
|
|
||||||
$filename = "{$params['startDate']}-{$params['endDate']}_invoiceninja-".strtolower(Utils::normalizeChars(trans("texts.$reportType")))."-report";
|
|
||||||
|
|
||||||
$formats = ['csv', 'pdf', 'xlsx', 'zip'];
|
|
||||||
if (! in_array($format, $formats)) {
|
|
||||||
throw new \Exception("Invalid format request to export report");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get labeled header
|
|
||||||
$data = array_merge(
|
|
||||||
[
|
|
||||||
array_map(function($col) {
|
|
||||||
return $col['label'];
|
|
||||||
}, $report->tableHeaderArray())
|
|
||||||
],
|
|
||||||
$data
|
|
||||||
);
|
|
||||||
|
|
||||||
$summary = [];
|
|
||||||
if (count(array_values($totals))) {
|
|
||||||
$summary[] = array_merge([
|
|
||||||
trans("texts.totals")
|
|
||||||
], array_map(function ($key) {
|
|
||||||
return trans("texts.{$key}");
|
|
||||||
}, array_keys(array_values(array_values($totals)[0])[0])));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($totals as $currencyId => $each) {
|
|
||||||
foreach ($each as $dimension => $val) {
|
|
||||||
$tmp = [];
|
|
||||||
$tmp[] = Utils::getFromCache($currencyId, 'currencies')->name . (($dimension) ? ' - ' . $dimension : '');
|
|
||||||
foreach ($val as $id => $field) {
|
|
||||||
$tmp[] = Utils::formatMoney($field, $currencyId);
|
|
||||||
}
|
|
||||||
$summary[] = $tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Excel::create($filename, function($excel) use($report, $data, $reportType, $format, $summary) {
|
|
||||||
|
|
||||||
$excel->sheet(trans("texts.$reportType"), function($sheet) use($report, $data, $format, $summary) {
|
|
||||||
$sheet->setOrientation('landscape');
|
|
||||||
$sheet->freezeFirstRow();
|
|
||||||
if ($format == 'pdf') {
|
|
||||||
$sheet->setAllBorders('thin');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($format == 'csv') {
|
|
||||||
$sheet->rows(array_merge($data, [[]], $summary));
|
|
||||||
} else {
|
|
||||||
$sheet->rows($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Styling header
|
|
||||||
$sheet->cells('A1:'.Utils::num2alpha(count($data[0])-1).'1', function($cells) {
|
|
||||||
$cells->setBackground('#777777');
|
|
||||||
$cells->setFontColor('#FFFFFF');
|
|
||||||
$cells->setFontSize(13);
|
|
||||||
$cells->setFontFamily('Calibri');
|
|
||||||
$cells->setFontWeight('bold');
|
|
||||||
});
|
|
||||||
$sheet->setAutoSize(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$excel->sheet(trans("texts.totals"), function($sheet) use($report, $summary, $format) {
|
|
||||||
$sheet->setOrientation('landscape');
|
|
||||||
$sheet->freezeFirstRow();
|
|
||||||
|
|
||||||
if ($format == 'pdf') {
|
|
||||||
$sheet->setAllBorders('thin');
|
|
||||||
}
|
|
||||||
$sheet->rows($summary);
|
|
||||||
|
|
||||||
// Styling header
|
|
||||||
$sheet->cells('A1:'.Utils::num2alpha(count($summary[0])-1).'1', function($cells) {
|
|
||||||
$cells->setBackground('#777777');
|
|
||||||
$cells->setFontColor('#FFFFFF');
|
|
||||||
$cells->setFontSize(13);
|
|
||||||
$cells->setFontFamily('Calibri');
|
|
||||||
$cells->setFontWeight('bold');
|
|
||||||
});
|
|
||||||
$sheet->setAutoSize(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
})->export($format);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
124
app/Jobs/ExportReportResults.php
Normal file
124
app/Jobs/ExportReportResults.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use Utils;
|
||||||
|
use Excel;
|
||||||
|
use App\Jobs\Job;
|
||||||
|
|
||||||
|
class ExportReportResults extends Job
|
||||||
|
{
|
||||||
|
public function __construct($user, $format, $reportType, $params)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->format = strtolower($format);
|
||||||
|
$this->reportType = $reportType;
|
||||||
|
$this->params = $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
if (! $this->user->hasPermission('view_all')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$format = $this->format;
|
||||||
|
$reportType = $this->reportType;
|
||||||
|
$params = $this->params;
|
||||||
|
|
||||||
|
$data = $params['displayData'];
|
||||||
|
$columns = $params['columns'];
|
||||||
|
$totals = $params['reportTotals'];
|
||||||
|
$report = $params['report'];
|
||||||
|
|
||||||
|
$filename = "{$params['startDate']}-{$params['endDate']}_invoiceninja-".strtolower(Utils::normalizeChars(trans("texts.$reportType")))."-report";
|
||||||
|
|
||||||
|
$formats = ['csv', 'pdf', 'xlsx', 'zip'];
|
||||||
|
if (! in_array($format, $formats)) {
|
||||||
|
throw new \Exception("Invalid format request to export report");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get labeled header
|
||||||
|
$data = array_merge(
|
||||||
|
[
|
||||||
|
array_map(function($col) {
|
||||||
|
return $col['label'];
|
||||||
|
}, $report->tableHeaderArray())
|
||||||
|
],
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
|
||||||
|
$summary = [];
|
||||||
|
if (count(array_values($totals))) {
|
||||||
|
$summary[] = array_merge([
|
||||||
|
trans("texts.totals")
|
||||||
|
], array_map(function ($key) {
|
||||||
|
return trans("texts.{$key}");
|
||||||
|
}, array_keys(array_values(array_values($totals)[0])[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($totals as $currencyId => $each) {
|
||||||
|
foreach ($each as $dimension => $val) {
|
||||||
|
$tmp = [];
|
||||||
|
$tmp[] = Utils::getFromCache($currencyId, 'currencies')->name . (($dimension) ? ' - ' . $dimension : '');
|
||||||
|
foreach ($val as $id => $field) {
|
||||||
|
$tmp[] = Utils::formatMoney($field, $currencyId);
|
||||||
|
}
|
||||||
|
$summary[] = $tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Excel::create($filename, function($excel) use($report, $data, $reportType, $format, $summary) {
|
||||||
|
|
||||||
|
$excel->sheet(trans("texts.$reportType"), function($sheet) use($report, $data, $format, $summary) {
|
||||||
|
$sheet->setOrientation('landscape');
|
||||||
|
$sheet->freezeFirstRow();
|
||||||
|
if ($format == 'pdf') {
|
||||||
|
$sheet->setAllBorders('thin');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($format == 'csv') {
|
||||||
|
$sheet->rows(array_merge($data, [[]], $summary));
|
||||||
|
} else {
|
||||||
|
$sheet->rows($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styling header
|
||||||
|
$sheet->cells('A1:'.Utils::num2alpha(count($data[0])-1).'1', function($cells) {
|
||||||
|
$cells->setBackground('#777777');
|
||||||
|
$cells->setFontColor('#FFFFFF');
|
||||||
|
$cells->setFontSize(13);
|
||||||
|
$cells->setFontFamily('Calibri');
|
||||||
|
$cells->setFontWeight('bold');
|
||||||
|
});
|
||||||
|
$sheet->setAutoSize(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$excel->sheet(trans("texts.totals"), function($sheet) use($report, $summary, $format) {
|
||||||
|
$sheet->setOrientation('landscape');
|
||||||
|
$sheet->freezeFirstRow();
|
||||||
|
|
||||||
|
if ($format == 'pdf') {
|
||||||
|
$sheet->setAllBorders('thin');
|
||||||
|
}
|
||||||
|
$sheet->rows($summary);
|
||||||
|
|
||||||
|
// Styling header
|
||||||
|
$sheet->cells('A1:'.Utils::num2alpha(count($summary[0])-1).'1', function($cells) {
|
||||||
|
$cells->setBackground('#777777');
|
||||||
|
$cells->setFontColor('#FFFFFF');
|
||||||
|
$cells->setFontSize(13);
|
||||||
|
$cells->setFontFamily('Calibri');
|
||||||
|
$cells->setFontWeight('bold');
|
||||||
|
});
|
||||||
|
$sheet->setAutoSize(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,23 @@ class ScheduledReport extends EntityModel
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'frequency',
|
'frequency',
|
||||||
'config',
|
'config',
|
||||||
|
'send_date',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
|
*/
|
||||||
|
public function account()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\Account');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\User')->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -169,4 +169,27 @@ class UserMailer extends Mailer
|
|||||||
|
|
||||||
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sendScheduledReport($scheduledReport, $file)
|
||||||
|
{
|
||||||
|
$user = $scheduledReport->user;
|
||||||
|
$config = json_decode($scheduledReport->config);
|
||||||
|
|
||||||
|
if (! $user->email) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subject = sprintf('%s - %s %s', APP_NAME, trans('texts.' . $config->report_type), trans('texts.report'));
|
||||||
|
$view = 'user_message';
|
||||||
|
$data = [
|
||||||
|
'userName' => $user->getDisplayName(),
|
||||||
|
'primaryMessage' => trans('texts.scheduled_report_attached', ['type' => trans('texts.' . $config->report_type)]),
|
||||||
|
'documents' => [[
|
||||||
|
'name' => $file->filename . '.' . $config->export_format,
|
||||||
|
'data' => $file->string($config->export_format),
|
||||||
|
]]
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,8 @@ class AddSubdomainToLookups extends Migration
|
|||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
|
||||||
$table->text('config');
|
$table->text('config');
|
||||||
$table->enum('frequency', ['daily', 'weekly', 'monthly']);
|
$table->enum('frequency', ['daily', 'weekly', 'biweekly', 'monthly']);
|
||||||
|
$table->date('send_date');
|
||||||
|
|
||||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||||
|
@ -1380,6 +1380,7 @@ $LANG = array(
|
|||||||
'freq_inactive' => 'Inactive',
|
'freq_inactive' => 'Inactive',
|
||||||
'freq_daily' => 'Daily',
|
'freq_daily' => 'Daily',
|
||||||
'freq_weekly' => 'Weekly',
|
'freq_weekly' => 'Weekly',
|
||||||
|
'freq_biweekly' => 'Biweekly',
|
||||||
'freq_two_weeks' => 'Two weeks',
|
'freq_two_weeks' => 'Two weeks',
|
||||||
'freq_four_weeks' => 'Four weeks',
|
'freq_four_weeks' => 'Four weeks',
|
||||||
'freq_monthly' => 'Monthly',
|
'freq_monthly' => 'Monthly',
|
||||||
@ -2547,6 +2548,11 @@ $LANG = array(
|
|||||||
'delivery_note' => 'Delivery Note',
|
'delivery_note' => 'Delivery Note',
|
||||||
'show_tasks_in_portal' => 'Show tasks in the client portal',
|
'show_tasks_in_portal' => 'Show tasks in the client portal',
|
||||||
'cancel_schedule' => 'Cancel Schedule',
|
'cancel_schedule' => 'Cancel Schedule',
|
||||||
|
'scheduled_report' => 'Scheduled Report',
|
||||||
|
'scheduled_report_help' => 'Email the :report report as :format to :email',
|
||||||
|
'created_scheduled_report' => 'Successfully scheduled report',
|
||||||
|
'deleted_scheduled_report' => 'Successfully canceled scheduled report',
|
||||||
|
'scheduled_report_attached' => 'Your scheduled :type report is attached.',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
color: white;
|
color: white;
|
||||||
background-color: #777 !important;
|
background-color: #777 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@stop
|
@stop
|
||||||
@ -42,10 +41,25 @@
|
|||||||
var chartEndDate = moment("{{ $endDate }}");
|
var chartEndDate = moment("{{ $endDate }}");
|
||||||
var dateRanges = {!! $account->present()->dateRangeOptions !!};
|
var dateRanges = {!! $account->present()->dateRangeOptions !!};
|
||||||
|
|
||||||
|
function resolveRange(range) {
|
||||||
|
if (range == "{{ trans('texts.this_month') }}") {
|
||||||
|
return 'this_month';
|
||||||
|
} else if (range == "{{ trans('texts.last_month') }}") {
|
||||||
|
return 'last_month';
|
||||||
|
} else if (range == "{{ trans('texts.this_year') }}") {
|
||||||
|
return 'this_year';
|
||||||
|
} else if (range == "{{ trans('texts.last_year') }}") {
|
||||||
|
return 'last_year';
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
if (isStorageSupported()) {
|
if (isStorageSupported()) {
|
||||||
var lastRange = localStorage.getItem('last:report_range');
|
var lastRange = localStorage.getItem('last:report_range');
|
||||||
|
$('#range').val(resolveRange(lastRange));
|
||||||
lastRange = dateRanges[lastRange];
|
lastRange = dateRanges[lastRange];
|
||||||
if (lastRange) {
|
if (lastRange) {
|
||||||
chartStartDate = lastRange[0];
|
chartStartDate = lastRange[0];
|
||||||
@ -58,6 +72,9 @@
|
|||||||
$('#reportrange span').html(start.format('{{ $account->getMomentDateFormat() }}') + ' - ' + end.format('{{ $account->getMomentDateFormat() }}'));
|
$('#reportrange span').html(start.format('{{ $account->getMomentDateFormat() }}') + ' - ' + end.format('{{ $account->getMomentDateFormat() }}'));
|
||||||
$('#start_date').val(start.format('YYYY-MM-DD'));
|
$('#start_date').val(start.format('YYYY-MM-DD'));
|
||||||
$('#end_date').val(end.format('YYYY-MM-DD'));
|
$('#end_date').val(end.format('YYYY-MM-DD'));
|
||||||
|
if (label) {
|
||||||
|
$('#range').val(resolveRange(label));
|
||||||
|
}
|
||||||
|
|
||||||
if (isStorageSupported() && label && label != "{{ trans('texts.custom_range') }}") {
|
if (isStorageSupported() && label && label != "{{ trans('texts.custom_range') }}") {
|
||||||
localStorage.setItem('last:report_range', label);
|
localStorage.setItem('last:report_range', label);
|
||||||
@ -86,7 +103,7 @@
|
|||||||
|
|
||||||
<div style="display:none">
|
<div style="display:none">
|
||||||
{!! Former::text('action') !!}
|
{!! Former::text('action') !!}
|
||||||
{!! Former::text('frequency') !!}
|
{!! Former::text('range') !!}
|
||||||
{!! Former::text('scheduled_report_id') !!}
|
{!! Former::text('scheduled_report_id') !!}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -194,14 +211,10 @@
|
|||||||
->withAttributes(['id' => 'cancelSchduleButton', 'onclick' => 'onCancelScheduleClick()', 'style' => 'display:none'])
|
->withAttributes(['id' => 'cancelSchduleButton', 'onclick' => 'onCancelScheduleClick()', 'style' => 'display:none'])
|
||||||
->appendIcon(Icon::create('remove')) !!}
|
->appendIcon(Icon::create('remove')) !!}
|
||||||
|
|
||||||
|
{!! Button::primary(trans('texts.schedule'))
|
||||||
|
->withAttributes(['id'=>'scheduleButton', 'onclick' => 'showScheduleModal()'])
|
||||||
|
->appendIcon(Icon::create('time')) !!}
|
||||||
|
|
||||||
{!! DropdownButton::primary(trans('texts.schedule'))
|
|
||||||
->withAttributes(['id'=>'scheduleDropDown'])
|
|
||||||
->withContents([
|
|
||||||
['url' => 'javascript:onScheduleClick("daily")', 'label' => trans('texts.freq_daily')],
|
|
||||||
['url' => 'javascript:onScheduleClick("weekly")', 'label' => trans('texts.freq_weekly')],
|
|
||||||
['url' => 'javascript:onScheduleClick("monthly")', 'label' => trans('texts.freq_monthly')],
|
|
||||||
]) !!}
|
|
||||||
</span>
|
</span>
|
||||||
{!! Button::success(trans('texts.run'))
|
{!! Button::success(trans('texts.run'))
|
||||||
->withAttributes(array('id' => 'submitButton'))
|
->withAttributes(array('id' => 'submitButton'))
|
||||||
@ -210,9 +223,6 @@
|
|||||||
->large() !!}
|
->large() !!}
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
{!! Former::close() !!}
|
|
||||||
|
|
||||||
|
|
||||||
@if (request()->report_type)
|
@if (request()->report_type)
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
@ -260,7 +270,7 @@
|
|||||||
<table class="tablesorter tablesorter-data" style="display:none">
|
<table class="tablesorter tablesorter-data" style="display:none">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{!! $report->tableHeader() !!}
|
{!! $report ? $report->tableHeader() : '' !!}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -292,6 +302,51 @@
|
|||||||
|
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
<div class="modal fade" id="scheduleModal" tabindex="-1" role="dialog" aria-labelledby="scheduleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="myModalLabel">{{ trans('texts.scheduled_report') }}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" style="width: 100%; padding-bottom: 0px !important">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
<center style="padding-bottom:40px;font-size:16px;">
|
||||||
|
<div id="scheduleHelp"></div>
|
||||||
|
</center>
|
||||||
|
|
||||||
|
{!! Former::select('frequency')
|
||||||
|
->addOption(trans('texts.freq_daily'), 'daily')
|
||||||
|
->addOption(trans('texts.freq_weekly'), 'weekly')
|
||||||
|
->addOption(trans('texts.freq_biweekly'), 'biweekly')
|
||||||
|
->addOption(trans('texts.freq_monthly'), 'monthly')
|
||||||
|
->value('weekly') !!}
|
||||||
|
|
||||||
|
{!! Former::text('send_date')
|
||||||
|
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))
|
||||||
|
->label('start_date')
|
||||||
|
->appendIcon('calendar')
|
||||||
|
->placeholder('')
|
||||||
|
->addGroupClass('send-date') !!}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer" id="signUpFooter" style="margin-top: 0px">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.cancel') }} </button>
|
||||||
|
<button type="button" class="btn btn-success" onclick="onScheduleClick()">{{ trans('texts.schedule') }} </button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!! Former::close() !!}
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var scheduledReports = {!! $scheduledReports !!};
|
var scheduledReports = {!! $scheduledReports !!};
|
||||||
@ -303,6 +358,15 @@
|
|||||||
scheduledReportMap[config.report_type] = schedule.public_id;
|
scheduledReportMap[config.report_type] = schedule.public_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showScheduleModal() {
|
||||||
|
var help = "{{ trans('texts.scheduled_report_help') }}";
|
||||||
|
help = help.replace(':email', "{{ auth()->user()->email }}");
|
||||||
|
help = help.replace(':format', $("#format").val().toUpperCase());
|
||||||
|
help = help.replace(':report', $("#report_type option:selected").text());
|
||||||
|
$('#scheduleHelp').text(help);
|
||||||
|
$('#scheduleModal').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
function onExportClick() {
|
function onExportClick() {
|
||||||
$('#action').val('export');
|
$('#action').val('export');
|
||||||
$('#submitButton').click();
|
$('#submitButton').click();
|
||||||
@ -311,7 +375,6 @@
|
|||||||
|
|
||||||
function onScheduleClick(frequency) {
|
function onScheduleClick(frequency) {
|
||||||
$('#action').val('schedule');
|
$('#action').val('schedule');
|
||||||
$('#frequency').val(frequency);
|
|
||||||
$('#submitButton').click();
|
$('#submitButton').click();
|
||||||
$('#action').val('');
|
$('#action').val('');
|
||||||
}
|
}
|
||||||
@ -346,7 +409,7 @@
|
|||||||
|
|
||||||
function setScheduleButton() {
|
function setScheduleButton() {
|
||||||
var reportType = $('#report_type').val();
|
var reportType = $('#report_type').val();
|
||||||
$('#scheduleDropDown').toggle(! scheduledReportMap[reportType]);
|
$('#scheduleButton').toggle(! scheduledReportMap[reportType]);
|
||||||
$('#cancelSchduleButton').toggle(!! scheduledReportMap[reportType]);
|
$('#cancelSchduleButton').toggle(!! scheduledReportMap[reportType]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,4 +529,8 @@
|
|||||||
keyboardNavigation: false
|
keyboardNavigation: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var currentDate = new Date();
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
|
$('#send_date').datepicker('update', currentDate);
|
||||||
|
|
||||||
@stop
|
@stop
|
||||||
|
Loading…
x
Reference in New Issue
Block a user