1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-19 16:01:34 +02:00

Enhancements to the dashboard

This commit is contained in:
Hillel Coren 2015-07-29 22:55:12 +03:00
parent abe3eb6367
commit 914334511e
19 changed files with 175 additions and 91 deletions

View File

@ -211,7 +211,7 @@ class AccountController extends BaseController
$client->work_email = '';
$invoice->invoice_number = $account->getNextInvoiceNumber();
$invoice->invoice_date = date_create()->format('Y-m-d');
$invoice->invoice_date = Utils::fromSqlDate(date('Y-m-d'));
$invoice->account = json_decode($account->toJson());
$invoice->amount = $invoice->balance = 100;

View File

@ -88,7 +88,9 @@ class AppController extends BaseController
"MAIL_HOST={$mail['host']}\n".
"MAIL_USERNAME={$mail['username']}\n".
"MAIL_FROM_NAME={$mail['from']['name']}\n".
"MAIL_PASSWORD={$mail['password']}\n";
"MAIL_PASSWORD={$mail['password']}\n\n".
"ADMIN_USER_ID=1\n".
"ALLOW_NEW_ACCOUNTS\n";
// Write Config Settings
$fp = fopen(base_path()."/.env", 'w');

View File

@ -5,6 +5,7 @@ use DB;
use View;
use App\Models\Activity;
use App\Models\Invoice;
use App\Models\Payment;
class DashboardController extends BaseController
{
@ -50,41 +51,81 @@ class DashboardController extends BaseController
->groupBy(DB::raw('CASE WHEN clients.currency_id IS NULL THEN CASE WHEN accounts.currency_id IS NULL THEN 1 ELSE accounts.currency_id END ELSE clients.currency_id END'))
->get();
$select = DB::raw('SUM(clients.balance) as value, clients.currency_id as currency_id');
$balances = DB::table('accounts')
->select($select)
->leftJoin('clients', 'accounts.id', '=', 'clients.account_id')
->where('accounts.id', '=', Auth::user()->account_id)
->where('clients.is_deleted', '=', false)
->groupBy('accounts.id')
->groupBy(DB::raw('CASE WHEN clients.currency_id IS NULL THEN CASE WHEN accounts.currency_id IS NULL THEN 1 ELSE accounts.currency_id END ELSE clients.currency_id END'))
->get();
$activities = Activity::where('activities.account_id', '=', Auth::user()->account_id)
->where('activity_type_id', '>', 0)
->orderBy('created_at', 'desc')->take(14)->get();
->orderBy('created_at', 'desc')
->take(50)
->get();
$pastDue = Invoice::scope()->whereHas('client', function($query) {
$query->where('deleted_at', '=', null);
})
->where('due_date', '<', date('Y-m-d'))
->where('balance', '>', 0)
->where('is_recurring', '=', false)
->where('is_quote', '=', false)
->where('is_deleted', '=', false)
->orderBy('due_date', 'asc')->take(6)->get();
$pastDue = DB::table('invoices')
->leftJoin('clients', 'clients.id', '=', 'invoices.client_id')
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
->where('invoices.account_id', '=', Auth::user()->account_id)
->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null)
->where('invoices.is_recurring', '=', false)
->where('invoices.is_quote', '=', false)
->where('invoices.balance', '>', 0)
->where('invoices.is_deleted', '=', false)
->where('contacts.is_primary', '=', true)
->where('invoices.due_date', '<', date('Y-m-d'))
->select(['invoices.due_date', 'invoices.balance', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id'])
->orderBy('invoices.due_date', 'asc')
->take(50)
->get();
$upcoming = DB::table('invoices')
->leftJoin('clients', 'clients.id', '=', 'invoices.client_id')
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
->where('invoices.account_id', '=', Auth::user()->account_id)
->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null)
->where('invoices.is_recurring', '=', false)
->where('invoices.is_quote', '=', false)
->where('invoices.balance', '>', 0)
->where('invoices.is_deleted', '=', false)
->where('contacts.is_primary', '=', true)
->where('invoices.due_date', '>=', date('Y-m-d'))
->orderBy('invoices.due_date', 'asc')
->take(50)
->select(['invoices.due_date', 'invoices.balance', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id'])
->get();
$payments = DB::table('payments')
->leftJoin('clients', 'clients.id', '=', 'payments.client_id')
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
->where('payments.account_id', '=', Auth::user()->account_id)
->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null)
->where('contacts.is_primary', '=', true)
->select(['payments.payment_date', 'payments.amount', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id'])
->orderBy('payments.payment_date', 'asc')
->take(50)
->get();
$upcoming = Invoice::scope()->whereHas('client', function($query) {
$query->where('deleted_at', '=', null);
})
->where('due_date', '>=', date('Y-m-d'))
->where('balance', '>', 0)
->where('is_recurring', '=', false)
->where('is_quote', '=', false)
->where('is_deleted', '=', false)
->orderBy('due_date', 'asc')->take(6)->get();
$data = [
'account' => Auth::user()->account,
'paidToDate' => $paidToDate,
'balances' => $balances,
'averageInvoice' => $averageInvoice,
//'billedClients' => $metrics ? $metrics->billed_clients : 0,
'invoicesSent' => $metrics ? $metrics->invoices_sent : 0,
'activeClients' => $metrics ? $metrics->active_clients : 0,
'activities' => $activities,
'pastDue' => $pastDue,
'upcoming' => $upcoming,
'payments' => $payments,
'title' => trans('texts.dashboard'),
];

View File

@ -336,6 +336,7 @@ class PaymentController extends BaseController
'acceptedCreditCardTypes' => $acceptedCreditCardTypes,
'countries' => Cache::get('countries'),
'currencyId' => $client->getCurrencyId(),
'currencyCode' => $client->currency->code,
'account' => $client->account,
'hideLogo' => $account->isWhiteLabel(),
'showAddress' => $accountGateway->show_address,

View File

@ -95,7 +95,7 @@ class UserController extends BaseController
$user->force_pdfjs = true;
$user->save();
Session::flash('message', trans('texts.security.updated_settings'));
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('/dashboard');
}
@ -132,9 +132,12 @@ class UserController extends BaseController
*/
public function create()
{
if (!Auth::user()->confirmed) {
if (!Auth::user()->registered) {
Session::flash('error', trans('texts.register_to_add_user'));
return Redirect::to('company/advanced_settings/user_management');
}
if (!Auth::user()->confirmed) {
Session::flash('error', trans('texts.confirmation_required'));
return Redirect::to('company/advanced_settings/user_management');
}

View File

@ -76,14 +76,16 @@ class Client extends EntityModel
{
return $this->name;
}
public function getDisplayName()
{
if ($this->name) {
return $this->name;
}
$this->load('contacts');
if (!$this->contacts || !count($this->contacts)) {
$this->load('contacts');
}
$contact = $this->contacts()->first();
@ -152,11 +154,15 @@ class Client extends EntityModel
public function getCurrencyId()
{
if ($this->currency_id) {
return $this->currency_id;
}
if (!$this->account) {
$this->load('account');
}
return $this->currency_id ?: ($this->account->currency_id ?: DEFAULT_CURRENCY);
return $this->account->currency_id ?: DEFAULT_CURRENCY;
}
}

View File

@ -69,9 +69,14 @@ class Invoice extends EntityModel
return storage_path() . '/pdfcache/cache-' . $this->id . '.pdf';
}
public static function calcLink($invoice)
{
return link_to('invoices/' . $invoice->public_id, $invoice->invoice_number);
}
public function getLink()
{
return link_to('invoices/'.$this->public_id, $this->invoice_number);
return self::calcLink($this);
}
public function getEntityType()

View File

@ -2839,15 +2839,12 @@ background-clip: padding-box;
.dashboard .panel-body {padding: 0;}
.dashboard .table-striped>tbody>tr>td, .table-striped>tbody>tr>th { background-color: #fbfbfb;}
.dashboard .table-striped>tbody>tr:nth-child(odd)>tr, .table-striped>tbody>tr:nth-child(odd)>th {
background-color: #fff;
}
.dashboard th {
border-left: none;
background-color: #fbfbfb;
border-bottom: 1px solid #dfe0e1;
}
.dashboard table.table thead > tr > th {
border-bottom-width: 1px;
}

View File

@ -489,15 +489,12 @@ background-clip: padding-box;
.dashboard .panel-body {padding: 0;}
.dashboard .table-striped>tbody>tr>td, .table-striped>tbody>tr>th { background-color: #fbfbfb;}
.dashboard .table-striped>tbody>tr:nth-child(odd)>tr, .table-striped>tbody>tr:nth-child(odd)>th {
background-color: #fff;
}
.dashboard th {
border-left: none;
background-color: #fbfbfb;
border-bottom: 1px solid #dfe0e1;
}
.dashboard table.table thead > tr > th {
border-bottom-width: 1px;
}

File diff suppressed because one or more lines are too long

View File

@ -119,7 +119,7 @@ return array(
'active_client' => 'active client',
'active_clients' => 'active clients',
'invoices_past_due' => 'Invoices Past Due',
'upcoming_invoices' => 'Upcoming invoices',
'upcoming_invoices' => 'Upcoming Invoices',
'average_invoice' => 'Average invoice',
// list pages
@ -738,6 +738,9 @@ return array(
'custom' => 'Custom',
'invoice_to' => 'Invoice to',
'invoice_no' => 'Invoice No.',
'recent_payments' => 'Recent Payments',
'outstanding' => 'Outstanding',
);

View File

@ -6,7 +6,7 @@
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<img src="{{ asset('images/totalincome.png') }}" class="in-image"/>
<img src="{{ asset('images/totalinvoices.png') }}" class="in-image"/>
<div class="in-bold">
@if (count($paidToDate))
@foreach ($paidToDate as $item)
@ -44,12 +44,18 @@
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<img src="{{ asset('images/totalinvoices.png') }}" class="in-image"/>
<div class="in-bold">
{{ $invoicesSent }}
</div>
<img src="{{ asset('images/totalincome.png') }}" class="in-image"/>
<div class="in-thin">
{{ Utils::pluralize('invoice', $invoicesSent) }} {{ trans('texts.sent') }}
{{ trans('texts.outstanding') }}
</div>
<div class="in-bold">
@if (count($balances))
@foreach ($balances as $item)
{{ Utils::formatMoney($item->value, $item->currency_id) }}<br/>
@endforeach
@else
{{ Utils::formatMoney(0) }}
@endif
</div>
</div>
</div>
@ -61,13 +67,16 @@
<div class="row">
<div class="col-md-6">
<div class="panel panel-default dashboard" style="min-height:660px">
<div class="panel panel-default dashboard" style="height:320px">
<div class="panel-heading" style="background-color:#0b4d78 !important">
<h3 class="panel-title in-bold-white">
<i class="glyphicon glyphicon-exclamation-sign"></i> {{ trans('texts.notifications') }}
<div class="pull-right" style="font-size:14px;padding-top:4px">
{{ $invoicesSent }} {{ Utils::pluralize('invoice', $invoicesSent) }} {{ trans('texts.sent') }}
</div>
</h3>
</div>
<ul class="panel-body list-group">
<ul class="panel-body list-group" style="height:276px;overflow-y:auto;">
@foreach ($activities as $activity)
<li class="list-group-item">
<span style="color:#888;font-style:italic">{{ Utils::timestampToDateString(strtotime($activity->created_at)) }}:</span>
@ -76,15 +85,43 @@
@endforeach
</ul>
</div>
<div class="panel panel-default dashboard" style="height:320px;">
<div class="panel-heading" style="margin:0; background-color: #f5f5f5 !important;">
<h3 class="panel-title" style="color: black !important">
<i class="glyphicon glyphicon-ok-sign"></i> {{ trans('texts.recent_payments') }}
</h3>
</div>
<div class="panel-body" style="height:274px;overflow-y:auto;">
<table class="table table-striped">
<thead>
<th>{{ trans('texts.invoice_number_short') }}</th>
<th>{{ trans('texts.client') }}</th>
<th>{{ trans('texts.payment_date') }}</th>
<th>{{ trans('texts.amount') }}</th>
</thead>
<tbody>
@foreach ($payments as $payment)
<tr>
<td>{!! \App\Models\Invoice::calcLink($payment) !!}</td>
<td>{!! link_to('/clients/'.$payment->client_public_id, trim($payment->client_name) ?: (trim($payment->first_name . ' ' . $payment->last_name) ?: $payment->email)) !!}</td>
<td>{{ Utils::fromSqlDate($payment->payment_date) }}</td>
<td>{{ Utils::formatMoney($payment->amount, $payment->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default dashboard" style="min-height:320px">
<div class="panel panel-default dashboard" style="height:320px">
<div class="panel-heading" style="background-color:#e37329 !important">
<h3 class="panel-title in-bold-white">
<i class="glyphicon glyphicon-time"></i> {{ trans('texts.invoices_past_due') }}
</h3>
</div>
<div class="panel-body">
<div class="panel-body" style="height:274px;overflow-y:auto;">
<table class="table table-striped">
<thead>
<th>{{ trans('texts.invoice_number_short') }}</th>
@ -95,23 +132,23 @@
<tbody>
@foreach ($pastDue as $invoice)
<tr>
<td>{!! $invoice->getLink() !!}</td>
<td>{{ $invoice->client->getDisplayName() }}</td>
<td>{!! \App\Models\Invoice::calcLink($invoice) !!}</td>
<td>{!! link_to('/clients/'.$invoice->client_public_id, trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email)) !!}</td>
<td>{{ Utils::fromSqlDate($invoice->due_date) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->client->getCurrencyId()) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="panel panel-default dashboard" style="min-height:320px;">
<div class="panel panel-default dashboard" style="height:320px;">
<div class="panel-heading" style="margin:0; background-color: #f5f5f5 !important;">
<h3 class="panel-title" style="color: black !important">
<i class="glyphicon glyphicon-time"></i> {{ trans('texts.upcoming_invoices') }}
</h3>
</div>
<div class="panel-body">
<div class="panel-body" style="height:274px;overflow-y:auto;">
<table class="table table-striped">
<thead>
<th>{{ trans('texts.invoice_number_short') }}</th>
@ -122,10 +159,10 @@
<tbody>
@foreach ($upcoming as $invoice)
<tr>
<td>{!! $invoice->getLink() !!}</td>
<td>{{ $invoice->client->getDisplayName() }}</td>
<td>{!! \App\Models\Invoice::calcLink($invoice) !!}</td>
<td>{!! link_to('/clients/'.$invoice->client_public_id, trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email)) !!}</td>
<td>{{ Utils::fromSqlDate($invoice->due_date) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->client->getCurrencyId()) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}</td>
</tr>
@endforeach
</tbody>

View File

@ -169,7 +169,7 @@ header h3 em {
<header>
@if ($client)
<h2>{{ $client->getDisplayName() }}</h2>
<h3>{{ trans('texts.invoice') . ' ' . $invoiceNumber }}<span>|&nbsp; {{ trans('texts.amount_due') }}: <em>{{ Utils::formatMoney($amount, $currencyId) }}</em></span></h3>
<h3>{{ trans('texts.invoice') . ' ' . $invoiceNumber }}<span>|&nbsp; {{ trans('texts.amount_due') }}: <em>{{ Utils::formatMoney($amount, $currencyId) }} {{ $currencyCode }}</em></span></h3>
@elseif ($paymentTitle)
<h2>{{ $paymentTitle }}<br/><small>{{ $paymentSubtitle }}</small></h2>
@endif

View File

@ -223,7 +223,7 @@
});
self.startTime.pretty = ko.computed({
read: function() {
read: function() {
return self.startTime() ? moment.unix(self.startTime()).utcOffset({{ $minuteOffset }}).format('MMM D YYYY h:mm:ss a') : '';
},
write: function(data) {
@ -341,13 +341,6 @@
$clientSelect.combobox();
@if ($task)
$('#date').datepicker('update', new Date('{{ Utils::fromSqlDateTime($task->start_time) }}'));
@else
var date = new Date();
$('#date').datepicker('update', date);
@endif
@if (!$task && !$clientPublicId)
$('.client-select input.form-control').focus();
@else

View File

@ -2,7 +2,7 @@
@if (isset($user_id) && $show_remove)
<a href='{{ URL::to("/switch_account/{$user_id}") }}'>
@else
<a href='#' onclick="return false;">
<a href='{{ URL::to("/company/details") }}'>
@endif
@if (isset($show_remove) && $show_remove)
@ -10,7 +10,9 @@
@endif
@if (file_exists('logo/'.$account_key.'.jpg'))
<img class="pull-left" style="width: 40px; min-height: 40px; margin-right: 16px" src="{{ asset('logo/'.$account_key.'.jpg') }}"/>
<div class="pull-left" style="height: 40px; margin-right: 16px;">
<img style="width: 40px; margin-top:6px" src="{{ asset('logo/'.$account_key.'.jpg') }}"/>
</div>
@else
<div class="pull-left" style="width: 40px; min-height: 40px; margin-right: 16px">&nbsp;</div>
@endif

View File

@ -65,13 +65,13 @@
"$notesAndTerms",
{
"table": {
"widths": ["*", "*"],
"widths": ["*", "auto"],
"body": "$subtotals"
},
"layout": {
"hLineWidth": "$none",
"vLineWidth": "$none",
"paddingLeft": "$amount:8",
"paddingLeft": "$amount:34",
"paddingRight": "$amount:8",
"paddingTop": "$amount:4",
"paddingBottom": "$amount:4"

View File

@ -3,7 +3,7 @@
"columns": [
{
"image": "$accountLogo",
"width": 140
"fit": [120, 80]
},
{
"stack": "$accountDetails",
@ -16,7 +16,7 @@
},
{
"text": "$entityTypeUC",
"margin": [8, 50, 8, 5],
"margin": [8, 30, 8, 5],
"style": "entityTypeLabel"
},
@ -70,17 +70,17 @@
}
},
{
"columns": [
"columns": [
"$notesAndTerms",
{
"table": {
"widths": ["*", "*"],
"widths": ["*", "auto"],
"body": "$subtotals"
},
"layout": {
"hLineWidth": "$none",
"vLineWidth": "$none",
"paddingLeft": "$amount:8",
"paddingLeft": "$amount:34",
"paddingRight": "$amount:8",
"paddingTop": "$amount:4",
"paddingBottom": "$amount:4"
@ -97,12 +97,10 @@
"columns": [
{
"text": "$invoiceFooter",
"alignment": "left",
"margin": [0, 0, 0, 12]
"alignment": "left"
}
],
"margin": [40, -20, 40, 40]
"margin": [40, -20, 40, 0]
},
"styles": {
"entityTypeLabel": {
@ -171,8 +169,7 @@
"alignment": "right"
},
"termsLabel": {
"bold": true,
"margin": [0, 0, 0, 4]
"bold": true
}
},
"pageMargins": [40, 40, 40, 60]

View File

@ -4,7 +4,7 @@
"columns": [
{
"image": "$accountLogo",
"width": 80,
"fit": [120, 80],
"margin": [0, 60, 0, 30]
},
{
@ -37,13 +37,13 @@
"$notesAndTerms",
{
"table": {
"widths": ["*", "*"],
"widths": ["*", "auto"],
"body": "$subtotalsWithoutBalance"
},
"layout": {
"hLineWidth": "$none",
"vLineWidth": "$none",
"paddingLeft": "$amount:8",
"paddingLeft": "$amount:34",
"paddingRight": "$amount:8",
"paddingTop": "$amount:4",
"paddingBottom": "$amount:4"

View File

@ -11,7 +11,7 @@
[
{
"image": "$accountLogo",
"width": 100
"fit": [120, 80]
}
]
]},
@ -66,13 +66,13 @@
{
"style": "subtotals",
"table": {
"widths": ["*", "*"],
"widths": ["*", "auto"],
"body": "$subtotals"
},
"layout": {
"hLineWidth": "$none",
"vLineWidth": "$none",
"paddingLeft": "$amount:8",
"paddingLeft": "$amount:34",
"paddingRight": "$amount:8",
"paddingTop": "$amount:4",
"paddingBottom": "$amount:4"