diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 1757cb5850..f6aa72bf53 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -10,6 +10,9 @@ use DatePeriod; use Session; use View; use App\Models\Account; +use App\Models\Client; +use App\Models\Payment; +use App\Models\Expense; class ReportController extends BaseController { @@ -47,6 +50,7 @@ class ReportController extends BaseController $groupBy = Input::get('group_by'); $chartType = Input::get('chart_type'); $reportType = Input::get('report_type'); + $dateField = Input::get('date_field'); $startDate = Utils::toSqlDate(Input::get('start_date'), false); $endDate = Utils::toSqlDate(Input::get('end_date'), false); $enableReport = Input::get('enable_report') ? true : false; @@ -55,6 +59,7 @@ class ReportController extends BaseController $groupBy = 'MONTH'; $chartType = 'Bar'; $reportType = ENTITY_INVOICE; + $dateField = FILTER_INVOICE_DATE; $startDate = Utils::today(false)->modify('-3 month'); $endDate = Utils::today(false); $enableReport = true; @@ -76,6 +81,8 @@ class ReportController extends BaseController ENTITY_CLIENT => trans('texts.client'), ENTITY_INVOICE => trans('texts.invoice'), ENTITY_PAYMENT => trans('texts.payment'), + ENTITY_EXPENSE => trans('texts.expenses'), + ENTITY_TAX_RATE => trans('texts.taxes'), ]; $params = [ @@ -94,10 +101,11 @@ class ReportController extends BaseController if (Auth::user()->account->isPro()) { if ($enableReport) { - $params = array_merge($params, self::generateReport($reportType, $groupBy, $startDate, $endDate)); + $isExport = $action == 'export'; + $params = array_merge($params, self::generateReport($reportType, $startDate, $endDate, $dateField, $isExport)); - if ($action == 'export') { - self::export($params['exportData'], $params['reportTotals']); + if ($isExport) { + self::export($params['displayData'], $params['columns'], $params['reportTotals']); } } if ($enableChart) { @@ -212,165 +220,310 @@ class ReportController extends BaseController ]; } - private function generateReport($reportType, $groupBy, $startDate, $endDate) + private function generateReport($reportType, $startDate, $endDate, $dateField, $isExport) { if ($reportType == ENTITY_CLIENT) { - $columns = ['client', 'amount', 'paid', 'balance']; + return $this->generateClientReport($startDate, $endDate, $isExport); } elseif ($reportType == ENTITY_INVOICE) { - $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'paid', 'balance']; - } else { - $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'payment_date', 'paid', 'method']; + return $this->generateInvoiceReport($startDate, $endDate, $isExport); + } elseif ($reportType == ENTITY_PAYMENT) { + return $this->generatePaymentReport($startDate, $endDate, $isExport); + } elseif ($reportType == ENTITY_TAX_RATE) { + return $this->generateTaxRateReport($startDate, $endDate, $dateField, $isExport); + } elseif ($reportType == ENTITY_EXPENSE) { + return $this->generateExpenseReport($startDate, $endDate, $isExport); } + } - $query = DB::table('invoices') - ->join('accounts', 'accounts.id', '=', 'invoices.account_id') - ->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); + private function generateTaxRateReport($startDate, $endDate, $dateField, $isExport) + { + $columns = ['tax_name', 'tax_rate', 'amount', 'paid']; - $select = [ - DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'), - 'accounts.country_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 == ENTITY_CLIENT) { - $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')); - } else { - $query->orderBy('invoices.id'); - array_push($select, 'invoices.invoice_number', 'invoices.amount', 'invoices.balance', 'invoices.invoice_date'); - if ($reportType == ENTITY_INVOICE) { - array_push($select, DB::raw('(invoices.amount - invoices.balance) paid')); - } else { - $query->join('payments', 'payments.invoice_id', '=', 'invoices.id') - ->leftJoin('payment_types', 'payment_types.id', '=', 'payments.payment_type_id') - ->leftJoin('account_gateways', 'account_gateways.id', '=', 'payments.account_gateway_id') - ->leftJoin('gateways', 'gateways.id', '=', 'account_gateways.gateway_id'); - array_push($select, 'payments.payment_date', 'payments.amount as paid', 'payment_types.name as payment_type', 'gateways.name as gateway'); - } - } - - $query->select($select); - $data = $query->get(); - - $lastInvoiceId = null; - $sameAsLast = false; + $account = Auth::user()->account; $displayData = []; + $reportTotals = []; - $exportData = []; - $reportTotals = [ - 'amount' => [], - 'balance' => [], - 'paid' => [], - ]; + $clients = Client::scope() + ->withArchived() + ->with('contacts') + ->with(['invoices' => function($query) use ($startDate, $endDate, $dateField) { + $query->withArchived(); + if ($dateField == FILTER_PAYMENT_DATE) { + $query->where('invoice_date', '>=', $startDate) + ->where('invoice_date', '<=', $endDate) + ->whereHas('payments', function($query) use ($startDate, $endDate) { + $query->where('payment_date', '>=', $startDate) + ->where('payment_date', '<=', $endDate) + ->withArchived(); + }) + ->with(['payments' => function($query) use ($startDate, $endDate) { + $query->where('payment_date', '>=', $startDate) + ->where('payment_date', '<=', $endDate) + ->withArchived() + ->with('payment_type', 'account_gateway.gateway'); + }, 'invoice_items']); + } + }]); - foreach ($data as $record) { - $sameAsLast = ($lastInvoiceId == $record->invoice_public_id); - $lastInvoiceId = $record->invoice_public_id; + foreach ($clients->get() as $client) { + $currencyId = $client->currency_id ?: Auth::user()->account->getCurrencyId(); + $amount = 0; + $paid = 0; + $taxTotals = []; - $displayRow = []; - if ($sameAsLast) { - array_push($displayRow, '', '', '', ''); - } else { - array_push($displayRow, link_to('/clients/'.$record->client_public_id, Utils::getClientDisplayName($record))); - if ($reportType != ENTITY_CLIENT) { - array_push($displayRow, - link_to('/invoices/'.$record->invoice_public_id, $record->invoice_number), - Utils::fromSqlDate($record->invoice_date, true) - ); + foreach ($client->invoices as $invoice) { + foreach ($invoice->getTaxes(true) as $key => $tax) { + if ( ! isset($taxTotals[$currencyId])) { + $taxTotals[$currencyId] = []; + } + if (isset($taxTotals[$currencyId][$key])) { + $taxTotals[$currencyId][$key]['amount'] += $tax['amount']; + $taxTotals[$currencyId][$key]['paid'] += $tax['paid']; + } else { + $taxTotals[$currencyId][$key] = $tax; + } } - array_push($displayRow, Utils::formatMoney($record->amount, $record->currency_id, $record->country_id)); - } - if ($reportType != ENTITY_PAYMENT) { - array_push($displayRow, Utils::formatMoney($record->paid, $record->currency_id, $record->country_id)); - } - if ($reportType == ENTITY_PAYMENT) { - array_push($displayRow, - Utils::fromSqlDate($record->payment_date, true), - Utils::formatMoney($record->paid, $record->currency_id, $record->country_id), - $record->gateway ?: $record->payment_type - ); - } else { - array_push($displayRow, Utils::formatMoney($record->balance, $record->currency_id, $record->country_id)); + + $amount += $invoice->amount; + $paid += $invoice->getAmountPaid(); } - // export data - $exportRow = []; - if ($sameAsLast) { - $exportRow[trans('texts.client')] = ' '; - $exportRow[trans('texts.invoice_number')] = ' '; - $exportRow[trans('texts.invoice_date')] = ' '; - $exportRow[trans('texts.amount')] = ' '; - } else { - $exportRow[trans('texts.client')] = Utils::getClientDisplayName($record); - if ($reportType != ENTITY_CLIENT) { - $exportRow[trans('texts.invoice_number')] = $record->invoice_number; - $exportRow[trans('texts.invoice_date')] = Utils::fromSqlDate($record->invoice_date, true); + foreach ($taxTotals as $currencyId => $taxes) { + foreach ($taxes as $tax) { + $displayData[] = [ + $tax['name'], + $tax['rate'], + $account->formatMoney($tax['amount'], $client), + $account->formatMoney($tax['paid'], $client) + ]; } - $exportRow[trans('texts.amount')] = Utils::formatMoney($record->amount, $record->currency_id, $record->country_id); + + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $tax['amount']); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $tax['paid']); } - if ($reportType != ENTITY_PAYMENT) { - $exportRow[trans('texts.paid')] = Utils::formatMoney($record->paid, $record->currency_id, $record->country_id); - } - if ($reportType == ENTITY_PAYMENT) { - $exportRow[trans('texts.payment_date')] = Utils::fromSqlDate($record->payment_date, true); - $exportRow[trans('texts.payment_amount')] = Utils::formatMoney($record->paid, $record->currency_id, $record->country_id); - $exportRow[trans('texts.method')] = $record->gateway ?: $record->payment_type; - } else { - $exportRow[trans('texts.balance')] = Utils::formatMoney($record->balance, $record->currency_id, $record->country_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; - } - if (!$sameAsLast) { - $reportTotals['amount'][$currencyId] += $record->amount; - $reportTotals['balance'][$currencyId] += $record->balance; - } - $reportTotals['paid'][$currencyId] += $record->paid; } return [ 'columns' => $columns, 'displayData' => $displayData, 'reportTotals' => $reportTotals, - 'exportData' => $exportData + ]; + + } + + private function generatePaymentReport($startDate, $endDate, $isExport) + { + $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'payment_date', 'paid', 'method']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $payments = Payment::scope() + ->withTrashed() + ->where('is_deleted', '=', false) + ->whereHas('client', function($query) { + $query->where('is_deleted', '=', false); + }) + ->whereHas('invoice', function($query) { + $query->where('is_deleted', '=', false); + }) + ->with('client.contacts', 'invoice', 'payment_type', 'account_gateway.gateway') + ->where('payment_date', '>=', $startDate) + ->where('payment_date', '<=', $endDate); + + foreach ($payments->get() as $payment) { + $invoice = $payment->invoice; + $client = $payment->client; + $displayData[] = [ + $isExport ? $client->getDisplayName() : $client->present()->link, + $isExport ? $invoice->invoice_number : $invoice->present()->link, + $invoice->present()->invoice_date, + $account->formatMoney($invoice->amount, $client), + $payment->present()->payment_date, + $account->formatMoney($payment->amount, $client), + $payment->present()->method, + ]; + + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $invoice->amount); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $payment->amount); + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, ]; } - private function export($data, $totals) + private function generateInvoiceReport($startDate, $endDate, $isExport) + { + $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'paid', 'balance']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $clients = Client::scope() + ->withTrashed() + ->with('contacts') + ->where('is_deleted', '=', false) + ->with(['invoices' => function($query) use ($startDate, $endDate) { + $query->where('invoice_date', '>=', $startDate) + ->where('invoice_date', '<=', $endDate) + ->where('is_deleted', '=', false) + ->with(['payments' => function($query) { + $query->withTrashed() + ->with('payment_type', 'account_gateway.gateway') + ->where('is_deleted', '=', false); + }, 'invoice_items']) + ->withTrashed(); + }]); + + foreach ($clients->get() as $client) { + $currencyId = $client->currency_id ?: Auth::user()->account->getCurrencyId(); + + foreach ($client->invoices as $invoice) { + $displayData[] = [ + $isExport ? $client->getDisplayName() : $client->present()->link, + $isExport ? $invoice->invoice_number : $invoice->present()->link, + $invoice->present()->invoice_date, + $account->formatMoney($invoice->amount, $client), + $account->formatMoney($invoice->getAmountPaid(), $client), + $account->formatMoney($invoice->balance, $client), + ]; + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $invoice->amount); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $invoice->getAmountPaid()); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'balance', $invoice->balance); + } + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, + ]; + } + + private function generateClientReport($startDate, $endDate, $isExport) + { + $columns = ['client', 'amount', 'paid', 'balance']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $clients = Client::scope() + ->withArchived() + ->with('contacts') + ->with(['invoices' => function($query) use ($startDate, $endDate) { + $query->where('invoice_date', '>=', $startDate) + ->where('invoice_date', '<=', $endDate) + ->withArchived(); + }]); + + foreach ($clients->get() as $client) { + $amount = 0; + $paid = 0; + + foreach ($client->invoices as $invoice) { + $amount += $invoice->amount; + $paid += $invoice->getAmountPaid(); + } + + $displayData[] = [ + $isExport ? $client->getDisplayName() : $client->present()->link, + $account->formatMoney($amount, $client), + $account->formatMoney($paid, $client), + $account->formatMoney($amount - $paid, $client) + ]; + + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $amount); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $paid); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'balance', $amount - $paid); + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, + ]; + } + + private function generateExpenseReport($startDate, $endDate, $isExport) + { + $columns = ['vendor', 'client', 'date', 'expense_amount', 'invoiced_amount']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $expenses = Expense::scope() + ->withTrashed() + ->with('client.contacts', 'vendor') + ->where('expense_date', '>=', $startDate) + ->where('expense_date', '<=', $endDate); + + + foreach ($expenses->get() as $expense) { + $amount = $expense->amount; + $invoiced = $expense->present()->invoiced_amount; + + $displayData[] = [ + $expense->vendor ? ($isExport ? $expense->vendor->name : $expense->vendor->present()->link) : '', + $expense->client ? ($isExport ? $expense->client->getDisplayName() : $expense->client->present()->link) : '', + $expense->present()->expense_date, + Utils::formatMoney($amount, $expense->currency_id), + Utils::formatMoney($invoiced, $expense->invoice_currency_id), + ]; + + $reportTotals = $this->addToTotals($reportTotals, $expense->expense_currency_id, 'amount', $amount); + $reportTotals = $this->addToTotals($reportTotals, $expense->invoice_currency_id, 'amount', 0); + + $reportTotals = $this->addToTotals($reportTotals, $expense->invoice_currency_id, 'invoiced', $invoiced); + $reportTotals = $this->addToTotals($reportTotals, $expense->expense_currency_id, 'invoiced', 0); + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, + ]; + } + + private function addToTotals($data, $currencyId, $field, $value) { + $currencyId = $currencyId ?: Auth::user()->account->getCurrencyId(); + + if (!isset($data[$currencyId][$field])) { + $data[$currencyId][$field] = 0; + } + + $data[$currencyId][$field] += $value; + + return $data; + } + + private function export($data, $columns, $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); + Utils::exportData($output, $data, Utils::trans($columns)); + + fwrite($output, trans('texts.totals')); + foreach ($totals as $currencyId => $fields) { + foreach ($fields as $key => $value) { + fwrite($output, ',' . trans("texts.{$key}")); + } + fwrite($output, "\n"); + break; + } - foreach (['amount', 'paid', 'balance'] as $type) { - $csv = trans("texts.{$type}").','; - foreach ($totals[$type] as $currencyId => $amount) { - $csv .= Utils::formatMoney($amount, $currencyId).','; + foreach ($totals as $currencyId => $fields) { + $csv = Utils::getFromCache($currencyId, 'currencies')->name . ','; + foreach ($fields as $key => $value) { + $csv .= '"' . Utils::formatMoney($value, $currencyId).'",'; } fwrite($output, $csv."\n"); } diff --git a/app/Http/routes.php b/app/Http/routes.php index f7bed59f68..7789d48253 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,5 +1,6 @@ 0) { + if ($headers) { + fputcsv($output, $headers); + } elseif (count($data) > 0) { fputcsv($output, array_keys($data[0])); } diff --git a/app/Models/Client.php b/app/Models/Client.php index 2167af0ddf..61194fe93c 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -272,6 +272,11 @@ class Client extends EntityModel return $token ? "https://dashboard.stripe.com/customers/{$token}" : false; } + public function getAmount() + { + return $this->balance + $this->paid_to_date; + } + public function getCurrencyId() { if ($this->currency_id) { diff --git a/app/Models/EntityModel.php b/app/Models/EntityModel.php index 9e3fd6ec53..71905d000b 100644 --- a/app/Models/EntityModel.php +++ b/app/Models/EntityModel.php @@ -81,6 +81,11 @@ class EntityModel extends Eloquent return $query; } + public function scopeWithArchived($query) + { + return $query->withTrashed()->where('is_deleted', '=', false); + } + public function getName() { return $this->public_id; diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 4e15934efe..835de501c6 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -129,13 +129,21 @@ class Invoice extends EntityModel implements BalanceAffecting return false; } - public function getAmountPaid() + public function getAmountPaid($calculate = false) { if ($this->is_quote || $this->is_recurring) { return 0; } - return ($this->amount - $this->balance); + if ($calculate) { + $amount = 0; + foreach ($this->payments as $payment) { + $amount += $payment->amount; + } + return $amount; + } else { + return ($this->amount - $this->balance); + } } public function trashed() @@ -752,6 +760,98 @@ class Invoice extends EntityModel implements BalanceAffecting return Utils::decodePDF($pdfString); } + + public function getItemTaxable($invoiceItem, $invoiceTotal) + { + $total = $invoiceItem->qty * $invoiceItem->cost; + + if ($this->discount > 0) { + if ($this->is_amount_discount) { + $total -= $invoiceTotal ? ($total / $invoiceTotal * $this->discount) : 0; + } else { + $total *= (100 - $this->discount) / 100; + $total = round($total, 2); + } + } + + return $total; + } + + public function getTaxable() + { + $total = 0; + + foreach ($this->invoice_items as $invoiceItem) { + $total += $invoiceItem->qty * $invoiceItem->cost; + } + + if ($this->discount > 0) { + if ($this->is_amount_discount) { + $total -= $this->discount; + } else { + $total *= (100 - $this->discount) / 100; + $total = round($total, 2); + } + } + + if ($this->custom_value1 && $this->custom_taxes1) { + $total += $this->custom_value1; + } + + if ($this->custom_value2 && $this->custom_taxes2) { + $total += $this->custom_value2; + } + + return $total; + } + + public function getTaxes($calculatePaid = false) + { + $taxes = []; + $taxable = $this->getTaxable(); + + if ($this->tax_rate && $this->tax_name) { + $taxAmount = $taxable * ($this->tax_rate / 100); + $taxAmount = round($taxAmount, 2); + + if ($taxAmount) { + $taxes[$this->tax_name.$this->tax_rate] = [ + 'name' => $this->tax_name, + 'rate' => $this->tax_rate, + 'amount' => $taxAmount, + 'paid' => round($this->getAmountPaid($calculatePaid) / $this->amount * $taxAmount, 2) + ]; + } + } + + foreach ($this->invoice_items as $invoiceItem) { + if ( ! $invoiceItem->tax_rate || ! $invoiceItem->tax_name) { + continue; + } + + $taxAmount = $this->getItemTaxable($invoiceItem, $taxable); + $taxAmount = $taxable * ($invoiceItem->tax_rate / 100); + $taxAmount = round($taxAmount, 2); + + if ($taxAmount) { + $key = $invoiceItem->tax_name.$invoiceItem->tax_rate; + + if ( ! isset($taxes[$key])) { + $taxes[$key] = [ + 'amount' => 0, + 'paid' => 0 + ]; + } + + $taxes[$key]['amount'] += $taxAmount; + $taxes[$key]['paid'] += $this->amount && $taxAmount ? round($this->getAmountPaid($calculatePaid) / $this->amount * $taxAmount, 2) : 0; + $taxes[$key]['name'] = $invoiceItem->tax_name; + $taxes[$key]['rate'] = $invoiceItem->tax_rate; + } + } + + return $taxes; + } } Invoice::creating(function ($invoice) { diff --git a/app/Ninja/Presenters/ClientPresenter.php b/app/Ninja/Presenters/ClientPresenter.php index 97551185d5..cd32151a37 100644 --- a/app/Ninja/Presenters/ClientPresenter.php +++ b/app/Ninja/Presenters/ClientPresenter.php @@ -26,6 +26,10 @@ class ClientPresenter extends Presenter { } return "{$text}"; + } + public function link() + { + return link_to('/clients/' . $this->entity->public_id, $this->entity->getDisplayName()); } } \ No newline at end of file diff --git a/app/Ninja/Presenters/ExpensePresenter.php b/app/Ninja/Presenters/ExpensePresenter.php index 9cede24d03..6b66080ded 100644 --- a/app/Ninja/Presenters/ExpensePresenter.php +++ b/app/Ninja/Presenters/ExpensePresenter.php @@ -20,4 +20,14 @@ class ExpensePresenter extends Presenter { { return round($this->entity->amount * $this->entity->exchange_rate, 2); } + + public function invoiced_amount() + { + return $this->entity->invoice_id ? $this->converted_amount() : 0; + } + + public function link() + { + return link_to('/expenses/' . $this->entity->public_id, $this->entity->name); + } } \ No newline at end of file diff --git a/app/Ninja/Presenters/InvoicePresenter.php b/app/Ninja/Presenters/InvoicePresenter.php index fb292a8859..2bab049d2a 100644 --- a/app/Ninja/Presenters/InvoicePresenter.php +++ b/app/Ninja/Presenters/InvoicePresenter.php @@ -55,4 +55,9 @@ class InvoicePresenter extends Presenter { return Utils::fromSqlDate($this->entity->due_date); } + public function link() + { + return link_to('/invoices/' . $this->entity->public_id, $this->entity->invoice_number); + } + } \ No newline at end of file diff --git a/app/Ninja/Presenters/VendorPresenter.php b/app/Ninja/Presenters/VendorPresenter.php index b3da402bec..d0bef4e0c8 100644 --- a/app/Ninja/Presenters/VendorPresenter.php +++ b/app/Ninja/Presenters/VendorPresenter.php @@ -9,4 +9,9 @@ class VendorPresenter extends Presenter { { return $this->entity->country ? $this->entity->country->name : ''; } + + public function link() + { + return link_to('/vendors/' . $this->entity->public_id, $this->entity->name); + } } \ No newline at end of file diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php index 3a2ea488e8..880ded2baf 100644 --- a/app/Ninja/Repositories/AccountRepository.php +++ b/app/Ninja/Repositories/AccountRepository.php @@ -130,11 +130,6 @@ class AccountRepository private function getNavigationSearchData() { - $features = [ - ['dashboard', '/dashboard'], - ['customize_design', '/settings/customize_design'], - ]; - $entityTypes = [ ENTITY_INVOICE, ENTITY_CLIENT, @@ -157,6 +152,12 @@ class AccountRepository ]; } + $features[] = ['dashboard', '/dashboard']; + $features[] = ['customize_design', '/settings/customize_design']; + $features[] = ['new_tax_rate', '/tax_rates/create']; + $features[] = ['new_product', '/products/create']; + $features[] = ['new_user', '/users/create']; + $settings = array_merge(Account::$basicSettings, Account::$advancedSettings); foreach ($settings as $setting) { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 0309b6a8fe..2d6689b554 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -223,11 +223,6 @@ class AppServiceProvider extends ServiceProvider { 'Illuminate\Contracts\Auth\Registrar', 'App\Services\Registrar' ); - - $this->app->bind( - 'App\Ninja\Import\DataImporterServiceInterface', - 'App\Ninja\Import\FreshBooks\FreshBooksDataImporterService' - ); } } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index e063596ebc..d130919802 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -1034,10 +1034,19 @@ $LANG = array( 'list_clients' => 'List Clients', 'list_quotes' => 'List Quotes', 'list_tasks' => 'List Tasks', - 'list_expensess' => 'List Expenses', + 'list_expenses' => 'List Expenses', 'list_recurring_invoices' => 'List Recurring Invoices', 'list_payments' => 'List Payments', 'list_credits' => 'List Credits', + 'tax_name' => 'Tax Name', + 'report_settings' => 'Report Settings', + 'search_hotkey' => 'shortcut is /', + + 'new_user' => 'New User', + 'new_product' => 'New Product', + 'new_tax_rate' => 'New Tax Rate', + 'invoiced_amount' => 'Invoiced Amount', + ); return $LANG; diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php index 8b31666054..e5f52b0a7a 100644 --- a/resources/views/header.blade.php +++ b/resources/views/header.blade.php @@ -498,7 +498,7 @@ diff --git a/resources/views/reports/chart_builder.blade.php b/resources/views/reports/chart_builder.blade.php index 159b71b177..5095c097f7 100644 --- a/resources/views/reports/chart_builder.blade.php +++ b/resources/views/reports/chart_builder.blade.php @@ -26,7 +26,7 @@
-

{!! trans('texts.settings') !!}

+

{!! trans('texts.report_settings') !!}

@@ -54,12 +54,17 @@ @endif -
+
- {!! Former::checkbox('enable_report')->text(trans('texts.enable')) !!} - {!! Former::select('report_type')->options($reportTypes, $reportType)->label(trans('texts.group_by')) !!} + {!! Former::checkbox('enable_report')->text(trans('texts.enable')) !!} + {!! Former::select('report_type')->options($reportTypes, $reportType)->label(trans('texts.type')) !!} +
+ {!! Former::select('date_field')->label(trans('texts.filter')) + ->addOption(trans('texts.invoice_date'), FILTER_INVOICE_DATE) + ->addOption(trans('texts.payment_date'), FILTER_PAYMENT_DATE) !!} +

 

- {!! Former::checkbox('enable_chart')->text(trans('texts.enable')) !!} + {!! Former::checkbox('enable_chart')->text(trans('texts.enable')) !!} {!! Former::select('group_by')->options($dateTypes, $groupBy) !!} {!! Former::select('chart_type')->options($chartTypes, $chartType) !!} @@ -77,56 +82,48 @@ @foreach ($columns as $column) - - {{ trans("texts.{$column}") }} - + {{ trans("texts.{$column}") }} @endforeach - + @foreach ($displayData as $record) @foreach ($record as $field) - - {!! $field !!} - + {!! $field !!} @endforeach @endforeach - - - {{ trans('texts.totals') }} - @if ($reportType != ENTITY_CLIENT) - - - @endif - - @foreach ($reportTotals['amount'] as $currencyId => $total) - {{ Utils::formatMoney($total, $currencyId) }}
- @endforeach - - @if ($reportType == ENTITY_PAYMENT) - - @endif - - @foreach ($reportTotals['paid'] as $currencyId => $total) - {{ Utils::formatMoney($total, $currencyId) }}
- @endforeach - - @if ($reportType != ENTITY_PAYMENT) - - @foreach ($reportTotals['balance'] as $currencyId => $total) - {{ Utils::formatMoney($total, $currencyId) }}
- @endforeach - - @endif - - +

 

+ + @if (count(array_values($reportTotals))) + + + + + @foreach (array_values($reportTotals)[0] as $key => $val) + + @endforeach + + + + @foreach ($reportTotals as $currencyId => $val) + + + @foreach ($val as $id => $field) + + @endforeach + + @endforeach + +
{{ trans("texts.totals") }}{{ trans("texts.{$key}") }}
{!! Utils::getFromCache($currencyId, 'currencies')->name !!}{!! Utils::formatMoney($field, $currencyId) !!}
+ @endif + +
-
@endif @if ($enableChart) @@ -194,6 +191,15 @@ $('.end_date .input-group-addon').click(function() { toggleDatePicker('end_date'); }); + + $('#report_type').change(function() { + var val = $('#report_type').val(); + if (val == '{{ ENTITY_TAX_RATE }}') { + $('#dateField').fadeIn(); + } else { + $('#dateField').fadeOut(); + } + }); })