Merge branch 'master' of github.com:akaunting/akaunting

Conflicts:
	app/Http/Controllers/Auth/Login.php
This commit is contained in:
cuneytsenturk
2018-12-03 13:49:31 +03:00
853 changed files with 22158 additions and 3528 deletions

View File

@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api\Incomes;
use App\Events\InvoiceCreated;
use App\Events\InvoiceUpdated;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Income\Invoice as Request;
use App\Jobs\Income\CreateInvoice;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoiceItem;
@ -13,13 +13,13 @@ use App\Models\Income\InvoicePayment;
use App\Models\Income\InvoiceTotal;
use App\Models\Common\Item;
use App\Models\Setting\Tax;
use App\Notifications\Common\Item as ItemNotification;
use App\Traits\Incomes;
use App\Transformers\Income\Invoice as Transformer;
use Dingo\Api\Routing\Helpers;
class Invoices extends ApiController
{
use Helpers;
use Helpers, Incomes;
/**
* Display a listing of the resource.
@ -63,114 +63,9 @@ class Invoices extends ApiController
$request['amount'] = 0;
}
$invoice = Invoice::create($request->all());
$invoice = dispatch(new CreateInvoice($request));
$taxes = [];
$tax_total = 0;
$sub_total = 0;
$invoice_item = array();
$invoice_item['company_id'] = $request['company_id'];
$invoice_item['invoice_id'] = $invoice->id;
if ($request['item']) {
foreach ($request['item'] as $item) {
$item_id = 0;
$item_sku = '';
if (!empty($item['item_id'])) {
$item_object = Item::find($item['item_id']);
$item_id = $item['item_id'];
$item['name'] = $item_object->name;
$item_sku = $item_object->sku;
// Decrease stock (item sold)
$item_object->quantity -= $item['quantity'];
$item_object->save();
// Notify users if out of stock
if ($item_object->quantity == 0) {
foreach ($item_object->company->users as $user) {
if (!$user->can('read-notifications')) {
continue;
}
$user->notify(new ItemNotification($item_object));
}
}
} elseif (!empty($item['sku'])) {
$item_sku = $item['sku'];
}
$tax = $tax_id = 0;
if (!empty($item['tax_id'])) {
$tax_object = Tax::find($item['tax_id']);
$tax_id = $item['tax_id'];
$tax = (($item['price'] * $item['quantity']) / 100) * $tax_object->rate;
} elseif (!empty($item['tax'])) {
$tax = $item['tax'];
}
$invoice_item['item_id'] = $item_id;
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
$invoice_item['tax'] = $tax;
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = $item['price'] * $item['quantity'];
InvoiceItem::create($invoice_item);
if (isset($tax_object)) {
if (array_key_exists($tax_object->id, $taxes)) {
$taxes[$tax_object->id]['amount'] += $tax;
} else {
$taxes[$tax_object->id] = [
'name' => $tax_object->name,
'amount' => $tax
];
}
}
$tax_total += $tax;
$sub_total += $invoice_item['total'];
unset($item_object);
unset($tax_object);
}
}
if (empty($request['amount'])) {
$request['amount'] = $sub_total + $tax_total;
}
$invoice->update($request->input());
// Add invoice totals
$this->addTotals($invoice, $request, $taxes, $sub_total, $tax_total);
$request['invoice_id'] = $invoice->id;
$request['status_code'] = $request['invoice_status_code'];
$request['notify'] = 0;
$request['description'] = trans('messages.success.added', ['type' => $request['invoice_number']]);
InvoiceHistory::create($request->input());
// Update next invoice number
$next = setting('general.invoice_number_next', 1) + 1;
setting(['general.invoice_number_next' => $next]);
setting()->save();
// Fire the event to make it extendible
event(new InvoiceCreated($invoice));
return $this->response->created(url('api/invoices/'.$invoice->id));
return $this->response->created(url('api/invoices/' . $invoice->id));
}
/**
@ -277,12 +172,9 @@ class Invoices extends ApiController
*/
public function destroy(Invoice $invoice)
{
$this->deleteRelationships($invoice, ['items', 'histories', 'payments', 'recurring', 'totals']);
$invoice->delete();
InvoiceItem::where('invoice_id', $invoice->id)->delete();
InvoicePayment::where('invoice_id', $invoice->id)->delete();
InvoiceHistory::where('invoice_id', $invoice->id)->delete();
return $this->response->noContent();
}

View File

@ -49,7 +49,7 @@ class Login extends Controller
public function store()
{
// Attempt to login
if (!auth()->attempt(request(['email', 'password']))) {
if (!auth()->attempt(request(['email', 'password']), request('remember', false))) {
flash(trans('auth.failed'))->error();
return back();
@ -79,6 +79,11 @@ class Login extends Controller
return redirect($path);
}
// Check wizard
if (!setting('general.wizard', false)) {
return redirect('wizard');
}
return redirect()->intended('/');
}

View File

@ -29,9 +29,21 @@ class Roles extends Controller
*/
public function create()
{
$permissions = Permission::all();
$names = $permissions = [];
$allPermissions = Permission::all();
return view('auth.roles.create', compact('permissions'));
foreach ($allPermissions as $permission) {
// permission code explode - and get permission type
$n = explode('-', $permission->name);
if (!in_array($n[0], $names)) {
$names[] = $n[0];
}
$permissions[$n[0]][] = $permission;
}
return view('auth.roles.create', compact('names', 'permissions'));
}
/**
@ -66,11 +78,23 @@ class Roles extends Controller
public function edit(Role $role)
{
//$permissions = Permission::all()->sortBy('display_name');
$permissions = Permission::all();
$names = $permissions = [];
$allPermissions = Permission::all();
$rolePermissions = $role->permissions->pluck('id', 'id')->toArray();
return view('auth.roles.edit', compact('role', 'permissions', 'rolePermissions'));
foreach ($allPermissions as $permission) {
// permission code explode - and get permission type
$n = explode('-', $permission->name);
if (!in_array($n[0], $names)) {
$names[] = $n[0];
}
$permissions[$n[0]][] = $permission;
}
return view('auth.roles.edit', compact('role', 'names', 'permissions', 'rolePermissions'));
}
/**

View File

@ -98,8 +98,15 @@ class Accounts extends Controller
*/
public function update(Account $account, Request $request)
{
// Check if we can disable it
if (!$request['enabled']) {
// Check if we can disable or change the code
if (!$request['enabled'] || ($account->currency_code != $request['currency_code'])) {
$relationships = $this->countRelationships($account, [
'invoice_payments' => 'invoices',
'revenues' => 'revenues',
'bill_payments' => 'bills',
'payments' => 'payments',
]);
if ($account->id == setting('general.default_account')) {
$relationships[] = strtolower(trans_choice('general.companies', 1));
}
@ -120,7 +127,7 @@ class Accounts extends Controller
return redirect('banking/accounts');
} else {
$message = trans('messages.warning.disabled', ['name' => $account->name, 'text' => implode(', ', $relationships)]);
$message = trans('messages.warning.disable_code', ['name' => $account->name, 'text' => implode(', ', $relationships)]);
flash($message)->warning();

View File

@ -0,0 +1,315 @@
<?php
namespace App\Http\Controllers\Banking;
use App\Http\Controllers\Controller;
use App\Http\Requests\Banking\Reconciliation as Request;
use App\Models\Banking\Account;
use App\Models\Banking\Reconciliation;
use App\Models\Setting\Currency;
use Date;
class Reconciliations extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$reconciliations = Reconciliation::collect();
$accounts = collect(Account::enabled()->orderBy('name')->pluck('name', 'id'));
return view('banking.reconciliations.index', compact('reconciliations', 'accounts'));
}
/**
* Show the form for viewing the specified resource.
*
* @return Response
*/
public function show()
{
return redirect()->route('reconciliations.index');
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$accounts = Account::enabled()->pluck('name', 'id');
$account_id = request('account_id', setting('general.default_account'));
$started_at = request('started_at', '0000-00-00');
$ended_at = request('ended_at', '0000-00-00');
$account = Account::find($account_id);
$currency = $account->currency;
$transactions = $this->getTransactions($account, $started_at, $ended_at);
$opening_balance = $this->getOpeningBalance($account, $started_at, $ended_at);
return view('banking.reconciliations.create', compact('accounts', 'account', 'currency', 'opening_balance', 'transactions'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
$reconcile = $request->get('reconcile');
$transactions = $request->get('transactions');
Reconciliation::create([
'company_id' => session('company_id'),
'account_id' => $request->get('account_id'),
'started_at' => $request->get('started_at'),
'ended_at' => $request->get('ended_at'),
'closing_balance' => $request->get('closing_balance'),
'reconciled' => $reconcile ? 1 : 0,
]);
if ($transactions) {
foreach ($transactions as $key => $value) {
$t = explode('_', $key);
$m = '\\' . $t['1'];
$transaction = $m::find($t[0]);
$transaction->reconciled = 1;
$transaction->save();
}
}
$message = trans('messages.success.added', ['type' => trans_choice('general.reconciliations', 1)]);
flash($message)->success();
return redirect()->route('reconciliations.index');
}
/**
* Show the form for editing the specified resource.
*
* @param Reconciliation $reconciliation
*
* @return Response
*/
public function edit(Reconciliation $reconciliation)
{
$account = $reconciliation->account;
$currency = $account->currency;
$transactions = $this->getTransactions($account, $reconciliation->started_at, $reconciliation->ended_at);
$opening_balance = $this->getOpeningBalance($account, $reconciliation->started_at, $reconciliation->ended_at);
return view('banking.reconciliations.edit', compact('reconciliation', 'account', 'currency', 'opening_balance', 'transactions'));
}
/**
* Update the specified resource in storage.
*
* @param Reconciliation $reconciliation
* @param Request $request
*
* @return Response
*/
public function update(Reconciliation $reconciliation, Request $request)
{
$reconcile = $request->get('reconcile');
$transactions = $request->get('transactions');
$reconciliation->reconciled = $reconcile ? 1 : 0;
$reconciliation->save();
if ($transactions) {
foreach ($transactions as $key => $value) {
$t = explode('_', $key);
$m = '\\' . $t['1'];
$transaction = $m::find($t[0]);
$transaction->reconciled = 1;
$transaction->save();
}
}
$message = trans('messages.success.updated', ['type' => trans_choice('general.reconciliations', 1)]);
flash($message)->success();
return redirect()->route('reconciliations.index');
}
/**
* Remove the specified resource from storage.
*
* @param Reconciliation $reconciliation
*
* @return Response
*/
public function destroy(Reconciliation $reconciliation)
{
$reconciliation->delete();
$models = [
'App\Models\Expense\Payment',
'App\Models\Expense\BillPayment',
'App\Models\Income\Revenue',
'App\Models\Income\InvoicePayment',
];
foreach ($models as $model) {
$m = '\\' . $model;
$m::where('account_id', $reconciliation->account_id)
->reconciled()
->whereBetween('paid_at', [$reconciliation->started_at, $reconciliation->ended_at])->each(function ($item) {
$item->reconciled = 0;
$item->save();
});
}
$message = trans('messages.success.deleted', ['type' => trans_choice('general.reconciliations', 1)]);
flash($message)->success();
return redirect()->route('reconciliations.index');
}
/**
* Add transactions array.
*
* @param $account_id
* @param $started_at
* @param $ended_at
*
* @return array
*/
protected function getTransactions($account, $started_at, $ended_at)
{
$started = explode(' ', $started_at);
$ended = explode(' ', $ended_at);
$models = [
'App\Models\Expense\Payment',
'App\Models\Expense\BillPayment',
'App\Models\Income\Revenue',
'App\Models\Income\InvoicePayment',
];
$transactions = [];
foreach ($models as $model) {
$m = '\\' . $model;
$m::where('account_id', $account->id)->whereBetween('paid_at', [$started[0], $ended[0]])->each(function($item) use(&$transactions, $model) {
$item->model = $model;
if (($model == 'App\Models\Income\Invoice') || ($model == 'App\Models\Income\Revenue')) {
if ($item->invoice) {
$item->contact = $item->invoice->customer;
} else {
$item->contact = $item->customer;
}
} else {
if ($item->bill) {
$item->contact = $item->bill->vendor;
} else {
$item->contact = $item->vendor;
}
}
$transactions[] = $item;
});
}
return collect($transactions)->sortByDesc('paid_at');
}
/**
* Get the opening balance
*
* @param $account
* @param $started_at
*
* @return string
*/
public function getOpeningBalance($account, $started_at)
{
// Opening Balance
$total = $account->opening_balance;
// Sum invoices
$invoice_payments = $account->invoice_payments()->whereDate('paid_at', '<', $started_at)->get();
foreach ($invoice_payments as $item) {
$total += $item->amount;
}
// Sum revenues
$revenues = $account->revenues()->whereDate('paid_at', '<', $started_at)->get();
foreach ($revenues as $item) {
$total += $item->amount;
}
// Subtract bills
$bill_payments = $account->bill_payments()->whereDate('paid_at', '<', $started_at)->get();
foreach ($bill_payments as $item) {
$total -= $item->amount;
}
// Subtract payments
$payments = $account->payments()->whereDate('paid_at', '<', $started_at)->get();
foreach ($payments as $item) {
$total -= $item->amount;
}
return $total;
}
public function calculate()
{
$currency_code = request('currency_code');
$closing_balance = request('closing_balance');
$json = new \stdClass();
$cleared_amount = $difference = $income_total = $expense_total = 0;
if ($transactions = request('transactions')) {
$opening_balance = request('opening_balance');
foreach ($transactions as $key => $value) {
$model = explode('_', $key);
if (($model[1] == 'App\Models\Income\Invoice') || ($model[1] == 'App\Models\Income\Revenue')) {
$income_total += $value;
} else {
$expense_total += $value;
}
}
$cleared_amount = $opening_balance + ($income_total - $expense_total);
}
$difference = $closing_balance - $cleared_amount;
$json->closing_balance = money($closing_balance, $currency_code, true)->format();
$json->cleared_amount = money($cleared_amount, $currency_code, true)->format();
$json->difference = money($difference, $currency_code, true)->format();
$json->difference_raw = (int) $difference;
return response()->json($json);
}
}

View File

@ -25,25 +25,24 @@ class Transactions extends Controller
{
$request = request();
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
$accounts = collect(Account::enabled()->pluck('name', 'id'));
$types = collect(['expense' => 'Expense', 'income' => 'Income'])
->prepend(trans('general.all_type', ['type' => trans_choice('general.types', 2)]), '');
$categories = collect(Category::enabled()->type('income')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.categories', 2)]), '');
$type = $request->get('type');
$type_cats = empty($type) ? ['income', 'expense'] : $type;
$categories = collect(Category::enabled()->type($type_cats)->pluck('name', 'id'));
if ($type != 'income') {
$this->addTransactions(Payment::collect(['paid_at'=> 'desc']), trans_choice('general.expenses', 1));
$this->addTransactions(BillPayment::collect(['paid_at'=> 'desc']), trans_choice('general.expenses', 1), trans_choice('general.bills', 1));
$this->addTransactions(BillPayment::collect(['paid_at'=> 'desc']), trans_choice('general.expenses', 1));
}
if ($type != 'expense') {
$this->addTransactions(Revenue::collect(['paid_at'=> 'desc']), trans_choice('general.incomes', 1));
$this->addTransactions(InvoicePayment::collect(['paid_at'=> 'desc']), trans_choice('general.incomes', 1), trans_choice('general.invoices', 1));
$this->addTransactions(InvoicePayment::collect(['paid_at'=> 'desc']), trans_choice('general.incomes', 1));
}
$transactions = $this->getTransactions($request);
@ -56,27 +55,29 @@ class Transactions extends Controller
*
* @param $items
* @param $type
* @param $category
*/
protected function addTransactions($items, $type, $category = null)
protected function addTransactions($items, $type)
{
foreach ($items as $item) {
$data = [
if (!empty($item->category)) {
$category_name = ($item->category) ? $item->category->name : trans('general.na');
} else {
if ($type == trans_choice('general.incomes', 1)) {
$category_name = ($item->invoice->category) ? $item->invoice->category->name : trans('general.na');
} else {
$category_name = ($item->bill->category) ? $item->bill->category->name : trans('general.na');
}
}
$this->transactions[] = (object) [
'paid_at' => $item->paid_at,
'account_name' => $item->account->name,
'type' => $type,
'description' => $item->description,
'amount' => $item->amount,
'currency_code' => $item->currency_code,
'category_name' => $category_name,
];
if (!is_null($category)) {
$data['category_name'] = $category;
} else {
$data['category_name'] = $item->category->name;
}
$this->transactions[] = (object) $data;
}
}

View File

@ -264,6 +264,11 @@ class Companies extends Controller
event(new CompanySwitched($company));
}
// Check wizard
if (!setting('general.wizard', false)) {
return redirect('wizard');
}
return redirect('/');
}

View File

@ -126,6 +126,7 @@ class Dashboard extends Controller
$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');
$range = request('range', 'custom');
$start_month = $start->month;
$end_month = $end->month;
@ -135,6 +136,14 @@ class Dashboard extends Controller
$s = clone $start;
if ($range == 'last_12_months') {
$end_month = 12;
$start_month = 0;
} elseif ($range == 'custom') {
$end_month = $end->diffInMonths($start);
$start_month = 0;
}
for ($j = $end_month; $j >= $start_month; $j--) {
$labels[$end_month - $j] = $s->format('M Y');

View File

@ -26,8 +26,7 @@ class Items extends Controller
{
$items = Item::with('category')->collect();
$categories = Category::enabled()->orderBy('name')->type('item')->pluck('name', 'id')
->prepend(trans('general.all_type', ['type' => trans_choice('general.categories', 2)]), '');
$categories = Category::enabled()->orderBy('name')->type('item')->pluck('name', 'id');
return view('common.items.index', compact('items', 'categories'));
}
@ -51,7 +50,7 @@ class Items extends Controller
{
$categories = Category::enabled()->orderBy('name')->type('item')->pluck('name', 'id');
$taxes = Tax::enabled()->orderBy('rate')->get()->pluck('title', 'id');
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
$currency = Currency::where('code', '=', setting('general.default_currency', 'USD'))->first();
@ -132,7 +131,7 @@ class Items extends Controller
{
$categories = Category::enabled()->orderBy('name')->type('item')->pluck('name', 'id');
$taxes = Tax::enabled()->orderBy('rate')->get()->pluck('title', 'id');
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
$currency = Currency::where('code', '=', setting('general.default_currency', 'USD'))->first();
@ -323,22 +322,83 @@ class Items extends Controller
$price = (double) $item['price'];
$quantity = (double) $item['quantity'];
$item_tax_total= 0;
$item_tax_total = 0;
$item_tax_amount = 0;
$item_sub_total = ($price * $quantity);
$item_discount_total = $item_sub_total;
// Apply discount to item
if ($discount) {
$item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100));
}
if (!empty($item['tax_id'])) {
$tax = Tax::find($item['tax_id']);
$inclusives = $compounds = $taxes = [];
$item_tax_total = (($price * $quantity) / 100) * $tax->rate;
foreach ($item['tax_id'] as $tax_id) {
$tax = Tax::find($tax_id);
switch ($tax->type) {
case 'inclusive':
$inclusives[] = $tax;
break;
case 'compound':
$compounds[] = $tax;
break;
case 'normal':
default:
$taxes[] = $tax;
$item_tax_amount = ($item_discount_total / 100) * $tax->rate;
$item_tax_total += $item_tax_amount;
break;
}
}
if ($inclusives) {
if ($discount) {
$item_tax_total = 0;
if ($taxes) {
foreach ($taxes as $tax) {
$item_tax_amount = ($item_sub_total / 100) * $tax->rate;
$item_tax_total += $item_tax_amount;
}
}
foreach ($inclusives as $inclusive) {
$item_sub_and_tax_total = $item_sub_total + $item_tax_total;
$item_tax_total = $item_sub_and_tax_total - (($item_sub_and_tax_total * (100 - $inclusive->rate)) / 100);
$item_sub_total = $item_sub_and_tax_total - $item_tax_total;
$item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100));
}
} else {
foreach ($inclusives as $inclusive) {
$item_sub_and_tax_total = $item_discount_total + $item_tax_total;
$item_tax_total = $item_sub_and_tax_total - (($item_sub_and_tax_total * (100 - $inclusive->rate)) / 100);
$item_sub_total = $item_sub_and_tax_total - $item_tax_total;
$item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100));
}
}
}
if ($compounds) {
foreach ($compounds as $compound) {
$item_tax_total += (($item_discount_total + $item_tax_total) / 100) * $compound->rate;
}
}
}
$sub_total += $item_sub_total;
// Apply discount to tax
if ($discount) {
$item_tax_total = $item_tax_total - ($item_tax_total * ($discount / 100));
}
$tax_total += $item_tax_total;
$items[$key] = money($item_sub_total, $currency_code, true)->format();

View File

@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers\Common;
use Date;
use App\Http\Controllers\Controller;
use App\Traits\Modules as RemoteModules;
use App\Http\Requests\Common\Notification as Request;
class Notifications extends Controller
{
use RemoteModules;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$notifications = setting('notifications');
return view('common.notifications.index', compact('notifications'));
}
/**
* Show the form for viewing the specified resource.
*
* @return Response
*/
public function show($path, $id)
{
$notification = setting('notifications.' . $path . '.' . $id);
return view('common.notifications.show', compact('notification'));
}
/**
* Disable the specified resource.
*
* @param Company $company
*
* @return Response
*/
public function disable(Request $request)
{
$id = $request['id'];
$path = str_replace('#', '/', $request['path']);
$notifications = $this->getNotifications($path);
foreach ($notifications as $notification) {
if ($notification->id == $id) {
setting()->set('notifications.'. $path . '.' . $id . '.name', $notification->name);
setting()->set('notifications.'. $path . '.' . $id . '.message', $notification->message);
setting()->set('notifications.'. $path . '.' . $id . '.date', Date::now());
setting()->set('notifications.'. $path . '.' . $id . '.status', '0');
setting()->save();
break;
}
}
return response()->json([
'success' => true,
'error' => false,
'data' => null,
]);
}
}

View File

@ -91,6 +91,10 @@ class Uploads extends Controller
*/
protected function getPath($media)
{
if (!is_object($media)) {
return false;
}
$path = $media->basename;
if (!empty($media->directory)) {

View File

@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Events\InvoicePrinting;
use App\Models\Banking\Account;
use App\Models\Income\Customer;
use App\Models\Income\Revenue;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceStatus;
use App\Models\Setting\Category;
@ -16,8 +17,10 @@ use App\Traits\DateTime;
use App\Traits\Uploads;
use App\Utilities\Modules;
use File;
use Illuminate\Http\Request;
use Image;
use Storage;
use SignedUrl;
class Invoices extends Controller
{
@ -178,4 +181,52 @@ class Invoices extends Controller
return $logo;
}
public function link(Invoice $invoice, Request $request)
{
session(['company_id' => $invoice->company_id]);
$paid = 0;
foreach ($invoice->payments as $item) {
$amount = $item->amount;
if ($invoice->currency_code != $item->currency_code) {
$item->default_currency_code = $invoice->currency_code;
$amount = $item->getDynamicConvertedAmount();
}
$paid += $amount;
}
$invoice->paid = $paid;
$accounts = Account::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code')->toArray();
$account_currency_code = Account::where('id', setting('general.default_account'))->pluck('currency_code')->first();
$customers = Customer::enabled()->pluck('name', 'id');
$categories = Category::enabled()->type('income')->pluck('name', 'id');
$payment_methods = Modules::getPaymentMethods();
$payment_actions = [];
foreach ($payment_methods as $payment_method_key => $payment_method_value) {
$codes = explode('.', $payment_method_key);
if (!isset($payment_actions[$codes[0]])) {
$payment_actions[$codes[0]] = SignedUrl::sign(url('links/invoices/' . $invoice->id . '/' . $codes[0]), 1);
}
}
$print_action = SignedUrl::sign(url('links/invoices/' . $invoice->id . '/print'), 1);
$pdf_action = SignedUrl::sign(url('links/invoices/' . $invoice->id . '/pdf'), 1);
return view('customers.invoices.link', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods', 'payment_actions', 'print_action', 'pdf_action'));
}
}

View File

@ -8,12 +8,16 @@ use App\Events\BillUpdated;
use App\Http\Controllers\Controller;
use App\Http\Requests\Expense\Bill as Request;
use App\Http\Requests\Expense\BillPayment as PaymentRequest;
use App\Jobs\Expense\CreateBill;
use App\Jobs\Expense\UpdateBill;
use App\Jobs\Expense\CreateBillPayment;
use App\Models\Banking\Account;
use App\Models\Common\Media;
use App\Models\Expense\BillStatus;
use App\Models\Expense\Vendor;
use App\Models\Expense\Bill;
use App\Models\Expense\BillItem;
use App\Models\Expense\BillItemTax;
use App\Models\Expense\BillTotal;
use App\Models\Expense\BillHistory;
use App\Models\Expense\BillPayment;
@ -46,13 +50,13 @@ class Bills extends Controller
{
$bills = Bill::with(['vendor', 'status', 'items', 'payments', 'histories'])->collect(['billed_at'=> 'desc']);
$vendors = collect(Vendor::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.vendors', 2)]), '');
$vendors = collect(Vendor::enabled()->orderBy('name')->pluck('name', 'id'));
$statuses = collect(BillStatus::all()->pluck('name', 'code'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.statuses', 2)]), '');
$categories = collect(Category::enabled()->type('expense')->orderBy('name')->pluck('name', 'id'));
return view('expenses.bills.index', compact('bills', 'vendors', 'statuses'));
$statuses = collect(BillStatus::all()->pluck('name', 'code'));
return view('expenses.bills.index', compact('bills', 'vendors', 'categories', 'statuses'));
}
/**
@ -64,43 +68,6 @@ class Bills extends Controller
*/
public function show(Bill $bill)
{
$paid = 0;
// Get Bill Payments
if ($bill->payments->count()) {
$_currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
foreach ($bill->payments as $item) {
$default_amount = (double) $item->amount;
if ($bill->currency_code == $item->currency_code) {
$amount = $default_amount;
} else {
$default_amount_model = new BillPayment();
$default_amount_model->default_currency_code = $bill->currency_code;
$default_amount_model->amount = $default_amount;
$default_amount_model->currency_code = $item->currency_code;
$default_amount_model->currency_rate = $_currencies[$item->currency_code];
$default_amount = (double) $default_amount_model->getDivideConvertedAmount();
$convert_amount = new BillPayment();
$convert_amount->default_currency_code = $item->currency_code;
$convert_amount->amount = $default_amount;
$convert_amount->currency_code = $bill->currency_code;
$convert_amount->currency_rate = $_currencies[$bill->currency_code];
$amount = (double) $convert_amount->getDynamicConvertedAmount();
}
$paid += $amount;
}
}
$bill->paid = $paid;
$accounts = Account::enabled()->orderBy('name')->pluck('name', 'id');
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code')->toArray();
@ -131,7 +98,7 @@ class Bills extends Controller
$items = Item::enabled()->orderBy('name')->pluck('name', 'id');
$taxes = Tax::enabled()->orderBy('rate')->get()->pluck('title', 'id');
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
$categories = Category::enabled()->type('expense')->orderBy('name')->pluck('name', 'id');
@ -147,120 +114,7 @@ class Bills extends Controller
*/
public function store(Request $request)
{
$bill = Bill::create($request->input());
// Upload attachment
if ($request->file('attachment')) {
$media = $this->getMedia($request->file('attachment'), 'bills');
$bill->attachMedia($media, 'attachment');
}
$taxes = [];
$tax_total = 0;
$sub_total = 0;
$discount_total = 0;
$discount = $request['discount'];
$bill_item = [];
$bill_item['company_id'] = $request['company_id'];
$bill_item['bill_id'] = $bill->id;
if ($request['item']) {
foreach ($request['item'] as $item) {
unset($tax_object);
$item_sku = '';
if (!empty($item['item_id'])) {
$item_object = Item::find($item['item_id']);
$item['name'] = $item_object->name;
$item_sku = $item_object->sku;
// Increase stock (item bought)
$item_object->quantity += $item['quantity'];
$item_object->save();
}
$tax = $tax_id = 0;
if (!empty($item['tax_id'])) {
$tax_object = Tax::find($item['tax_id']);
$tax_id = $item['tax_id'];
$tax = (((double) $item['price'] * (double) $item['quantity']) / 100) * $tax_object->rate;
// Apply discount to tax
if ($discount) {
$tax = $tax - ($tax * ($discount / 100));
}
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = str_limit($item['name'], 180, '');
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = (double) $item['quantity'];
$bill_item['price'] = (double) $item['price'];
$bill_item['tax'] = $tax;
$bill_item['tax_id'] = $tax_id;
$bill_item['total'] = (double) $item['price'] * (double) $item['quantity'];
BillItem::create($bill_item);
// Set taxes
if (isset($tax_object)) {
if (array_key_exists($tax_object->id, $taxes)) {
$taxes[$tax_object->id]['amount'] += $tax;
} else {
$taxes[$tax_object->id] = [
'name' => $tax_object->name,
'amount' => $tax
];
}
}
// Calculate totals
$tax_total += $tax;
$sub_total += $bill_item['total'];
unset($tax_object);
}
}
$s_total = $sub_total;
// Apply discount to total
if ($discount) {
$s_discount = $s_total * ($discount / 100);
$discount_total += $s_discount;
$s_total = $s_total - $s_discount;
}
$amount = $s_total + $tax_total;
$request['amount'] = money($amount, $request['currency_code'])->getAmount();
$bill->update($request->input());
// Add bill totals
$this->addTotals($bill, $request, $taxes, $sub_total, $discount_total, $tax_total);
// Add bill history
BillHistory::create([
'company_id' => session('company_id'),
'bill_id' => $bill->id,
'status_code' => 'draft',
'notify' => 0,
'description' => trans('messages.success.added', ['type' => $bill->bill_number]),
]);
// Recurring
$bill->createRecurring();
// Fire the event to make it extendible
event(new BillCreated($bill));
$bill = dispatch(new CreateBill($request));
$message = trans('messages.success.added', ['type' => trans_choice('general.bills', 1)]);
@ -373,105 +227,7 @@ class Bills extends Controller
*/
public function update(Bill $bill, Request $request)
{
$taxes = [];
$tax_total = 0;
$sub_total = 0;
$discount_total = 0;
$discount = $request['discount'];
$bill_item = [];
$bill_item['company_id'] = $request['company_id'];
$bill_item['bill_id'] = $bill->id;
if ($request['item']) {
$this->deleteRelationships($bill, 'items');
foreach ($request['item'] as $item) {
unset($tax_object);
$item_sku = '';
if (!empty($item['item_id'])) {
$item_object = Item::find($item['item_id']);
$item['name'] = $item_object->name;
$item_sku = $item_object->sku;
}
$tax = $tax_id = 0;
if (!empty($item['tax_id'])) {
$tax_object = Tax::find($item['tax_id']);
$tax_id = $item['tax_id'];
$tax = (((double) $item['price'] * (double) $item['quantity']) / 100) * $tax_object->rate;
// Apply discount to tax
if ($discount) {
$tax = $tax - ($tax * ($discount / 100));
}
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = str_limit($item['name'], 180, '');
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = (double) $item['quantity'];
$bill_item['price'] = (double) $item['price'];
$bill_item['tax'] = $tax;
$bill_item['tax_id'] = $tax_id;
$bill_item['total'] = (double) $item['price'] * (double) $item['quantity'];
if (isset($tax_object)) {
if (array_key_exists($tax_object->id, $taxes)) {
$taxes[$tax_object->id]['amount'] += $tax;
} else {
$taxes[$tax_object->id] = [
'name' => $tax_object->name,
'amount' => $tax
];
}
}
$tax_total += $tax;
$sub_total += $bill_item['total'];
BillItem::create($bill_item);
}
}
$s_total = $sub_total;
// Apply discount to total
if ($discount) {
$s_discount = $s_total * ($discount / 100);
$discount_total += $s_discount;
$s_total = $s_total - $s_discount;
}
$amount = $s_total + $tax_total;
$request['amount'] = money($amount, $request['currency_code'])->getAmount();
$bill->update($request->input());
// Upload attachment
if ($request->file('attachment')) {
$media = $this->getMedia($request->file('attachment'), 'bills');
$bill->attachMedia($media, 'attachment');
}
// Delete previous bill totals
$this->deleteRelationships($bill, 'totals');
// Add bill totals
$this->addTotals($bill, $request, $taxes, $sub_total, $discount_total, $tax_total);
// Recurring
$bill->updateRecurring();
// Fire the event to make it extendible
event(new BillUpdated($bill));
$bill = dispatch(new UpdateBill($bill, $request));
$message = trans('messages.success.updated', ['type' => trans_choice('general.bills', 1)]);
@ -509,9 +265,9 @@ class Bills extends Controller
\Excel::create('bills', function ($excel) {
$bills = Bill::with(['items', 'histories', 'payments', 'totals'])->filter(request()->input())->get();
$excel->sheet('invoices', function ($sheet) use ($bills) {
$excel->sheet('bills', function ($sheet) use ($bills) {
$sheet->fromModel($bills->makeHidden([
'company_id', 'parent_id', 'created_at', 'updated_at', 'deleted_at', 'attachment', 'discount', 'items', 'histories', 'payments', 'totals', 'media'
'company_id', 'parent_id', 'created_at', 'updated_at', 'deleted_at', 'attachment', 'discount', 'items', 'histories', 'payments', 'totals', 'media', 'paid'
]));
});
@ -581,7 +337,9 @@ class Bills extends Controller
{
$bill = $this->prepareBill($bill);
$html = view($bill->template_path, compact('bill'))->render();
$currency_style = true;
$html = view($bill->template_path, compact('bill', 'currency_style'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($html);
@ -652,20 +410,7 @@ class Bills extends Controller
$bill->save();
$bill_payment_request = [
'company_id' => $request['company_id'],
'bill_id' => $request['bill_id'],
'account_id' => $request['account_id'],
'paid_at' => $request['paid_at'],
'amount' => $request['amount'],
'currency_code' => $request['currency_code'],
'currency_rate' => $request['currency_rate'],
'description' => $request['description'],
'payment_method' => $request['payment_method'],
'reference' => $request['reference']
];
$bill_payment = BillPayment::create($bill_payment_request);
$bill_payment = dispatch(new CreateBillPayment($request, $bill));
// Upload attachment
if ($request->file('attachment')) {
@ -674,15 +419,6 @@ class Bills extends Controller
$bill_payment->attachMedia($media, 'attachment');
}
$request['status_code'] = $bill->bill_status_code;
$request['notify'] = 0;
$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.payments', 1)]);
return response()->json([
@ -791,64 +527,4 @@ class Bills extends Controller
return $bill;
}
protected function addTotals($bill, $request, $taxes, $sub_total, $discount_total, $tax_total)
{
$sort_order = 1;
// Added bill sub total
BillTotal::create([
'company_id' => $request['company_id'],
'bill_id' => $bill->id,
'code' => 'sub_total',
'name' => 'bills.sub_total',
'amount' => $sub_total,
'sort_order' => $sort_order,
]);
$sort_order++;
// Added bill discount
if ($discount_total) {
BillTotal::create([
'company_id' => $request['company_id'],
'bill_id' => $bill->id,
'code' => 'discount',
'name' => 'bills.discount',
'amount' => $discount_total,
'sort_order' => $sort_order,
]);
// This is for total
$sub_total = $sub_total - $discount_total;
}
$sort_order++;
// Added bill taxes
if ($taxes) {
foreach ($taxes as $tax) {
BillTotal::create([
'company_id' => $request['company_id'],
'bill_id' => $bill->id,
'code' => 'tax',
'name' => $tax['name'],
'amount' => $tax['amount'],
'sort_order' => $sort_order,
]);
$sort_order++;
}
}
// Added bill total
BillTotal::create([
'company_id' => $request['company_id'],
'bill_id' => $bill->id,
'code' => 'total',
'name' => 'bills.total',
'amount' => $sub_total + $tax_total,
'sort_order' => $sort_order,
]);
}
}

View File

@ -27,14 +27,11 @@ class Payments extends Controller
{
$payments = Payment::with(['vendor', 'account', 'category'])->isNotTransfer()->collect(['paid_at'=> 'desc']);
$vendors = collect(Vendor::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.vendors', 2)]), '');
$vendors = collect(Vendor::enabled()->orderBy('name')->pluck('name', 'id'));
$categories = collect(Category::enabled()->type('expense')->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.categories', 2)]), '');
$categories = collect(Category::enabled()->type('expense')->orderBy('name')->pluck('name', 'id'));
$accounts = collect(Account::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
$accounts = collect(Account::enabled()->orderBy('name')->pluck('name', 'id'));
$transfer_cat_id = Category::transfer();
@ -64,7 +61,7 @@ class Payments extends Controller
$account_currency_code = Account::where('id', setting('general.default_account'))->pluck('currency_code')->first();
$currency = Currency::where('code', '=', $account_currency_code)->first();
$currency = Currency::where('code', $account_currency_code)->first();
$vendors = Vendor::enabled()->orderBy('name')->pluck('name', 'id');
@ -154,9 +151,7 @@ class Payments extends Controller
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code')->toArray();
$account_currency_code = Account::where('id', $payment->account_id)->pluck('currency_code')->first();
$currency = Currency::where('code', '=', $account_currency_code)->first();
$currency = Currency::where('code', $payment->currency_code)->first();
$vendors = Vendor::enabled()->orderBy('name')->pluck('name', 'id');
@ -164,7 +159,7 @@ class Payments extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('expenses.payments.edit', compact('payment', 'accounts', 'currencies', 'account_currency_code', 'currency', 'vendors', 'categories', 'payment_methods'));
return view('expenses.payments.edit', compact('payment', 'accounts', 'currencies', 'currency', 'vendors', 'categories', 'payment_methods'));
}
/**

View File

@ -100,8 +100,10 @@ class Vendors extends Controller
$limit = request('limit', setting('general.list_limit', '25'));
$transactions = $this->paginate($items->merge($bill_payments)->sortByDesc('paid_at'), $limit);
$bills = $this->paginate($bills->sortByDesc('paid_at'), $limit);
$payments = $this->paginate($payments->sortByDesc('paid_at'), $limit);
return view('expenses.vendors.show', compact('vendor', 'counts', 'amounts', 'transactions'));
return view('expenses.vendors.show', compact('vendor', 'counts', 'amounts', 'transactions', 'bills', 'payments'));
}
/**
@ -309,7 +311,7 @@ class Vendors extends Controller
if (empty($vendor_id)) {
return response()->json([]);
}
$vendor = Vendor::find($vendor_id);
if (empty($vendor)) {
@ -332,6 +334,12 @@ class Vendors extends Controller
$vendor->currency_code = $currency_code;
$vendor->currency_rate = $currency->rate;
$vendor->thousands_separator = $currency->thousands_separator;
$vendor->decimal_mark = $currency->decimal_mark;
$vendor->precision = (int) $currency->precision;
$vendor->symbol_first = $currency->symbol_first;
$vendor->symbol = $currency->symbol;
return response()->json($vendor);
}

View File

@ -100,8 +100,10 @@ class Customers extends Controller
$limit = request('limit', setting('general.list_limit', '25'));
$transactions = $this->paginate($items->merge($invoice_payments)->sortByDesc('paid_at'), $limit);
$invoices = $this->paginate($invoices->sortByDesc('paid_at'), $limit);
$revenues = $this->paginate($revenues->sortByDesc('paid_at'), $limit);
return view('incomes.customers.show', compact('customer', 'counts', 'amounts', 'transactions'));
return view('incomes.customers.show', compact('customer', 'counts', 'amounts', 'transactions', 'invoices', 'revenues'));
}
/**

View File

@ -8,21 +8,26 @@ use App\Events\InvoiceUpdated;
use App\Http\Controllers\Controller;
use App\Http\Requests\Income\Invoice as Request;
use App\Http\Requests\Income\InvoicePayment as PaymentRequest;
use App\Jobs\Income\CreateInvoice;
use App\Jobs\Income\UpdateInvoice;
use App\Jobs\Income\CreateInvoicePayment;
use App\Models\Banking\Account;
use App\Models\Common\Item;
use App\Models\Common\Media;
use App\Models\Income\Customer;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoiceItem;
use App\Models\Income\InvoiceItemTax;
use App\Models\Income\InvoiceTotal;
use App\Models\Income\InvoicePayment;
use App\Models\Income\InvoiceStatus;
use App\Models\Common\Item;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Notifications\Income\Invoice as Notification;
use App\Notifications\Common\Item as ItemNotification;
use App\Notifications\Common\ItemReminder as ItemReminderNotification;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Incomes;
@ -35,6 +40,7 @@ use File;
use Illuminate\Http\Request as ItemRequest;
use Image;
use Storage;
use SignedUrl;
class Invoices extends Controller
{
@ -49,13 +55,13 @@ class Invoices extends Controller
{
$invoices = Invoice::with(['customer', 'status', 'items', 'payments', 'histories'])->collect(['invoice_number'=> 'desc']);
$customers = collect(Customer::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.customers', 2)]), '');
$customers = collect(Customer::enabled()->orderBy('name')->pluck('name', 'id'));
$status = collect(InvoiceStatus::all()->pluck('name', 'code'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.statuses', 2)]), '');
$categories = collect(Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id'));
return view('incomes.invoices.index', compact('invoices', 'customers', 'status'));
$statuses = collect(InvoiceStatus::all()->pluck('name', 'code'));
return view('incomes.invoices.index', compact('invoices', 'customers', 'categories', 'statuses'));
}
/**
@ -67,43 +73,6 @@ class Invoices extends Controller
*/
public function show(Invoice $invoice)
{
$paid = 0;
// Get Invoice Payments
if ($invoice->payments->count()) {
$_currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
foreach ($invoice->payments as $item) {
$default_amount = $item->amount;
if ($invoice->currency_code == $item->currency_code) {
$amount = (double)$default_amount;
} else {
$default_amount_model = new InvoicePayment();
$default_amount_model->default_currency_code = $invoice->currency_code;
$default_amount_model->amount = $default_amount;
$default_amount_model->currency_code = $item->currency_code;
$default_amount_model->currency_rate = $_currencies[$item->currency_code];
$default_amount = (double) $default_amount_model->getDivideConvertedAmount();
$convert_amount = new InvoicePayment();
$convert_amount->default_currency_code = $item->currency_code;
$convert_amount->amount = $default_amount;
$convert_amount->currency_code = $invoice->currency_code;
$convert_amount->currency_rate = $_currencies[$invoice->currency_code];
$amount = (double) $convert_amount->getDynamicConvertedAmount();
}
$paid += $amount;
}
}
$invoice->paid = $paid;
$accounts = Account::enabled()->orderBy('name')->pluck('name', 'id');
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code')->toArray();
@ -116,7 +85,9 @@ class Invoices extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('incomes.invoices.show', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
$customer_share = SignedUrl::sign(url('links/invoices/' . $invoice->id));
return view('incomes.invoices.show', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods', 'customer_share'));
}
/**
@ -134,7 +105,7 @@ class Invoices extends Controller
$items = Item::enabled()->orderBy('name')->pluck('name', 'id');
$taxes = Tax::enabled()->orderBy('rate')->get()->pluck('title', 'id');
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
$categories = Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id');
@ -152,133 +123,7 @@ class Invoices extends Controller
*/
public function store(Request $request)
{
$invoice = Invoice::create($request->input());
// Upload attachment
if ($request->file('attachment')) {
$media = $this->getMedia($request->file('attachment'), 'invoices');
$invoice->attachMedia($media, 'attachment');
}
$taxes = [];
$tax_total = 0;
$sub_total = 0;
$discount_total = 0;
$discount = $request['discount'];
$invoice_item = [];
$invoice_item['company_id'] = $request['company_id'];
$invoice_item['invoice_id'] = $invoice->id;
if ($request['item']) {
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$item_object = Item::find($item['item_id']);
$item['name'] = $item_object->name;
$item_sku = $item_object->sku;
// Decrease stock (item sold)
$item_object->quantity -= $item['quantity'];
$item_object->save();
// Notify users if out of stock
if ($item_object->quantity == 0) {
foreach ($item_object->company->users as $user) {
if (!$user->can('read-notifications')) {
continue;
}
$user->notify(new ItemNotification($item_object));
}
}
}
$tax = $tax_id = 0;
if (!empty($item['tax_id'])) {
$tax_object = Tax::find($item['tax_id']);
$tax_id = $item['tax_id'];
$tax = (((double) $item['price'] * (double) $item['quantity']) / 100) * $tax_object->rate;
// Apply discount to tax
if ($discount) {
$tax = $tax - ($tax * ($discount / 100));
}
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = (double) $item['quantity'];
$invoice_item['price'] = (double) $item['price'];
$invoice_item['tax'] = $tax;
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = (double) $item['price'] * (double) $item['quantity'];
InvoiceItem::create($invoice_item);
// Set taxes
if (isset($tax_object)) {
if (array_key_exists($tax_object->id, $taxes)) {
$taxes[$tax_object->id]['amount'] += $tax;
} else {
$taxes[$tax_object->id] = [
'name' => $tax_object->name,
'amount' => $tax
];
}
}
// Calculate totals
$tax_total += $tax;
$sub_total += $invoice_item['total'];
unset($tax_object);
}
}
$s_total = $sub_total;
// Apply discount to total
if ($discount) {
$s_discount = $s_total * ($discount / 100);
$discount_total += $s_discount;
$s_total = $s_total - $s_discount;
}
$amount = $s_total + $tax_total;
$request['amount'] = money($amount, $request['currency_code'])->getAmount();
$invoice->update($request->input());
// Add invoice totals
$this->addTotals($invoice, $request, $taxes, $sub_total, $discount_total, $tax_total);
// Add invoice history
InvoiceHistory::create([
'company_id' => session('company_id'),
'invoice_id' => $invoice->id,
'status_code' => 'draft',
'notify' => 0,
'description' => trans('messages.success.added', ['type' => $invoice->invoice_number]),
]);
// Update next invoice number
$this->increaseNextInvoiceNumber();
// Recurring
$invoice->createRecurring();
// Fire the event to make it extendible
event(new InvoiceCreated($invoice));
$invoice = dispatch(new CreateInvoice($request));
$message = trans('messages.success.added', ['type' => trans_choice('general.invoices', 1)]);
@ -377,7 +222,7 @@ class Invoices extends Controller
$items = Item::enabled()->orderBy('name')->pluck('name', 'id');
$taxes = Tax::enabled()->orderBy('rate')->get()->pluck('title', 'id');
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
$categories = Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id');
@ -394,105 +239,7 @@ class Invoices extends Controller
*/
public function update(Invoice $invoice, Request $request)
{
$taxes = [];
$tax_total = 0;
$sub_total = 0;
$discount_total = 0;
$discount = $request['discount'];
$invoice_item = [];
$invoice_item['company_id'] = $request['company_id'];
$invoice_item['invoice_id'] = $invoice->id;
if ($request['item']) {
$this->deleteRelationships($invoice, 'items');
foreach ($request['item'] as $item) {
unset($tax_object);
$item_sku = '';
if (!empty($item['item_id'])) {
$item_object = Item::find($item['item_id']);
$item['name'] = $item_object->name;
$item_sku = $item_object->sku;
}
$tax = $tax_id = 0;
if (!empty($item['tax_id'])) {
$tax_object = Tax::find($item['tax_id']);
$tax_id = $item['tax_id'];
$tax = (((double) $item['price'] * (double) $item['quantity']) / 100) * $tax_object->rate;
// Apply discount to tax
if ($discount) {
$tax = $tax - ($tax * ($discount / 100));
}
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = str_limit($item['name'], 180, '');
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = (double) $item['quantity'];
$invoice_item['price'] = (double) $item['price'];
$invoice_item['tax'] = $tax;
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = (double) $item['price'] * (double) $item['quantity'];
if (isset($tax_object)) {
if (array_key_exists($tax_object->id, $taxes)) {
$taxes[$tax_object->id]['amount'] += $tax;
} else {
$taxes[$tax_object->id] = [
'name' => $tax_object->name,
'amount' => $tax
];
}
}
$tax_total += $tax;
$sub_total += $invoice_item['total'];
InvoiceItem::create($invoice_item);
}
}
$s_total = $sub_total;
// Apply discount to total
if ($discount) {
$s_discount = $s_total * ($discount / 100);
$discount_total += $s_discount;
$s_total = $s_total - $s_discount;
}
$amount = $s_total + $tax_total;
$request['amount'] = money($amount, $request['currency_code'])->getAmount();
$invoice->update($request->input());
// Upload attachment
if ($request->file('attachment')) {
$media = $this->getMedia($request->file('attachment'), 'invoices');
$invoice->attachMedia($media, 'attachment');
}
// Delete previous invoice totals
$this->deleteRelationships($invoice, 'totals');
// Add invoice totals
$this->addTotals($invoice, $request, $taxes, $sub_total, $discount_total, $tax_total);
// Recurring
$invoice->updateRecurring();
// Fire the event to make it extendible
event(new InvoiceUpdated($invoice));
$invoice = dispatch(new UpdateInvoice($invoice, $request));
$message = trans('messages.success.updated', ['type' => trans_choice('general.invoices', 1)]);
@ -532,7 +279,7 @@ class Invoices extends Controller
$excel->sheet('invoices', function ($sheet) use ($invoices) {
$sheet->fromModel($invoices->makeHidden([
'company_id', 'parent_id', 'created_at', 'updated_at', 'deleted_at', 'attachment', 'discount', 'items', 'histories', 'payments', 'totals', 'media'
'company_id', 'parent_id', 'created_at', 'updated_at', 'deleted_at', 'attachment', 'discount', 'items', 'histories', 'payments', 'totals', 'media', 'paid'
]));
});
@ -623,6 +370,7 @@ class Invoices extends Controller
unset($invoice->paid);
unset($invoice->template_path);
unset($invoice->pdf_path);
unset($invoice->reconciled);
// Mark invoice as sent
if ($invoice->invoice_status_code != 'partial') {
@ -670,7 +418,9 @@ class Invoices extends Controller
{
$invoice = $this->prepareInvoice($invoice);
$html = view($invoice->template_path, compact('invoice'))->render();
$currency_style = true;
$html = view($invoice->template_path, compact('invoice', 'currency_style'))->render();
$pdf = app('dompdf.wrapper');
$pdf->loadHTML($html);
@ -789,20 +539,7 @@ class Invoices extends Controller
$invoice->save();
$invoice_payment_request = [
'company_id' => $request['company_id'],
'invoice_id' => $request['invoice_id'],
'account_id' => $request['account_id'],
'paid_at' => $request['paid_at'],
'amount' => $request['amount'],
'currency_code' => $request['currency_code'],
'currency_rate' => $request['currency_rate'],
'description' => $request['description'],
'payment_method' => $request['payment_method'],
'reference' => $request['reference']
];
$invoice_payment = InvoicePayment::create($invoice_payment_request);
$invoice_payment = dispatch(new CreateInvoicePayment($request, $invoice));
// Upload attachment
if ($request->file('attachment')) {
@ -811,15 +548,6 @@ class Invoices extends Controller
$invoice_payment->attachMedia($media, 'attachment');
}
$request['status_code'] = $invoice->invoice_status_code;
$request['notify'] = 0;
$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.payments', 1)]);
return response()->json([
@ -928,64 +656,4 @@ class Invoices extends Controller
return $invoice;
}
protected function addTotals($invoice, $request, $taxes, $sub_total, $discount_total, $tax_total)
{
$sort_order = 1;
// Added invoice sub total
InvoiceTotal::create([
'company_id' => $request['company_id'],
'invoice_id' => $invoice->id,
'code' => 'sub_total',
'name' => 'invoices.sub_total',
'amount' => $sub_total,
'sort_order' => $sort_order,
]);
$sort_order++;
// Added invoice discount
if ($discount_total) {
InvoiceTotal::create([
'company_id' => $request['company_id'],
'invoice_id' => $invoice->id,
'code' => 'discount',
'name' => 'invoices.discount',
'amount' => $discount_total,
'sort_order' => $sort_order,
]);
// This is for total
$sub_total = $sub_total - $discount_total;
}
$sort_order++;
// Added invoice taxes
if ($taxes) {
foreach ($taxes as $tax) {
InvoiceTotal::create([
'company_id' => $request['company_id'],
'invoice_id' => $invoice->id,
'code' => 'tax',
'name' => $tax['name'],
'amount' => $tax['amount'],
'sort_order' => $sort_order,
]);
$sort_order++;
}
}
// Added invoice total
InvoiceTotal::create([
'company_id' => $request['company_id'],
'invoice_id' => $invoice->id,
'code' => 'total',
'name' => 'invoices.total',
'amount' => $sub_total + $tax_total,
'sort_order' => $sort_order,
]);
}
}

View File

@ -29,14 +29,11 @@ class Revenues extends Controller
{
$revenues = Revenue::with(['account', 'category', 'customer'])->isNotTransfer()->collect(['paid_at'=> 'desc']);
$customers = collect(Customer::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.customers', 2)]), '');
$customers = collect(Customer::enabled()->orderBy('name')->pluck('name', 'id'));
$categories = collect(Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.categories', 2)]), '');
$categories = collect(Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id'));
$accounts = collect(Account::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
$accounts = collect(Account::enabled()->orderBy('name')->pluck('name', 'id'));
$transfer_cat_id = Category::transfer();
@ -66,7 +63,7 @@ class Revenues extends Controller
$account_currency_code = Account::where('id', setting('general.default_account'))->pluck('currency_code')->first();
$currency = Currency::where('code', '=', $account_currency_code)->first();
$currency = Currency::where('code', $account_currency_code)->first();
$customers = Customer::enabled()->orderBy('name')->pluck('name', 'id');
@ -156,9 +153,7 @@ class Revenues extends Controller
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code')->toArray();
$account_currency_code = Account::where('id', $revenue->account_id)->pluck('currency_code')->first();
$currency = Currency::where('code', '=', $account_currency_code)->first();
$currency = Currency::where('code', $revenue->currency_code)->first();
$customers = Customer::enabled()->orderBy('name')->pluck('name', 'id');
@ -166,7 +161,7 @@ class Revenues extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('incomes.revenues.edit', compact('revenue', 'accounts', 'currencies', 'account_currency_code', 'currency', 'customers', 'categories', 'payment_methods'));
return view('incomes.revenues.edit', compact('revenue', 'accounts', 'currencies', 'currency', 'customers', 'categories', 'payment_methods'));
}
/**

View File

@ -6,8 +6,10 @@ use App\Http\Controllers\Controller;
use App\Events\UpdateFinished;
use App\Utilities\Updater;
use App\Utilities\Versions;
use Illuminate\Http\Request;
use Artisan;
use Module;
use File;
class Updates extends Controller
{
@ -80,15 +82,20 @@ class Updates extends Controller
*/
public function update($alias, $version)
{
set_time_limit(600); // 10 minutes
if ($alias == 'core') {
$name = 'Akaunting v' . $version;
if (Updater::update($alias, $version)) {
return redirect('install/updates/post/' . $alias . '/' . version('short') . '/' . $version);
$installed = version('short');
} else {
// Get module instance
$module = Module::findByAlias($alias);
$name = $module->get('name');
$installed = $module->get('version');
}
flash(trans('updates.error'))->error()->important();
return redirect()->back();
return view('install.updates.edit', compact('alias', 'name', 'installed', 'version'));
}
/**
@ -117,4 +124,229 @@ class Updates extends Controller
return redirect('install/updates');
}
/**
* Show the form for viewing the specified resource.
*
* @param $request
*
* @return Response
*/
public function steps(Request $request)
{
$json = [];
$json['step'] = [];
$name = $request['name'];
$version = $request['version'];
// Download
$json['step'][] = [
'text' => trans('modules.installation.download', ['module' => $name]),
'url' => url('install/updates/download')
];
// Unzip
$json['step'][] = [
'text' => trans('modules.installation.unzip', ['module' => $name]),
'url' => url('install/updates/unzip')
];
// File Copy
$json['step'][] = [
'text' => trans('modules.installation.file_copy', ['module' => $name]),
'url' => url('install/updates/file-copy')
];
// Migrate DB and trigger event UpdateFinish event
$json['step'][] = [
'text' => trans('modules.installation.migrate', ['module' => $name]),
'url' => url('install/updates/migrate')
];
// redirect update page
$json['step'][] = [
'text' => trans('modules.installation.finish'),
'url' => url('install/updates/finish')
];
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $request
*
* @return Response
*/
public function download(Request $request)
{
set_time_limit(600); // 10 minutes
$status = true;
if ($request['alias'] != 'core') {
$this->checkApiToken();
}
// Download file
if (!$data = Updater::download($request['alias'], $request['version'])) {
$status = false;
$message = trans('modules.errors.download', ['module' => $request['name']]);
}
// Create temp directory
$path = 'temp-' . md5(mt_rand());
$temp_path = storage_path('app/temp') . '/' . $path;
if (!File::isDirectory($temp_path)) {
File::makeDirectory($temp_path);
}
$file = $temp_path . '/upload.zip';
// Add content to the Zip file
$uploaded = is_int(file_put_contents($file, $data)) ? true : false;
if (!$uploaded) {
$status = false;
$message = trans('modules.errors.upload', ['module' => $request['name']]);
}
$json = [
'success' => ($status) ? true : false,
'errors' => (!$status) ? $message : false,
'data' => [
'path' => $path
]
];
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $request
*
* @return Response
*/
public function unzip(Request $request)
{
set_time_limit(600); // 10 minutes
if ($request['alias'] != 'core') {
$this->checkApiToken();
}
$path = storage_path('app/temp') . '/' . $request['path'];
$file = $path . '/upload.zip';
$result = Updater::unzip($file, $path);
$json = [
'success' => ($result) ? true : false,
'errors' => (!$result) ? trans('modules.errors.unzip', ['module' => $request['name']]) : false,
'data' => [
'path' => $request['path']
]
];
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $request
*
* @return Response
*/
public function fileCopy(Request $request)
{
set_time_limit(600); // 10 minutes
if ($request['alias'] != 'core') {
$this->checkApiToken();
}
$path = storage_path('app/temp') . '/' . $request['path'];
$result = Updater::fileCopy($request['alias'], $path, $request['version']);
$json = [
'success' => ($result) ? true : false,
'errors' => (!$result) ? trans('modules.errors.file_copy', ['module' => $request['name']]) : false,
'data' => [
'path' => $request['path']
]
];
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $request
*
* @return Response
*/
public function migrate(Request $request)
{
// Check if the file mirror was successful
if (($request['alias'] == 'core') && (version('short') != $request['version'])) {
$json = [
'success' => false,
'errors' => trans('modules.errors.migrate core', ['module' => $request['name']]),
'data' => []
];
return response()->json($json);
}
// Clear cache after update
Artisan::call('cache:clear');
try {
event(new UpdateFinished($request['alias'], $request['installed'], $request['version']));
$json = [
'success' => true,
'errors' => false,
'data' => []
];
} catch (\Exception $e) {
$json = [
'success' => false,
'errors' => trans('modules.errors.migrate', ['module' => $request['name']]),
'data' => []
];
}
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $request
*
* @return Response
*/
public function finish(Request $request)
{
$json = [
'success' => true,
'errors' => false,
'redirect' => url("install/updates"),
'data' => [],
];
return response()->json($json);
}
}

View File

@ -39,10 +39,10 @@ class BillPayments extends Controller
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code')->toArray();
$currency = Currency::where('code', setting('general.default_currency'))->first();
$account_currency_code = Account::where('id', setting('general.default_account'))->pluck('currency_code')->first();
$currency = Currency::where('code', $account_currency_code)->first();
$payment_methods = Modules::getPaymentMethods();
$bill->paid = $this->getPaid($bill);
@ -52,7 +52,9 @@ class BillPayments extends Controller
$bill->{$bill_total->code} = $bill_total->amount;
}
$bill->grand_total = $bill->total;
$total = money($bill->total, $currency->code, true)->format();
$bill->grand_total = money($total, $currency->code)->getAmount();
if (!empty($paid)) {
$bill->grand_total = $bill->total - $paid;

View File

@ -52,7 +52,9 @@ class InvoicePayments extends Controller
$invoice->{$invoice_total->code} = $invoice_total->amount;
}
$invoice->grand_total = $invoice->total;
$total = money($invoice->total, $currency->code, true)->format();
$invoice->grand_total = money($total, $currency->code)->getAmount();
if (!empty($paid)) {
$invoice->grand_total = $invoice->total - $paid;
@ -147,7 +149,7 @@ class InvoicePayments extends Controller
$error_amount = (double) $convert_amount->getDynamicConvertedAmount();
}
$message = trans('messages.error.over_payment', ['amount' => money($error_amount, $request['currency_code'],true)]);
$message = trans('messages.error.over_payment', ['amount' => money($error_amount, $request['currency_code'], true)]);
return response()->json([
'success' => false,

View File

@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers\Modals;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Tax as Request;
use App\Models\Setting\Tax;
class Taxes extends Controller
{
/**
* Instantiate a new controller instance.
*/
public function __construct()
{
// Add CRUD permission check
$this->middleware('permission:create-settings-taxes')->only(['create', 'store']);
$this->middleware('permission:read-settings-taxes')->only(['index', 'edit']);
$this->middleware('permission:update-settings-taxes')->only(['update', 'enable', 'disable']);
$this->middleware('permission:delete-settings-taxes')->only('destroy');
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$types = [
'normal' => trans('taxes.normal'),
'inclusive' => trans('taxes.inclusive'),
'compound' => trans('taxes.compound'),
];
$html = view('modals.taxes.create', compact('types'))->render();
return response()->json([
'success' => true,
'error' => false,
'message' => 'null',
'html' => $html,
]);
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
$request['enabled'] = 1;
$tax = Tax::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.taxes', 1)]);
return response()->json([
'success' => true,
'error' => false,
'data' => $tax,
'message' => $message,
'html' => 'null',
]);
}
}

View File

@ -67,7 +67,7 @@ class Item extends Controller
$module->action_url .= $character . http_build_query($parameters);
}
return view('modules.item.show', compact('module', 'about', 'installed', 'enable'));
return view('modules.item.show', compact('module', 'installed', 'enable'));
}
/**
@ -302,4 +302,42 @@ class Item extends Controller
return redirect('apps/' . $alias);
}
public function reviews($alias, Request $request)
{
$page = $request['page'];
$data = [
'query' => [
'page' => ($page) ? $page : 1,
]
];
$reviews = $this->getModuleReviews($alias, $data);
$html = view('partials.modules.reviews', compact('reviews'))->render();
return response()->json([
'success' => true,
'error' => false,
'data' => null,
'message' => null,
'html' => $html,
]);
}
public function documentation($alias)
{
$this->checkApiToken();
$documentation = $this->getDocumentation($alias);
if (empty($documentation)) {
return redirect('apps/' . $alias)->send();
}
$back = 'apps/' . $alias;
return view('modules.item.documentation', compact('documentation', 'back'));
}
}

View File

@ -23,7 +23,15 @@ class Tiles extends Controller
{
$this->checkApiToken();
$data = $this->getModulesByCategory($alias);
$page = request('page', 1);
$request = [
'query' => [
'page' => $page,
]
];
$data = $this->getModulesByCategory($alias, $request);
$title = $data->category->name;
$modules = $data->modules;
@ -32,6 +40,34 @@ class Tiles extends Controller
return view('modules.tiles.index', compact('title', 'modules', 'installed'));
}
/**
* Show the form for viewing the specified resource.
*
* @param $alias
*
* @return Response
*/
public function vendorModules($alias)
{
$this->checkApiToken();
$page = request('page', 1);
$request = [
'query' => [
'page' => $page,
]
];
$data = $this->getModulesByVendor($alias, $request);
$title = $data->vendor->name;
$modules = $data->modules;
$installed = Module::all()->pluck('status', 'alias')->toArray();
return view('modules.tiles.index', compact('title', 'modules', 'installed'));
}
/**
* Show the form for viewing the specified resource.
*
@ -41,8 +77,16 @@ class Tiles extends Controller
{
$this->checkApiToken();
$page = request('page', 1);
$data = [
'query' => [
'page' => $page,
]
];
$title = trans('modules.top_paid');
$modules = $this->getPaidModules();
$modules = $this->getPaidModules($data);
$installed = Module::all()->pluck('status', 'alias')->toArray();
return view('modules.tiles.index', compact('title', 'modules', 'installed'));
@ -57,8 +101,16 @@ class Tiles extends Controller
{
$this->checkApiToken();
$page = request('page', 1);
$data = [
'query' => [
'page' => $page,
]
];
$title = trans('modules.new');
$modules = $this->getNewModules();
$modules = $this->getNewModules($data);
$installed = Module::all()->pluck('status', 'alias')->toArray();
return view('modules.tiles.index', compact('title', 'modules', 'installed'));
@ -73,8 +125,16 @@ class Tiles extends Controller
{
$this->checkApiToken();
$page = request('page', 1);
$data = [
'query' => [
'page' => $page,
]
];
$title = trans('modules.top_free');
$modules = $this->getFreeModules();
$modules = $this->getFreeModules($data);
$installed = Module::all()->pluck('status', 'alias')->toArray();
return view('modules.tiles.index', compact('title', 'modules', 'installed'));
@ -90,10 +150,12 @@ class Tiles extends Controller
$this->checkApiToken();
$keyword = $request['keyword'];
$page = request('page', 1);
$data = [
'query' => [
'keyword' => $keyword,
'page' => $page,
]
];

View File

@ -3,10 +3,13 @@
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use App\Models\Banking\Account;
use App\Models\Expense\Bill;
use App\Models\Expense\BillPayment;
use App\Models\Expense\Payment;
use App\Models\Expense\Vendor;
use App\Models\Setting\Category;
use App\Utilities\Recurring;
use Charts;
use Date;
@ -22,13 +25,16 @@ class ExpenseSummary extends Controller
$dates = $totals = $expenses = $expenses_graph = $categories = [];
$status = request('status');
$year = request('year', Date::now()->year);
$categories = Category::enabled()->type('expense')->pluck('name', 'id')->toArray();
$categories = Category::enabled()->type('expense')->orderBy('name')->pluck('name', 'id')->toArray();
// Get year
$year = request('year');
if (empty($year)) {
$year = Date::now()->year;
if ($categories_filter = request('categories')) {
$cats = collect($categories)->filter(function ($value, $key) use ($categories_filter) {
return in_array($key, $categories_filter);
});
} else {
$cats = $categories;
}
// Dates
@ -44,7 +50,7 @@ class ExpenseSummary extends Controller
'currency_rate' => 1
);
foreach ($categories as $category_id => $category_name) {
foreach ($cats as $category_id => $category_name) {
$expenses[$category_id][$dates[$j]] = array(
'category_id' => $category_id,
'name' => $category_name,
@ -55,27 +61,47 @@ class ExpenseSummary extends Controller
}
}
// Bills
$payments = Payment::monthsOfYear('paid_at')->account(request('accounts'))->vendor(request('vendors'))->isNotTransfer()->get();
switch ($status) {
case 'paid':
$bills = BillPayment::monthsOfYear('paid_at')->get();
// Bills
$bills = BillPayment::monthsOfYear('paid_at')->account(request('accounts'))->get();
$this->setAmount($expenses_graph, $totals, $expenses, $bills, 'bill', 'paid_at');
// Payments
$this->setAmount($expenses_graph, $totals, $expenses, $payments, 'payment', 'paid_at');
break;
case 'upcoming':
$bills = Bill::accrued()->monthsOfYear('due_at')->get();
// Bills
$bills = Bill::accrued()->monthsOfYear('due_at')->vendor(request('vendors'))->get();
Recurring::reflect($bills, 'bill', 'billed_at', $status);
$this->setAmount($expenses_graph, $totals, $expenses, $bills, 'bill', 'due_at');
// Payments
Recurring::reflect($payments, 'payment', 'paid_at', $status);
$this->setAmount($expenses_graph, $totals, $expenses, $payments, 'payment', 'paid_at');
break;
default:
$bills = Bill::accrued()->monthsOfYear('billed_at')->get();
// Bills
$bills = Bill::accrued()->monthsOfYear('billed_at')->vendor(request('vendors'))->get();
Recurring::reflect($bills, 'bill', 'billed_at', $status);
$this->setAmount($expenses_graph, $totals, $expenses, $bills, 'bill', 'billed_at');
// Payments
Recurring::reflect($payments, 'payment', 'paid_at', $status);
$this->setAmount($expenses_graph, $totals, $expenses, $payments, 'payment', 'paid_at');
break;
}
// Payments
if ($status != 'upcoming') {
$payments = Payment::monthsOfYear('paid_at')->isNotTransfer()->get();
$this->setAmount($expenses_graph, $totals, $expenses, $payments, 'payment', 'paid_at');
}
$statuses = collect([
'all' => trans('general.all'),
'paid' => trans('invoices.paid'),
'upcoming' => trans('dashboard.payables'),
]);
$accounts = Account::enabled()->pluck('name', 'id')->toArray();
$vendors = Vendor::enabled()->pluck('name', 'id')->toArray();
// Check if it's a print or normal request
if (request('print')) {
@ -86,6 +112,8 @@ class ExpenseSummary extends Controller
$view_template = 'reports.expense_summary.index';
}
$print_url = $this->getPrintUrl($year);
// Expenses chart
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
@ -95,21 +123,49 @@ class ExpenseSummary extends Controller
->credits(false)
->view($chart_template);
return view($view_template, compact('chart', 'dates', 'categories', 'expenses', 'totals'));
return view($view_template, compact(
'chart',
'dates',
'categories',
'statuses',
'accounts',
'vendors',
'expenses',
'totals',
'print_url'
));
}
private function setAmount(&$graph, &$totals, &$expenses, $items, $type, $date_field)
{
foreach ($items as $item) {
if ($item['table'] == 'bill_payments') {
$bill = $item->bill;
switch ($item->getTable()) {
case 'bill_payments':
$bill = $item->bill;
$item->category_id = $bill->category_id;
if ($vendors = request('vendors')) {
if (!in_array($bill->vendor_id, $vendors)) {
continue;
}
}
$item->category_id = $bill->category_id;
break;
case 'bills':
if ($accounts = request('accounts')) {
foreach ($item->payments as $payment) {
if (!in_array($payment->account_id, $accounts)) {
continue 2;
}
}
}
break;
}
$date = Date::parse($item->$date_field)->format('F');
$month = Date::parse($item->$date_field)->format('F');
$month_year = Date::parse($item->$date_field)->format('F-Y');
if (!isset($expenses[$item->category_id])) {
if (!isset($expenses[$item->category_id]) || !isset($expenses[$item->category_id][$month]) || !isset($graph[$month_year])) {
continue;
}
@ -122,13 +178,34 @@ class ExpenseSummary extends Controller
}
}
$expenses[$item->category_id][$date]['amount'] += $amount;
$expenses[$item->category_id][$date]['currency_code'] = $item->currency_code;
$expenses[$item->category_id][$date]['currency_rate'] = $item->currency_rate;
$expenses[$item->category_id][$month]['amount'] += $amount;
$expenses[$item->category_id][$month]['currency_code'] = $item->currency_code;
$expenses[$item->category_id][$month]['currency_rate'] = $item->currency_rate;
$graph[Date::parse($item->$date_field)->format('F-Y')] += $amount;
$graph[$month_year] += $amount;
$totals[$date]['amount'] += $amount;
$totals[$month]['amount'] += $amount;
}
}
private function getPrintUrl($year)
{
$print_url = 'reports/expense-summary?print=1'
. '&status=' . request('status')
. '&year='. request('year', $year);
collect(request('accounts'))->each(function($item) use(&$print_url) {
$print_url .= '&accounts[]=' . $item;
});
collect(request('vendors'))->each(function($item) use(&$print_url) {
$print_url .= '&vendors[]=' . $item;
});
collect(request('categories'))->each(function($item) use(&$print_url) {
$print_url .= '&categories[]=' . $item;
});
return $print_url;
}
}

View File

@ -3,13 +3,17 @@
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use App\Models\Banking\Account;
use App\Models\Income\Customer;
use App\Models\Income\Invoice;
use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Expense\Bill;
use App\Models\Expense\BillPayment;
use App\Models\Expense\Payment;
use App\Models\Expense\Vendor;
use App\Models\Setting\Category;
use App\Utilities\Recurring;
use Charts;
use Date;
@ -25,16 +29,16 @@ class IncomeExpenseSummary extends Controller
$dates = $totals = $compares = $profit_graph = $categories = [];
$status = request('status');
$year = request('year', Date::now()->year);
$categories_filter = request('categories');
$income_categories = Category::enabled()->type('income')->pluck('name', 'id')->toArray();
$income_categories = Category::enabled()->type('income')->when($categories_filter, function ($query) use ($categories_filter) {
return $query->whereIn('id', $categories_filter);
})->orderBy('name')->pluck('name', 'id')->toArray();
$expense_categories = Category::enabled()->type('expense')->pluck('name', 'id')->toArray();
// Get year
$year = request('year');
if (empty($year)) {
$year = Date::now()->year;
}
$expense_categories = Category::enabled()->type('expense')->when($categories_filter, function ($query) use ($categories_filter) {
return $query->whereIn('id', $categories_filter);
})->orderBy('name')->pluck('name', 'id')->toArray();
// Dates
for ($j = 1; $j <= 12; $j++) {
@ -70,49 +74,75 @@ class IncomeExpenseSummary extends Controller
}
}
// Invoices
$revenues = Revenue::monthsOfYear('paid_at')->account(request('accounts'))->customer(request('customers'))->isNotTransfer()->get();
$payments = Payment::monthsOfYear('paid_at')->account(request('accounts'))->vendor(request('vendors'))->isNotTransfer()->get();
switch ($status) {
case 'paid':
$invoices = InvoicePayment::monthsOfYear('paid_at')->get();
// Invoices
$invoices = InvoicePayment::monthsOfYear('paid_at')->account(request('accounts'))->get();
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'paid_at');
break;
case 'upcoming':
$invoices = Invoice::accrued()->monthsOfYear('due_at')->get();
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'due_at');
break;
default:
$invoices = Invoice::accrued()->monthsOfYear('invoiced_at')->get();
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'invoiced_at');
break;
}
// Revenues
if ($status != 'upcoming') {
$revenues = Revenue::monthsOfYear('paid_at')->isNotTransfer()->get();
$this->setAmount($profit_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
}
// Revenues
$this->setAmount($profit_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
// Bills
switch ($status) {
case 'paid':
$bills = BillPayment::monthsOfYear('paid_at')->get();
// Bills
$bills = BillPayment::monthsOfYear('paid_at')->account(request('accounts'))->get();
$this->setAmount($profit_graph, $totals, $compares, $bills, 'bill', 'paid_at');
// Payments
$this->setAmount($profit_graph, $totals, $compares, $payments, 'payment', 'paid_at');
break;
case 'upcoming':
$bills = Bill::accrued()->monthsOfYear('due_at')->get();
// Invoices
$invoices = Invoice::accrued()->monthsOfYear('due_at')->customer(request('customers'))->get();
Recurring::reflect($invoices, 'invoice', 'due_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'due_at');
// Revenues
Recurring::reflect($revenues, 'revenue', 'paid_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
// Bills
$bills = Bill::accrued()->monthsOfYear('due_at')->vendor(request('vendors'))->get();
Recurring::reflect($bills, 'bill', 'billed_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $bills, 'bill', 'due_at');
// Payments
Recurring::reflect($payments, 'payment', 'paid_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $payments, 'payment', 'paid_at');
break;
default:
$bills = Bill::accrued()->monthsOfYear('billed_at')->get();
// Invoices
$invoices = Invoice::accrued()->monthsOfYear('invoiced_at')->customer(request('customers'))->get();
Recurring::reflect($invoices, 'invoice', 'invoiced_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $invoices, 'invoice', 'invoiced_at');
// Revenues
Recurring::reflect($revenues, 'revenue', 'paid_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
// Bills
$bills = Bill::accrued()->monthsOfYear('billed_at')->vendor(request('vendors'))->get();
Recurring::reflect($bills, 'bill', 'billed_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $bills, 'bill', 'billed_at');
// Payments
Recurring::reflect($payments, 'payment', 'paid_at', $status);
$this->setAmount($profit_graph, $totals, $compares, $payments, 'payment', 'paid_at');
break;
}
// Payments
if ($status != 'upcoming') {
$payments = Payment::monthsOfYear('paid_at')->isNotTransfer()->get();
$this->setAmount($profit_graph, $totals, $compares, $payments, 'payment', 'paid_at');
}
$statuses = collect([
'all' => trans('general.all'),
'paid' => trans('invoices.paid'),
'upcoming' => trans('general.upcoming'),
]);
$accounts = Account::enabled()->pluck('name', 'id')->toArray();
$customers = Customer::enabled()->pluck('name', 'id')->toArray();
$vendors = Vendor::enabled()->pluck('name', 'id')->toArray();
$categories = Category::enabled()->type(['income', 'expense'])->pluck('name', 'id')->toArray();
// Check if it's a print or normal request
if (request('print')) {
@ -123,6 +153,8 @@ class IncomeExpenseSummary extends Controller
$view_template = 'reports.income_expense_summary.index';
}
$print_url = $this->getPrintUrl($year);
// Profit chart
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
@ -132,23 +164,72 @@ class IncomeExpenseSummary extends Controller
->credits(false)
->view($chart_template);
return view($view_template, compact('chart', 'dates', 'income_categories', 'expense_categories', 'compares', 'totals'));
return view($view_template, compact(
'chart',
'dates',
'income_categories',
'expense_categories',
'categories',
'statuses',
'accounts',
'customers',
'vendors',
'compares',
'totals',
'print_url'
));
}
private function setAmount(&$graph, &$totals, &$compares, $items, $type, $date_field)
{
foreach ($items as $item) {
if ($item['table'] == 'bill_payments' || $item['table'] == 'invoice_payments') {
if ($item->getTable() == 'bill_payments' || $item->getTable() == 'invoice_payments') {
$type_item = $item->$type;
$item->category_id = $type_item->category_id;
}
$date = Date::parse($item->$date_field)->format('F');
switch ($item->getTable()) {
case 'invoice_payments':
$invoice = $item->invoice;
if ($customers = request('customers')) {
if (!in_array($invoice->customer_id, $customers)) {
continue;
}
}
$item->category_id = $invoice->category_id;
break;
case 'bill_payments':
$bill = $item->bill;
if ($vendors = request('vendors')) {
if (!in_array($bill->vendor_id, $vendors)) {
continue;
}
}
$item->category_id = $bill->category_id;
break;
case 'invoices':
case 'bills':
if ($accounts = request('accounts')) {
foreach ($item->payments as $payment) {
if (!in_array($payment->account_id, $accounts)) {
continue 2;
}
}
}
break;
}
$month = Date::parse($item->$date_field)->format('F');
$month_year = Date::parse($item->$date_field)->format('F-Y');
$group = (($type == 'invoice') || ($type == 'revenue')) ? 'income' : 'expense';
if (!isset($compares[$group][$item->category_id])) {
if (!isset($compares[$group][$item->category_id]) || !isset($compares[$group][$item->category_id][$month]) || !isset($graph[$month_year])) {
continue;
}
@ -161,19 +242,44 @@ class IncomeExpenseSummary extends Controller
}
}
$compares[$group][$item->category_id][$date]['amount'] += $amount;
$compares[$group][$item->category_id][$date]['currency_code'] = $item->currency_code;
$compares[$group][$item->category_id][$date]['currency_rate'] = $item->currency_rate;
$compares[$group][$item->category_id][$month]['amount'] += $amount;
$compares[$group][$item->category_id][$month]['currency_code'] = $item->currency_code;
$compares[$group][$item->category_id][$month]['currency_rate'] = $item->currency_rate;
if ($group == 'income') {
$graph[Date::parse($item->$date_field)->format('F-Y')] += $amount;
$graph[$month_year] += $amount;
$totals[$date]['amount'] += $amount;
$totals[$month]['amount'] += $amount;
} else {
$graph[Date::parse($item->$date_field)->format('F-Y')] -= $amount;
$graph[$month_year] -= $amount;
$totals[$date]['amount'] -= $amount;
$totals[$month]['amount'] -= $amount;
}
}
}
private function getPrintUrl($year)
{
$print_url = 'reports/income-expense-summary?print=1'
. '&status=' . request('status')
. '&year='. request('year', $year);
collect(request('accounts'))->each(function($item) use(&$print_url) {
$print_url .= '&accounts[]=' . $item;
});
collect(request('customers'))->each(function($item) use(&$print_url) {
$print_url .= '&customers[]=' . $item;
});
collect(request('vendors'))->each(function($item) use(&$print_url) {
$print_url .= '&vendors[]=' . $item;
});
collect(request('categories'))->each(function($item) use(&$print_url) {
$print_url .= '&categories[]=' . $item;
});
return $print_url;
}
}

View File

@ -3,10 +3,13 @@
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use App\Models\Banking\Account;
use App\Models\Income\Customer;
use App\Models\Income\Invoice;
use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use App\Utilities\Recurring;
use Charts;
use Date;
@ -22,13 +25,16 @@ class IncomeSummary extends Controller
$dates = $totals = $incomes = $incomes_graph = $categories = [];
$status = request('status');
$year = request('year', Date::now()->year);
$categories = Category::enabled()->type('income')->pluck('name', 'id')->toArray();
$categories = Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id')->toArray();
// Get year
$year = request('year');
if (empty($year)) {
$year = Date::now()->year;
if ($categories_filter = request('categories')) {
$cats = collect($categories)->filter(function ($value, $key) use ($categories_filter) {
return in_array($key, $categories_filter);
});
} else {
$cats = $categories;
}
// Dates
@ -44,38 +50,58 @@ class IncomeSummary extends Controller
'currency_rate' => 1
);
foreach ($categories as $category_id => $category_name) {
$incomes[$category_id][$dates[$j]] = array(
foreach ($cats as $category_id => $category_name) {
$incomes[$category_id][$dates[$j]] = [
'category_id' => $category_id,
'name' => $category_name,
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
];
}
}
// Invoices
$revenues = Revenue::monthsOfYear('paid_at')->account(request('accounts'))->customer(request('customers'))->isNotTransfer()->get();
switch ($status) {
case 'paid':
$invoices = InvoicePayment::monthsOfYear('paid_at')->get();
// Invoices
$invoices = InvoicePayment::monthsOfYear('paid_at')->account(request('accounts'))->get();
$this->setAmount($incomes_graph, $totals, $incomes, $invoices, 'invoice', 'paid_at');
// Revenues
$this->setAmount($incomes_graph, $totals, $incomes, $revenues, 'revenue', 'paid_at');
break;
case 'upcoming':
$invoices = Invoice::accrued()->monthsOfYear('due_at')->get();
// Invoices
$invoices = Invoice::accrued()->monthsOfYear('due_at')->customer(request('customers'))->get();
Recurring::reflect($invoices, 'invoice', 'invoiced_at', $status);
$this->setAmount($incomes_graph, $totals, $incomes, $invoices, 'invoice', 'due_at');
// Revenues
Recurring::reflect($revenues, 'revenue', 'paid_at', $status);
$this->setAmount($incomes_graph, $totals, $incomes, $revenues, 'revenue', 'paid_at');
break;
default:
$invoices = Invoice::accrued()->monthsOfYear('invoiced_at')->get();
// Invoices
$invoices = Invoice::accrued()->monthsOfYear('invoiced_at')->customer(request('customers'))->get();
Recurring::reflect($invoices, 'invoice', 'invoiced_at', $status);
$this->setAmount($incomes_graph, $totals, $incomes, $invoices, 'invoice', 'invoiced_at');
// Revenues
Recurring::reflect($revenues, 'revenue', 'paid_at', $status);
$this->setAmount($incomes_graph, $totals, $incomes, $revenues, 'revenue', 'paid_at');
break;
}
// Revenues
if ($status != 'upcoming') {
$revenues = Revenue::monthsOfYear('paid_at')->isNotTransfer()->get();
$this->setAmount($incomes_graph, $totals, $incomes, $revenues, 'revenue', 'paid_at');
}
$statuses = collect([
'all' => trans('general.all'),
'paid' => trans('invoices.paid'),
'upcoming' => trans('dashboard.receivables'),
]);
$accounts = Account::enabled()->pluck('name', 'id')->toArray();
$customers = Customer::enabled()->pluck('name', 'id')->toArray();
// Check if it's a print or normal request
if (request('print')) {
@ -86,6 +112,8 @@ class IncomeSummary extends Controller
$view_template = 'reports.income_summary.index';
}
$print_url = $this->getPrintUrl($year);
// Incomes chart
$chart = Charts::multi('line', 'chartjs')
->dimensions(0, 300)
@ -95,21 +123,49 @@ class IncomeSummary extends Controller
->credits(false)
->view($chart_template);
return view($view_template, compact('chart', 'dates', 'categories', 'incomes', 'totals'));
return view($view_template, compact(
'chart',
'dates',
'categories',
'statuses',
'accounts',
'customers',
'incomes',
'totals',
'print_url'
));
}
private function setAmount(&$graph, &$totals, &$incomes, $items, $type, $date_field)
{
foreach ($items as $item) {
if ($item['table'] == 'invoice_payments') {
$invoice = $item->invoice;
switch ($item->getTable()) {
case 'invoice_payments':
$invoice = $item->invoice;
$item->category_id = $invoice->category_id;
if ($customers = request('customers')) {
if (!in_array($invoice->customer_id, $customers)) {
continue;
}
}
$item->category_id = $invoice->category_id;
break;
case 'invoices':
if ($accounts = request('accounts')) {
foreach ($item->payments as $payment) {
if (!in_array($payment->account_id, $accounts)) {
continue 2;
}
}
}
break;
}
$date = Date::parse($item->$date_field)->format('F');
$month = Date::parse($item->$date_field)->format('F');
$month_year = Date::parse($item->$date_field)->format('F-Y');
if (!isset($incomes[$item->category_id])) {
if (!isset($incomes[$item->category_id]) || !isset($incomes[$item->category_id][$month]) || !isset($graph[$month_year])) {
continue;
}
@ -122,13 +178,34 @@ class IncomeSummary extends Controller
}
}
$incomes[$item->category_id][$date]['amount'] += $amount;
$incomes[$item->category_id][$date]['currency_code'] = $item->currency_code;
$incomes[$item->category_id][$date]['currency_rate'] = $item->currency_rate;
$incomes[$item->category_id][$month]['amount'] += $amount;
$incomes[$item->category_id][$month]['currency_code'] = $item->currency_code;
$incomes[$item->category_id][$month]['currency_rate'] = $item->currency_rate;
$graph[Date::parse($item->$date_field)->format('F-Y')] += $amount;
$graph[$month_year] += $amount;
$totals[$date]['amount'] += $amount;
$totals[$month]['amount'] += $amount;
}
}
private function getPrintUrl($year)
{
$print_url = 'reports/income-summary?print=1'
. '&status=' . request('status')
. '&year='. request('year', $year);
collect(request('accounts'))->each(function($item) use(&$print_url) {
$print_url .= '&accounts[]=' . $item;
});
collect(request('customers'))->each(function($item) use(&$print_url) {
$print_url .= '&customers[]=' . $item;
});
collect(request('categories'))->each(function($item) use(&$print_url) {
$print_url .= '&categories[]=' . $item;
});
return $print_url;
}
}

View File

@ -25,16 +25,11 @@ class ProfitLoss extends Controller
$dates = $totals = $compares = $categories = [];
$status = request('status');
$year = request('year', Date::now()->year);
$income_categories = Category::enabled()->type('income')->pluck('name', 'id')->toArray();
$income_categories = Category::enabled()->type('income')->orderBy('name')->pluck('name', 'id')->toArray();
$expense_categories = Category::enabled()->type('expense')->pluck('name', 'id')->toArray();
// Get year
$year = request('year');
if (empty($year)) {
$year = Date::now()->year;
}
$expense_categories = Category::enabled()->type('expense')->orderBy('name')->pluck('name', 'id')->toArray();
// Dates
for ($j = 1; $j <= 12; $j++) {
@ -142,6 +137,12 @@ class ProfitLoss extends Controller
$this->setAmount($totals, $compares, $payments, 'payment', 'paid_at');
}
$statuses = collect([
'all' => trans('general.all'),
'paid' => trans('invoices.paid'),
'upcoming' => trans('general.upcoming'),
]);
// Check if it's a print or normal request
if (request('print')) {
$view_template = 'reports.profit_loss.print';
@ -149,7 +150,7 @@ class ProfitLoss extends Controller
$view_template = 'reports.profit_loss.index';
}
return view($view_template, compact('dates', 'income_categories', 'expense_categories', 'compares', 'totals', 'gross'));
return view($view_template, compact('dates', 'income_categories', 'expense_categories', 'compares', 'totals', 'gross', 'statuses'));
}
private function setAmount(&$totals, &$compares, $items, $type, $date_field)

View File

@ -27,17 +27,12 @@ class TaxSummary extends Controller
$dates = $incomes = $expenses = $totals = [];
$status = request('status');
$year = request('year', Date::now()->year);
$t = Tax::enabled()->where('rate', '<>', '0')->pluck('name')->toArray();
$taxes = array_combine($t, $t);
// Get year
$year = request('year');
if (empty($year)) {
$year = Date::now()->year;
}
// Dates
for ($j = 1; $j <= 12; $j++) {
$dates[$j] = Date::parse($year . '-' . $j)->format('M');
@ -90,6 +85,12 @@ class TaxSummary extends Controller
break;
}
$statuses = collect([
'all' => trans('general.all'),
'paid' => trans('invoices.paid'),
'upcoming' => trans('general.upcoming'),
]);
// Check if it's a print or normal request
if (request('print')) {
$view_template = 'reports.tax_summary.print';
@ -97,13 +98,13 @@ class TaxSummary extends Controller
$view_template = 'reports.tax_summary.index';
}
return view($view_template, compact('dates', 'taxes', 'incomes', 'expenses', 'totals'));
return view($view_template, compact('dates', 'taxes', 'incomes', 'expenses', 'totals', 'statuses'));
}
private function setAmount(&$items, &$totals, $rows, $type, $date_field)
{
foreach ($rows as $row) {
if ($row['table'] == 'bill_payments' || $row['table'] == 'invoice_payments') {
if ($row->getTable() == 'bill_payments' || $row->getTable() == 'invoice_payments') {
$type_row = $row->$type;
$row->category_id = $type_row->category_id;
@ -126,7 +127,14 @@ class TaxSummary extends Controller
continue;
}
$amount = $this->convert($row_total->amount, $row->currency_code, $row->currency_rate);
if ($date_field == 'paid_at') {
$rate = ($row->amount * 100) / $type_row->amount;
$row_amount = ($row_total->amount / 100) * $rate;
} else {
$row_amount = $row_total->amount;
}
$amount = $this->convert($row_amount, $row->currency_code, $row->currency_rate);
$items[$row_total->name][$date]['amount'] += $amount;

View File

@ -25,7 +25,7 @@ class Categories extends Controller
'income' => trans_choice('general.incomes', 1),
'item' => trans_choice('general.items', 1),
'other' => trans_choice('general.others', 1),
])->prepend(trans('general.all_type', ['type' => trans_choice('general.types', 2)]), '');
]);
return view('settings.categories.index', compact('categories', 'types', 'transfer_id'));
}

View File

@ -162,7 +162,7 @@ class Currencies extends Controller
return redirect('settings/currencies');
} else {
$message = trans('messages.warning.disabled', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
$message = trans('messages.warning.disable_code', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
flash($message)->warning();

View File

@ -47,7 +47,7 @@ class Settings extends Controller
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code');
$taxes = Tax::enabled()->orderBy('rate')->get()->pluck('title', 'id');
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
$payment_methods = Modules::getPaymentMethods();
@ -67,6 +67,24 @@ class Settings extends Controller
'space' => trans('settings.localisation.date.space'),
];
$item_names = [
'settings.invoice.item' => trans('settings.invoice.item'),
'settings.invoice.product' => trans('settings.invoice.product'),
'settings.invoice.service' => trans('settings.invoice.service'),
'custom' => trans('settings.invoice.custom'),
];
$price_names = [
'settings.invoice.price' => trans('settings.invoice.price'),
'settings.invoice.rate' => trans('settings.invoice.rate'),
'custom' => trans('settings.invoice.custom'),
];
$quantity_names = [
'settings.invoice.quantity' => trans('settings.invoice.quantity'),
'custom' => trans('settings.invoice.custom'),
];
$email_protocols = [
'mail' => trans('settings.email.php'),
'smtp' => trans('settings.email.smtp.name'),
@ -88,6 +106,9 @@ class Settings extends Controller
'payment_methods',
'date_formats',
'date_separators',
'item_names',
'price_names',
'quantity_names',
'email_protocols',
'percent_positions'
));
@ -160,17 +181,17 @@ class Settings extends Controller
protected function oneCompany($key, $value)
{
switch ($key) {
case 'company_name':
Installer::updateEnv(['MAIL_FROM_NAME' => '"' . $value . '"']);
break;
case 'company_email':
Installer::updateEnv(['MAIL_FROM_ADDRESS' => $value]);
break;
case 'default_locale':
// Change default locale
Installer::updateEnv([
'APP_LOCALE' => $value
]);
Installer::updateEnv(['APP_LOCALE' => $value]);
break;
case 'session_handler':
// Change session handler
Installer::updateEnv([
'SESSION_DRIVER' => $value
]);
Installer::updateEnv(['SESSION_DRIVER' => $value]);
break;
}
}

View File

@ -18,7 +18,13 @@ class Taxes extends Controller
{
$taxes = Tax::collect();
return view('settings.taxes.index', compact('taxes', 'rates'));
$types = [
'normal' => trans('taxes.normal'),
'inclusive' => trans('taxes.inclusive'),
'compound' => trans('taxes.compound'),
];
return view('settings.taxes.index', compact('taxes', 'types'));
}
/**
@ -38,7 +44,13 @@ class Taxes extends Controller
*/
public function create()
{
return view('settings.taxes.create');
$types = [
'normal' => trans('taxes.normal'),
'inclusive' => trans('taxes.inclusive'),
'compound' => trans('taxes.compound'),
];
return view('settings.taxes.create', compact('types'));
}
/**
@ -68,7 +80,13 @@ class Taxes extends Controller
*/
public function edit(Tax $tax)
{
return view('settings.taxes.edit', compact('tax'));
$types = [
'normal' => trans('taxes.normal'),
'inclusive' => trans('taxes.inclusive'),
'compound' => trans('taxes.compound'),
];
return view('settings.taxes.edit', compact('tax', 'types'));
}
/**

View File

@ -0,0 +1,81 @@
<?php
namespace App\Http\Controllers\Wizard;
use App\Http\Controllers\Controller;
use App\Http\Requests\Wizard\Company as Request;
use App\Models\Common\Company;
use App\Traits\Uploads;
class Companies extends Controller
{
use Uploads;
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function edit()
{
if (setting('general.wizard', false)) {
return redirect('/');
}
$company = Company::find(session('company_id'));
$company->setSettings();
return view('wizard.companies.edit', compact('company'));
}
/**
* Update the specified resource in storage.
*
* @param Company $company
* @param Request $request
*
* @return Response
*/
public function update(Request $request)
{
// Company
$company = Company::find(session('company_id'));
$fields = $request->all();
$skip_keys = ['company_id', '_method', '_token'];
$file_keys = ['company_logo', 'invoice_logo'];
foreach ($fields as $key => $value) {
// Don't process unwanted keys
if (in_array($key, $skip_keys)) {
continue;
}
// Process file uploads
if (in_array($key, $file_keys)) {
// Upload attachment
if ($request->file($key)) {
$media = $this->getMedia($request->file($key), 'settings');
$company->attachMedia($media, $key);
$value = $media->id;
}
// Prevent reset
if (empty($value)) {
continue;
}
}
setting()->set('general.' . $key, $value);
}
// Save all settings
setting()->save();
return redirect('wizard/currencies');
}
}

View File

@ -0,0 +1,311 @@
<?php
namespace App\Http\Controllers\Wizard;
use Akaunting\Money\Currency as MoneyCurrency;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Currency as Request;
use App\Models\Banking\Account;
use App\Models\Setting\Currency;
class Currencies extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @param Currency $currency
*
* @return Response
*/
public function index()
{
if (setting('general.wizard', false)) {
return redirect('/');
}
$currencies = Currency::all();
return view('wizard.currencies.index', compact('currencies'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
if (setting(setting('general.wizard', false))) {
return redirect('/');
}
// Get current currencies
$current = Currency::pluck('code')->toArray();
// Prepare codes
$codes = array();
$currencies = MoneyCurrency::getCurrencies();
foreach ($currencies as $key => $item) {
// Don't show if already available
if (in_array($key, $current)) {
continue;
}
$codes[$key] = $key;
}
$html = view('wizard.currencies.create', compact('codes'))->render();
return response()->json([
'success' => true,
'error' => false,
'message' => 'null',
'html' => $html,
]);
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Force the rate to be 1 for default currency
if ($request['default_currency']) {
$request['rate'] = '1';
}
$currency = Currency::create($request->all());
// Update default currency setting
if ($request['default_currency']) {
setting()->set('general.default_currency', $request['code']);
setting()->save();
}
$message = trans('messages.success.added', ['type' => trans_choice('general.currencies', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $currency,
]);
}
/**
* Show the form for editing the specified resource.
*
* @param Currency $currency
*
* @return Response
*/
public function edit(Currency $currency)
{
if (setting('general.wizard', false)) {
return redirect('/');
}
// Get current currencies
$current = Currency::pluck('code')->toArray();
// Prepare codes
$codes = array();
$currencies = MoneyCurrency::getCurrencies();
foreach ($currencies as $key => $item) {
// Don't show if already available
if (($key != $currency->code) && in_array($key, $current)) {
continue;
}
$codes[$key] = $key;
}
$item = $currency;
$html = view('wizard.currencies.edit', compact('item', 'codes'))->render();
return response()->json([
'success' => true,
'error' => false,
'message' => 'null',
'html' => $html,
]);
}
/**
* Update the specified resource in storage.
*
* @param Currency $currency
* @param Request $request
*
* @return Response
*/
public function update(Currency $currency, Request $request)
{
// Check if we can disable or change the code
if (!$request['enabled'] || ($currency->code != $request['code'])) {
$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 (empty($relationships)) {
// Force the rate to be 1 for default currency
if ($request['default_currency']) {
$request['rate'] = '1';
}
$currency->update($request->all());
// Update default currency setting
if ($request['default_currency']) {
setting()->set('general.default_currency', $request['code']);
setting()->save();
}
$message = trans('messages.success.updated', ['type' => trans_choice('general.currencies', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $currency,
]);
} else {
$message = trans('messages.warning.disabled', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $currency,
]);
}
}
/**
* Enable the specified resource.
*
* @param Currency $currency
*
* @return Response
*/
public function enable(Currency $currency)
{
$currency->enabled = 1;
$currency->save();
$message = trans('messages.success.enabled', ['type' => trans_choice('general.currencies', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $currency,
]);
}
/**
* Disable the specified resource.
*
* @param Currency $currency
*
* @return Response
*/
public function disable(Currency $currency)
{
$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 (empty($relationships)) {
$currency->enabled = 0;
$currency->save();
$message = trans('messages.success.disabled', ['type' => trans_choice('general.currencies', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $currency,
]);
} else {
$message = trans('messages.warning.disabled', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
return response()->json([
'success' => false,
'error' => true,
'message' => $message,
'data' => $currency,
]);
}
}
/**
* Remove the specified resource from storage.
*
* @param Currency $currency
*
* @return Response
*/
public function destroy(Currency $currency)
{
$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 (empty($relationships)) {
$currency->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.currencies', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $currency,
]);
} else {
$message = trans('messages.warning.deleted', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
return response()->json([
'success' => false,
'error' => true,
'message' => $message,
'data' => $currency,
]);
}
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers\Wizard;
use Illuminate\Routing\Controller;
use App\Traits\Modules;
use App\Models\Module\Module;
class Finish extends Controller
{
use Modules;
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function index()
{
if (setting(setting('general.wizard', false))) {
return redirect('/');
}
setting()->set('general.wizard', true);
// Save all settings
setting()->save();
$data = [
'query' => [
'limit' => 4
]
];
$modules = $this->getFeaturedModules($data);
return view('wizard.finish.index', compact('modules'));
}
}

View File

@ -0,0 +1,231 @@
<?php
namespace App\Http\Controllers\Wizard;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Tax as Request;
use App\Models\Setting\Tax;
class Taxes extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @return Response
*/
public function index()
{
if (setting(setting('general.wizard', false))) {
return redirect('/');
}
$taxes = Tax::all();
return view('wizard.taxes.index', compact('taxes'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
if (setting(setting('general.wizard', false))) {
return redirect('/');
}
$html = view('wizard.taxes.create', compact('codes'))->render();
return response()->json([
'success' => true,
'error' => false,
'message' => 'null',
'html' => $html,
]);
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
$tax = Tax::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.tax_rates', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $tax,
]);
}
/**
* Show the form for editing the specified resource.
*
* @param Tax $tax
*
* @return Response
*/
public function edit(Tax $tax)
{
if (setting(setting('general.wizard', false))) {
return redirect('/');
}
$item = $tax;
$html = view('wizard.taxes.edit', compact('item'))->render();
return response()->json([
'success' => true,
'error' => false,
'message' => 'null',
'html' => $html,
]);
}
/**
* Update the specified resource in storage.
*
* @param Tax $tax
* @param Request $request
*
* @return Response
*/
public function update(Tax $tax, Request $request)
{
$relationships = $this->countRelationships($tax, [
'items' => 'items',
'invoice_items' => 'invoices',
'bill_items' => 'bills',
]);
if (empty($relationships) || $request['enabled']) {
$tax->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.tax_rates', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $tax,
]);
} else {
$message = trans('messages.warning.disabled', ['name' => $tax->name, 'text' => implode(', ', $relationships)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $tax,
]);
}
}
/**
* Enable the specified resource.
*
* @param Tax $tax
*
* @return Response
*/
public function enable(Tax $tax)
{
$tax->enabled = 1;
$tax->save();
$message = trans('messages.success.enabled', ['type' => trans_choice('general.tax_rates', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $tax,
]);
}
/**
* Disable the specified resource.
*
* @param Tax $tax
*
* @return Response
*/
public function disable(Tax $tax)
{
$relationships = $this->countRelationships($tax, [
'items' => 'items',
'invoice_items' => 'invoices',
'bill_items' => 'bills',
]);
if (empty($relationships)) {
$tax->enabled = 0;
$tax->save();
$message = trans('messages.success.disabled', ['type' => trans_choice('general.tax_rates', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $tax,
]);
} else {
$message = trans('messages.warning.disabled', ['name' => $tax->name, 'text' => implode(', ', $relationships)]);
return response()->json([
'success' => false,
'error' => true,
'message' => $message,
'data' => $tax,
]);
}
}
/**
* Remove the specified resource from storage.
*
* @param Tax $tax
*
* @return Response
*/
public function destroy(Tax $tax)
{
$relationships = $this->countRelationships($tax, [
'items' => 'items',
'invoice_items' => 'invoices',
'bill_items' => 'bills',
]);
if (empty($relationships)) {
$tax->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.taxes', 1)]);
return response()->json([
'success' => true,
'error' => false,
'message' => $message,
'data' => $tax,
]);
} else {
$message = trans('messages.warning.deleted', ['name' => $tax->name, 'text' => implode(', ', $relationships)]);
return response()->json([
'success' => false,
'error' => true,
'message' => $message,
'data' => $tax,
]);
}
}
}