1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-18 00:53:10 +01:00

Working on basic reports

This commit is contained in:
Hillel Coren 2015-04-30 20:54:19 +03:00
parent bc10719fbe
commit 1d6013178f
20 changed files with 462 additions and 206 deletions

View File

@ -98,7 +98,7 @@ class AccountController extends BaseController
Auth::login($user, true);
Event::fire(new UserLoggedIn());
return Redirect::to('invoices/create')->with('sign_up', Input::get('sign_up'));
}
@ -343,40 +343,27 @@ class AccountController extends BaseController
header('Content-Disposition:attachment;filename=export.csv');
$clients = Client::scope()->get();
AccountController::exportData($output, $clients->toArray());
Utils::exportData($output, $clients->toArray());
$contacts = Contact::scope()->get();
AccountController::exportData($output, $contacts->toArray());
Utils::exportData($output, $contacts->toArray());
$invoices = Invoice::scope()->get();
AccountController::exportData($output, $invoices->toArray());
Utils::exportData($output, $invoices->toArray());
$invoiceItems = InvoiceItem::scope()->get();
AccountController::exportData($output, $invoiceItems->toArray());
Utils::exportData($output, $invoiceItems->toArray());
$payments = Payment::scope()->get();
AccountController::exportData($output, $payments->toArray());
Utils::exportData($output, $payments->toArray());
$credits = Credit::scope()->get();
AccountController::exportData($output, $credits->toArray());
Utils::exportData($output, $credits->toArray());
fclose($output);
exit;
}
private function exportData($output, $data)
{
if (count($data) > 0) {
fputcsv($output, array_keys($data[0]));
}
foreach ($data as $record) {
fputcsv($output, $record);
}
fwrite($output, "\n");
}
private function importFile()
{
$data = Session::get('data');

View File

@ -187,7 +187,7 @@ class InvoiceController extends BaseController
$server = explode('.', Request::server('HTTP_HOST'));
$subdomain = $server[0];
if ($subdomain != 'app' && $subdomain != $account->subdomain) {
if (!in_array($subdomain, ['app', 'www']) && $subdomain != $account->subdomain) {
return View::make('invoices.deleted');
}
}

View File

@ -37,18 +37,26 @@ class ReportController extends BaseController
return View::make('reports.d3', $data);
}
public function report()
public function showReports()
{
$action = Input::get('action');
if (Input::all()) {
$groupBy = Input::get('group_by');
$chartType = Input::get('chart_type');
$reportType = Input::get('report_type');
$startDate = Utils::toSqlDate(Input::get('start_date'), false);
$endDate = Utils::toSqlDate(Input::get('end_date'), false);
$enableReport = Input::get('enable_report') ? true : false;
$enableChart = Input::get('enable_chart') ? true : false;
} else {
$groupBy = 'MONTH';
$chartType = 'Bar';
$reportType = '';
$startDate = Utils::today(false)->modify('-3 month');
$endDate = Utils::today(false);
$enableReport = true;
$enableChart = true;
}
$padding = $groupBy == 'DAYOFYEAR' ? 'day' : ($groupBy == 'WEEK' ? 'week' : 'month');
@ -58,55 +66,142 @@ class ReportController extends BaseController
$maxTotals = 0;
$width = 10;
$displayData = [];
$exportData = [];
$columns = [];
$reportTotals = [
'amount' => [],
'balance' => [],
'paid' => []
];
if (Auth::user()->account->isPro()) {
foreach ([ENTITY_INVOICE, ENTITY_PAYMENT, ENTITY_CREDIT] as $entityType) {
$records = DB::table($entityType.'s')
->select(DB::raw('sum(amount) as total, '.$groupBy.'('.$entityType.'_date) as '.$groupBy))
->where('account_id', '=', Auth::user()->account_id)
->where($entityType.'s.is_deleted', '=', false)
->where($entityType.'s.'.$entityType.'_date', '>=', $startDate->format('Y-m-d'))
->where($entityType.'s.'.$entityType.'_date', '<=', $endDate->format('Y-m-d'))
->groupBy($groupBy);
if ($entityType == ENTITY_INVOICE) {
$records->where('is_quote', '=', false)
->where('is_recurring', '=', false);
if ($enableReport) {
$query = DB::table('invoices')
->join('clients', 'clients.id', '=', 'invoices.client_id')
->join('contacts', 'contacts.client_id', '=', 'clients.id')
->where('invoices.account_id', '=', Auth::user()->account_id)
->where('invoices.is_deleted', '=', false)
->where('clients.is_deleted', '=', false)
->where('contacts.deleted_at', '=', null)
->where('invoices.invoice_date', '>=', $startDate->format('Y-m-d'))
->where('invoices.invoice_date', '<=', $endDate->format('Y-m-d'))
->where('invoices.is_quote', '=', false)
->where('invoices.is_recurring', '=', false)
->where('contacts.is_primary', '=', true);
$select = ['clients.currency_id', 'contacts.first_name', 'contacts.last_name', 'contacts.email', 'clients.name as client_name', 'clients.public_id as client_public_id', 'invoices.public_id as invoice_public_id'];
if ($reportType) {
$query->groupBy('clients.id');
array_push($select, DB::raw('sum(invoices.amount) amount'), DB::raw('sum(invoices.balance) balance'), DB::raw('sum(invoices.amount - invoices.balance) paid'));
$columns = ['client', 'amount', 'paid', 'balance'];
} else {
array_push($select, 'invoices.invoice_number', 'invoices.amount', 'invoices.balance', 'invoices.invoice_date', DB::raw('(invoices.amount - invoices.balance) paid'));
$query->orderBy('invoices.id');
$columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'paid', 'balance'];
}
$query->select($select);
$data = $query->get();
$totals = $records->lists('total');
$dates = $records->lists($groupBy);
$data = array_combine($dates, $totals);
$interval = new DateInterval('P1'.substr($groupBy, 0, 1));
$period = new DatePeriod($startDate, $interval, $endDate);
$totals = [];
foreach ($period as $d) {
$dateFormat = $groupBy == 'DAYOFYEAR' ? 'z' : ($groupBy == 'WEEK' ? 'W' : 'n');
$date = $d->format($dateFormat);
$totals[] = isset($data[$date]) ? $data[$date] : 0;
if ($entityType == ENTITY_INVOICE) {
$labelFormat = $groupBy == 'DAYOFYEAR' ? 'j' : ($groupBy == 'WEEK' ? 'W' : 'F');
$label = $d->format($labelFormat);
$labels[] = $label;
foreach ($data as $record) {
// web display data
$displayRow = [link_to('/clients/'.$record->client_public_id, Utils::getClientDisplayName($record))];
if (!$reportType) {
array_push($displayRow,
link_to('/invoices/'.$record->invoice_public_id, $record->invoice_number),
Utils::fromSqlDate($record->invoice_date, true)
);
}
array_push($displayRow,
Utils::formatMoney($record->amount, $record->currency_id),
Utils::formatMoney($record->paid, $record->currency_id),
Utils::formatMoney($record->balance, $record->currency_id)
);
// export data
$exportRow = [trans('texts.client') => Utils::getClientDisplayName($record)];
if (!$reportType) {
$exportRow[trans('texts.invoice_number')] = $record->invoice_number;
$exportRow[trans('texts.invoice_date')] = Utils::fromSqlDate($record->invoice_date, true);
}
$exportRow[trans('texts.amount')] = Utils::formatMoney($record->amount, $record->currency_id);
$exportRow[trans('texts.paid')] = Utils::formatMoney($record->paid, $record->currency_id);
$exportRow[trans('texts.balance')] = Utils::formatMoney($record->balance, $record->currency_id);
$displayData[] = $displayRow;
$exportData[] = $exportRow;
$accountCurrencyId = Auth::user()->account->currency_id;
$currencyId = $record->currency_id ? $record->currency_id : ($accountCurrencyId ? $accountCurrencyId : DEFAULT_CURRENCY);
if (!isset($reportTotals['amount'][$currencyId])) {
$reportTotals['amount'][$currencyId] = 0;
$reportTotals['balance'][$currencyId] = 0;
$reportTotals['paid'][$currencyId] = 0;
}
$reportTotals['amount'][$currencyId] += $record->amount;
$reportTotals['paid'][$currencyId] += $record->paid;
$reportTotals['balance'][$currencyId] += $record->balance;
}
$max = max($totals);
if ($max > 0) {
$datasets[] = [
'totals' => $totals,
'colors' => $entityType == ENTITY_INVOICE ? '78,205,196' : ($entityType == ENTITY_CREDIT ? '199,244,100' : '255,107,107'),
];
$maxTotals = max($max, $maxTotals);
if ($action == 'export') {
self::export($exportData, $reportTotals);
}
}
$width = (ceil($maxTotals / 100) * 100) / 10;
$width = max($width, 10);
if ($enableChart) {
foreach ([ENTITY_INVOICE, ENTITY_PAYMENT, ENTITY_CREDIT] as $entityType) {
$records = DB::table($entityType.'s')
->select(DB::raw('sum(amount) as total, '.$groupBy.'('.$entityType.'_date) as '.$groupBy))
->where('account_id', '=', Auth::user()->account_id)
->where($entityType.'s.is_deleted', '=', false)
->where($entityType.'s.'.$entityType.'_date', '>=', $startDate->format('Y-m-d'))
->where($entityType.'s.'.$entityType.'_date', '<=', $endDate->format('Y-m-d'))
->groupBy($groupBy);
if ($entityType == ENTITY_INVOICE) {
$records->where('is_quote', '=', false)
->where('is_recurring', '=', false);
}
$totals = $records->lists('total');
$dates = $records->lists($groupBy);
$data = array_combine($dates, $totals);
$interval = new DateInterval('P1'.substr($groupBy, 0, 1));
$period = new DatePeriod($startDate, $interval, $endDate);
$totals = [];
foreach ($period as $d) {
$dateFormat = $groupBy == 'DAYOFYEAR' ? 'z' : ($groupBy == 'WEEK' ? 'W' : 'n');
$date = $d->format($dateFormat);
$totals[] = isset($data[$date]) ? $data[$date] : 0;
if ($entityType == ENTITY_INVOICE) {
$labelFormat = $groupBy == 'DAYOFYEAR' ? 'j' : ($groupBy == 'WEEK' ? 'W' : 'F');
$label = $d->format($labelFormat);
$labels[] = $label;
}
}
$max = max($totals);
if ($max > 0) {
$datasets[] = [
'totals' => $totals,
'colors' => $entityType == ENTITY_INVOICE ? '78,205,196' : ($entityType == ENTITY_CREDIT ? '199,244,100' : '255,107,107'),
];
$maxTotals = max($max, $maxTotals);
}
}
$width = (ceil($maxTotals / 100) * 100) / 10;
$width = max($width, 10);
}
}
$dateTypes = [
@ -120,6 +215,11 @@ class ReportController extends BaseController
'Line' => 'Line',
];
$reportTypes = [
'' => '',
'Client' => trans('texts.client')
];
$params = [
'labels' => $labels,
'datasets' => $datasets,
@ -131,8 +231,35 @@ class ReportController extends BaseController
'endDate' => $endDate->modify('-1'.$padding)->format(Session::get(SESSION_DATE_FORMAT)),
'groupBy' => $groupBy,
'feature' => ACCOUNT_CHART_BUILDER,
'displayData' => $displayData,
'columns' => $columns,
'reportTotals' => $reportTotals,
'reportTypes' => $reportTypes,
'reportType' => $reportType,
'enableChart' => $enableChart,
'enableReport' => $enableReport,
];
return View::make('reports.report_builder', $params);
return View::make('reports.chart_builder', $params);
}
private function export($data, $totals)
{
$output = fopen('php://output', 'w') or Utils::fatalError();
header('Content-Type:application/csv');
header('Content-Disposition:attachment;filename=ninja-report.csv');
Utils::exportData($output, $data);
foreach (['amount', 'paid', 'balance'] as $type) {
$csv = trans("texts.{$type}") . ',';
foreach ($totals[$type] as $currencyId => $amount) {
$csv .= Utils::formatMoney($amount, $currencyId) . ',';
}
fwrite($output, $csv . "\n");
}
fclose($output);
exit;
}
}

View File

@ -7,11 +7,17 @@ class DuplicateSubmissionCheck
// Prevent users from submitting forms twice
public function handle($request, Closure $next)
{
$path = $request->path();
if (strpos($path, 'charts_and_reports') !== false) {
return $next($request);
}
if (in_array($request->method(), ['POST', 'PUT', 'DELETE'])) {
$lastPage = session(SESSION_LAST_REQUEST_PAGE);
$lastTime = session(SESSION_LAST_REQUEST_TIME);
if ($lastPage == $request->path() && (microtime(true) - $lastTime <= 1.5)) {
if ($lastPage == $path && (microtime(true) - $lastTime <= 1.5)) {
return redirect('/')->with('warning', trans('texts.duplicate_post'));
}

View File

@ -66,7 +66,8 @@ class StartupCheck
$count = Session::get(SESSION_COUNTER, 0);
Session::put(SESSION_COUNTER, ++$count);
if (!Utils::startsWith($_SERVER['REQUEST_URI'], '/news_feed') && !Session::has('news_feed_id')) {
//if (!Utils::startsWith($_SERVER['REQUEST_URI'], '/news_feed') && !Session::has('news_feed_id')) {
if (true) {
$data = false;
if (Utils::isNinja()) {
$data = Utils::getNewsFeedResponse();
@ -75,12 +76,12 @@ class StartupCheck
$data = @json_decode($file);
}
if ($data) {
if ($data->version != NINJA_VERSION) {
if (version_compare(NINJA_VERSION, $data->version, '<')) {
$params = [
'user_version' => NINJA_VERSION,
'latest_version' => $data->version,
'releases_link' => link_to(RELEASES_URL, 'Invoice Ninja', ['target' => '_blank']),
];
'user_version' => NINJA_VERSION,
'latest_version' => $data->version,
'releases_link' => link_to(RELEASES_URL, 'Invoice Ninja', ['target' => '_blank']),
];
Session::put('news_feed_id', NEW_VERSION_AVAILABLE);
Session::put('news_feed_message', trans('texts.new_version_available', $params));
} else {

View File

@ -112,8 +112,8 @@ Route::group(['middleware' => 'auth'], function() {
Route::get('products/{product_id}/archive', 'ProductController@archive');
Route::get('company/advanced_settings/data_visualizations', 'ReportController@d3');
Route::get('company/advanced_settings/chart_builder', 'ReportController@report');
Route::post('company/advanced_settings/chart_builder', 'ReportController@report');
Route::get('company/advanced_settings/charts_and_reports', 'ReportController@showReports');
Route::post('company/advanced_settings/charts_and_reports', 'ReportController@showReports');
Route::post('company/cancel_account', 'AccountController@cancelAccount');
Route::get('account/getSearchData', array('as' => 'getSearchData', 'uses' => 'AccountController@getSearchData'));
@ -354,10 +354,11 @@ define('NINJA_GATEWAY_ID', GATEWAY_AUTHORIZE_NET);
define('NINJA_GATEWAY_CONFIG', '');
define('NINJA_WEB_URL', 'https://www.invoiceninja.com');
define('NINJA_APP_URL', 'https://app.invoiceninja.com');
define('NINJA_VERSION', '1.7.2');
define('NINJA_VERSION', '2.0.0');
define('NINJA_DATE', '2000-01-01');
define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com');
define('RELEASES_URL', 'https://github.com/hillelcoren/invoice-ninja/releases/');
define('ZAPIER_URL', 'https://zapier.com/developer/invite/11276/85cf0ee4beae8e802c6c579eb4e351f1/');
define('COUNT_FREE_DESIGNS', 4);
define('PRODUCT_ONE_CLICK_INSTALL', 1);

View File

@ -623,4 +623,17 @@ class Utils
return $str;
}
public static function exportData($output, $data)
{
if (count($data) > 0) {
fputcsv($output, array_keys($data[0]));
}
foreach ($data as $record) {
fputcsv($output, $record);
}
fwrite($output, "\n");
}
}

View File

@ -44,7 +44,7 @@ return [
|
*/
'encrypt' => false,
'encrypt' => env('SESSION_ENCRYPT', false),
/*
|--------------------------------------------------------------------------
@ -109,7 +109,7 @@ return [
|
*/
'cookie' => 'laravel_session',
'cookie' => 'ninja_session',
/*
|--------------------------------------------------------------------------
@ -135,7 +135,7 @@ return [
|
*/
'domain' => null,
'domain' => env('SESSION_DOMAIN', null),
/*
|--------------------------------------------------------------------------
@ -148,6 +148,6 @@ return [
|
*/
'secure' => false,
'secure' => env('SESSION_SECURE', false),
];

10
public/css/built.css vendored
View File

@ -3238,11 +3238,15 @@ div.checkbox > label {
z-index: 9999;
}
.dataTables_length {
div.dataTables_length {
padding-left: 20px;
padding-top: 8px;
padding-top: 10px;
}
.dataTables_length label {
div.dataTables_length select {
background-color: white !important;
}
div.dataTables_length label {
font-weight: 500;
}

10
public/css/style.css vendored
View File

@ -854,11 +854,15 @@ div.checkbox > label {
z-index: 9999;
}
.dataTables_length {
div.dataTables_length {
padding-left: 20px;
padding-top: 8px;
padding-top: 10px;
}
.dataTables_length label {
div.dataTables_length select {
background-color: white !important;
}
div.dataTables_length label {
font-weight: 500;
}

View File

@ -4,6 +4,16 @@
If you'd like to use our code to sell your own invoicing app we have an affiliate program. Get in touch for more details.
### Introduction
To setup the site you can either use the [zip file](https://www.invoiceninja.com/knowledgebase/self-host/) (easier to run) or checkout the code from GitHub (easier to make changes).
For updates follow [@invoiceninja](https://twitter.com/invoiceninja) or join the [Facebook Group](https://www.facebook.com/invoiceninja). For discussion of the code please use the [Google Group](https://groups.google.com/d/forum/invoiceninja).
If you'd like to translate the site please use [caouecs/Laravel4-long](https://github.com/caouecs/Laravel4-lang) for the starter files.
Developed by [@hillelcoren](https://twitter.com/hillelcoren) | Designed by [kantorp-wegl.in](http://kantorp-wegl.in/).
### Features
* Core application built using Laravel 5

View File

@ -637,5 +637,18 @@ return array(
'www' => 'www',
'logo' => 'Logo',
'subdomain' => 'Subdomain',
'provide_name_or_email' => 'Please provide a contact name or email',
'charts_and_reports' => 'Charts & Reports',
'chart' => 'Chart',
'report' => 'Report',
'group_by' => 'Group by',
'paid' => 'Paid',
'enable_report' => 'Report',
'enable_chart' => 'Chart',
'totals' => 'Totals',
'run' => 'Run',
'export' => 'Export',
'documentation' => 'Documentation',
'zapier' => 'Zapier <sup>Beta</sup>',
);

View File

@ -2,7 +2,7 @@
{!! HTML::nav_link('company/advanced_settings/invoice_settings', 'invoice_settings') !!}
{!! HTML::nav_link('company/advanced_settings/invoice_design', 'invoice_design') !!}
{!! HTML::nav_link('company/advanced_settings/email_templates', 'email_templates') !!}
{!! HTML::nav_link('company/advanced_settings/chart_builder', 'chart_builder') !!}
{!! HTML::nav_link('company/advanced_settings/charts_and_reports', 'charts_and_reports') !!}
{!! HTML::nav_link('company/advanced_settings/user_management', 'users_and_tokens') !!}
</ul>
<p>&nbsp;</p>

View File

@ -13,7 +13,8 @@
<div class="pull-right">
{!! Button::normal(trans('texts.view_documentation'))->asLinkTo(NINJA_WEB_URL.'/knowledgebase/api-documentation/')->withAttributes(['target' => '_blank']) !!}
{!! Button::normal(trans('texts.documentation'))->asLinkTo(NINJA_WEB_URL.'/knowledgebase/api-documentation/')->withAttributes(['target' => '_blank']) !!}
{!! Button::normal(trans('texts.zapier'))->asLinkTo(ZAPIER_URL)->withAttributes(['target' => '_blank']) !!}
@if (Utils::isPro())
{!! Button::primary(trans('texts.add_token'))->asLinkTo('/tokens/create')->appendIcon(Icon::create('plus-sign')) !!}
@endif

View File

@ -215,7 +215,7 @@
$(function() {
window.setTimeout(function() {
$(".alert-hide").fadeOut(500);
}, 3000);
}, 2000);
$('#search').focus(function(){
if (!window.hasOwnProperty('searchData')) {

View File

@ -473,7 +473,7 @@
</div>
<div class="modal-footer" style="margin-top: 0px; padding-top:0px;">
<span class="error-block" id="emailError" style="display:none;float:left;font-weight:bold">{{ trans('texts.provide_email') }}</span><span>&nbsp;</span>
<span class="error-block" id="emailError" style="display:none;float:left;font-weight:bold">{{ trans('texts.provide_name_or_email') }}</span><span>&nbsp;</span>
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.cancel') }}</button>
<button type="button" class="btn btn-default" data-bind="click: $root.showMoreFields, text: $root.showMore() ? '{{ trans('texts.less_fields') }}' : '{{ trans('texts.more_fields') }}'"></button>
<button id="clientDoneButton" type="button" class="btn btn-primary" data-bind="click: $root.clientFormComplete">{{ trans('texts.done') }}</button>

View File

@ -10,8 +10,8 @@
</div>
{!! DropdownButton::normal(trans('texts.archive'))->withContents([
['label' => trans('texts.archive_'.$entityType), 'url' => "javascript:submitForm('archive')"],
['label' => trans('texts.delete_'.$entityType), 'url' => "javascript:submitForm('delete')"],
['label' => trans('texts.archive_'.$entityType), 'url' => 'javascript:submitForm("archive")'],
['label' => trans('texts.delete_'.$entityType), 'url' => 'javascript:submitForm("delete")'],
])->withAttributes(['class'=>'archive'])->split() !!}
&nbsp;<label for="trashed" style="font-weight:normal; margin-left: 10px;">

View File

@ -0,0 +1,206 @@
@extends('accounts.nav')
@section('head')
@parent
<script src="{!! asset('js/Chart.js') !!}" type="text/javascript"></script>
@stop
@section('content')
@parent
@include('accounts.nav_advanced')
{!! Button::primary(trans('texts.data_visualizations'))
->asLinkTo('/company/advanced_settings/data_visualizations')
->withAttributes(['class' => 'pull-right'])
->appendIcon(Icon::create('globe')) !!}
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="row">
<div class="col-lg-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.settings') !!}</h3>
</div>
<div class="panel-body">
{!! Former::open()->addClass('warn-on-exit') !!}
<div style="display:none">
{!! Former::text('action') !!}
</div>
{!! Former::populateField('start_date', $startDate) !!}
{!! Former::populateField('end_date', $endDate) !!}
{!! Former::populateField('enable_report', intval($enableReport)) !!}
{!! Former::populateField('enable_chart', intval($enableChart)) !!}
{!! Former::text('start_date')->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
->append('<i class="glyphicon glyphicon-calendar" onclick="toggleDatePicker(\'start_date\')"></i>') !!}
{!! Former::text('end_date')->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
->append('<i class="glyphicon glyphicon-calendar" onclick="toggleDatePicker(\'end_date\')"></i>') !!}
<p>&nbsp;</p>
{!! Former::checkbox('enable_report')->text(trans('texts.enable')) !!}
{!! Former::select('report_type')->options($reportTypes, $reportType)->label(trans('texts.group_by')) !!}
<p>&nbsp;</p>
{!! Former::checkbox('enable_chart')->text(trans('texts.enable')) !!}
{!! Former::select('chart_type')->options($chartTypes, $chartType) !!}
{!! Former::select('group_by')->options($dateTypes, $groupBy) !!}
<p>&nbsp;</p>
@if (Auth::user()->isPro())
{!! Former::actions(
Button::primary(trans('texts.export'))->withAttributes(array('onclick' => 'onExportClick()'))->appendIcon(Icon::create('export')),
Button::success(trans('texts.run'))->withAttributes(array('id' => 'submitButton'))->submit()->appendIcon(Icon::create('play'))
) !!}
@else
<script>
$(function() {
$('form.warn-on-exit').find('input, select').prop('disabled', true);
});
</script>
@endif
{!! Former::close() !!}
</div>
</div>
</div>
<div class="col-lg-8">
@if ($enableReport)
<div class="panel panel-default">
<div class="panel-body">
<table class="table table-striped invoice-table">
<thead>
<tr>
@foreach ($columns as $column)
<th>
{{ trans("texts.{$column}") }}
</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach ($displayData as $record)
<tr>
@foreach ($record as $field)
<td>
{!! $field !!}
</td>
@endforeach
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<td><b>{{ trans('texts.totals') }}</b></td>
@if (!$reportType)
<td></td>
<td></td>
@endif
<td>
@foreach ($reportTotals['amount'] as $currencyId => $total)
<b>{{ Utils::formatMoney($total, $currencyId) }}</b><br/>
@endforeach
</td>
<td>
@foreach ($reportTotals['paid'] as $currencyId => $total)
<b>{{ Utils::formatMoney($total, $currencyId) }}</b><br/>
@endforeach
</td>
<td>
@foreach ($reportTotals['balance'] as $currencyId => $total)
<b>{{ Utils::formatMoney($total, $currencyId) }}</b><br/>
@endforeach
</td>
<td>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
@endif
@if ($enableChart)
<div class="panel panel-default">
<div class="panel-body">
<canvas id="monthly-reports" width="700" height="400"></canvas>
<p>&nbsp;</p>
<div style="padding-bottom:8px">
<div style="float:left; height:22px; width:60px; background-color:rgba(78,205,196,.5); border: 1px solid rgba(78,205,196,1)"></div>
<div style="vertical-align: middle">&nbsp;Invoices</div>
</div>
<div style="padding-bottom:8px; clear:both">
<div style="float:left; height:22px; width:60px; background-color:rgba(255,107,107,.5); border: 1px solid rgba(255,107,107,1)"></div>
<div style="vertical-align: middle">&nbsp;Payments</div>
</div>
<div style="clear:both">
<div style="float:left; height:22px; width:60px; background-color:rgba(199,244,100,.5); border: 1px solid rgba(199,244,100,1)"></div>
<div style="vertical-align: middle">&nbsp;Credits</div>
</div>
</div>
</div>
@endif
</div>
</div>
<script type="text/javascript">
function onExportClick() {
$('#action').val('export');
$('#submitButton').click();
$('#action').val('');
}
var ctx = document.getElementById('monthly-reports').getContext('2d');
var chart = {
labels: {!! json_encode($labels) !!},
datasets: [
@foreach ($datasets as $dataset)
{
data: {!! json_encode($dataset['totals']) !!},
fillColor : "rgba({!! $dataset['colors'] !!},0.5)",
strokeColor : "rgba({!! $dataset['colors'] !!},1)",
},
@endforeach
]
}
var options = {
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: {!! $scaleStepWidth !!},
scaleStartValue: 0,
scaleLabel : "<%=value%>",
};
new Chart(ctx).{!! $chartType !!}(chart, options);
</script>
@stop
@section('onReady')
$('#start_date, #end_date').datepicker({
autoclose: true,
todayHighlight: true,
keyboardNavigation: false
});
@stop

View File

@ -32,10 +32,6 @@
@parent
@include('accounts.nav_advanced')
{!! Former::open() !!}
{!! Former::legend('data_visualizations') !!}
{!! Former::close() !!}
<div id="tooltip" class="hidden">
<p>
<strong><span id="tooltipTitle"></span></strong>
@ -48,7 +44,7 @@
<form class="form-inline" role="form">
Group By &nbsp;&nbsp;
<select id="groupBySelect" class="form-control" onchange="update()">
<select id="groupBySelect" class="form-control" onchange="update()" style="background-color:white !important">
<option>Clients</option>
<option>Invoices</option>
<option>Products</option>

View File

@ -1,113 +0,0 @@
@extends('accounts.nav')
@section('head')
@parent
<script src="{!! asset('js/Chart.js') !!}" type="text/javascript"></script>
@stop
@section('content')
@parent
@include('accounts.nav_advanced')
{!! Button::primary(trans('texts.data_visualizations'))
->asLinkTo('/company/advanced_settings/data_visualizations')
->withAttributes(['class' => 'pull-right'])
->appendIcon(Icon::create('globe')) !!}
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-lg-4">
{!! Former::open()->addClass('warn-on-exit') !!}
{!! Former::populateField('start_date', $startDate) !!}
{!! Former::populateField('end_date', $endDate) !!}
{!! Former::select('chart_type')->options($chartTypes, $chartType) !!}
{!! Former::select('group_by')->options($dateTypes, $groupBy) !!}
{!! Former::text('start_date')->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
->append('<i class="glyphicon glyphicon-calendar" onclick="toggleDatePicker(\'start_date\')"></i>') !!}
{!! Former::text('end_date')->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
->append('<i class="glyphicon glyphicon-calendar" onclick="toggleDatePicker(\'end_date\')"></i>') !!}
@if (Auth::user()->isPro())
{!! Former::actions( Button::primary('Generate')->submit() ) !!}
@else
<script>
$(function() {
$('form.warn-on-exit').find('input, select').prop('disabled', true);
});
</script>
@endif
{!! Former::close() !!}
<p>&nbsp;</p>
<div style="padding-bottom:8px">
<div style="float:left; height:22px; width:60px; background-color:rgba(78,205,196,.5); border: 1px solid rgba(78,205,196,1)"></div>
<div style="vertical-align: middle">&nbsp;Invoices</div>
</div>
<div style="padding-bottom:8px; clear:both">
<div style="float:left; height:22px; width:60px; background-color:rgba(255,107,107,.5); border: 1px solid rgba(255,107,107,1)"></div>
<div style="vertical-align: middle">&nbsp;Payments</div>
</div>
<div style="clear:both">
<div style="float:left; height:22px; width:60px; background-color:rgba(199,244,100,.5); border: 1px solid rgba(199,244,100,1)"></div>
<div style="vertical-align: middle">&nbsp;Credits</div>
</div>
</div>
<div class="col-lg-8">
<canvas id="monthly-reports" width="772" height="400"></canvas>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var ctx = document.getElementById('monthly-reports').getContext('2d');
var chart = {
labels: {!! json_encode($labels) !!},
datasets: [
@foreach ($datasets as $dataset)
{
data: {!! json_encode($dataset['totals']) !!},
fillColor : "rgba({!! $dataset['colors'] !!},0.5)",
strokeColor : "rgba({!! $dataset['colors'] !!},1)",
},
@endforeach
]
}
var options = {
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: {!! $scaleStepWidth !!},
scaleStartValue: 0,
scaleLabel : "<%=formatMoney(value)%>",
};
new Chart(ctx).{!! $chartType !!}(chart, options);
</script>
@stop
@section('onReady')
$('#start_date, #end_date').datepicker({
autoclose: true,
todayHighlight: true,
keyboardNavigation: false
});
@stop