This commit is contained in:
Carvallegro
2017-12-31 06:12:28 +11:00
398 changed files with 23534 additions and 1562 deletions

View File

@ -70,7 +70,7 @@ class Bills extends ApiController
$item_sku = $item_object->sku;
// Increase stock (item bought)
$item_object->quantity++;
$item_object->quantity += $item['quantity'];
$item_object->save();
} elseif (!empty($item['sku'])) {
$item_sku = $item['sku'];
@ -89,7 +89,7 @@ class Bills extends ApiController
}
$bill_item['item_id'] = $item_id;
$bill_item['name'] = $item['name'];
$bill_item['name'] = str_limit($item['name'], 180, '');
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
@ -161,7 +161,7 @@ class Bills extends ApiController
}
$bill_item['item_id'] = $item_id;
$bill_item['name'] = $item['name'];
$bill_item['name'] = str_limit($item['name'], 180, '');
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];

View File

@ -79,7 +79,7 @@ class Invoices extends ApiController
$item_sku = $item_object->sku;
// Decrease stock (item sold)
$item_object->quantity--;
$item_object->quantity -= $item['quantity'];
$item_object->save();
// Notify users if out of stock
@ -109,7 +109,7 @@ class Invoices extends ApiController
}
$invoice_item['item_id'] = $item_id;
$invoice_item['name'] = $item['name'];
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
@ -212,7 +212,7 @@ class Invoices extends ApiController
}
$invoice_item['item_id'] = $item_id;
$invoice_item['name'] = $item['name'];
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];

View File

@ -243,6 +243,7 @@ class Users extends Controller
public function autocomplete(ARequest $request)
{
$user = false;
$data = false;
$column = $request['column'];
$value = $request['value'];
@ -250,7 +251,7 @@ class Users extends Controller
if (!empty($column) && !empty($value)) {
switch ($column) {
case 'id':
$user = User::find();
$user = User::find((int) $value);
break;
case 'email':
$user = User::where('email', $value)->first();
@ -258,12 +259,16 @@ class Users extends Controller
default:
$user = User::where($column, $value)->first();
}
$data = $user;
} elseif (!empty($column) && empty($value)) {
$data = trans('validation.required', ['attribute' => $column]);
}
return response()->json([
'errors' => ($user) ? false: true,
'success' => ($user) ? true: false,
'data' => $user
'errors' => ($user) ? false : true,
'success' => ($user) ? true : false,
'data' => $data
]);
}
}

View File

@ -5,13 +5,17 @@ namespace App\Http\Controllers\Banking;
use App\Http\Controllers\Controller;
use App\Models\Banking\Account;
use App\Models\Banking\Transaction;
use App\Models\Expense\BillPayment;
use App\Models\Expense\Payment;
use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
class Transactions extends Controller
{
public $transactions = [];
/**
* Display a listing of the resource.
*
@ -21,8 +25,6 @@ class Transactions extends Controller
{
$request = request();
$transactions = array();
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
@ -35,62 +37,64 @@ class Transactions extends Controller
$type = $request->get('type');
if ($type != 'income') {
$payments = Payment::collect('paid_at');
foreach ($payments as $payment) {
$transactions[] = (object)[
'paid_at' => $payment->paid_at,
'account_name' => $payment->account->name,
'type' => trans_choice('general.expenses', 1),
'category_name' => $payment->category->name,
'description' => $payment->description,
'amount' => $payment->amount,
'currency_code' => $payment->currency_code,
];
}
$this->addTransactions(Payment::collect('paid_at'), trans_choice('general.expenses', 1));
$this->addTransactions(BillPayment::collect('paid_at'), trans_choice('general.expenses', 1), trans_choice('general.bills', 1));
}
if ($type != 'expense') {
$revenues = Revenue::collect('paid_at');
foreach ($revenues as $revenue) {
$transactions[] = (object)[
'paid_at' => $revenue->paid_at,
'account_name' => $revenue->account->name,
'type' => trans_choice('general.incomes', 1),
'category_name' => $revenue->category->name,
'description' => $revenue->description,
'amount' => $revenue->amount,
'currency_code' => $revenue->currency_code,
];
}
$this->addTransactions(Revenue::collect('paid_at'), trans_choice('general.incomes', 1));
$this->addTransactions(InvoicePayment::collect('paid_at'), trans_choice('general.incomes', 1), trans_choice('general.invoices', 1));
}
$special_key = array(
'account.name' => 'account_name',
'category.name' => 'category_name',
);
if (isset($request['sort']) && array_key_exists($request['sort'], $special_key)) {
$sort_order = array();
foreach ($transactions as $key => $value) {
$sort = $request['sort'];
if (array_key_exists($request['sort'], $special_key)) {
$sort = $special_key[$request['sort']];
}
$sort_order[$key] = $value->{$sort};
}
$sort_type = (isset($request['order']) && $request['order'] == 'asc') ? SORT_ASC : SORT_DESC;
array_multisort($sort_order, $sort_type, $transactions);
}
$transactions = (object) $transactions;
$transactions = $this->getTransactions($request);
return view('banking.transactions.index', compact('transactions', 'accounts', 'types', 'categories'));
}
/**
* Add items to transactions array.
*
* @param $items
* @param $type
* @param $category
*/
protected function addTransactions($items, $type, $category = null)
{
foreach ($items as $item) {
$data = [
'paid_at' => $item->paid_at,
'account_name' => $item->account->name,
'type' => $type,
'description' => $item->description,
'amount' => $item->amount,
'currency_code' => $item->currency_code,
];
if (!is_null($category)) {
$data['category_name'] = $category;
} else {
$data['category_name'] = $item->category->name;
}
$this->transactions[] = (object) $data;
}
}
protected function getTransactions($request)
{
// Sort items
if (isset($request['sort'])) {
if ($request['order'] == 'asc') {
$f = 'sortBy';
} else {
$f = 'sortByDesc';
}
$transactions = collect($this->transactions)->$f($request['sort']);
} else {
$transactions = collect($this->transactions)->sortByDesc('paid_at');
}
return $transactions;
}
}

View File

@ -102,14 +102,10 @@ class Transfers extends Controller
$request['account_id'] = $request['from_account_id'];
$request['paid_at'] = $request['transferred_at'];
// amount
$request['currency_code'] = $payment_currency_code;
$request['currency_rate'] = $currencies[$payment_currency_code];
$request['vendor_id'] = '0';
// description
$request['category_id'] = Category::enabled()->type('other')->pluck('id')->first(); // Transfer Category ID
// payment_method
// reference
$request['category_id'] = Category::transfer(); // Transfer Category ID
$request['attachment'] = '';
$payment = Payment::create($request->all());
@ -195,14 +191,10 @@ class Transfers extends Controller
$request['account_id'] = $request['from_account_id'];
$request['paid_at'] = $request['transferred_at'];
// amount
$request['currency_code'] = $payment_currency_code;
$request['currency_rate'] = $currencies[$payment_currency_code];
$request['vendor_id'] = '0';
// description
$request['category_id'] = Category::enabled()->type('other')->pluck('id')->first(); // Transfer Category ID
// payment_method
// reference
$request['category_id'] = Category::transfer(); // Transfer Category ID
$request['attachment'] = '';
$payment->update($request->all());

View File

@ -2,14 +2,12 @@
namespace App\Http\Controllers\Companies;
use App\Events\CompanySwitched;
use App\Http\Controllers\Controller;
use App\Http\Requests\Company\Company as Request;
use App\Models\Company\Company;
use App\Models\Setting\Currency;
use App\Traits\Uploads;
use Auth;
use Redirect;
use Setting;
class Companies extends Controller
{
@ -51,26 +49,26 @@ class Companies extends Controller
*/
public function store(Request $request)
{
Setting::forgetAll();
setting()->forgetAll();
// Create company
$company = Company::create($request->input());
// Create settings
Setting::set('general.company_name', $request->get('company_name'));
Setting::set('general.company_email', $request->get('company_email'));
Setting::set('general.company_address', $request->get('company_address'));
setting()->set('general.company_name', $request->get('company_name'));
setting()->set('general.company_email', $request->get('company_email'));
setting()->set('general.company_address', $request->get('company_address'));
$logo_path = $this->getUploadedFilePath($request->file('company_logo'), 'settings', $company->id);
if ($logo_path) {
Setting::set('general.company_logo', $logo_path);
setting()->set('general.company_logo', $logo_path);
}
Setting::set('general.default_currency', $request->get('default_currency'));
Setting::set('general.default_locale', session('locale'));
setting()->set('general.default_currency', $request->get('default_currency'));
setting()->set('general.default_locale', session('locale'));
Setting::setExtraColumns(['company_id' => $company->id]);
Setting::save();
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->save();
// Redirect
$message = trans('messages.success.added', ['type' => trans_choice('general.companies', 1)]);
@ -90,7 +88,13 @@ class Companies extends Controller
public function edit(Company $company)
{
// Check if user can edit company
$this->authorizeUserOrRedirect($company);
if (!$this->isUserCompany($company)) {
$message = trans('companies.error.not_user_company');
flash($message)->error();
return redirect('companies/companies');
}
$company->setSettings();
@ -110,30 +114,36 @@ class Companies extends Controller
public function update(Company $company, Request $request)
{
// Check if user can update company
$this->authorizeUserOrRedirect($company);
if (!$this->isUserCompany($company)) {
$message = trans('companies.error.not_user_company');
flash($message)->error();
return redirect('companies/companies');
}
// Update company
$company->update($request->input());
// Get the company settings
Setting::forgetAll();
Setting::setExtraColumns(['company_id' => $company->id]);
Setting::load(true);
setting()->forgetAll();
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->load(true);
// Update settings
Setting::set('general.company_name', $request->get('company_name'));
Setting::set('general.company_email', $request->get('company_email'));
Setting::set('general.company_address', $request->get('company_address'));
setting()->set('general.company_name', $request->get('company_name'));
setting()->set('general.company_email', $request->get('company_email'));
setting()->set('general.company_address', $request->get('company_address'));
$logo_path = $this->getUploadedFilePath($request->file('company_logo'), 'settings', $company->id);
if ($logo_path) {
Setting::set('general.company_logo', $logo_path);
setting()->set('general.company_logo', $logo_path);
}
Setting::set('general.default_payment_method', 'offlinepayment.cash.1');
Setting::set('general.default_currency', $request->get('default_currency'));
setting()->set('general.default_payment_method', 'offlinepayment.cash.1');
setting()->set('general.default_currency', $request->get('default_currency'));
Setting::save();
setting()->save();
// Redirect
$message = trans('messages.success.updated', ['type' => trans_choice('general.companies', 1)]);
@ -182,9 +192,10 @@ class Companies extends Controller
// Check if user can manage company
if ($this->isUserCompany($company)) {
session(['company_id' => $company->id]);
event(new CompanySwitched($company));
}
//return redirect('/');
return redirect()->back();
}
@ -197,7 +208,7 @@ class Companies extends Controller
*/
public function isUserCompany(Company $company)
{
$companies = Auth::user()->companies()->pluck('id')->toArray();
$companies = auth()->user()->companies()->pluck('id')->toArray();
if (in_array($company->id, $companies)) {
return true;
@ -205,24 +216,4 @@ class Companies extends Controller
return false;
}
/**
* Check user company permission and redirect if not
*
* @param Company $company
*
* @return boolean
*/
public function authorizeUserOrRedirect(Company $company)
{
if ($this->isUserCompany($company)) {
return true;
}
$message = trans('companies.error.not_user_company');
flash($message)->error();
Redirect::away(url('companies/companies'))->send();
}
}

View File

@ -3,12 +3,12 @@
namespace App\Http\Controllers\Customers;
use App\Http\Controllers\Controller;
use Auth;
use App\Models\Income\Invoice;
use Charts;
use Date;
class Dashboard extends Controller
{
/**
* Display a listing of the resource.
*
@ -16,8 +16,110 @@ class Dashboard extends Controller
*/
public function index()
{
$user = Auth::user()->customer;
$customer = auth()->user()->customer;
return view('customers.dashboard.index', compact('user'));
$invoices = Invoice::with('status')->accrued()->where('customer_id', $customer->id)->get();
$start = Date::parse(request('start', Date::today()->startOfYear()->format('Y-m-d')));
$end = Date::parse(request('end', Date::today()->endOfYear()->format('Y-m-d')));
$start_month = $start->month;
$end_month = $end->month;
// Monthly
$labels = [];
$s = clone $start;
for ($j = $end_month; $j >= $start_month; $j--) {
$labels[$end_month - $j] = $s->format('M Y');
$s->addMonth();
}
$unpaid = $paid = $overdue = $partial_paid = [];
foreach ($invoices as $invoice) {
switch ($invoice->invoice_status_code) {
case 'paid':
$paid[] = $invoice;
break;
case 'partial':
$partial_paid[] = $invoice;
break;
case 'sent':
default:
if (Date::today()->format('Y-m-d') > $invoice->due_at->format('Y-m-d')) {
$overdue[] = $invoice;
} else {
$unpaid[] = $invoice;
}
}
}
$total = count($unpaid) + count($paid) + count($partial_paid) + count($overdue);
$progress = [
'unpaid' => count($unpaid),
'paid' => count($paid),
'overdue' => count($overdue),
'partially_paid' => count($partial_paid),
'total' => $total,
];
$unpaid = $this->calculateTotals($unpaid, $start, $end, 'unpaid');
$paid = $this->calculateTotals($paid, $start, $end, 'paid');
$partial_paid = $this->calculateTotals($partial_paid, $start, $end, 'partial');
$overdue = $this->calculateTotals($overdue, $start, $end, 'overdue');
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
->colors(['#dd4b39', '#6da252', '#f39c12', '#00c0ef'])
->dataset(trans('general.unpaid'), $unpaid)
->dataset(trans('general.paid'), $paid)
->dataset(trans('general.overdue'), $overdue)
->dataset(trans('general.partially_paid'), $partial_paid)
->labels($labels)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.multi.line');
return view('customers.dashboard.index', compact('customer', 'invoices', 'progress', 'chart'));
}
private function calculateTotals($items, $start, $end, $type)
{
$totals = [];
$date_format = 'Y-m';
$n = 1;
$start_date = $start->format($date_format);
$end_date = $end->format($date_format);
$next_date = $start_date;
$s = clone $start;
while ($next_date <= $end_date) {
$totals[$next_date] = 0;
$next_date = $s->addMonths($n)->format($date_format);
}
$this->setTotals($totals, $items, $date_format, $type);
return $totals;
}
private function setTotals(&$totals, $items, $date_format, $type)
{
foreach ($items as $item) {
if ($type == 'partial') {
$item->amount = $item->payments()->paid();
}
$i = Date::parse($item->paid_at)->format($date_format);
$totals[$i] += $item->getConvertedAmount();
}
}
}

View File

@ -12,8 +12,6 @@ use App\Models\Setting\Currency;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use Auth;
use App\Utilities\Modules;
class Invoices extends Controller
@ -27,19 +25,7 @@ class Invoices extends Controller
*/
public function index()
{
$invoices = Invoice::with('status')->where('customer_id', '=', Auth::user()->customer->id)->paginate();
foreach ($invoices as $invoice) {
$paid = 0;
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->amount = $invoice->amount - $paid;
}
$invoices = Invoice::with('status')->accrued()->where('customer_id', auth()->user()->customer->id)->paginate();
$status = collect(InvoiceStatus::all()->pluck('name', 'code'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.statuses', 2)]), '');
@ -94,7 +80,7 @@ class Invoices extends Controller
/**
* Show the form for viewing the specified resource.
*
* @param int $invoice_id
* @param Invoice $invoice
*
* @return Response
*/
@ -126,7 +112,7 @@ class Invoices extends Controller
/**
* Show the form for viewing the specified resource.
*
* @param int $invoice_id
* @param Invoice $invoice
*
* @return Response
*/

View File

@ -0,0 +1,92 @@
<?php
namespace App\Http\Controllers\Customers;
use App\Http\Controllers\Controller;
use App\Http\Requests\Customer\Profile as Request;
use App\Models\Auth\User;
class Profile extends Controller
{
public function index()
{
return $this->edit();
}
public function show()
{
return $this->edit();
}
/**
* Show the form for editing the specified resource.
*
* @return Response
*/
public function edit()
{
$user = auth()->user();
return view('customers.profile.edit', compact('user'));
}
/**
* Update the specified resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function update(Request $request)
{
$user = auth()->user();
// Upload picture
$picture = $request->file('picture');
if ($picture && $picture->isValid()) {
$request['picture'] = $picture->store('users');
}
// Do not reset password if not entered/changed
if (empty($request['password'])) {
unset($request['password']);
unset($request['password_confirmation']);
}
// Update user
$user->update($request->input());
// Update customer
$user->customer->update($request->input());
$message = trans('messages.success.updated', ['type' => trans('auth.profile')]);
flash($message)->success();
return redirect('customers/profile/edit');
}
/**
* Mark overdue invoices notifications are read and redirect to invoices page.
*
* @return Response
*/
public function readOverdueInvoices()
{
$user = auth()->user();
// Mark invoice notifications as read
foreach ($user->unreadNotifications as $notification) {
// Not an invoice notification
if ($notification->getAttribute('type') != 'App\Notifications\Income\Invoice') {
continue;
}
$notification->markAsRead();
}
// Redirect to invoices
return redirect('customers/invoices');
}
}

View File

@ -12,6 +12,7 @@ use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use App\Traits\Currencies;
use Charts;
use Date;
class Dashboard extends Controller
@ -20,6 +21,10 @@ class Dashboard extends Controller
public $today;
public $income_donut = ['colors' => [], 'labels' => [], 'values' => []];
public $expense_donut = ['colors' => [], 'labels' => [], 'values' => []];
/**
* Display a listing of the resource.
*
@ -28,174 +33,46 @@ class Dashboard extends Controller
public function index()
{
$this->today = Date::today();
$month_days = $this->today->daysInMonth;
/*
* Cash Flow
*/
list($total_incomes, $total_expenses, $total_profit) = $this->getTotals();
// Daily
$day = array();
$cashflow = $this->getCashFlow();
for ($j = $month_days; $j > -1; $j--) {
$day[$month_days - $j] = date("d M", strtotime("-$j day"));
}
list($donut_incomes, $donut_expenses) = $this->getDonuts();
$daily_income = $this->getCashFlow('income', 'daily');
$daily_expense = $this->getCashFlow('expense', 'daily');
$accounts = Account::enabled()->take(6)->get();
$daily_profit = $this->getProfit($daily_income, $daily_expense);
$latest_incomes = $this->getLatestIncomes();
// Monthly
$month = array();
$latest_expenses = $this->getLatestExpenses();
for ($j = 12; $j >= 0; $j--) {
$month[12 - $j] = date("F-Y", strtotime(" -$j month"));
}
return view('dashboard.dashboard.index', compact(
'total_incomes',
'total_expenses',
'total_profit',
'cashflow',
'donut_incomes',
'donut_expenses',
'accounts',
'latest_incomes',
'latest_expenses'
));
}
$monthly_income = $this->getCashFlow('income', 'monthly');
$monthly_expense = $this->getCashFlow('expense', 'monthly');
public function cashFlow()
{
$this->today = Date::today();
$monthly_profit = $this->getProfit($monthly_income, $monthly_expense);
$content = $this->getCashFlow()->render();
$cash_flow = [
'daily' => [
'date' => json_encode($day),
'income' => json_encode(array_values($daily_income)),
'expense' => json_encode(array_values($daily_expense)),
'profit' => json_encode(array_values($daily_profit))
],
'monthly' => [
'date' => json_encode($month),
'income' => json_encode(array_values($monthly_income)),
'expense' => json_encode(array_values($monthly_expense)),
'profit' => json_encode(array_values($monthly_profit))
],
];
//return response()->setContent($content)->send();
/*
* Totals & Pie Charts
*/
echo $content;
}
$incomes = $expenses = array();
$incomes_amount = $expenses_amount = 0;
// Invoices
$invoices = Invoice::with('payments')->accrued()->get();
list($invoice_paid_amount, $open_invoice, $overdue_invoice) = $this->getTotals($invoices, 'invoice');
$incomes_amount += $invoice_paid_amount;
// Bills
$bills = Bill::with('payments')->accrued()->get();
list($bill_paid_amount, $open_bill, $overdue_bill) = $this->getTotals($bills, 'bill');
$expenses_amount += $bill_paid_amount;
// Add to Incomes By Category
$incomes[] = array(
'amount' => money($invoice_paid_amount, setting('general.default_currency'), true)->format(),
'value' => (int) $invoice_paid_amount,
'color' => '#00c0ef',
'highlight' => '#00c0ef',
'label' => trans_choice('general.invoices', 2)
);
// Add to Expenses By Category
$expenses[] = array(
'amount' => money($bill_paid_amount, setting('general.default_currency'), true)->format(),
'value' => (int) $bill_paid_amount,
'color' => '#dd4b39',
'highlight' => '#dd4b39',
'label' => trans_choice('general.bills', 2)
);
// Revenues & Payments
$categories = Category::orWhere('type', 'income')->orWhere('type', 'expense')->enabled()->get();
foreach ($categories as $category) {
switch ($category->type) {
case 'income':
$revenues = $category->revenues;
$amount = 0;
if ($revenues) {
foreach ($revenues as $revenue) {
$amount += $revenue->getConvertedAmount();
}
$incomes[] = array(
'amount' => money($amount, setting('general.default_currency'), true)->format(),
'value' => (int) $amount,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
} else {
$incomes[] = array(
'amount' => money(0, setting('general.default_currency'), true)->format(),
'value' => (int) 0,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
}
$incomes_amount += $amount;
break;
case 'expense':
$payments = $category->payments;
$amount = 0;
if ($payments) {
foreach ($payments as $payment) {
$amount += $payment->getConvertedAmount();
}
$expenses[] = array(
'amount' => money($amount, setting('general.default_currency'), true)->format(),
'value' => (int) $amount,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
} else {
$expenses[] = array(
'amount' => money(0, setting('general.default_currency'), true)->format(),
'value' => (int) 0,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
}
$expenses_amount += $amount;
break;
}
}
if (empty($incomes_amount)) {
foreach ($incomes as $key => $income) {
$incomes[$key]['amount'] = money(0, setting('general.default_currency'), true)->format();
$incomes[$key]['value'] = (int) 100 / count($incomes);
}
}
// Incomes Pie Chart
$income_graph = json_encode($incomes);
if (empty($expenses_amount)) {
foreach ($expenses as $key => $expense) {
$expenses[$key]['amount'] = money(0, setting('general.default_currency'), true)->format();
$expenses[$key]['value'] = (int) 100 / count($expenses);
}
}
// Expenses Pie Chart
$expense_graph = json_encode($expenses);
private function getTotals()
{
list($incomes_amount, $open_invoice, $overdue_invoice, $expenses_amount, $open_bill, $overdue_bill) = $this->calculateAmounts();
$incomes_progress = 100;
@ -241,44 +118,175 @@ class Dashboard extends Controller
'progress' => $total_progress
);
/*
* Accounts
*/
$accounts = Account::enabled()->get();
/*
* Latest Incomes
*/
$latest_incomes = collect(Invoice::accrued()->latest()->take(10)->get());
$latest_incomes = $latest_incomes->merge(Revenue::latest()->take(10)->get())->take(5)->sortByDesc('invoiced_at');
/*
* Latest Expenses
*/
$latest_expenses = collect(Bill::accrued()->latest()->take(10)->get());
$latest_expenses = $latest_expenses->merge(Payment::latest()->take(10)->get())->take(5)->sortByDesc('billed_at');
return view('dashboard.dashboard.index', compact(
'total_incomes',
'total_expenses',
'total_profit',
'cash_flow',
'incomes',
'incomes_amount',
'income_graph',
'expenses',
'expenses_amount',
'expense_graph',
'accounts',
'latest_incomes',
'latest_expenses'
));
return array($total_incomes, $total_expenses, $total_profit);
}
private function getCashFlow($type, $period)
private function getCashFlow()
{
$start = Date::parse(request('start', $this->today->startOfYear()->format('Y-m-d')));
$end = Date::parse(request('end', $this->today->endOfYear()->format('Y-m-d')));
$period = request('period', 'month');
$start_month = $start->month;
$end_month = $end->month;
// Monthly
$labels = array();
$s = clone $start;
for ($j = $end_month; $j >= $start_month; $j--) {
$labels[$end_month - $j] = $s->format('M Y');
if ($period == 'month') {
$s->addMonth();
} else {
$s->addMonths(3);
$j -= 2;
}
}
$income = $this->calculateCashFlowTotals('income', $start, $end, $period);
$expense = $this->calculateCashFlowTotals('expense', $start, $end, $period);
$profit = $this->calculateCashFlowProfit($income, $expense);
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
->colors(['#6da252', '#00c0ef', '#F56954'])
->dataset(trans_choice('general.profits', 1), $profit)
->dataset(trans_choice('general.incomes', 1), $income)
->dataset(trans_choice('general.expenses', 1), $expense)
->labels($labels)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.multi.line');
return $chart;
}
private function getDonuts()
{
// Show donut prorated if there is no income
if (array_sum($this->income_donut['values']) == 0) {
foreach ($this->income_donut['values'] as $key => $value) {
$this->income_donut['values'][$key] = 1;
}
}
// Get 6 categories by amount
$colors = $labels = [];
$values = collect($this->income_donut['values'])->sort()->reverse()->take(6)->all();
foreach ($values as $id => $val) {
$colors[$id] = $this->income_donut['colors'][$id];
$labels[$id] = $this->income_donut['labels'][$id];
}
$donut_incomes = Charts::create('donut', 'chartjs')
->colors($colors)
->labels($labels)
->values($values)
->dimensions(0, 160)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.donut');
// Show donut prorated if there is no expense
if (array_sum($this->expense_donut['values']) == 0) {
foreach ($this->expense_donut['values'] as $key => $value) {
$this->expense_donut['values'][$key] = 1;
}
}
// Get 6 categories by amount
$colors = $labels = [];
$values = collect($this->expense_donut['values'])->sort()->reverse()->take(6)->all();
foreach ($values as $id => $val) {
$colors[$id] = $this->expense_donut['colors'][$id];
$labels[$id] = $this->expense_donut['labels'][$id];
}
$donut_expenses = Charts::create('donut', 'chartjs')
->colors($colors)
->labels($labels)
->values($values)
->dimensions(0, 160)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.donut');
return array($donut_incomes, $donut_expenses);
}
private function getLatestIncomes()
{
$latest = collect(Invoice::accrued()->latest()->take(10)->get());
$latest = $latest->merge(Revenue::latest()->take(10)->get())->take(5)->sortByDesc('invoiced_at');
return $latest;
}
private function getLatestExpenses()
{
$latest = collect(Bill::accrued()->latest()->take(10)->get());
$latest = $latest->merge(Payment::latest()->take(10)->get())->take(5)->sortByDesc('billed_at');
return $latest;
}
private function calculateAmounts()
{
$incomes_amount = $expenses_amount = 0;
// Invoices
$invoices = Invoice::with('payments')->accrued()->get();
list($invoice_paid_amount, $open_invoice, $overdue_invoice) = $this->calculateTotals($invoices, 'invoice');
$incomes_amount += $invoice_paid_amount;
// Add to Incomes By Category
$this->addToIncomeDonut('#00c0ef', $invoice_paid_amount, trans_choice('general.invoices', 2));
// Bills
$bills = Bill::with('payments')->accrued()->get();
list($bill_paid_amount, $open_bill, $overdue_bill) = $this->calculateTotals($bills, 'bill');
$expenses_amount += $bill_paid_amount;
// Add to Expenses By Category
$this->addToExpenseDonut('#dd4b39', $bill_paid_amount, trans_choice('general.bills', 2));
// Revenues & Payments
$categories = Category::orWhere('type', 'income')->orWhere('type', 'expense')->enabled()->get();
foreach ($categories as $category) {
switch ($category->type) {
case 'income':
$amount = 0;
foreach ($category->revenues as $revenue) {
$amount += $revenue->getConvertedAmount();
}
$this->addToIncomeDonut($category->color, $amount, $category->name);
$incomes_amount += $amount;
break;
case 'expense':
$amount = 0;
foreach ($category->payments as $payment) {
$amount += $payment->getConvertedAmount();
}
$this->addToExpenseDonut($category->color, $amount, $category->name);
$expenses_amount += $amount;
break;
}
}
return array($incomes_amount, $open_invoice, $overdue_invoice, $expenses_amount, $open_bill, $overdue_bill);
}
private function calculateCashFlowTotals($type, $start, $end, $period)
{
$totals = array();
@ -290,64 +298,77 @@ class Dashboard extends Controller
$m2 = '\App\Models\Expense\BillPayment';
}
switch ($period) {
case 'yearly':
$f1 = 'subYear';
$f2 = 'addYear';
$date_format = 'Y-m';
$date_format = 'Y';
break;
case 'monthly':
$f1 = 'subYear';
$f2 = 'addMonth';
$date_format = 'Y-m';
break;
default:
case 'daily':
$f1 = 'subMonth';
$f2 = 'addDay';
$date_format = 'Y-m-d';
break;
if ($period == 'month') {
$n = 1;
$start_date = $start->format($date_format);
$end_date = $end->format($date_format);
$next_date = $start_date;
} else {
$n = 3;
$start_date = $start->quarter;
$end_date = $end->quarter;
$next_date = $start_date;
}
$now = Date::now();
$sub = Date::now()->$f1();
$start_date = $sub->format($date_format);
$end_date = $now->format($date_format);
$next_date = $start_date;
$totals[$start_date] = 0;
do {
$next_date = Date::parse($next_date)->$f2()->format($date_format);
$s = clone $start;
//$totals[$start_date] = 0;
while ($next_date <= $end_date) {
$totals[$next_date] = 0;
} while ($next_date < $end_date);
$items_1 = $m1::whereBetween('paid_at', [$sub, $now])->get();
if ($period == 'month') {
$next_date = $s->addMonths($n)->format($date_format);
} else {
if (isset($totals[4])) {
break;
}
$this->setCashFlowTotals($totals, $items_1, $date_format);
$next_date = $s->addMonths($n)->quarter;
}
}
$items_2 = $m2::whereBetween('paid_at', [$sub, $now])->get();
$items_1 = $m1::whereBetween('paid_at', [$start, $end])->get();
$this->setCashFlowTotals($totals, $items_2, $date_format);
$this->setCashFlowTotals($totals, $items_1, $date_format, $period);
$items_2 = $m2::whereBetween('paid_at', [$start, $end])->get();
$this->setCashFlowTotals($totals, $items_2, $date_format, $period);
return $totals;
}
private function setCashFlowTotals(&$totals, $items, $date_format)
private function setCashFlowTotals(&$totals, $items, $date_format, $period)
{
foreach ($items as $item) {
$i = Date::parse($item->paid_at)->format($date_format);
if ($period == 'month') {
$i = Date::parse($item->paid_at)->format($date_format);
} else {
$i = Date::parse($item->paid_at)->quarter;
}
$totals[$i] += $item->getConvertedAmount();
}
}
private function getTotals($items, $type)
private function calculateCashFlowProfit($incomes, $expenses)
{
$profit = [];
foreach ($incomes as $key => $income) {
if ($income > 0 && $income > $expenses[$key]) {
$profit[$key] = $income - $expenses[$key];
} else {
$profit[$key] = 0;
}
}
return $profit;
}
private function calculateTotals($items, $type)
{
$paid = $open = $overdue = 0;
@ -380,18 +401,17 @@ class Dashboard extends Controller
return array($paid, $open, $overdue);
}
private function getProfit($incomes, $expenses)
private function addToIncomeDonut($color, $amount, $text)
{
$profit = [];
$this->income_donut['colors'][] = $color;
$this->income_donut['labels'][] = money($amount, setting('general.default_currency'), true)->format() . ' - ' . $text;
$this->income_donut['values'][] = (int) $amount;
}
foreach ($incomes as $key => $income) {
if ($income > 0 && $income > $expenses[$key]) {
$profit[$key] = $income - $expenses[$key];
} else {
$profit[$key] = 0;
}
}
return $profit;
private function addToExpenseDonut($color, $amount, $text)
{
$this->expense_donut['colors'][] = $color;
$this->expense_donut['labels'][] = money($amount, setting('general.default_currency'), true)->format() . ' - ' . $text;
$this->expense_donut['values'][] = (int) $amount;
}
}

View File

@ -37,7 +37,7 @@ class Bills extends Controller
*/
public function index()
{
$bills = Bill::with(['vendor', 'status', 'items', 'payments', 'histories'])->collect();
$bills = Bill::with(['vendor', 'status', 'items', 'payments', 'histories'])->collect(['billed_at'=> 'desc']);
$vendors = collect(Vendor::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.vendors', 2)]), '');
@ -156,7 +156,7 @@ class Bills extends Controller
$item_sku = $item_object->sku;
// Increase stock (item bought)
$item_object->quantity++;
$item_object->quantity += $item['quantity'];
$item_object->save();
}
@ -171,7 +171,7 @@ class Bills extends Controller
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = $item['name'];
$bill_item['name'] = str_limit($item['name'], 180, '');
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
@ -396,7 +396,7 @@ class Bills extends Controller
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = $item['name'];
$bill_item['name'] = str_limit($item['name'], 180, '');
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
@ -603,17 +603,11 @@ class Bills extends Controller
$bill = Bill::find($request['bill_id']);
if ($request['currency_code'] == $bill->currency_code) {
if ($request['amount'] > $bill->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
$total_amount = $bill->amount;
return response()->json($message);
} elseif ($request['amount'] == $bill->amount) {
$bill->bill_status_code = 'paid';
} else {
$bill->bill_status_code = 'partial';
}
} else {
$amount = (double) $request['amount'];
if ($request['currency_code'] != $bill->currency_code) {
$request_bill = new Bill();
$request_bill->amount = (float) $request['amount'];
@ -621,16 +615,24 @@ class Bills extends Controller
$request_bill->currency_rate = $currency->rate;
$amount = $request_bill->getConvertedAmount();
}
if ($amount > $bill->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
if ($bill->payments()->count()) {
$total_amount -= $bill->payments()->paid();
}
return response()->json($message);
} elseif ($amount == $bill->amount) {
$bill->bill_status_code = 'paid';
} else {
$bill->bill_status_code = 'partial';
}
if ($amount > $total_amount) {
$message = trans('messages.error.payment_add');
return response()->json([
'success' => false,
'error' => true,
'message' => $message,
]);
} elseif ($amount == $total_amount) {
$bill->bill_status_code = 'paid';
} else {
$bill->bill_status_code = 'partial';
}
$bill->save();
@ -640,15 +642,19 @@ class Bills extends Controller
$request['status_code'] = $bill->bill_status_code;
$request['notify'] = 0;
$desc_date = Date::parse($request['paid_at'])->format($this->getCompanyDateFormat());
$desc_amount = money((float) $request['amount'], $request['currency_code'], true)->format();
$request['description'] = $desc_date . ' ' . $desc_amount;
$desc_amount = money((float) $request['amount'], (string) $request['currency_code'], true)->format();
$request['description'] = $desc_amount . ' ' . trans_choice('general.payments', 1);
BillHistory::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.revenues', 1)]);
return response()->json($message);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
]);
}
/**
@ -660,12 +666,22 @@ class Bills extends Controller
*/
public function paymentDestroy(BillPayment $payment)
{
$bill = Bill::find($payment->bill_id);
if ($bill->payments()->count() > 1) {
$bill->bill_status_code = 'partial';
} else {
$bill->bill_status_code = 'draft';
}
$bill->save();
$payment->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
return redirect('expenses/bills');
return redirect()->back();
}
}

View File

@ -24,7 +24,7 @@ class Payments extends Controller
*/
public function index()
{
$payments = Payment::with(['vendor', 'account', 'category'])->collect();
$payments = Payment::with(['vendor', 'account', 'category'])->collect(['paid_at'=> 'desc']);
$vendors = collect(Vendor::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.vendors', 2)]), '');
@ -35,7 +35,9 @@ class Payments extends Controller
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
return view('expenses.payments.index', compact('payments', 'vendors', 'categories', 'accounts'));
$transfer_cat_id = Category::transfer();
return view('expenses.payments.index', compact('payments', 'vendors', 'categories', 'accounts', 'transfer_cat_id'));
}
/**
@ -197,6 +199,11 @@ class Payments extends Controller
*/
public function destroy(Payment $payment)
{
// Can't delete transfer payment
if ($payment->category->id == Category::transfer()) {
return redirect('expenses/payments');
}
$payment->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.payments', 1)]);

View File

@ -44,6 +44,10 @@ class Vendors extends Controller
*/
public function store(Request $request)
{
if (empty($request['email'])) {
$request['email'] = '';
}
Vendor::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.vendors', 1)]);
@ -84,6 +88,11 @@ class Vendors extends Controller
foreach ($rows as $row) {
$data = $row->toArray();
if (empty($data['email'])) {
$data['email'] = '';
}
$data['company_id'] = session('company_id');
Vendor::create($data);
@ -120,6 +129,10 @@ class Vendors extends Controller
*/
public function update(Vendor $vendor, Request $request)
{
if (empty($request['email'])) {
$request['email'] = '';
}
$vendor->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.vendors', 1)]);
@ -169,6 +182,10 @@ class Vendors extends Controller
public function vendor(Request $request)
{
if (empty($request['email'])) {
$request['email'] = '';
}
$vendor = Vendor::create($request->all());
return response()->json($vendor);

View File

@ -46,6 +46,10 @@ class Customers extends Controller
public function store(Request $request)
{
if (empty($request->input('create_user'))) {
if (empty($request['email'])) {
$request['email'] = '';
}
Customer::create($request->all());
} else {
// Check if user exist
@ -61,10 +65,14 @@ class Customers extends Controller
}
// Create user first
$user = User::create($request->all());
$data = $request->all();
$data['locale'] = setting('general.default_locale', 'en-GB');
$user = User::create($data);
$user->roles()->attach(['3']);
$user->companies()->attach([session('company_id')]);
// Finally create customer
$request['user_id'] = $user->id;
Customer::create($request->all());
@ -108,6 +116,11 @@ class Customers extends Controller
foreach ($rows as $row) {
$data = $row->toArray();
if (empty($data['email'])) {
$data['email'] = '';
}
$data['company_id'] = session('company_id');
Customer::create($data);
@ -145,6 +158,10 @@ class Customers extends Controller
public function update(Customer $customer, Request $request)
{
if (empty($request->input('create_user'))) {
if (empty($request['email'])) {
$request['email'] = '';
}
$customer->update($request->all());
} else {
// Check if user exist
@ -216,6 +233,10 @@ class Customers extends Controller
public function customer(Request $request)
{
if (empty($request['email'])) {
$request['email'] = '';
}
$customer = Customer::create($request->all());
return response()->json($customer);

View File

@ -30,6 +30,8 @@ use App\Utilities\ImportFile;
use App\Utilities\Modules;
use Date;
use File;
use Image;
use Storage;
class Invoices extends Controller
{
@ -42,7 +44,7 @@ class Invoices extends Controller
*/
public function index()
{
$invoices = Invoice::with(['customer', 'status', 'items', 'payments', 'histories'])->collect();
$invoices = Invoice::with(['customer', 'status', 'items', 'payments', 'histories'])->collect(['invoice_number'=> 'desc']);
$customers = collect(Customer::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.customers', 2)]), '');
@ -162,7 +164,7 @@ class Invoices extends Controller
$item_sku = $item_object->sku;
// Decrease stock (item sold)
$item_object->quantity--;
$item_object->quantity -= $item['quantity'];
$item_object->save();
// Notify users if out of stock
@ -188,7 +190,7 @@ class Invoices extends Controller
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = $item['name'];
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
@ -386,7 +388,7 @@ class Invoices extends Controller
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = $item['name'];
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
@ -487,9 +489,15 @@ class Invoices extends Controller
*/
public function emailInvoice(Invoice $invoice)
{
if (empty($invoice->customer_email)) {
return redirect()->back();
}
$invoice = $this->prepareInvoice($invoice);
$html = view($invoice->template_path, compact('invoice'))->render();
$logo = $this->getLogo();
$html = view($invoice->template_path, compact('invoice', 'logo'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($html);
@ -531,7 +539,9 @@ class Invoices extends Controller
{
$invoice = $this->prepareInvoice($invoice);
return view($invoice->template_path, compact('invoice'));
$logo = $this->getLogo();
return view($invoice->template_path, compact('invoice', 'logo'));
}
/**
@ -545,7 +555,9 @@ class Invoices extends Controller
{
$invoice = $this->prepareInvoice($invoice);
$html = view($invoice->template_path, compact('invoice'))->render();
$logo = $this->getLogo();
$html = view($invoice->template_path, compact('invoice', 'logo'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($html);
@ -576,18 +588,23 @@ class Invoices extends Controller
$amount = $invoice->amount - $paid;
$request = new PaymentRequest();
if (!empty($amount)) {
$request = new PaymentRequest();
$request['company_id'] = $invoice->company_id;
$request['invoice_id'] = $invoice->id;
$request['account_id'] = setting('general.default_account');
$request['payment_method'] = setting('general.default_payment_method');
$request['currency_code'] = $invoice->currency_code;
$request['amount'] = $amount;
$request['paid_at'] = Date::now();
$request['_token'] = csrf_token();
$request['company_id'] = $invoice->company_id;
$request['invoice_id'] = $invoice->id;
$request['account_id'] = setting('general.default_account');
$request['payment_method'] = setting('general.default_payment_method', 'offlinepayment.cash.1');
$request['currency_code'] = $invoice->currency_code;
$request['amount'] = $amount;
$request['paid_at'] = Date::now();
$request['_token'] = csrf_token();
$this->payment($request);
$this->payment($request);
} else {
$invoice->invoice_status_code = 'paid';
$invoice->save();
}
return redirect()->back();
}
@ -616,17 +633,11 @@ class Invoices extends Controller
$invoice = Invoice::find($request['invoice_id']);
if ($request['currency_code'] == $invoice->currency_code) {
if ($request['amount'] > $invoice->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
$total_amount = $invoice->amount;
return response()->json($message);
} elseif ($request['amount'] == $invoice->amount) {
$invoice->invoice_status_code = 'paid';
} else {
$invoice->invoice_status_code = 'partial';
}
} else {
$amount = (double) $request['amount'];
if ($request['currency_code'] != $invoice->currency_code) {
$request_invoice = new Invoice();
$request_invoice->amount = (float) $request['amount'];
@ -634,16 +645,24 @@ class Invoices extends Controller
$request_invoice->currency_rate = $currency->rate;
$amount = $request_invoice->getConvertedAmount();
}
if ($amount > $invoice->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
if ($invoice->payments()->count()) {
$total_amount -= $invoice->payments()->paid();
}
return response()->json($message);
} elseif ($amount == $invoice->amount) {
$invoice->invoice_status_code = 'paid';
} else {
$invoice->invoice_status_code = 'partial';
}
if ($amount > $total_amount) {
$message = trans('messages.error.payment_add');
return response()->json([
'success' => false,
'error' => true,
'message' => $message,
]);
} elseif ($amount == $total_amount) {
$invoice->invoice_status_code = 'paid';
} else {
$invoice->invoice_status_code = 'partial';
}
$invoice->save();
@ -653,15 +672,19 @@ class Invoices extends Controller
$request['status_code'] = $invoice->invoice_status_code;
$request['notify'] = 0;
$desc_date = Date::parse($request['paid_at'])->format($this->getCompanyDateFormat());
$desc_amount = money((float) $request['amount'], $request['currency_code'], true)->format();
$request['description'] = $desc_date . ' ' . $desc_amount;
$desc_amount = money((float) $request['amount'], (string) $request['currency_code'], true)->format();
$request['description'] = $desc_amount . ' ' . trans_choice('general.payments', 1);
InvoiceHistory::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.revenues', 1)]);
return response()->json($message);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
]);
}
/**
@ -673,13 +696,25 @@ class Invoices extends Controller
*/
public function paymentDestroy(InvoicePayment $payment)
{
$invoice = Invoice::find($payment->invoice_id);
if ($invoice->payments()->paid() == $invoice->amount) {
$invoice->invoice_status_code = 'paid';
} elseif ($invoice->payments()->count() > 1) {
$invoice->invoice_status_code = 'partial';
} else {
$invoice->invoice_status_code = 'draft';
}
$invoice->save();
$payment->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.invoices', 1)]);
flash($message)->success();
return redirect('incomes/invoices');
return redirect()->back();
}
protected function prepareInvoice(Invoice $invoice)
@ -743,4 +778,31 @@ class Invoices extends Controller
'sort_order' => $sort_order,
]);
}
protected function getLogo()
{
$logo = '';
if (setting('general.invoice_logo')) {
$file = session('company_id') . '/' . setting('general.invoice_logo');
} else {
$file = session('company_id') . '/' . setting('general.company_logo');
}
$path = Storage::path($file);
if (!is_file($path)) {
return $logo;
}
$image = Image::make($path)->encode()->getEncoded();
if (empty($image)) {
return $logo;
}
$extension = File::extension($path);
$logo = 'data:image/' . $extension . ';base64,' . base64_encode($image);
return $logo;
}
}

View File

@ -26,7 +26,7 @@ class Revenues extends Controller
*/
public function index()
{
$revenues = Revenue::with(['account', 'category', 'customer'])->collect();
$revenues = Revenue::with(['account', 'category', 'customer'])->collect(['paid_at'=> 'desc']);
$customers = collect(Customer::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.customers', 2)]), '');
@ -37,7 +37,9 @@ class Revenues extends Controller
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
return view('incomes.revenues.index', compact('revenues', 'customers', 'categories', 'accounts'));
$transfer_cat_id = Category::transfer();
return view('incomes.revenues.index', compact('revenues', 'customers', 'categories', 'accounts', 'transfer_cat_id'));
}
/**
@ -199,6 +201,11 @@ class Revenues extends Controller
*/
public function destroy(Revenue $revenue)
{
// Can't delete transfer revenue
if ($revenue->category->id == Category::transfer()) {
return redirect('incomes/revenues');
}
$revenue->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.revenues', 1)]);

View File

@ -247,13 +247,16 @@ class Items extends Controller
if ($input_items) {
foreach ($input_items as $key => $item) {
$price = (double) $item['price'];
$quantity = (int) $item['quantity'];
$item_tax_total= 0;
$item_sub_total = ($item['price'] * $item['quantity']);
$item_sub_total = ($price * $quantity);
if (!empty($item['tax_id'])) {
$tax = Tax::find($item['tax_id']);
$item_tax_total = (($item['price'] * $item['quantity']) / 100) * $tax->rate;
$item_tax_total = (($price * $quantity) / 100) * $tax->rate;
}
$sub_total += $item_sub_total;

View File

@ -19,9 +19,15 @@ class Home extends Controller
{
$this->checkApiToken();
$paid = $this->getPaidModules();
$new = $this->getNewModules();
$free = $this->getFreeModules();
$data = [
'query' => [
'limit' => 4
]
];
$paid = $this->getPaidModules($data);
$new = $this->getNewModules($data);
$free = $this->getFreeModules($data);
return view('modules.home.index', compact('paid', 'new', 'free'));
}

View File

@ -2,19 +2,33 @@
namespace App\Http\Controllers\Modules;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Module\Module;
use App\Models\Module\ModuleHistory;
use App\Traits\Modules;
use Artisan;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
class Item extends Controller
{
use Modules;
/**
* Instantiate a new controller instance.
*
* @param Route $route
*/
public function __construct(Route $route)
{
parent::__construct($route);
// Add CRUD permission check
$this->middleware('permission:create-modules-item')->only(['install']);
$this->middleware('permission:update-modules-item')->only(['update', 'enable', 'disable']);
$this->middleware('permission:delete-modules-item')->only(['uninstall']);
}
/**
* Show the form for viewing the specified resource.
*
@ -31,7 +45,7 @@ class Item extends Controller
$module = $this->getModule($alias);
$check = Module::where('alias', $alias)->first();
$check = Module::alias($alias)->first();
if ($check) {
$installed = true;
@ -154,7 +168,7 @@ class Item extends Controller
$json = $this->uninstallModule($alias);
$module = Module::where('alias', $alias)->first();
$module = Module::alias($alias)->first();
$data = array(
'company_id' => session('company_id'),
@ -181,7 +195,7 @@ class Item extends Controller
$json = $this->updateModule($alias);
$module = Module::where('alias', $alias)->first();
$module = Module::alias($alias)->first();
$data = array(
'company_id' => session('company_id'),
@ -206,7 +220,7 @@ class Item extends Controller
$json = $this->enableModule($alias);
$module = Module::where('alias', $alias)->first();
$module = Module::alias($alias)->first();
$data = array(
'company_id' => session('company_id'),
@ -235,7 +249,7 @@ class Item extends Controller
$json = $this->disableModule($alias);
$module = Module::where('alias', $alias)->first();
$module = Module::alias($alias)->first();
$data = array(
'company_id' => session('company_id'),

View File

@ -7,6 +7,7 @@ use App\Models\Expense\Bill;
use App\Models\Expense\BillPayment;
use App\Models\Expense\Payment;
use App\Models\Setting\Category;
use Charts;
use Date;
class ExpenseSummary extends Controller
@ -90,10 +91,19 @@ class ExpenseSummary extends Controller
$this->setAmount($expenses_graph, $totals, $expenses, $payments, 'payment', 'paid_at');
}
// Expenses chart
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
->colors(['#F56954'])
->dataset(trans_choice('general.expenses', 1), $expenses_graph)
->labels($dates)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.multi.line');
// Expenses Graph
$expenses_graph = json_encode($expenses_graph);
return view('reports.expense_summary.index', compact('dates', 'categories', 'expenses', 'expenses_graph', 'totals'));
return view('reports.expense_summary.index', compact('chart', 'dates', 'categories', 'expenses', 'totals'));
}
private function setAmount(&$graph, &$totals, &$expenses, $items, $type, $date_field)

View File

@ -10,6 +10,7 @@ use App\Models\Expense\Bill;
use App\Models\Expense\BillPayment;
use App\Models\Expense\Payment;
use App\Models\Setting\Category;
use Charts;
use Date;
class IncomeExpenseSummary extends Controller
@ -21,7 +22,7 @@ class IncomeExpenseSummary extends Controller
*/
public function index()
{
$dates = $totals = $compares = $compares_graph = $categories = [];
$dates = $totals = $compares = $profit_graph = $categories = [];
$status = request('status');
@ -49,7 +50,7 @@ class IncomeExpenseSummary extends Controller
for ($j = 1; $j <= 12; $j++) {
$dates[$j] = Date::parse($year . '-' . $j)->format('F');
$compares_graph[Date::parse($year . '-' . $j)->format('F-Y')] = 0;
$profit_graph[Date::parse($year . '-' . $j)->format('F-Y')] = 0;
// Totals
$totals[$dates[$j]] = array(
@ -100,50 +101,56 @@ class IncomeExpenseSummary extends Controller
switch ($status) {
case 'paid':
$invoices = InvoicePayment::monthsOfYear('paid_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $invoices, 'invoice', 'paid_at');
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'paid_at');
break;
case 'upcoming':
$invoices = Invoice::accrued()->monthsOfYear('due_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $invoices, 'invoice', 'due_at');
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'due_at');
break;
default:
$invoices = Invoice::accrued()->monthsOfYear('invoiced_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $invoices, 'invoice', 'invoiced_at');
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'invoiced_at');
break;
}
// Revenues
if ($status != 'upcoming') {
$revenues = Revenue::monthsOfYear('paid_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
$this->setAmount($profit_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
}
// Bills
switch ($status) {
case 'paid':
$bills = BillPayment::monthsOfYear('paid_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $bills, 'bill', 'paid_at');
$this->setAmount($profit_graph, $totals, $compares, $bills, 'bill', 'paid_at');
break;
case 'upcoming':
$bills = Bill::accrued()->monthsOfYear('due_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $bills, 'bill', 'due_at');
$this->setAmount($profit_graph, $totals, $compares, $bills, 'bill', 'due_at');
break;
default:
$bills = Bill::accrued()->monthsOfYear('billed_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $bills, 'bill', 'billed_at');
$this->setAmount($profit_graph, $totals, $compares, $bills, 'bill', 'billed_at');
break;
}
// Payments
if ($status != 'upcoming') {
$payments = Payment::monthsOfYear('paid_at')->get();
$this->setAmount($compares_graph, $totals, $compares, $payments, 'payment', 'paid_at');
$this->setAmount($profit_graph, $totals, $compares, $payments, 'payment', 'paid_at');
}
// Incomes Graph
$compares_graph = json_encode($compares_graph);
// Profit chart
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
->colors(['#6da252'])
->dataset(trans_choice('general.profits', 1), $profit_graph)
->labels($dates)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.multi.line');
return view('reports.income_expense_summary.index', compact('dates', 'income_categories', 'expense_categories', 'compares', 'compares_graph', 'totals'));
return view('reports.income_expense_summary.index', compact('chart', 'dates', 'income_categories', 'expense_categories', 'compares', 'totals'));
}
private function setAmount(&$graph, &$totals, &$compares, $items, $type, $date_field)

View File

@ -7,6 +7,7 @@ use App\Models\Income\Invoice;
use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use Charts;
use Date;
class IncomeSummary extends Controller
@ -90,10 +91,16 @@ class IncomeSummary extends Controller
$this->setAmount($incomes_graph, $totals, $incomes, $revenues, 'revenue', 'paid_at');
}
// Incomes Graph
$incomes_graph = json_encode($incomes_graph);
// Incomes chart
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
->colors(['#00c0ef'])
->dataset(trans_choice('general.incomes', 1), $incomes_graph)
->labels($dates)
->credits(false)
->view('vendor.consoletvs.charts.chartjs.multi.line');
return view('reports.income_summary.index', compact('dates', 'categories', 'incomes', 'incomes_graph', 'totals'));
return view('reports.income_summary.index', compact('chart', 'dates', 'categories', 'incomes', 'totals'));
}
private function setAmount(&$graph, &$totals, &$incomes, $items, $type, $date_field)

View File

@ -18,10 +18,12 @@ class Categories extends Controller
{
$categories = Category::collect();
$transfer_id = Category::transfer();
$types = collect(['expense' => 'Expense', 'income' => 'Income', 'item' => 'Item', 'other' => 'Other'])
->prepend(trans('general.all_type', ['type' => trans_choice('general.types', 2)]), '');
return view('settings.categories.index', compact('categories', 'types'));
return view('settings.categories.index', compact('categories', 'types', 'transfer_id'));
}
/**
@ -112,6 +114,11 @@ class Categories extends Controller
'payments' => 'payments',
]);
// Can't delete transfer category
if ($category->id == Category::transfer()) {
return redirect('settings/categories');
}
if (empty($relationships)) {
$category->delete();

View File

@ -19,7 +19,7 @@ class Currencies extends Controller
{
$currencies = Currency::collect();
return view('settings.currencies.index', compact('currencies', 'codes', 'rates'));
return view('settings.currencies.index', compact('currencies'));
}
/**
@ -116,20 +116,23 @@ class Currencies extends Controller
*/
public function update(Currency $currency, Request $request)
{
$relationships = $this->countRelationships($currency, [
'accounts' => 'accounts',
'customers' => 'customers',
'invoices' => 'invoices',
'revenues' => 'revenues',
'bills' => 'bills',
'payments' => 'payments',
]);
// Check if we can disable it
if (!$request['enabled']) {
$relationships = $this->countRelationships($currency, [
'accounts' => 'accounts',
'customers' => 'customers',
'invoices' => 'invoices',
'revenues' => 'revenues',
'bills' => 'bills',
'payments' => 'payments',
]);
if ($currency->code == setting('general.default_currency')) {
$relationships[] = strtolower(trans_choice('general.companies', 1));
if ($currency->code == setting('general.default_currency')) {
$relationships[] = strtolower(trans_choice('general.companies', 1));
}
}
if (empty($relationships) || $request['enabled']) {
if (empty($relationships)) {
// Force the rate to be 1 for default currency
if ($request['default_currency']) {
$request['rate'] = '1';
@ -209,4 +212,20 @@ class Currencies extends Controller
return response()->json($json);
}
public function config()
{
$json = new \stdClass();
$code = request('code');
if ($code) {
$currency = config('money.' . $code);
$currency['symbol_first'] = $currency['symbol_first'] ? 1 : 0;
$json = (object) $currency;
}
return response()->json($json);
}
}

View File

@ -5,13 +5,14 @@ namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Setting as Request;
use App\Models\Banking\Account;
use App\Models\Company\Company;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Models\Setting\Setting;
use App\Models\Setting\Tax;
use App\Traits\DateTime;
use App\Traits\Uploads;
use App\Utilities\Modules;
use DotenvEditor;
class Settings extends Controller
{
@ -90,6 +91,8 @@ class Settings extends Controller
$skip_keys = ['company_id', '_method', '_token'];
$file_keys = ['company_logo', 'invoice_logo'];
$companies = Company::all()->count();
foreach ($fields as $key => $value) {
// Don't process unwanted keys
@ -107,6 +110,17 @@ class Settings extends Controller
}
}
// Change default locale if only 1 company
if (($key == 'default_locale') && ($companies == 1)) {
// Update .env file
DotenvEditor::setKeys([
[
'key' => 'APP_LOCALE',
'value' => $value,
],
])->save();
}
setting()->set('general.' . $key, $value);
}