first commit

This commit is contained in:
denisdulici
2017-09-14 22:21:00 +03:00
commit 515bdaf5cd
598 changed files with 48030 additions and 0 deletions

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Auth;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Auth\Permission as Request;
use App\Http\Transformers\Auth\Permission as Transformer;
use App\Models\Auth\Permission;
use Dingo\Api\Routing\Helpers;
class Permissions extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$permissions = Permission::collect();
return $this->response->paginator($permissions, new Transformer());
}
/**
* Display the specified resource.
*
* @param Permission $permission
* @return \Dingo\Api\Http\Response
*/
public function show(Permission $permission)
{
return $this->response->item($permission, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$permission = Permission::create($request->all());
return $this->response->created(url('api/permissions/'.$permission->id));
}
/**
* Update the specified resource in storage.
*
* @param $permission
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Permission $permission, Request $request)
{
$permission->update($request->all());
return $this->response->item($permission->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Permission $permission
* @return \Dingo\Api\Http\Response
*/
public function destroy(Permission $permission)
{
$permission->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace App\Http\Controllers\Api\Auth;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Auth\Role as Request;
use App\Http\Transformers\Auth\Role as Transformer;
use App\Models\Auth\Role;
use Dingo\Api\Routing\Helpers;
class Roles extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$roles = Role::with('permissions')->collect();
return $this->response->paginator($roles, new Transformer());
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Dingo\Api\Http\Response
*/
public function show($id)
{
$role = Role::with('permissions')->findOrFail($id);
return $this->response->item($role, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$role = Role::create($request->input());
if ($request->has('permissions')) {
$role->permissions()->attach($request->get('permissions'));
}
return $this->response->created(url('api/roles/'.$role->id));
}
/**
* Update the specified resource in storage.
*
* @param $role
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Role $role, Request $request)
{
$role->update($request->all());
if ($request->has('permissions')) {
$role->permissions()->attach($request->get('permissions'));
}
return $this->response->item($role->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Role $role
* @return \Dingo\Api\Http\Response
*/
public function destroy(Role $role)
{
$role->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,96 @@
<?php
namespace App\Http\Controllers\Api\Auth;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Auth\User as Request;
use App\Http\Transformers\Auth\User as Transformer;
use App\Models\Auth\User;
use Dingo\Api\Routing\Helpers;
class Users extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$users = User::with(['roles', 'permissions'])->collect();
return $this->response->paginator($users, new Transformer());
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Dingo\Api\Http\Response
*/
public function show($id)
{
$user = User::with(['roles', 'permissions'])->findOrFail($id);
return $this->response->item($user, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$user = User::create($request->input());
if ($request->has('roles')) {
$user->roles()->attach($request->get('roles'));
}
if ($request->has('companies')) {
$user->companies()->attach($request->get('companies'));
}
return $this->response->created(url('api/users/'.$user->id));
}
/**
* Update the specified resource in storage.
*
* @param $user
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(User $user, Request $request)
{
// Except password as we don't want to let the users change a password from this endpoint
$user->update($request->except('password'));
if ($request->has('roles')) {
$user->roles()->attach($request->get('roles'));
}
if ($request->has('companies')) {
$user->companies()->attach($request->get('companies'));
}
return $this->response->item($user->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param User $user
* @return \Dingo\Api\Http\Response
*/
public function destroy(User $user)
{
$user->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Banking;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Banking\Account as Request;
use App\Http\Transformers\Banking\Account as Transformer;
use App\Models\Banking\Account;
use Dingo\Api\Routing\Helpers;
class Accounts extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$accounts = Account::collect();
return $this->response->paginator($accounts, new Transformer());
}
/**
* Display the specified resource.
*
* @param Account $account
* @return \Dingo\Api\Http\Response
*/
public function show(Account $account)
{
return $this->response->item($account, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$account = Account::create($request->all());
return $this->response->created(url('api/accounts/'.$account->id));
}
/**
* Update the specified resource in storage.
*
* @param $account
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Account $account, Request $request)
{
$account->update($request->all());
return $this->response->item($account->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Account $account
* @return \Dingo\Api\Http\Response
*/
public function destroy(Account $account)
{
$account->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers\Api\Banking;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Banking\Transfer as Request;
use App\Http\Transformers\Banking\Transfer as Transformer;
use App\Models\Banking\Transfer;
use App\Models\Expense\Payment;
use App\Models\Income\Revenue;
use Dingo\Api\Routing\Helpers;
class Transfers extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$transfers = Transfer::with(['payment', 'revenue'])->collect('payment.paid_at');
return $this->response->paginator($transfers, new Transformer());
}
/**
* Display the specified resource.
*
* @param Transfer $transfer
* @return \Dingo\Api\Http\Response
*/
public function show(Transfer $transfer)
{
return $this->response->item($transfer, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$transfer = Transfer::create($request->all());
return $this->response->created(url('api/transfers/'.$transfer->id));
}
/**
* Update the specified resource in storage.
*
* @param $transfer
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Transfer $transfer, Request $request)
{
$transfer->update($request->all());
return $this->response->item($transfer->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Transfer $transfer
* @return \Dingo\Api\Http\Response
*/
public function destroy(Transfer $transfer)
{
$payment = Payment::findOrFail($transfer['payment_id']);
$revenue = Revenue::findOrFail($transfer['revenue_id']);
$transfer->delete();
$payment->delete();
$revenue->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers\Api\Common;
use App\Http\Controllers\ApiController;
use Date;
use Dingo\Api\Routing\Helpers;
class Ping extends ApiController
{
use Helpers;
/**
* Responds with a status for heath check.
*
* @return \Illuminate\Http\JsonResponse
*/
public function index()
{
return $this->response->array([
'status' => 'ok',
'timestamp' => Date::now(),
]);
}
}

View File

@ -0,0 +1,92 @@
<?php
namespace App\Http\Controllers\Api\Banking;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Company\Company as Request;
use App\Http\Transformers\Banking\Company as Transformer;
use App\Models\Company\Company;
use Dingo\Api\Routing\Helpers;
class Companies extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$companies = app('Dingo\Api\Auth\Auth')->user()->companies()->get()->sortBy('name');
foreach ($companies as $company) {
$company->setSettings();
}
return $this->response->paginator($companies, new Transformer());
}
/**
* Display the specified resource.
*
* @param Company $company
* @return \Dingo\Api\Http\Response
*/
public function show(Company $company)
{
$company->setSettings();
return $this->response->item($company, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$company = Company::create($request->all());
return $this->response->created(url('api/companies/'.$company->id));
}
/**
* Update the specified resource in storage.
*
* @param $company
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Company $company, Request $request)
{
// Check if user can access company
$companies = app('Dingo\Api\Auth\Auth')->user()->companies()->pluck('id')->toArray();
if (!in_array($company->id, $companies)) {
return $this->response->noContent();
}
return $this->response->item($company->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Company $company
* @return \Dingo\Api\Http\Response
*/
public function destroy(Company $company)
{
// Check if user can access company
$companies = app('Dingo\Api\Auth\Auth')->user()->companies()->pluck('id')->toArray();
if (in_array($company->id, $companies)) {
$company->delete();
}
return $this->response->noContent();
}
}

View File

@ -0,0 +1,184 @@
<?php
namespace App\Http\Controllers\Api\Expenses;
use App\Events\BillCreated;
use App\Events\BillUpdated;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Expense\Bill as Request;
use App\Http\Transformers\Expense\Bill as Transformer;
use App\Models\Expense\Bill;
use App\Models\Expense\BillHistory;
use App\Models\Expense\BillItem;
use App\Models\Expense\BillPayment;
use App\Models\Expense\BillStatus;
use App\Models\Item\Item;
use App\Models\Setting\Tax;
use Dingo\Api\Routing\Helpers;
class Bills extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$bills = Bill::with('bill_statuses')->collect();
return $this->response->paginator($bills, new Transformer());
}
/**
* Display the specified resource.
*
* @param Bill $bill
* @return \Dingo\Api\Http\Response
*/
public function show(Bill $bill)
{
return $this->response->item($bill, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$bill = Bill::create($request->all());
$bill_item = array();
$bill_item['company_id'] = $request['company_id'];
$bill_item['bill_id'] = $bill->id;
if ($request['item']) {
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = $item['name'];
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
$bill_item['tax'] = (($item['price'] * $item['quantity']) / 100) * $tax_rate;
$bill_item['tax_id'] = $tax_id;
$bill_item['total'] = ($item['price'] + $bill_item['tax']) * $item['quantity'];
$request['amount'] += $bill_item['total'];
BillItem::create($bill_item);
}
}
$bill->update($request->input());
$request['bill_id'] = $bill->id;
$request['status_code'] = 'draft';
$request['notify'] = 0;
$request['description'] = trans('messages.success.added', ['type' => $request['bill_number']]);
BillHistory::create($request->input());
// Fire the event to make it extendible
event(new BillCreated($bill));
return $this->response->created(url('api/bills/'.$bill->id));
}
/**
* Update the specified resource in storage.
*
* @param $bill
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Bill $bill, Request $request)
{
$bill_item = array();
$bill_item['company_id'] = $request['company_id'];
$bill_item['bill_id'] = $bill->id;
if ($request['item']) {
BillItem::where('bill_id', $bill->id)->delete();
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = $item['name'];
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
$bill_item['tax'] = (($item['price'] * $item['quantity']) / 100 * $tax_rate);
$bill_item['tax_id'] = $tax_id;
$bill_item['total'] = ($item['price'] + $bill_item['tax']) * $item['quantity'];
$request['amount'] += $bill_item['total'];
BillItem::create($bill_item);
}
}
$bill->update($request->input());
// Fire the event to make it extendible
event(new BillUpdated($bill));
return $this->response->item($bill->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Bill $bill
* @return \Dingo\Api\Http\Response
*/
public function destroy(Bill $bill)
{
$bill->delete();
BillItem::where('bill_id', $bill->id)->delete();
BillPayment::where('bill_id', $bill->id)->delete();
BillHistory::where('bill_id', $bill->id)->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Expenses;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Expense\Payment as Request;
use App\Http\Transformers\Expense\Payment as Transformer;
use App\Models\Expense\Payment;
use Dingo\Api\Routing\Helpers;
class Payments extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$payments = Payment::with('account', 'vendor', 'category')->collect();
return $this->response->paginator($payments, new Transformer());
}
/**
* Display the specified resource.
*
* @param Payment $payment
* @return \Dingo\Api\Http\Response
*/
public function show(Payment $payment)
{
return $this->response->item($payment, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$payment = Payment::create($request->all());
return $this->response->created(url('api/payments/'.$payment->id));
}
/**
* Update the specified resource in storage.
*
* @param $payment
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Payment $payment, Request $request)
{
$payment->update($request->all());
return $this->response->item($payment->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Payment $payment
* @return \Dingo\Api\Http\Response
*/
public function destroy(Payment $payment)
{
$payment->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Expenses;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Expense\Vendor as Request;
use App\Http\Transformers\Expense\Vendor as Transformer;
use App\Models\Expense\Vendor;
use Dingo\Api\Routing\Helpers;
class Vendors extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$vendors = Vendor::collect();
return $this->response->paginator($vendors, new Transformer());
}
/**
* Display the specified resource.
*
* @param Vendor $vendor
* @return \Dingo\Api\Http\Response
*/
public function show(Vendor $vendor)
{
return $this->response->item($vendor, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$vendor = Vendor::create($request->all());
return $this->response->created(url('api/vendors/'.$vendor->id));
}
/**
* Update the specified resource in storage.
*
* @param $vendor
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Vendor $vendor, Request $request)
{
$vendor->update($request->all());
return $this->response->item($vendor->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Vendor $vendor
* @return \Dingo\Api\Http\Response
*/
public function destroy(Vendor $vendor)
{
$vendor->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Incomes;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Income\Customer as Request;
use App\Http\Transformers\Income\Customer as Transformer;
use App\Models\Income\Customer;
use Dingo\Api\Routing\Helpers;
class Customers extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$customers = Customer::collect();
return $this->response->paginator($customers, new Transformer());
}
/**
* Display the specified resource.
*
* @param Customer $customer
* @return \Dingo\Api\Http\Response
*/
public function show(Customer $customer)
{
return $this->response->item($customer, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$customer = Customer::create($request->all());
return $this->response->created(url('api/customers/'.$customer->id));
}
/**
* Update the specified resource in storage.
*
* @param $customer
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Customer $customer, Request $request)
{
$customer->update($request->all());
return $this->response->item($customer->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Customer $customer
* @return \Dingo\Api\Http\Response
*/
public function destroy(Customer $customer)
{
$customer->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,184 @@
<?php
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\Http\Transformers\Income\Invoice as Transformer;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoiceItem;
use App\Models\Income\InvoicePayment;
use App\Models\Income\InvoiceStatus;
use App\Models\Item\Item;
use App\Models\Setting\Tax;
use Dingo\Api\Routing\Helpers;
class Invoices extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$invoices = Invoice::with('invoice_statuses')->collect();
return $this->response->paginator($invoices, new Transformer());
}
/**
* Display the specified resource.
*
* @param Invoice $invoice
* @return \Dingo\Api\Http\Response
*/
public function show(Invoice $invoice)
{
return $this->response->item($invoice, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$invoice = Invoice::create($request->all());
$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_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = $item['name'];
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
$invoice_item['tax'] = (($item['price'] * $item['quantity']) / 100) * $tax_rate;
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = ($item['price'] + $invoice_item['tax']) * $item['quantity'];
$request['amount'] += $invoice_item['total'];
InvoiceItem::create($invoice_item);
}
}
$invoice->update($request->input());
$request['invoice_id'] = $invoice->id;
$request['status_code'] = 'draft';
$request['notify'] = 0;
$request['description'] = trans('messages.success.added', ['type' => $request['invoice_number']]);
InvoiceHistory::create($request->input());
// Fire the event to make it extendible
event(new InvoiceCreated($invoice));
return $this->response->created(url('api/invoices/'.$invoice->id));
}
/**
* Update the specified resource in storage.
*
* @param $invoice
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Invoice $invoice, Request $request)
{
$invoice_item = array();
$invoice_item['company_id'] = $request['company_id'];
$invoice_item['invoice_id'] = $invoice->id;
if ($request['item']) {
InvoiceItem::where('invoice_id', $invoice->id)->delete();
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = $item['name'];
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
$invoice_item['tax'] = (($item['price'] * $item['quantity']) / 100 * $tax_rate);
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = ($item['price'] + $invoice_item['tax']) * $item['quantity'];
$request['amount'] += $invoice_item['total'];
InvoiceItem::create($invoice_item);
}
}
$invoice->update($request->input());
// Fire the event to make it extendible
event(new InvoiceUpdated($invoice));
return $this->response->item($invoice->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Invoice $invoice
* @return \Dingo\Api\Http\Response
*/
public function destroy(Invoice $invoice)
{
$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

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Incomes;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Income\Revenue as Request;
use App\Http\Transformers\Income\Revenue as Transformer;
use App\Models\Income\Revenue;
use Dingo\Api\Routing\Helpers;
class Revenues extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$revenues = Revenue::with('account', 'customer', 'category')->collect();
return $this->response->paginator($revenues, new Transformer());
}
/**
* Display the specified resource.
*
* @param Revenue $revenue
* @return \Dingo\Api\Http\Response
*/
public function show(Revenue $revenue)
{
return $this->response->item($revenue, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$revenue = Revenue::create($request->all());
return $this->response->created(url('api/revenues/'.$revenue->id));
}
/**
* Update the specified resource in storage.
*
* @param $revenue
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Revenue $revenue, Request $request)
{
$revenue->update($request->all());
return $this->response->item($revenue->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Revenue $revenue
* @return \Dingo\Api\Http\Response
*/
public function destroy(Revenue $revenue)
{
$revenue->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Items;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Item\Item as Request;
use App\Http\Transformers\Item\Item as Transformer;
use App\Models\Item\Item;
use Dingo\Api\Routing\Helpers;
class Items extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$items = Item::with(['category', 'tax'])->collect();
return $this->response->paginator($items, new Transformer());
}
/**
* Display the specified resource.
*
* @param Item $item
* @return \Dingo\Api\Http\Response
*/
public function show(Item $item)
{
return $this->response->item($item, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$item = Item::create($request->all());
return $this->response->created(url('api/items/'.$item->id));
}
/**
* Update the specified resource in storage.
*
* @param $item
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Item $item, Request $request)
{
$item->update($request->all());
return $this->response->item($item->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Item $item
* @return \Dingo\Api\Http\Response
*/
public function destroy(Item $item)
{
$item->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Settings;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Setting\Category as Request;
use App\Http\Transformers\Setting\Category as Transformer;
use App\Models\Setting\Category;
use Dingo\Api\Routing\Helpers;
class Categories extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$categories = Category::collect();
return $this->response->paginator($categories, new Transformer());
}
/**
* Display the specified resource.
*
* @param Category $category
* @return \Dingo\Api\Http\Response
*/
public function show(Category $category)
{
return $this->response->item($category, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$category = Category::create($request->all());
return $this->response->created(url('api/categories/'.$category->id));
}
/**
* Update the specified resource in storage.
*
* @param $category
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Category $category, Request $request)
{
$category->update($request->all());
return $this->response->item($category->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Category $category
* @return \Dingo\Api\Http\Response
*/
public function destroy(Category $category)
{
$category->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Settings;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Setting\Currency as Request;
use App\Http\Transformers\Setting\Currency as Transformer;
use App\Models\Setting\Currency;
use Dingo\Api\Routing\Helpers;
class Currencies extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$currencies = Currency::collect();
return $this->response->paginator($currencies, new Transformer());
}
/**
* Display the specified resource.
*
* @param Currency $currency
* @return \Dingo\Api\Http\Response
*/
public function show(Currency $currency)
{
return $this->response->item($currency, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$currency = Currency::create($request->all());
return $this->response->created(url('api/currencies/'.$currency->id));
}
/**
* Update the specified resource in storage.
*
* @param $currency
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Currency $currency, Request $request)
{
$currency->update($request->all());
return $this->response->item($currency->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Currency $currency
* @return \Dingo\Api\Http\Response
*/
public function destroy(Currency $currency)
{
$currency->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Api\Settings;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Setting\Tax as Request;
use App\Http\Transformers\Setting\Tax as Transformer;
use App\Models\Setting\Tax;
use Dingo\Api\Routing\Helpers;
class Taxes extends ApiController
{
use Helpers;
/**
* Display a listing of the resource.
*
* @return \Dingo\Api\Http\Response
*/
public function index()
{
$taxes = Tax::collect();
return $this->response->paginator($taxes, new Transformer());
}
/**
* Display the specified resource.
*
* @param Tax $tax
* @return \Dingo\Api\Http\Response
*/
public function show(Tax $tax)
{
return $this->response->item($tax, new Transformer());
}
/**
* Store a newly created resource in storage.
*
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function store(Request $request)
{
$tax = Tax::create($request->all());
return $this->response->created(url('api/taxes/'.$tax->id));
}
/**
* Update the specified resource in storage.
*
* @param $tax
* @param $request
* @return \Dingo\Api\Http\Response
*/
public function update(Tax $tax, Request $request)
{
$tax->update($request->all());
return $this->response->item($tax->fresh(), new Transformer());
}
/**
* Remove the specified resource from storage.
*
* @param Tax $tax
* @return \Dingo\Api\Http\Response
*/
public function destroy(Tax $tax)
{
$tax->delete();
return $this->response->noContent();
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers;
use Dingo\Api\Exception\ResourceException;
use Illuminate\Http\Request;
class ApiController extends Controller
{
/**
* Create the response for when a request fails validation.
*
* @param \Illuminate\Http\Request $request
* @param array $errors
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function buildFailedValidationResponse(Request $request, array $errors)
{
if ($request->expectsJson()) {
throw new ResourceException('Validation Error', $errors);
}
return redirect()->to($this->getRedirectUrl())->withInput($request->input())->withErrors($errors, $this->errorBag());
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
class Forgot extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Where to redirect users after reset.
*
* @var string
*/
protected $redirectTo = 'auth/forgot';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Display the form to request a password reset link.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('auth.forgot.create');
}
/**
* Send a reset link to the given user.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{
$this->validateEmail($request);
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$response = $this->broker()->sendResetLink(
$request->only('email')
);
return $response == Password::RESET_LINK_SENT
? $this->sendResetLinkResponse($response)
: $this->sendResetLinkFailedResponse($request, $response);
}
/**
* Get the response for a successful password reset link.
*
* @param string $response
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendResetLinkResponse($response)
{
flash(trans($response))->success();
return redirect($this->redirectTo);
}
/**
* Get the response for a failed password reset link.
*
* @param \Illuminate\Http\Request
* @param string $response
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendResetLinkFailedResponse(Request $request, $response)
{
return redirect($this->redirectTo)->withErrors(
['email' => trans($response)]
);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class Login extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* @return void
*/
/*public function __construct()
{
$this->middleware('guest')->except('logout');
}*/
public function __construct()
{
$this->middleware('guest', ['except' => 'destroy']);
}
public function create()
{
return view('auth.login.create');
}
public function store()
{
if (!auth()->attempt(request(['email', 'password']))) {
flash('Please check your credentials and try again.')->error();
return back();
}
if (auth()->user()->customer) {
return redirect('/customers');
}
return redirect('/');
}
public function destroy()
{
auth()->logout();
return redirect('auth/login');
}
}

View File

@ -0,0 +1,102 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\Permission as Request;
use App\Models\Auth\Permission;
class Permissions extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$permissions = Permission::collect();
return view('auth.permissions.index', compact('permissions'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('auth.permissions.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Create permission
$permission = Permission::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.permissions', 1)]);
flash($message)->success();
return redirect('auth/permissions');
}
/**
* Show the form for editing the specified resource.
*
* @param Permission $permission
*
* @return Response
*/
public function edit(Permission $permission)
{
return view('auth.permissions.edit', compact('permission'));
}
/**
* Update the specified resource in storage.
*
* @param Permission $permission
* @param Request $request
*
* @return Response
*/
public function update(Permission $permission, Request $request)
{
// Update permission
$permission->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.permissions', 1)]);
flash($message)->success();
return redirect('auth/permissions');
}
/**
* Remove the specified resource from storage.
*
* @param Permission $permission
*
* @return Response
*/
public function destroy(Permission $permission)
{
$permission->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.permissions', 1)]);
flash($message)->success();
return redirect('auth/permissions');
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
class Reset extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
public $redirectTo = '/';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
public function create(Request $request, $token = null)
{
return view('auth.reset.create')->with(
['token' => $token, 'email' => $request->email]
);
}
public function store(Request $request)
{
$this->validate($request, $this->rules(), $this->validationErrorMessages());
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($response)
: $this->sendResetFailedResponse($request, $response);
}
/**
* Get the response for a successful password reset.
*
* @param string $response
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendResetResponse($response)
{
flash(trans($response))->success();
return redirect($this->redirectTo);
}
/**
* Get the response for a failed password reset.
*
* @param \Illuminate\Http\Request
* @param string $response
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendResetFailedResponse(Request $request, $response)
{
return redirect()->back()
->withInput($request->only('email'))
->withErrors(['email' => trans($response)]);
}
}

View File

@ -0,0 +1,116 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\Role as Request;
use App\Models\Auth\Permission;
use App\Models\Auth\Role;
class Roles extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$roles = Role::collect();
return view('auth.roles.index', compact('roles'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$permissions = Permission::all();
return view('auth.roles.create', compact('permissions'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Create role
$role = Role::create($request->all());
// Attach permissions
$role->permissions()->attach($request['permissions']);
$message = trans('messages.success.added', ['type' => trans_choice('general.roles', 1)]);
flash($message)->success();
return redirect('auth/roles');
}
/**
* Show the form for editing the specified resource.
*
* @param Role $role
*
* @return Response
*/
public function edit(Role $role)
{
//$permissions = Permission::all()->sortBy('display_name');
$permissions = Permission::all();
$rolePermissions = $role->permissions->pluck('id', 'id')->toArray();
return view('auth.roles.edit', compact('role', 'permissions', 'rolePermissions'));
}
/**
* Update the specified resource in storage.
*
* @param Role $role
* @param Request $request
*
* @return Response
*/
public function update(Role $role, Request $request)
{
// Update role
$role->update($request->all());
// Sync permissions
$role->permissions()->sync($request['permissions']);
$message = trans('messages.success.updated', ['type' => trans_choice('general.roles', 1)]);
flash($message)->success();
return redirect('auth/roles');
}
/**
* Remove the specified resource from storage.
*
* @param Role $role
*
* @return Response
*/
public function destroy(Role $role)
{
$role->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.roles', 1)]);
flash($message)->success();
return redirect('auth/roles');
}
}

View File

@ -0,0 +1,206 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\User as Request;
use App\Models\Auth\User;
use App\Models\Auth\Role;
use Auth;
class Users extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$users = User::with('roles')->collect();
$roles = collect(Role::all()->pluck('display_name', 'id'))
->prepend(trans('roles.all'), '');
return view('auth.users.index', compact('users', 'roles'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$roles = Role::all();
$companies = Auth::user()->companies()->get()->sortBy('name');
foreach ($companies as $company) {
$company->setSettings();
}
return view('auth.users.create', compact('roles', 'companies'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Upload picture
$picture = $request->file('picture');
if ($picture && $picture->isValid()) {
$request['picture'] = $picture->store('uploads/users');
}
// Create user
$user = User::create($request->input());
// Attach roles
$user->roles()->attach($request['roles']);
// Attach companies
$user->companies()->attach($request['companies']);
$message = trans('messages.success.added', ['type' => trans_choice('general.users', 1)]);
flash($message)->success();
return redirect('auth/users');
}
/**
* Show the form for editing the specified resource.
*
* @param User $user
*
* @return Response
*/
public function edit(User $user)
{
$roles = Role::all();
$companies = Auth::user()->companies()->get()->sortBy('name');
foreach ($companies as $company) {
$company->setSettings();
}
return view('auth.users.edit', compact('user', 'companies', 'roles'));
}
/**
* Update the specified resource in storage.
*
* @param User $user
* @param Request $request
*
* @return Response
*/
public function update(User $user, Request $request)
{
// Upload picture
$picture = $request->file('picture');
if ($picture && $picture->isValid()) {
$request['picture'] = $picture->store('uploads/users');
}
// Do not reset password if not entered/changed
if (empty($request['password'])) {
unset($request['password']);
unset($request['password_confirmation']);
}
// Update user
$user->update($request->input());
// Attach roles
$user->roles()->sync($request['roles']);
// Sync companies
$user->companies()->sync($request['companies']);
$message = trans('messages.success.updated', ['type' => trans_choice('general.users', 1)]);
flash($message)->success();
return redirect('auth/users');
}
/**
* Remove the specified resource from storage.
*
* @param User $user
*
* @return Response
*/
public function destroy(User $user)
{
// Can't delete yourself
if ($user->id == \Auth::user()->id) {
$message = trans('auth.error.self_delete');
flash($message)->error();
return redirect('auth/users');
}
$user->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.users', 1)]);
flash($message)->success();
return redirect('auth/users');
}
/**
* Mark upcoming bills notifications are read and redirect to bills page.
*
* @param User $user
*
* @return Response
*/
public function readUpcomingBills(User $user)
{
// Mark bill notifications as read
foreach ($user->unreadNotifications as $notification) {
// Not a bill notification
if ($notification->getAttribute('type') != 'App\Notifications\Expense\Bill') {
continue;
}
$notification->markAsRead();
}
// Redirect to bills
return redirect('expenses/bills');
}
/**
* Mark overdue invoices notifications are read and redirect to invoices page.
*
* @param User $user
*
* @return Response
*/
public function readOverdueInvoices(User $user)
{
// Mark invoice notifications as read
foreach ($user->unreadNotifications as $notification) {
// Not an invoice notification
if ($notification->getAttribute('type') != 'App\Notifications\Income\Invoice') {
continue;
}
$notification->markAsRead();
}
// Redirect to invoices
return redirect('incomes/invoices');
}
}

View File

@ -0,0 +1,145 @@
<?php
namespace App\Http\Controllers\Banking;
use App\Http\Controllers\Controller;
use App\Http\Requests\Banking\Account as Request;
use App\Models\Banking\Account;
use App\Models\Setting\Currency;
class Accounts extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$accounts = Account::collect();
return view('banking.accounts.index', compact('accounts'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$currencies = Currency::enabled()->pluck('name', 'code');
return view('banking.accounts.create', compact('currencies'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
$account = Account::create($request->all());
// Set default account
if ($request['default_account']) {
setting()->set('general.default_account', $account->id);
setting()->save();
}
$message = trans('messages.success.added', ['type' => trans_choice('general.accounts', 1)]);
flash($message)->success();
return redirect('banking/accounts');
}
/**
* Show the form for editing the specified resource.
*
* @param Account $account
*
* @return Response
*/
public function edit(Account $account)
{
$currencies = Currency::enabled()->pluck('name', 'code');
$account->default_account = ($account->id == setting('general.default_account')) ?: 1;
return view('banking.accounts.edit', compact('account', 'currencies'));
}
/**
* Update the specified resource in storage.
*
* @param Account $account
* @param Request $request
*
* @return Response
*/
public function update(Account $account, Request $request)
{
$account->update($request->all());
// Set default account
if ($request['default_account']) {
setting()->set('general.default_account', $account->id);
setting()->save();
}
$message = trans('messages.success.updated', ['type' => trans_choice('general.accounts', 1)]);
flash($message)->success();
return redirect('banking/accounts');
}
/**
* Remove the specified resource from storage.
*
* @param Account $account
*
* @return Response
*/
public function destroy(Account $account)
{
$canDelete = $account->canDelete();
if ($canDelete === true) {
$account->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.accounts', 1)]);
flash($message)->success();
} else {
$text = array();
if (isset($canDelete['bills'])) {
$text[] = '<b>' . $canDelete['bills'] . '</b> ' . trans_choice('general.bills', ($canDelete['bills'] > 1) ? 2 : 1);
}
if (isset($canDelete['payments'])) {
$text[] = '<b>' . $canDelete['payments'] . '</b> ' . trans_choice('general.payments', ($canDelete['payments'] > 1) ? 2 : 1);
}
if (isset($canDelete['invoices'])) {
$text[] = '<b>' . $canDelete['invoices'] . '</b> ' . trans_choice('general.invoices', ($canDelete['invoices'] > 1) ? 2 : 1);
}
if (isset($canDelete['revenues'])) {
$text[] = '<b>' . $canDelete['revenues'] . '</b> ' . trans_choice('general.revenues', ($canDelete['revenues'] > 1) ? 2 : 1);
}
$message = trans('messages.warning.deleted', ['type' => trans_choice('general.accounts', 1), 'text' => implode(', ', $text)]);
flash($message)->warning();
}
return redirect('banking/accounts');
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace App\Http\Controllers\Banking;
use App\Http\Controllers\Controller;
use App\Models\Banking\Transaction;
use App\Models\Expense\Payment;
use App\Models\Income\Revenue;
class Transactions extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
//$transactions = Transaction::index();
$request = request();
$payments = Payment::collect('paid_at');
$transactions = array();
foreach ($payments as $payment) {
$transactions[] = (object)[
'paid_at' => $payment->paid_at,
'account_name' => $payment->account->name,
'type' => trans_choice('general.expenses', 1),
'category_name' => $payment->category->name,
'description' => $payment->description,
'amount' => $payment->amount,
'currency_code' => $payment->currency_code,
];
}
$revenues = Revenue::collect('paid_at');
foreach ($revenues as $revenue) {
$transactions[] = (object)[
'paid_at' => $revenue->paid_at,
'account_name' => $revenue->account->name,
'type' => trans_choice('general.incomes', 1),
'category_name' => $revenue->category->name,
'description' => $revenue->description,
'amount' => $revenue->amount,
'currency_code' => $revenue->currency_code,
];
}
$special_key = array(
'account.name' => 'account_name',
'category.name' => 'category_name',
);
if (isset($request['sort']) && array_key_exists($request['sort'], $special_key)) {
$sort_order = array();
foreach ($transactions as $key => $value) {
$sort = $request['sort'];
if (array_key_exists($request['sort'], $special_key)) {
$sort = $special_key[$request['sort']];
}
$sort_order[$key] = $value->{$sort};
}
$sort_type = (isset($request['order']) && $request['order'] == 'asc') ? SORT_ASC : SORT_DESC;
array_multisort($sort_order, $sort_type, $transactions);
}
$transactions = (object) $transactions;
return view('banking.transactions.index', compact('transactions'));
}
}

View File

@ -0,0 +1,263 @@
<?php
namespace App\Http\Controllers\Banking;
use App\Http\Controllers\Controller;
use App\Http\Requests\Banking\Transfer as Request;
use App\Models\Banking\Account;
use App\Models\Banking\Transfer;
use App\Models\Expense\Payment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
class Transfers extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$request = request();
$items = Transfer::with(['payment', 'revenue', 'account'])->collect('payment.paid_at');
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('accounts.all'), '');
$transfers = array();
foreach ($items as $item) {
$payment = $item->payment;
$revenue = $item->revenue;
$transfers[] = (object)[
'from_account' => $payment->account->name,
'to_account' => $revenue->account->name,
'amount' => $payment->amount,
'currency_code' => $payment->currency_code,
'paid_at' => $payment->paid_at,
];
}
$special_key = array(
'payment.name' => 'from_account',
'revenue.name' => 'to_account',
);
if (isset($request['sort']) && array_key_exists($request['sort'], $special_key)) {
$sort_order = array();
foreach ($transfers as $key => $value) {
$sort = $request['sort'];
if (array_key_exists($request['sort'], $special_key)) {
$sort = $special_key[$request['sort']];
}
$sort_order[$key] = $value->{$sort};
}
$sort_type = (isset($request['order']) && $request['order'] == 'asc') ? SORT_ASC : SORT_DESC;
array_multisort($sort_order, $sort_type, $transfers);
}
return view('banking.transfers.index', compact('transfers', 'items', 'accounts'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$accounts = Account::enabled()->pluck('name', 'id');
return view('banking.transfers.create', compact('accounts'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
$currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
$payment_currency_code = Account::where('id', $request['from_account_id'])->pluck('currency_code')->first();
$revenue_currency_code = Account::where('id', $request['to_account_id'])->pluck('currency_code')->first();
$request['account_id'] = $request['from_account_id'];
$request['paid_at'] = $request['transferred_at'];
// amount
$request['currency_code'] = $payment_currency_code;
$request['currency_rate'] = $currencies[$payment_currency_code];
$request['vendor_id'] = '0';
// description
$request['category_id'] = Category::enabled()->type('other')->pluck('id')->first(); // Transfer Category ID
// payment_method
// reference
$request['attachment'] = '';
$payment = Payment::create($request->all());
$transfer = new Transfer();
$transfer->default_currency_code = $payment_currency_code;
$transfer->amount = $request['amount'];
$transfer->currency_code = $revenue_currency_code;
$transfer->currency_rate = $currencies[$revenue_currency_code];
$amount = $transfer->getDynamicConvertedAmount();
$request['account_id'] = $request['to_account_id'];
// paid_at
$request['amount'] = $amount;
$request['currency_code'] = $revenue_currency_code;
$request['currency_rate'] = $currencies[$revenue_currency_code];
$request['customer_id'] = '0';
// description
// category_id
// payment_method
// reference
// attachment
$revenue = Revenue::create($request->all());
$request['payment_id'] = $payment->id;
$request['revenue_id'] = $revenue->id;
Transfer::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.transfers', 1)]);
flash($message)->success();
return redirect('banking/transfers');
}
/**
* Show the form for editing the specified resource.
*
* @param Request $request
*
* @return Response
*/
public function edit(Request $request)
{
$payment = Payment::findOrFail($request['payment_id']);
$revenue = Revenue::findOrFail($request['revenue_id']);
$transfer['from_account_id'] = $payment->account_id;
$transfer['to_account_id'] = $revenue->account_id;
$transfer['transferred_at'] = $revenue->deposited_at;
$transfer['description'] = $revenue->description;
$transfer['amount'] = $revenue->amount;
$transfer['payment_method'] = $revenue->payment_method;
$transfer['reference'] = $revenue->reference;
$accounts = Account::listArray();
return view('banking.transfers.edit', compact('transfer', 'accounts'));
}
/**
* Update the specified resource in storage.
*
* @param Transfer $transfer
* @param Request $request
*
* @return Response
*/
public function update(Transfer $transfer, Request $request)
{
$currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
$payment_currency_code = Account::where('id', $request['from_account_id'])->pluck('currency_code')->first();
$revenue_currency_code = Account::where('id', $request['to_account_id'])->pluck('currency_code')->first();
$payment = Payment::findOrFail($transfer->payment_id);
$request['account_id'] = $request['from_account_id'];
$request['paid_at'] = $request['transferred_at'];
// amount
$request['currency_code'] = $payment_currency_code;
$request['currency_rate'] = $currencies[$payment_currency_code];
$request['vendor_id'] = '0';
// description
$request['category_id'] = Category::enabled()->type('other')->pluck('id')->first(); // Transfer Category ID
// payment_method
// reference
$request['attachment'] = '';
$payment->update($request->all());
$revenue = Revenue::findOrFail($transfer->income_id);
$transfer = new Transfer();
$transfer->default_currency_code = $payment_currency_code;
$transfer->amount = $request['amount'];
$transfer->currency_code = $revenue_currency_code;
$transfer->currency_rate = $currencies[$revenue_currency_code];
$amount = $transfer->getDynamicConvertedAmount();
$request['account_id'] = $request['to_account_id'];
// paid_at
$request['amount'] = $amount;
$request['currency_code'] = $revenue_currency_code;
$request['currency_rate'] = $currencies[$revenue_currency_code];
$request['customer_id'] = '0';
// description
// category_id
// payment_method
// reference
// attachment
$revenue->update($request->all());
$request['payment_id'] = $payment->id;
$request['revenue_id'] = $revenue->id;
$transfer->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.transfers', 1)]);
flash($message)->success();
return redirect('banking/transfers');
}
/**
* Remove the specified resource from storage.
*
* @param Transfer $transfer
*
* @return Response
*/
public function destroy(Transfer $transfer)
{
$payment = Payment::findOrFail($transfer['payment_id']);
$revenue = Revenue::findOrFail($transfer['revenue_id']);
$transfer->delete();
$payment->delete();
$revenue->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.transfers', 1)]);
flash($message)->success();
return redirect('banking/transfers');
}
}

View File

@ -0,0 +1,228 @@
<?php
namespace App\Http\Controllers\Companies;
use App\Http\Controllers\Controller;
use App\Http\Requests\Company\Company as Request;
use App\Models\Company\Company;
use App\Models\Setting\Currency;
use App\Traits\Uploads;
use Auth;
use Redirect;
use Setting;
class Companies extends Controller
{
use Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$companies = Auth::user()->companies()->get()->sortBy('name');
foreach ($companies as $company) {
$company->setSettings();
}
return view('companies.companies.index', compact('companies'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$currencies = Currency::enabled()->pluck('name', 'code');
return view('companies.companies.create', compact('currencies'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
Setting::forgetAll();
// Create company
$company = Company::create(['domain' => $request->get('domain')]);
// Create settings
Setting::set('general.company_name', $request->get('company_name'));
Setting::set('general.company_email', $request->get('company_email'));
Setting::set('general.company_address', $request->get('company_address'));
$logo_path = $this->getUploadedFilePath($request->file('company_logo'), 'settings', $company->id);
if ($logo_path) {
Setting::set('general.company_logo', $logo_path);
}
Setting::set('general.default_currency', $request->get('default_currency'));
Setting::set('general.default_locale', session('locale'));
Setting::setExtraColumns(['company_id' => $company->id]);
Setting::save();
// Redirect
$message = trans('messages.success.added', ['type' => trans_choice('general.companies', 1)]);
flash($message)->success();
return redirect('companies/companies');
}
/**
* Show the form for editing the specified resource.
*
* @param Company $company
*
* @return Response
*/
public function edit(Company $company)
{
// Check if user can edit company
$this->authorizeUserOrRedirect($company);
$company->setSettings();
$currencies = Currency::enabled()->pluck('name', 'code');
return view('companies.companies.edit', compact('company', 'currencies'));
}
/**
* Update the specified resource in storage.
*
* @param Company $company
* @param Request $request
*
* @return Response
*/
public function update(Company $company, Request $request)
{
// Check if user can update company
$this->authorizeUserOrRedirect($company);
// Update company
$company->update(['domain' => $request->get('domain')]);
// Get the company settings
Setting::forgetAll();
Setting::setExtraColumns(['company_id' => $company->id]);
Setting::load(true);
// Update settings
Setting::set('general.company_name', $request->get('company_name'));
Setting::set('general.company_email', $request->get('company_email'));
Setting::set('general.company_address', $request->get('company_address'));
$logo_path = $this->getUploadedFilePath($request->file('company_logo'), 'settings', $company->id);
if ($logo_path) {
Setting::set('general.company_logo', $logo_path);
}
Setting::set('general.default_payment_method', 'cash');
Setting::set('general.default_currency', $request->get('default_currency'));
Setting::save();
// Redirect
$message = trans('messages.success.updated', ['type' => trans_choice('general.companies', 1)]);
flash($message)->success();
return redirect('companies/companies');
}
/**
* Remove the specified resource from storage.
*
* @param Company $company
*
* @return Response
*/
public function destroy(Company $company)
{
// Can't delete active company
if ($company->id == session('company_id')) {
$message = trans('companies.error.delete_active');
flash($message)->error();
return redirect('companies/companies');
}
$company->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.companies', 1)]);
flash($message)->success();
return redirect('companies/companies');
}
/**
* Change the active company.
*
* @param Company $company
*
* @return Response
*/
public function set(Company $company)
{
// Check if user can manage company
if ($this->isUserCompany($company)) {
session(['company_id' => $company->id]);
}
//return redirect('/');
return redirect()->back();
}
/**
* Check user company assignment
*
* @param Company $company
*
* @return boolean
*/
public function isUserCompany(Company $company)
{
$companies = Auth::user()->companies()->pluck('id')->toArray();
if (in_array($company->id, $companies)) {
return true;
}
return false;
}
/**
* Check user company permission and redirect if not
*
* @param Company $company
*
* @return boolean
*/
public function authorizeUserOrRedirect(Company $company)
{
if ($this->isUserCompany($company)) {
return true;
}
$message = trans('companies.error.not_user_company');
flash($message)->error();
Redirect::away(url('companies/companies'))->send();
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Route;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
/**
* Instantiate a new controller instance.
*
* @param Route $route
*/
public function __construct(Route $route)
{
// Get the controller array
$arr = array_reverse(explode('\\', explode('@', $route->getAction()['uses'])[0]));
$controller = '';
// Add folder
if ($arr[1] != 'controllers') {
$controller .= kebab_case($arr[1]) . '-';
}
// Add file
$controller .= kebab_case($arr[0]);
// Skip ACL
$skip = ['dashboard-dashboard'];
if (in_array($controller, $skip)) {
return;
}
// Add CRUD permission check
$this->middleware('permission:create-' . $controller)->only(['create', 'store']);
$this->middleware('permission:read-' . $controller)->only(['index', 'show', 'edit']);
$this->middleware('permission:update-' . $controller)->only(['update']);
$this->middleware('permission:delete-' . $controller)->only('destroy');
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Http\Controllers\Customers;
use App\Http\Controllers\Controller;
use Auth;
class Dashboard extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$user = Auth::user()->customer;
return view('customers.dashboard.index', compact('user'));
}
}

View File

@ -0,0 +1,215 @@
<?php
namespace App\Http\Controllers\Customers;
use App\Http\Controllers\Controller;
use App\Http\Requests\Income\InvoicePayment as PaymentRequest;
use App\Models\Banking\Account;
use App\Models\Income\Customer;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceStatus;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoicePayment;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use Auth;
use Jenssegers\Date\Date;
use App\Utilities\Modules;
class Invoices extends Controller
{
use DateTime, Currencies, Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$invoices = Invoice::with('status')->where('customer_id', '=', Auth::user()->customer->id)->paginate();
foreach ($invoices as $invoice) {
$paid = 0;
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->amount = $invoice->amount - $paid;
}
$status = collect(InvoiceStatus::all()->pluck('name', 'code'))
->prepend(trans('general.all_statuses'), '');
return view('customers.invoices.index', compact('invoices', 'status'));
}
/**
* Show the form for viewing the specified resource.
*
* @param Invoice $invoice
*
* @return Response
*/
public function show(Invoice $invoice)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
foreach ($invoice->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->sub_total = $sub_total;
$invoice->tax_total = $tax_total;
$invoice->paid = $paid;
$invoice->grand_total = (($sub_total + $tax_total) - $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();
return view('customers.invoices.show', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
}
/**
* Show the form for viewing the specified resource.
*
* @param int $invoice_id
*
* @return Response
*/
public function printInvoice($invoice_id)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
$invoice = Invoice::where('id', $invoice_id)->first();
foreach ($invoice->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->sub_total = $sub_total;
$invoice->tax_total = $tax_total;
$invoice->paid = $paid;
$invoice->grand_total = (($sub_total + $tax_total) - $paid);
return view('customers.invoices.invoice', compact('invoice'));
}
/**
* Show the form for viewing the specified resource.
*
* @param int $invoice_id
*
* @return Response
*/
public function pdfInvoice($invoice_id)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
$invoice = Invoice::where('id', $invoice_id)->first();
foreach ($invoice->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->sub_total = $sub_total;
$invoice->tax_total = $tax_total;
$invoice->paid = $paid;
$invoice->grand_total = (($sub_total + $tax_total) - $paid);
$html = view('incomes.invoices.invoice', compact('invoice'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($html);
$file_name = 'invoice_'.time().'.pdf';
return $pdf->download($file_name);
}
/**
* Show the form for viewing the specified resource.
*
* @param PaymentRequest $request
*
* @return Response
*/
public function payment(PaymentRequest $request)
{
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'revenues');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$invoice = Invoice::find($request['invoice_id']);
$invoice->invoice_status_code = 'partial';
$invoice->save();
$invoice_payment = InvoicePayment::create($request->input());
$request['status_code'] = 'partial';
$request['notify'] = 0;
$desc_date = Date::parse($request['paid_at'])->format($this->getCompanyDateFormat());
$desc_amount = money((float) $request['amount'], $request['currency_code'], true)->format();
$request['description'] = $desc_date . ' ' . $desc_amount;
InvoiceHistory::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.revenues', 1)]);
return response()->json($message);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers\Customers;
use App\Http\Controllers\Controller;
use App\Models\Income\Revenue as Payment;
use App\Models\Setting\Category;
use App\Models\Banking\Account;
use App\Utilities\Modules;
use Auth;
class Payments extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$payments = Payment::with('account', 'category')->where('customer_id', '=', Auth::user()->customer->id)->paginate();
$payment_methods = Modules::getPaymentMethods();
$categories = collect(Category::enabled()->type('income')->pluck('name', 'id'))
->prepend(trans('categories.all'), '');
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('accounts.all'), '');
return view('customers.payments.index', compact('payments', 'payment_methods', 'categories', 'accounts'));
}
/**
* Show the form for viewing the specified resource.
*
* @param Payment $payment
*
* @return Response
*/
public function show(Payment $payment)
{
$payment_methods = Modules::getPaymentMethods();
return view('customers.payments.show', compact('payment', 'payment_methods'));
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers\Customers;
use App\Http\Controllers\Controller;
use App\Models\Banking\Transaction;
use Auth;
class Transactions extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$transactions = Transaction::getUserTransactions(Auth::user()->customer->id, 'revenues');
return view('customers.transactions.index', compact('transactions'));
}
}

View File

@ -0,0 +1,396 @@
<?php
namespace App\Http\Controllers\Dashboard;
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\Income\Invoice;
use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use App\Traits\Currencies;
use Date;
class Dashboard extends Controller
{
use Currencies;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
/*
* Cash Flow
*/
// Daily
$day = array();
for ($j = 31; $j > -1; $j--) {
$day[31 - $j] = date("d M", strtotime("-$j day"));
}
$daily_income = $this->getCashFlow('income', 'daily');
$daily_expense = $this->getCashFlow('expense', 'daily');
$daily_profit = $this->getProfit($daily_income, $daily_expense);
// Monthly
$month = array();
for ($j = 12; $j >= 0; $j--) {
$month[12 - $j] = date("F-Y", strtotime(" -$j month"));
}
$monthly_income = $this->getCashFlow('income', 'monthly');
$monthly_expense = $this->getCashFlow('expense', 'monthly');
$monthly_profit = $this->getProfit($monthly_income, $monthly_expense);
$cash_flow = [
'daily' => [
'date' => json_encode($day),
'income' => json_encode(array_values($daily_income)),
'expense' => json_encode(array_values($daily_expense)),
'profit' => json_encode(array_values($daily_profit))
],
'monthly' => [
'date' => json_encode($month),
'income' => json_encode(array_values($monthly_income)),
'expense' => json_encode(array_values($monthly_expense)),
'profit' => json_encode(array_values($monthly_profit))
],
];
/*
* Totals & Pie Charts
*/
$incomes = $expenses = array();
$incomes_amount = $expenses_amount = 0;
$open_invoice = $overdue_invoice = 0;
$open_bill = $overdue_bill = 0;
$invoice_paid_amount = $bill_paid_amount = 0;
$today = Date::today()->toDateString();
// Invoices
$invoices = Invoice::with('payments')->get();
foreach ($invoices as $invoice) {
$invoice_payments = 0;
foreach ($invoice->payments as $payment) {
$invoice_payments += $payment->getConvertedAmount();
}
$invoice_paid_amount += $invoice_payments;
// Check if it's open or overdue invoice
if ($invoice->due_at > $today) {
$open_invoice += $invoice->getConvertedAmount() - $invoice_payments;
} else {
$overdue_invoice += $invoice->getConvertedAmount() - $invoice_payments;
}
}
$incomes_amount += $invoice_paid_amount;
// Bills
$bills = Bill::with('payments')->get();
foreach ($bills as $bill) {
$bill_payments = 0;
foreach ($bill->payments as $payment) {
$bill_payments += $payment->getConvertedAmount();
}
$bill_paid_amount += $bill_payments;
// Check if it's open or overdue bill
if ($bill->due_at > $today) {
$open_bill += $bill->getConvertedAmount() - $bill_payments;
} else {
$overdue_bill += $bill->getConvertedAmount() - $bill_payments;
}
}
$expenses_amount += $bill_paid_amount;
// Add to Incomes By Category
$incomes[] = array(
'amount' => money($invoice_paid_amount, setting('general.default_currency'), true)->format(),
'value' => (int) $invoice_paid_amount,
'color' => '#00c0ef',
'highlight' => '#00c0ef',
'label' => trans_choice('general.invoices', 2)
);
// Add to Expenses By Category
$expenses[] = array(
'amount' => money($bill_paid_amount, setting('general.default_currency'), true)->format(),
'value' => (int) $bill_paid_amount,
'color' => '#dd4b39',
'highlight' => '#dd4b39',
'label' => trans_choice('general.bills', 2)
);
// Revenues & Payments
$categories = Category::orWhere('type', 'income')->orWhere('type', 'expense')->enabled()->get();
foreach ($categories as $category) {
switch ($category->type) {
case 'income':
$revenues = $category->revenues;
$amount = 0;
if ($revenues) {
foreach ($revenues as $revenue) {
$amount += $revenue->getConvertedAmount();
}
$incomes[] = array(
'amount' => money($amount, setting('general.default_currency'), true)->format(),
'value' => (int) $amount,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
} else {
$incomes[] = array(
'amount' => money(0, setting('general.default_currency'), true)->format(),
'value' => (int) 0,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
}
$incomes_amount += $amount;
break;
case 'expense':
$payments = $category->payments;
$amount = 0;
if ($payments) {
foreach ($payments as $payment) {
$amount += $payment->getConvertedAmount();
}
$expenses[] = array(
'amount' => money($amount, setting('general.default_currency'), true)->format(),
'value' => (int) $amount,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
} else {
$expenses[] = array(
'amount' => money(0, setting('general.default_currency'), true)->format(),
'value' => (int) 0,
'color' => $category->color,
'highlight' => $category->color,
'label' => $category->name
);
}
$expenses_amount += $amount;
break;
}
}
if (empty($incomes_amount)) {
foreach ($incomes as $key => $income) {
$incomes[$key]['amount'] = money(0, setting('general.default_currency'), true)->format();
$incomes[$key]['value'] = (int) 100 / count($incomes);
}
}
// Incomes Pie Chart
$income_graph = json_encode($incomes);
if (empty($expenses_amount)) {
foreach ($expenses as $key => $expense) {
$expenses[$key]['amount'] = money(0, setting('general.default_currency'), true)->format();
$expenses[$key]['value'] = (int) 100 / count($expenses);
}
}
// Expenses Pie Chart
$expense_graph = json_encode($expenses);
$incomes_progress = 100;
if (!empty($open_invoice) && !empty($overdue_invoice)) {
$incomes_progress = (int) 100 - (100 * ($open_invoice / $overdue_invoice));
}
// Totals
$total_incomes = array(
'total' => $incomes_amount,
'open_invoice' => money($open_invoice, setting('general.default_currency'), true),
'overdue_invoice' => money($overdue_invoice, setting('general.default_currency'), true),
'progress' => $incomes_progress
);
$expenses_progress = 100;
if (!empty($open_bill) && !empty($overdue_bill)) {
$expenses_progress = (int) 100 - (100 * ($open_bill / $overdue_bill));
}
$total_expenses = array(
'total' => $expenses_amount,
'open_bill' => money($open_bill, setting('general.default_currency'), true),
'overdue_bill' => money($overdue_bill, setting('general.default_currency'), true),
'progress' => $expenses_progress
);
$amount_profit = $incomes_amount - $expenses_amount;
$open_profit = $open_invoice - $open_bill;
$overdue_profit = $overdue_invoice - $overdue_bill;
$total_progress = 100;
if (!empty($open_profit) && !empty($overdue_profit)) {
$total_progress = (int) 100 - (100 * ($open_profit / $overdue_profit));
}
$total_profit = array(
'total' => $amount_profit,
'open' => money($open_profit, setting('general.default_currency'), true),
'overdue' => money($overdue_profit, setting('general.default_currency'), true),
'progress' => $total_progress
);
/*
* Accounts
*/
$accounts = Account::enabled()->get();
/*
* Latest Incomes
*/
$latest_incomes = collect(InvoicePayment::latest()->take(5)->get());
$latest_incomes = $latest_incomes->merge(Revenue::latest()->take(5)->get())->sortByDesc('paid_at');
/*
* Latest Expenses
*/
$latest_expenses = collect(BillPayment::latest()->take(5)->get());
$latest_expenses = $latest_expenses->merge(Payment::latest()->take(5)->get())->sortByDesc('paid_at');
return view('dashboard.dashboard.index', compact(
'total_incomes',
'total_expenses',
'total_profit',
'cash_flow',
'incomes',
'incomes_amount',
'income_graph',
'expenses',
'expenses_amount',
'expense_graph',
'accounts',
'latest_incomes',
'latest_expenses'
));
}
private function getCashFlow($type, $period)
{
$totals = array();
if ($type == 'income') {
$m1 = '\App\Models\Income\Revenue';
$m2 = '\App\Models\Income\InvoicePayment';
} else {
$m1 = '\App\Models\Expense\Payment';
$m2 = '\App\Models\Expense\BillPayment';
}
switch ($period) {
case 'yearly':
$f1 = 'subYear';
$f2 = 'addYear';
$date_format = 'Y';
break;
case 'monthly':
$f1 = 'subYear';
$f2 = 'addMonth';
$date_format = 'Y-m';
break;
default:
case 'daily':
$f1 = 'subMonth';
$f2 = 'addDay';
$date_format = 'Y-m-d';
break;
}
$now = Date::now();
$sub = Date::now()->$f1();
$start_date = $sub->format($date_format);
$end_date = $now->format($date_format);
$next_date = $start_date;
$totals[$start_date] = 0;
do {
$next_date = Date::parse($next_date)->$f2()->format($date_format);
$totals[$next_date] = 0;
} while ($next_date < $end_date);
$items_1 = $m1::whereBetween('paid_at', [$sub, $now])->get();
$this->setTotals($totals, $items_1, $date_format);
$items_2 = $m2::whereBetween('paid_at', [$sub, $now])->get();
$this->setTotals($totals, $items_2, $date_format);
return $totals;
}
private function setTotals(&$totals, $items, $date_format)
{
foreach ($items as $item) {
$i = Date::parse($item->paid_at)->format($date_format);
$totals[$i] += $item->getConvertedAmount();
}
}
private function getProfit($incomes, $expenses)
{
$profit = [];
foreach ($incomes as $key => $income) {
if ($income > 0 && $income > $expenses[$key]) {
$profit[$key] = $income - $expenses[$key];
} else {
$profit[$key] = 0;
}
}
return $profit;
}
}

View File

@ -0,0 +1,503 @@
<?php
namespace App\Http\Controllers\Expenses;
use App\Events\BillCreated;
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\Models\Banking\Account;
use App\Models\Expense\BillStatus;
use App\Models\Expense\Vendor;
use App\Models\Expense\Bill;
use App\Models\Expense\BillHistory;
use App\Models\Expense\BillItem;
use App\Models\Expense\BillPayment;
use App\Models\Item\Item;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use Jenssegers\Date\Date;
use App\Utilities\Modules;
class Bills extends Controller
{
use DateTime, Currencies, Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$bills = Bill::with('bill_statuses')->collect();
$status = collect(BillStatus::all()->pluck('name', 'code'))
->prepend(trans('general.all_statuses'), '');
return view('expenses.bills.index', compact('bills', 'status'));
}
/**
* Show the form for viewing the specified resource.
*
* @param Bill $bill
*
* @return Response
*/
public function show(Bill $bill)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
foreach ($bill->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($bill->payments as $item) {
$item->default_currency_code = $bill->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$bill->sub_total = $sub_total;
$bill->tax_total = $tax_total;
$bill->paid = $paid;
$bill->grand_total = (($sub_total + $tax_total) - $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();
$vendors = Vendor::enabled()->pluck('name', 'id');
$categories = Category::enabled()->type('income')->pluck('name', 'id');
$payment_methods = Modules::getPaymentMethods();
return view('expenses.bills.show', compact('bill', 'accounts', 'currencies', 'account_currency_code', 'vendors', 'categories', 'payment_methods'));
}
/**
* Show the form for viewing the specified resource.
*
* @param int $bill_id
*
* @return Response
*/
public function printBill($bill_id)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
$bill = Bill::where('id', $bill_id)->first();
foreach ($bill->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($bill->payments as $item) {
$item->default_currency_code = $bill->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$bill->sub_total = $sub_total;
$bill->tax_total = $tax_total;
$bill->paid = $paid;
$bill->grand_total = (($sub_total + $tax_total) - $paid);
return view('expenses.bills.bill', compact('bill'));
}
/**
* Show the form for viewing the specified resource.
*
* @param int $bill_id
*
* @return Response
*/
public function pdfBill($bill_id)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
$bill = Bill::where('id', $bill_id)->first();
foreach ($bill->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($bill->payments as $item) {
$item->default_currency_code = $bill->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$bill->sub_total = $sub_total;
$bill->tax_total = $tax_total;
$bill->paid = $paid;
$bill->grand_total = (($sub_total + $tax_total) - $paid);
$html = view('expenses.bills.bill', compact('bill'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($html);
$file_name = 'bill_'.time().'.pdf';
return $pdf->download($file_name);
}
/**
* Show the form for viewing the specified resource.
*
* @param PaymentRequest $request
*
* @return Response
*/
public function payment(PaymentRequest $request)
{
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'revenues');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$bill = Bill::find($request['bill_id']);
if ($request['currency_code'] == $bill->currency_code) {
if ($request['amount'] > $bill->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
return response()->json($message);
} elseif ($request['amount'] == $bill->amount) {
$bill->bill_status_code = 'paid';
} else {
$bill->bill_status_code = 'partial';
}
} else {
$request_bill = new Bill();
$request_bill->amount = (float) $request['amount'];
$request_bill->currency_code = $currency->code;
$request_bill->currency_rate = $currency->rate;
$amount = $request_bill->getConvertedAmount();
if ($amount > $bill->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
return response()->json($message);
} elseif ($amount == $bill->amount) {
$bill->bill_status_code = 'paid';
} else {
$bill->bill_status_code = 'partial';
}
}
$bill->save();
$bill_payment = BillPayment::create($request->input());
$request['status_code'] = $bill->bill_status_code;
$request['notify'] = 0;
$desc_date = Date::parse($request['paid_at'])->format($this->getCompanyDateFormat());
$desc_amount = money((float) $request['amount'], $request['currency_code'], true)->format();
$request['description'] = $desc_date . ' ' . $desc_amount;
BillHistory::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.revenues', 1)]);
return response()->json($message);
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$vendors = Vendor::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code');
$items = Item::enabled()->pluck('name', 'id');
$taxes = Tax::enabled()->pluck('name', 'id');
return view('expenses.bills.create', compact('vendors', 'currencies', 'items', 'taxes'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Get vendor object
$vendor = Vendor::findOrFail($request['vendor_id']);
$request['vendor_name'] = $vendor->name;
$request['vendor_email'] = $vendor->email;
$request['vendor_tax_number'] = $vendor->tax_number;
$request['vendor_phone'] = $vendor->phone;
$request['vendor_address'] = $vendor->address;
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
$request['bill_status_code'] = 'new';
$request['amount'] = 0;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'bills');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$bill = Bill::create($request->input());
$bill_item = array();
$bill_item['company_id'] = $request['company_id'];
$bill_item['bill_id'] = $bill->id;
if ($request['item']) {
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = $item['name'];
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
$bill_item['tax'] = (($item['price'] * $item['quantity']) / 100) * $tax_rate;
$bill_item['tax_id'] = $tax_id;
$bill_item['total'] = ($item['price'] + $bill_item['tax']) * $item['quantity'];
$request['amount'] += $bill_item['total'];
BillItem::create($bill_item);
}
}
$bill->update($request->input());
$request['bill_id'] = $bill->id;
$request['status_code'] = 'new';
$request['notify'] = 0;
$request['description'] = trans('messages.success.added', ['type' => $request['bill_number']]);
BillHistory::create($request->input());
// Fire the event to make it extendible
event(new BillCreated($bill));
$message = trans('messages.success.added', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
return redirect('expenses/bills/' . $bill->id);
}
/**
* Show the form for editing the specified resource.
*
* @param Bill $bill
*
* @return Response
*/
public function edit(Bill $bill)
{
$vendors = Vendor::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code');
$items = Item::enabled()->pluck('name', 'id');
$taxes = Tax::enabled()->pluck('name', 'id');
return view('expenses.bills.edit', compact('bill', 'vendors', 'currencies', 'items', 'taxes'));
}
/**
* Update the specified resource in storage.
*
* @param Bill $bill
* @param Request $request
*
* @return Response
*/
public function update(Bill $bill, Request $request)
{
// Get vendor object
$vendor = Vendor::findOrFail($request['vendor_id']);
$request['vendor_name'] = $vendor->name;
$request['vendor_email'] = $vendor->email;
$request['vendor_tax_number'] = $vendor->tax_number;
$request['vendor_phone'] = $vendor->phone;
$request['vendor_address'] = $vendor->address;
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
$request['bill_status_code'] = 'updated';
$request['amount'] = 0;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'bills');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$bill_item = array();
$bill_item['company_id'] = $request['company_id'];
$bill_item['bill_id'] = $bill->id;
if ($request['item']) {
BillItem::where('bill_id', $bill->id)->delete();
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$bill_item['item_id'] = $item['item_id'];
$bill_item['name'] = $item['name'];
$bill_item['sku'] = $item_sku;
$bill_item['quantity'] = $item['quantity'];
$bill_item['price'] = $item['price'];
$bill_item['tax'] = (($item['price'] * $item['quantity']) / 100) * $tax_rate;
$bill_item['tax_id'] = $tax_id;
$bill_item['total'] = ($item['price'] + $bill_item['tax']) * $item['quantity'];
$request['amount'] += $bill_item['total'];
BillItem::create($bill_item);
}
}
$bill->update($request->input());
// Fire the event to make it extendible
event(new BillUpdated($bill));
$message = trans('messages.success.updated', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
return redirect('expenses/bills/' . $bill->id);
}
/**
* Remove the specified resource from storage.
*
* @param Bill $bill
*
* @return Response
*/
public function destroy(Bill $bill)
{
$bill->delete();
/*
$bill->items->delete();
$bill->payments->delete();
$bill->histories->delete();
*/
BillItem::where('bill_id', $bill->id)->delete();
BillPayment::where('bill_id', $bill->id)->delete();
BillHistory::where('bill_id', $bill->id)->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
return redirect('expenses/bills');
}
/**
* Remove the specified resource from storage.
*
* @param BillPayment $payment
*
* @return Response
*/
public function paymentDestroy(BillPayment $payment)
{
$payment->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
return redirect('expenses/bills');
}
}

View File

@ -0,0 +1,156 @@
<?php
namespace App\Http\Controllers\Expenses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Expense\Payment as Request;
use App\Models\Banking\Account;
use App\Models\Expense\Payment;
use App\Models\Expense\Vendor;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Traits\Uploads;
class Payments extends Controller
{
use Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$payments = Payment::with('account', 'category')->collect();
$categories = collect(Category::enabled()->type('expense')->pluck('name', 'id'))
->prepend(trans('categories.all'), '');
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('accounts.all'), '');
return view('expenses.payments.index', compact('payments', 'categories', 'accounts'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$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();
$vendors = Vendor::enabled()->pluck('name', 'id');
$categories = Category::enabled()->type('expense')->pluck('name', 'id');
return view('expenses.payments.create', compact('accounts', 'currencies', 'account_currency_code', 'vendors', 'categories'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'payments');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
Payment::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.payments', 1)]);
flash($message)->success();
return redirect('expenses/payments');
}
/**
* Show the form for editing the specified resource.
*
* @param Payment $payment
*
* @return Response
*/
public function edit(Payment $payment)
{
$accounts = Account::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code')->toArray();
$account_currency_code = Account::where('id', $payment->account_id)->pluck('currency_code')->first();
$vendors = Vendor::enabled()->pluck('name', 'id');
$categories = Category::enabled()->type('expense')->pluck('name', 'id');
return view('expenses.payments.edit', compact('payment', 'accounts', 'currencies', 'account_currency_code', 'vendors', 'categories'));
}
/**
* Update the specified resource in storage.
*
* @param Payment $payment
* @param Request $request
*
* @return Response
*/
public function update(Payment $payment, Request $request)
{
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'payments');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$payment->update($request->input());
$message = trans('messages.success.updated', ['type' => trans_choice('general.payments', 1)]);
flash($message)->success();
return redirect('expenses/payments');
}
/**
* Remove the specified resource from storage.
*
* @param Payment $payment
*
* @return Response
*/
public function destroy(Payment $payment)
{
$payment->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.payments', 1)]);
flash($message)->success();
return redirect('expenses/payments');
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace App\Http\Controllers\Expenses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Expense\Vendor as Request;
use App\Models\Expense\Vendor;
use App\Models\Setting\Currency;
class Vendors extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$vendors = Vendor::collect();
return view('expenses.vendors.index', compact('vendors'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$currencies = Currency::enabled()->pluck('name', 'code');
return view('expenses.vendors.create', compact('currencies'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
Vendor::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.vendors', 1)]);
flash($message)->success();
return redirect('expenses/vendors');
}
/**
* Show the form for editing the specified resource.
*
* @param Vendor $vendor
*
* @return Response
*/
public function edit(Vendor $vendor)
{
$currencies = Currency::enabled()->pluck('name', 'code');
return view('expenses.vendors.edit', compact('vendor', 'currencies'));
}
/**
* Update the specified resource in storage.
*
* @param Vendor $vendor
* @param Request $request
*
* @return Response
*/
public function update(Vendor $vendor, Request $request)
{
$vendor->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.vendors', 1)]);
flash($message)->success();
return redirect('expenses/vendors');
}
/**
* Remove the specified resource from storage.
*
* @param Vendor $vendor
*
* @return Response
*/
public function destroy(Vendor $vendor)
{
$canDelete = $vendor->canDelete();
if ($canDelete === true) {
$vendor->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.vendors', 1)]);
flash($message)->success();
} else {
$text = array();
if (isset($canDelete['bills'])) {
$text[] = '<b>' . $canDelete['bills'] . '</b> ' . trans_choice('general.bills', ($canDelete['bills'] > 1) ? 2 : 1);
}
if (isset($canDelete['payments'])) {
$text[] = '<b>' . $canDelete['payments'] . '</b> ' . trans_choice('general.payments', ($canDelete['payments'] > 1) ? 2 : 1);
}
$message = trans('messages.warning.deleted', ['type' => trans_choice('general.vendors', 1), 'text' => implode(', ', $text)]);
flash($message)->warning();
}
return redirect('expenses/vendors');
}
public function currency()
{
$vendor_id = request('vendor_id');
$vendor = Vendor::find($vendor_id);
return response()->json($vendor);
}
}

View File

@ -0,0 +1,165 @@
<?php
namespace App\Http\Controllers\Incomes;
use App\Http\Controllers\Controller;
use App\Http\Requests\Income\Customer as Request;
use App\Models\Auth\User;
use App\Models\Income\Customer;
use App\Models\Setting\Currency;
class Customers extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$customers = Customer::collect();
return view('incomes.customers.index', compact('customers', 'emails'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$currencies = Currency::enabled()->pluck('name', 'code');
return view('incomes.customers.create', compact('currencies'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
$customer = Customer::create($request->all());
if (!empty($request->input('create_user'))) {
$user = User::create($request->input());
$request['user_id'] = $user->id;
$request['roles'] = array('3');
$request['companies'] = array(session('company_id'));
// Attach roles
$user->roles()->attach($request['roles']);
// Attach companies
$user->companies()->attach($request['companies']);
$customer->update($request->all());
}
$message = trans('messages.success.added', ['type' => trans_choice('general.customers', 1)]);
flash($message)->success();
return redirect('incomes/customers');
}
/**
* Show the form for editing the specified resource.
*
* @param Customer $customer
*
* @return Response
*/
public function edit(Customer $customer)
{
$currencies = Currency::enabled()->pluck('name', 'code');
return view('incomes.customers.edit', compact('customer', 'currencies'));
}
/**
* Update the specified resource in storage.
*
* @param Customer $customer
* @param Request $request
*
* @return Response
*/
public function update(Customer $customer, Request $request)
{
$customer->update($request->all());
if (!empty($request->input('create_user'))) {
$user = User::create($request->input());
$request['user_id'] = $user->id;
$request['roles'] = array('3');
$request['companies'] = array(session('company_id'));
// Attach roles
$user->roles()->attach($request['roles']);
// Attach companies
$user->companies()->attach($request['companies']);
$customer->update($request->all());
}
$message = trans('messages.success.updated', ['type' => trans_choice('general.customers', 1)]);
flash($message)->success();
return redirect('incomes/customers');
}
/**
* Remove the specified resource from storage.
*
* @param Customer $customer
*
* @return Response
*/
public function destroy(Customer $customer)
{
$canDelete = $customer->canDelete();
if ($canDelete === true) {
$customer->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.customers', 1)]);
flash($message)->success();
} else {
$text = array();
if (isset($canDelete['invoices'])) {
$text[] = '<b>' . $canDelete['invoices'] . '</b> ' . trans_choice('general.invoices', ($canDelete['invoices'] > 1) ? 2 : 1);
}
if (isset($canDelete['revenues'])) {
$text[] = '<b>' . $canDelete['revenues'] . '</b> ' . trans_choice('general.revenues', ($canDelete['revenues'] > 1) ? 2 : 1);
}
$message = trans('messages.warning.deleted', ['type' => trans_choice('general.customers', 1), 'text' => implode(', ', $text)]);
flash($message)->warning();
}
return redirect('incomes/customers');
}
public function currency()
{
$customer_id = request('customer_id');
$customer = Customer::find($customer_id);
return response()->json($customer);
}
}

View File

@ -0,0 +1,513 @@
<?php
namespace App\Http\Controllers\Incomes;
use App\Events\InvoiceCreated;
use App\Events\InvoicePrinting;
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\Models\Banking\Account;
use App\Models\Income\Customer;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoiceItem;
use App\Models\Income\InvoicePayment;
use App\Models\Income\InvoiceStatus;
use App\Models\Item\Item;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use Jenssegers\Date\Date;
use App\Utilities\Modules;
class Invoices extends Controller
{
use DateTime, Currencies, Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$invoices = Invoice::with('invoice_statuses')->collect();
$status = collect(InvoiceStatus::all()->pluck('name', 'code'))
->prepend(trans('general.all_statuses'), '');
return view('incomes.invoices.index', compact('invoices', 'status'));
}
/**
* Show the form for viewing the specified resource.
*
* @param Invoice $invoice
*
* @return Response
*/
public function show(Invoice $invoice)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
foreach ($invoice->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->sub_total = $sub_total;
$invoice->tax_total = $tax_total;
$invoice->paid = $paid;
$invoice->grand_total = (($sub_total + $tax_total) - $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();
return view('incomes.invoices.show', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
}
/**
* Show the form for viewing the specified resource.
*
* @param int $invoice_id
*
* @return Response
*/
public function printInvoice($invoice_id)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
$invoice = Invoice::where('id', $invoice_id)->first();
foreach ($invoice->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->sub_total = $sub_total;
$invoice->tax_total = $tax_total;
$invoice->paid = $paid;
$invoice->grand_total = (($sub_total + $tax_total) - $paid);
$invoice->template_path = 'incomes.invoices.invoice';
event(new InvoicePrinting($invoice));
return view($invoice->template_path, compact('invoice'));
}
/**
* Show the form for viewing the specified resource.
*
* @param int $invoice_id
*
* @return Response
*/
public function pdfInvoice($invoice_id)
{
$sub_total = 0;
$tax_total = 0;
$paid = 0;
$invoice = Invoice::where('id', $invoice_id)->first();
foreach ($invoice->items as $item) {
$sub_total += ($item->price * $item->quantity);
$tax_total += ($item->tax * $item->quantity);
}
foreach ($invoice->payments as $item) {
$item->default_currency_code = $invoice->currency_code;
$paid += $item->getDynamicConvertedAmount();
}
$invoice->sub_total = $sub_total;
$invoice->tax_total = $tax_total;
$invoice->paid = $paid;
$invoice->grand_total = (($sub_total + $tax_total) - $paid);
$invoice->template_path = 'incomes.invoices.invoice';
event(new InvoicePrinting($invoice));
$html = view($invoice->template_path, compact('invoice'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($html);
$file_name = 'invoice_'.time().'.pdf';
return $pdf->download($file_name);
}
/**
* Show the form for viewing the specified resource.
*
* @param PaymentRequest $request
*
* @return Response
*/
public function payment(PaymentRequest $request)
{
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'revenues');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$invoice = Invoice::find($request['invoice_id']);
if ($request['currency_code'] == $invoice->currency_code) {
if ($request['amount'] > $invoice->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
return response()->json($message);
} elseif ($request['amount'] == $invoice->amount) {
$invoice->invoice_status_code = 'paid';
} else {
$invoice->invoice_status_code = 'partial';
}
} else {
$request_invoice = new Invoice();
$request_invoice->amount = (float) $request['amount'];
$request_invoice->currency_code = $currency->code;
$request_invoice->currency_rate = $currency->rate;
$amount = $request_invoice->getConvertedAmount();
if ($amount > $invoice->amount) {
$message = trans('messages.error.added', ['type' => trans_choice('general.payment', 1)]);
return response()->json($message);
} elseif ($amount == $invoice->amount) {
$invoice->invoice_status_code = 'paid';
} else {
$invoice->invoice_status_code = 'partial';
}
}
$invoice->save();
$invoice_payment = InvoicePayment::create($request->input());
$request['status_code'] = $invoice->invoice_status_code;
$request['notify'] = 0;
$desc_date = Date::parse($request['paid_at'])->format($this->getCompanyDateFormat());
$desc_amount = money((float) $request['amount'], $request['currency_code'], true)->format();
$request['description'] = $desc_date . ' ' . $desc_amount;
InvoiceHistory::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.revenues', 1)]);
return response()->json($message);
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$customers = Customer::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code');
$items = Item::enabled()->pluck('name', 'id');
$taxes = Tax::enabled()->pluck('name', 'id');
return view('incomes.invoices.create', compact('customers', 'currencies', 'items', 'taxes'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Get customer object
$customer = Customer::findOrFail($request['customer_id']);
$request['customer_name'] = $customer->name;
$request['customer_email'] = $customer->email;
$request['customer_tax_number'] = $customer->tax_number;
$request['customer_phone'] = $customer->phone;
$request['customer_address'] = $customer->address;
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
$request['invoice_status_code'] = 'draft';
$request['amount'] = 0;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'invoices');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$invoice = Invoice::create($request->input());
$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_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = $item['name'];
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
$invoice_item['tax'] = (($item['price'] * $item['quantity']) / 100) * $tax_rate;
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = ($item['price'] + $invoice_item['tax']) * $item['quantity'];
$request['amount'] += $invoice_item['total'];
InvoiceItem::create($invoice_item);
}
}
$invoice->update($request->input());
$request['invoice_id'] = $invoice->id;
$request['status_code'] = 'draft';
$request['notify'] = 0;
$request['description'] = trans('messages.success.added', ['type' => $request['invoice_number']]);
InvoiceHistory::create($request->all());
// Fire the event to make it extendible
event(new InvoiceCreated($invoice));
$message = trans('messages.success.added', ['type' => trans_choice('general.invoices', 1)]);
flash($message)->success();
return redirect('incomes/invoices/' . $invoice->id);
}
/**
* Show the form for editing the specified resource.
*
* @param Invoice $invoice
*
* @return Response
*/
public function edit(Invoice $invoice)
{
$customers = Customer::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code');
$items = Item::enabled()->pluck('name', 'id');
$taxes = Tax::enabled()->pluck('name', 'id');
return view('incomes.invoices.edit', compact('invoice', 'customers', 'currencies', 'items', 'taxes'));
}
/**
* Update the specified resource in storage.
*
* @param Invoice $invoice
* @param Request $request
*
* @return Response
*/
public function update(Invoice $invoice, Request $request)
{
// Get customer object
$customer = Customer::findOrFail($request['customer_id']);
$request['customer_name'] = $customer->name;
$request['customer_email'] = $customer->email;
$request['customer_tax_number'] = $customer->tax_number;
$request['customer_phone'] = $customer->phone;
$request['customer_address'] = $customer->address;
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
$request['invoice_status_code'] = 'draft';
$request['amount'] = 0;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'invoices');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$invoice_item = array();
$invoice_item['company_id'] = $request['company_id'];
$invoice_item['invoice_id'] = $invoice->id;
if ($request['item']) {
InvoiceItem::where('invoice_id', $invoice->id)->delete();
foreach ($request['item'] as $item) {
$item_sku = '';
if (!empty($item['item_id'])) {
$data = Item::where('id', $item['item_id'])->first();
$item_sku = $data['sku'];
}
$tax_id = 0;
$tax_rate = 0;
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$tax_rate = $tax->rate;
$tax_id = $item['tax'];
}
$invoice_item['item_id'] = $item['item_id'];
$invoice_item['name'] = $item['name'];
$invoice_item['sku'] = $item_sku;
$invoice_item['quantity'] = $item['quantity'];
$invoice_item['price'] = $item['price'];
$invoice_item['tax'] = (($item['price'] * $item['quantity']) / 100 * $tax_rate);
$invoice_item['tax_id'] = $tax_id;
$invoice_item['total'] = ($item['price'] + $invoice_item['tax']) * $item['quantity'];
$request['amount'] += $invoice_item['total'];
InvoiceItem::create($invoice_item);
}
}
$invoice->update($request->input());
// Fire the event to make it extendible
event(new InvoiceUpdated($invoice));
$message = trans('messages.success.updated', ['type' => trans_choice('general.invoices', 1)]);
flash($message)->success();
return redirect('incomes/invoices/' . $invoice->id);
}
/**
* Remove the specified resource from storage.
*
* @param Invoice $invoice
*
* @return Response
*/
public function destroy(Invoice $invoice)
{
$invoice->delete();
/*
$invoice->items->delete();
$invoice->payments->delete();
$invoice->histories->delete();
*/
InvoiceItem::where('invoice_id', $invoice->id)->delete();
InvoicePayment::where('invoice_id', $invoice->id)->delete();
InvoiceHistory::where('invoice_id', $invoice->id)->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.invoices', 1)]);
flash($message)->success();
return redirect('incomes/invoices');
}
/**
* Remove the specified resource from storage.
*
* @param InvoicePayment $payment
*
* @return Response
*/
public function paymentDestroy(InvoicePayment $payment)
{
$payment->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.invoices', 1)]);
flash($message)->success();
return redirect('incomes/invoices');
}
}

View File

@ -0,0 +1,166 @@
<?php
namespace App\Http\Controllers\Incomes;
use App\Http\Controllers\Controller;
use App\Http\Requests\Income\Revenue as Request;
use App\Models\Banking\Account;
use App\Models\Income\Customer;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use App\Utilities\Modules;
class Revenues extends Controller
{
use DateTime, Currencies, Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$revenues = Revenue::with('account', 'category', 'customer')->collect();
$customers = collect(Customer::enabled()->pluck('name', 'id'))
->prepend(trans('customer.all'), '');
$categories = collect(Category::enabled()->type('income')->pluck('name', 'id'))
->prepend(trans('categories.all'), '');
$accounts = collect(Account::enabled()->pluck('name', 'id'))
->prepend(trans('accounts.all'), '');
return view('incomes.revenues.index', compact('revenues', 'customers', 'categories', 'accounts'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$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();
return view('incomes.revenues.create', compact('accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Get currency object
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'revenues');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
Revenue::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.revenues', 1)]);
flash($message)->success();
return redirect('incomes/revenues');
}
/**
* Show the form for editing the specified resource.
*
* @param Revenue $revenue
*
* @return Response
*/
public function edit(Revenue $revenue)
{
$accounts = Account::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code')->toArray();
$account_currency_code = Account::where('id', $revenue->account_id)->pluck('currency_code')->first();
$customers = Customer::enabled()->pluck('name', 'id');
$categories = Category::enabled()->type('income')->pluck('name', 'id');
$payment_methods = Modules::getPaymentMethods();
return view('incomes.revenues.edit', compact('revenue', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
}
/**
* Update the specified resource in storage.
*
* @param Revenue $revenue
* @param Request $request
*
* @return Response
*/
public function update(Revenue $revenue, Request $request)
{
// Get currency
$currency = Currency::where('code', $request['currency_code'])->first();
$request['currency_code'] = $currency->code;
$request['currency_rate'] = $currency->rate;
// Upload attachment
$attachment_path = $this->getUploadedFilePath($request->file('attachment'), 'revenues');
if ($attachment_path) {
$request['attachment'] = $attachment_path;
}
$revenue->update($request->input());
$message = trans('messages.success.updated', ['type' => trans_choice('general.revenues', 1)]);
flash($message)->success();
return redirect('incomes/revenues');
}
/**
* Remove the specified resource from storage.
*
* @param Revenue $revenue
*
* @return Response
*/
public function destroy(Revenue $revenue)
{
$revenue->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.revenues', 1)]);
flash($message)->success();
return redirect('incomes/revenues');
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace App\Http\Controllers\Install;
use Artisan;
use Config;
use DB;
use DotenvEditor;
use App\Http\Requests\Install\Database as Request;
use Illuminate\Routing\Controller;
class Database extends Controller
{
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('install.database.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Check database connection
if (!$this->canConnect($request)) {
$message = trans('install.error.connection');
flash($message)->error()->important();
return redirect('install/database')->withInput();
}
// Set database details
$this->saveVariables($request);
// Try to increase the maximum execution time
set_time_limit(300); // 5 minutes
// Create tables
Artisan::call('migrate', ['--force' => true]);
// Create Roles
Artisan::call('db:seed', ['--class' => 'Database\Seeds\Roles', '--force' => true]);
return redirect('install/settings');
}
private function canConnect($request)
{
Config::set('database.connections.install_test', [
'host' => $request['hostname'],
'database' => $request['database'],
'username' => $request['username'],
'password' => $request['password'],
'driver' => 'mysql',
'port' => env('DB_PORT', '3306'),
]);
try {
DB::connection('install_test')->getPdo();
} catch (\Exception $e) {
return false;
}
// Purge test connection
DB::purge('install_test');
return true;
}
private function saveVariables($request)
{
$prefix = strtolower(str_random(3) . '_');
// Save to file
DotenvEditor::setKeys([
[
'key' => 'DB_HOST',
'value' => $request['hostname'],
],
[
'key' => 'DB_DATABASE',
'value' => $request['database'],
],
[
'key' => 'DB_USERNAME',
'value' => $request['username'],
],
[
'key' => 'DB_PASSWORD',
'value' => $request['password'],
],
[
'key' => 'DB_PREFIX',
'value' => $prefix,
],
])->save();
// Change current connection
$mysql = Config::get('database.connections.mysql');
$mysql['host'] = $request['hostname'];
$mysql['database'] = $request['database'];
$mysql['username'] = $request['username'];
$mysql['password'] = $request['password'];
$mysql['prefix'] = $prefix;
Config::set('database.connections.mysql', $mysql);
DB::purge('mysql');
DB::reconnect('mysql');
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace App\Http\Controllers\Install;
use Session;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class Language extends Controller
{
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('install.language.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Set locale
Session::put('locale', $request['lang']);
return redirect('install/database');
}
}

View File

@ -0,0 +1,233 @@
<?php
namespace App\Http\Controllers\Install;
use DotenvEditor;
use Illuminate\Routing\Controller;
class Requirements extends Controller
{
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function show()
{
// Check requirements
$requirements = $this->check();
if (empty($requirements)) {
// Create the .env file
$this->createEnvFile();
redirect('install/language')->send();
} else {
foreach ($requirements as $requirement) {
flash($requirement)->error()->important();
}
return view('install.requirements.show');
}
}
/**
* Check the requirements.
*
* @return array
*/
private function check()
{
$requirements = array();
if (version_compare(PHP_VERSION, '5.6.4', '<')) {
$requirements[] = trans('install.requirements.php_version');
}
if (ini_get('safe_mode')) {
$requirements[] = trans('install.requirements.disabled', ['feature' => 'Safe Mode']);
}
if (ini_get('register_globals')) {
$requirements[] = trans('install.requirements.disabled', ['feature' => 'Register Globals']);
}
if (ini_get('magic_quotes_gpc')) {
$requirements[] = trans('install.requirements.disabled', ['feature' => 'Magic Quotes']);
}
if (!ini_get('file_uploads')) {
$requirements[] = trans('install.requirements.enabled', ['feature' => 'File Uploads']);
}
if (!class_exists('PDO')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'MySQL PDO']);
}
if (!extension_loaded('openssl')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'OpenSSL']);
}
if (!extension_loaded('mcrypt')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'mCrypt']);
}
if (!extension_loaded('tokenizer')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'Tokenizer']);
}
if (!extension_loaded('mbstring')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'mbstring']);
}
if (!extension_loaded('curl')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'cURL']);
}
if (!extension_loaded('zip')) {
$requirements[] = trans('install.requirements.extension', ['extension' => 'ZIP']);
}
if (!is_writable(base_path('storage/app'))) {
$requirements[] = trans('install.requirements.directory', ['directory' => 'storage/app']);
}
if (!is_writable(base_path('storage/app/uploads'))) {
$requirements[] = trans('install.requirements.directory', ['directory' => 'storage/app/uploads']);
}
if (!is_writable(base_path('storage/framework'))) {
$requirements[] = trans('install.requirements.directory', ['directory' => 'storage/framework']);
}
if (!is_writable(base_path('storage/logs'))) {
$requirements[] = trans('install.requirements.directory', ['directory' => 'storage/logs']);
}
return $requirements;
}
/**
* Create the .env file.
*
* @return void
*/
private function createEnvFile()
{
// App
DotenvEditor::setKeys([
[
'key' => 'APP_NAME',
'value' => 'Akaunting',
],
[
'key' => 'APP_ENV',
'value' => 'production',
],
[
'key' => 'APP_KEY',
'value' => 'base64:'.base64_encode(random_bytes(32)),
],
[
'key' => 'APP_DEBUG',
'value' => 'false',
],
[
'key' => 'APP_LOG_LEVEL',
'value' => 'debug',
],
[
'key' => 'APP_URL',
'value' => url('/'),
],
]);
DotenvEditor::addEmpty();
// Database
DotenvEditor::setKeys([
[
'key' => 'DB_CONNECTION',
'value' => 'mysql',
],
[
'key' => 'DB_HOST',
'value' => 'localhost',
],
[
'key' => 'DB_PORT',
'value' => '3306',
],
[
'key' => 'DB_DATABASE',
'value' => '',
],
[
'key' => 'DB_USERNAME',
'value' => '',
],
[
'key' => 'DB_PASSWORD',
'value' => '',
],
[
'key' => 'DB_PREFIX',
'value' => '',
],
]);
DotenvEditor::addEmpty();
// Drivers
DotenvEditor::setKeys([
[
'key' => 'BROADCAST_DRIVER',
'value' => 'log',
],
[
'key' => 'CACHE_DRIVER',
'value' => 'file',
],
[
'key' => 'SESSION_DRIVER',
'value' => 'file',
],
[
'key' => 'QUEUE_DRIVER',
'value' => 'database',
],
]);
DotenvEditor::addEmpty();
// Mail
DotenvEditor::setKeys([
[
'key' => 'MAIL_DRIVER',
'value' => 'mail',
],
[
'key' => 'MAIL_HOST',
'value' => 'localhost',
],
[
'key' => 'MAIL_PORT',
'value' => '2525',
],
[
'key' => 'MAIL_USERNAME',
'value' => 'null',
],
[
'key' => 'MAIL_PASSWORD',
'value' => 'null',
],
[
'key' => 'MAIL_ENCRYPTION',
'value' => 'null',
],
]);
DotenvEditor::save();
}
}

View File

@ -0,0 +1,95 @@
<?php
namespace App\Http\Controllers\Install;
use Artisan;
use App\Http\Requests\Install\Setting as Request;
use App\Models\Auth\User;
use App\Models\Company\Company;
use File;
use Illuminate\Routing\Controller;
use Setting;
class Settings extends Controller
{
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('install.settings.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Create company
$this->createCompany($request);
// Create user
$this->createUser($request);
// Make the final touches
$this->finalTouches();
// Redirect to dashboard
return redirect('auth/login');
}
private function createCompany($request)
{
// Create company
$company = Company::create([
'domain' => '',
]);
// Set settings
Setting::set([
'general.company_name' => $request['company_name'],
'general.company_email' => $request['company_email'],
'general.default_currency' => 'USD',
'general.default_locale' => session('locale'),
]);
Setting::setExtraColumns(['company_id' => $company->id]);
Setting::save();
}
private function createUser($request)
{
// Create the user
$user = User::create([
'name' => $request[''],
'email' => $request['user_email'],
'password' => $request['user_password'],
'locale' => session('locale'),
]);
// Attach admin role
$user->roles()->attach('1');
// Attach company
$user->companies()->attach('1');
}
private function finalTouches()
{
// Caching the config and route
//Artisan::call('config:cache');
//Artisan::call('route:cache');
// Rename the robots.txt file
try {
File::move(base_path('robots.txt.dist'), base_path('robots.txt'));
} catch (\Exception $e) {
// nothing to do
}
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace App\Http\Controllers\Install;
use App\Http\Controllers\Controller;
use App\Models\Module\Module as Model;
use App\Utilities\Updater;
use App\Utilities\Versions;
use Module;
class Updates extends Controller
{
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function index()
{
$updates = Updater::all();
$core = $updates['core'];
$modules = array();
$rows = Module::all();
foreach ($rows as $row) {
$alias = $row->get('alias');
if (!isset($updates[$alias])) {
continue;
}
$m = new \stdClass();
$m->name = $row->get('name');
$m->alias = $row->get('alias');
$m->category = $row->get('category');
$m->installed = $row->get('version');
$m->latest = $updates[$alias];
$modules[] = $m;
}
return view('install.updates.index', compact('core', 'modules'));
}
public function changelog()
{
return Versions::changelog();
}
public function update($alias, $version)
{
set_time_limit(600); // 10 minutes
$status = Updater::update($alias, $version);
// Clear cache in order to check for updates again
Updater::clear();
return redirect()->back();
}
}

View File

@ -0,0 +1,257 @@
<?php
namespace App\Http\Controllers\Items;
use App\Http\Controllers\Controller;
use App\Http\Requests\Item\Item as Request;
use App\Models\Item\Item;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Traits\Uploads;
class Items extends Controller
{
use Uploads;
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$items = Item::with('category')->collect();
$categories = Category::enabled()->type('item')->pluck('name', 'id')->prepend(trans('categories.all'), '');
return view('items.items.index', compact('items', 'categories'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$categories = Category::enabled()->type('item')->pluck('name', 'id');
$taxes = Tax::enabled()->pluck('name', 'id');
return view('items.items.create', compact('categories', 'taxes'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Upload picture
$picture_path = $this->getUploadedFilePath($request->file('picture'), 'items');
if ($picture_path) {
$request['picture'] = $picture_path;
}
Item::create($request->input());
$message = trans('messages.success.added', ['type' => trans_choice('general.items', 1)]);
flash($message)->success();
return redirect('items/items');
}
/**
* Show the form for editing the specified resource.
*
* @param Item $item
*
* @return Response
*/
public function edit(Item $item)
{
$categories = Category::enabled()->type('item')->pluck('name', 'id');
$taxes = Tax::enabled()->pluck('name', 'id');
return view('items.items.edit', compact('item', 'categories', 'taxes'));
}
/**
* Update the specified resource in storage.
*
* @param Item $item
* @param Request $request
*
* @return Response
*/
public function update(Item $item, Request $request)
{
// Upload picture
$picture_path = $this->getUploadedFilePath($request->file('picture'), 'items');
if ($picture_path) {
$request['picture'] = $picture_path;
}
$item->update($request->input());
$message = trans('messages.success.updated', ['type' => trans_choice('general.items', 1)]);
flash($message)->success();
return redirect('items/items');
}
/**
* Remove the specified resource from storage.
*
* @param Item $item
*
* @return Response
*/
public function destroy(Item $item)
{
$canDelete = $item->canDelete();
if ($canDelete === true) {
$item->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.items', 1)]);
flash($message)->success();
} else {
$text = array();
if (isset($canDelete['bills'])) {
$text[] = '<b>' . $canDelete['bills'] . '</b> ' . trans_choice('general.bills', ($canDelete['bills'] > 1) ? 2 : 1);
}
if (isset($canDelete['invoices'])) {
$text[] = '<b>' . $canDelete['invoices'] . '</b> ' . trans_choice('general.items', ($canDelete['invoices'] > 1) ? 2 : 1);
}
$message = trans('messages.warning.deleted', ['type' => trans_choice('general.items', 1), 'text' => implode(', ', $text)]);
flash($message)->warning();
}
return redirect('items/items');
}
public function autocomplete()
{
$type = request('type');
$query = request('query');
$currency_code = request('currency_code');
if (empty($currency_code) || (strtolower($currency_code) == 'null')) {
$currency_code = setting('general.default_currency');
}
$currency = Currency::where('code', $currency_code)->first();
$filter_data = array(
'name' => $query
);
$items = Item::getItems($filter_data);
if ($items) {
foreach ($items as $item) {
$tax = Tax::where('id', $item->tax_id)->first();
$item_tax_price = 0;
if (!empty($tax)) {
$item_tax_price = ($item->sale_price / 100) * $tax->rate;
}
$item->sale_price = $this->convertPrice($item->sale_price, $currency_code, $currency->rate);
$item->purchase_price = $this->convertPrice($item->purchase_price, $currency_code, $currency->rate);
switch ($type) {
case 'bill':
$total = $item->purchase_price + $item_tax_price;
break;
case 'invoice':
default:
$total = $item->sale_price + $item_tax_price;
break;
}
$item->total = money($total, $currency_code, true)->format();
}
}
return response()->json($items);
}
public function totalItem()
{
$input_items = request('item');
$currency_code = request('currency_code');
if (empty($currency_code)) {
$currency_code = setting('general.default_currency');
}
$json = new \stdClass;
$sub_total = 0;
$tax_total = 0;
$items = array();
if ($input_items) {
foreach ($input_items as $key => $item) {
$item_tax_total= 0;
$item_sub_total = ($item['price'] * $item['quantity']);
if (!empty($item['tax'])) {
$tax = Tax::where('id', $item['tax'])->first();
$item_tax_total = (($item['price'] * $item['quantity']) / 100) * $tax->rate;
}
$sub_total += $item_sub_total;
$tax_total += $item_tax_total;
$total = $item_sub_total + $item_tax_total;
$items[$key] = money($total, $currency_code, true)->format();
}
}
$json->items = $items;
$json->sub_total = money($sub_total, $currency_code, true)->format();
$json->tax_total = money($tax_total, $currency_code, true)->format();
$grand_total = $sub_total + $tax_total;
$json->grand_total = money($grand_total, $currency_code, true)->format();
return response()->json($json);
}
protected function convertPrice($amount, $currency_code, $currency_rate, $format = false, $reverse = false)
{
$item = new Item();
$item->amount = $amount;
$item->currency_code = $currency_code;
$item->currency_rate = $currency_rate;
if ($reverse) {
return $item->getReverseConvertedAmount($format);
}
return $item->getConvertedAmount($format);
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Http\Controllers\Modules;
use App\Http\Controllers\Controller;
use App\Traits\Modules;
use Illuminate\Routing\Route;
class Home extends Controller
{
use Modules;
/**
* Instantiate a new controller instance.
*
* @param Route $route
*/
public function __construct(Route $route)
{
if (!setting('general.api_token')) {
return redirect('modules/token/create')->send();
}
parent::__construct($route);
}
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$paid = $this->getPaidModules();
$new = $this->getNewModules();
$free = $this->getFreeModules();
return view('modules.home.index', compact('paid', 'new', 'free'));
}
}

View File

@ -0,0 +1,272 @@
<?php
namespace App\Http\Controllers\Modules;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Module\Module;
use App\Models\Module\ModuleHistory;
use App\Traits\Modules;
use Illuminate\Routing\Route;
use Module as MModule;
class Item extends Controller
{
use Modules;
/**
* Instantiate a new controller instance.
*
* @param Route $route
*/
public function __construct(Route $route)
{
if (!setting('general.api_token')) {
return redirect('modules/token/create')->send();
}
parent::__construct($route);
}
/**
* Show the form for viewing the specified resource.
*
* @param $alias
*
* @return Response
*/
public function show($alias)
{
$installed = false;
$enable = false;
$module = $this->getModule($alias);
$check = Module::where('alias', $alias)->first();
if ($check) {
$installed = true;
if ($check->status) {
$enable = true;
}
}
return view('modules.item.show', compact('module', 'about', 'installed', 'enable'));
}
/**
* Show the form for viewing the specified resource.
*
* @param $path
*
* @return Response
*/
public function steps(Request $request)
{
$json = array();
$json['step'] = array();
$name = $request['name'];
$version = $request['version'];
// Download
$json['step'][] = array(
'text' => trans('modules.installation.download', ['module' => $name]),
'url' => url('modules/item/download')
);
// Unzip
$json['step'][] = array(
'text' => trans('modules.installation.unzip', ['module' => $name]),
'url' => url('modules/item/unzip')
);
// Download
$json['step'][] = array(
'text' => trans('modules.installation.install', ['module' => $name]),
'url' => url('modules/item/install')
);
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $path
*
* @return Response
*/
public function download(Request $request)
{
$path = $request['path'];
$version = $request['version'];
$path .= '/' . $version . '/' . version('short') . '/' . setting('general.api_token');
$json = $this->downloadModule($path);
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $path
*
* @return Response
*/
public function unzip(Request $request)
{
$path = $request['path'];
$json = $this->unzipModule($path);
return response()->json($json);
}
/**
* Show the form for viewing the specified resource.
*
* @param $path
*
* @return Response
*/
public function install(Request $request)
{
$path = $request['path'];
$json = $this->installModule($path);
if ($json['success']) {
$request['company_id'] = session('company_id');
$request['alias'] = 'paypal';
$module = Module::create($request->all());
$mmodule = MModule::findByAlias($module->alias);
$data = array(
'company_id' => session('company_id'),
'module_id' => $module->id,
'category' => $mmodule->get('category'),
'version' => $mmodule->get('version'),
'description' => trans('modules.history.installed', ['module' => $mmodule->get('name')]),
);
ModuleHistory::create($data);
$message = trans('messages.success.added', ['type' => trans('modules.installed', ['module' => $json['data']['name']])]);
flash($message)->success();
}
return response()->json($json);
}
public function uninstall($alias)
{
$json = $this->uninstallModule($alias);
$module = Module::where('alias', $alias)->first();
$data = array(
'company_id' => session('company_id'),
'module_id' => $module->id,
'category' => $json['data']['category'],
'version' => $json['data']['version'],
'description' => trans('modules.history.uninstalled', ['module' => $json['data']['name']]),
);
ModuleHistory::create($data);
$module->delete();
$message = trans('messages.success.added', ['type' => trans('modules.uninstalled', ['module' => $json['data']['name']])]);
flash($message)->success();
return redirect('modules/item/' . $alias)->send();
}
public function update($alias)
{
$json = $this->updateModule($alias);
$module = Module::where('alias', $alias)->first();
$data = array(
'company_id' => session('company_id'),
'module_id' => $module->id,
'category' => $json['data']['category'],
'version' => $json['data']['version'],
'description' => trans_choice('modules.history.updated', $json['data']['name']),
);
ModuleHistory::create($data);
$message = trans('messages.success.added', ['type' => trans('modules.updated', ['module' => $json['data']['name']])]);
flash($message)->success();
return redirect('modules/item/' . $alias)->send();
}
public function enabled($alias)
{
$json = $this->enabledModule($alias);
$module = Module::where('alias', $alias)->first();
$data = array(
'company_id' => session('company_id'),
'module_id' => $module->id,
'category' => $json['data']['category'],
'version' => $json['data']['version'],
'description' => trans('modules.history.enabled', ['module' => $json['data']['name']]),
);
$module->status = 1;
$module->save();
ModuleHistory::create($data);
$message = trans('messages.success.added', ['type' => trans('modules.enabled', ['module' => $json['data']['name']])]);
flash($message)->success();
return redirect('modules/item/' . $alias)->send();
}
public function disabled($alias)
{
$json = $this->disabledModule($alias);
$module = Module::where('alias', $alias)->first();
$data = array(
'company_id' => session('company_id'),
'module_id' => $module->id,
'category' => $json['data']['category'],
'version' => $json['data']['version'],
'description' => trans('modules.history.disabled', ['module' => $json['data']['name']]),
);
$module->status = 0;
$module->save();
ModuleHistory::create($data);
$message = trans('messages.success.added', ['type' => trans('modules.disabled', ['module' => $json['data']['name']])]);
flash($message)->success();
return redirect('modules/item/' . $alias)->send();
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Http\Controllers\Modules;
use App\Http\Controllers\Controller;
use App\Traits\Modules;
use Illuminate\Routing\Route;
class Tiles extends Controller
{
use Modules;
/**
* Instantiate a new controller instance.
*
* @param Route $route
*/
public function __construct(Route $route)
{
if (!setting('general.api_token')) {
return redirect('modules/token/create')->send();
}
parent::__construct($route);
}
/**
* Show the form for viewing the specified resource.
*
* @param $alias
*
* @return Response
*/
public function category($alias)
{
$data = $this->getModulesByCategory($alias);
$title = $data->category->name;
$modules = $data->modules;
return view('modules.tiles.index', compact('title', 'modules'));
}
/**
* Show the form for viewing the specified resource.
*
* @return Response
*/
public function paid()
{
$title = trans('modules.top_paid');
$modules = $this->getPaidModules();
return view('modules.tiles.index', compact('title', 'modules'));
}
/**
* Show the form for viewing the specified resource.
*
* @return Response
*/
public function new()
{
$title = trans('modules.new');
$modules = $this->getNewModules();
return view('modules.tiles.index', compact('title', 'modules'));
}
/**
* Show the form for viewing the specified resource.
*
* @return Response
*/
public function free()
{
$title = trans('modules.top_free');
$modules = $this->getFreeModules();
return view('modules.tiles.index', compact('title', 'modules'));
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Http\Controllers\Modules;
use App\Http\Controllers\Controller;
use App\Http\Requests\Module\Module as Request;
class Token extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function create()
{
return view('modules.token.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
// Set Api Token
setting()->set('general.api_token', $request['api_token']);
setting()->save();
return redirect('modules/home');
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use App\Models\Expense\Bill;
use App\Models\Expense\BillPayment;
use App\Models\Expense\Payment;
use App\Models\Setting\Category;
use Date;
class ExpenseSummary extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$dates = $totals = $expenses = $expenses_graph = $categories = [];
$status = request('status');
//if ($filter != 'upcoming') {
$categories = Category::enabled()->type('expense')->pluck('name', 'id')->toArray();
//}
// Add Bill in Categories
$categories[0] = trans_choice('general.bills', 2);
// 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('F');
$expenses_graph[Date::parse($year . '-' . $j)->format('F-Y')] = 0;
// Totals
$totals[$dates[$j]] = array(
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
// Bill
$expenses[0][$dates[$j]] = array(
'category_id' => 0,
'name' => trans_choice('general.bills', 1),
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
foreach ($categories as $category_id => $category_name) {
$expenses[$category_id][$dates[$j]] = array(
'category_id' => $category_id,
'name' => $category_name,
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
}
}
// Bills
switch ($status) {
case 'all':
$bills = Bill::getMonthsOfYear('billed_at');
$this->setAmount($expenses_graph, $totals, $expenses, $bills, 'bill', 'billed_at');
break;
case 'upcoming':
$bills = Bill::getMonthsOfYear('due_at');
$this->setAmount($expenses_graph, $totals, $expenses, $bills, 'bill', 'due_at');
break;
default:
$bills = BillPayment::getMonthsOfYear('paid_at');
$this->setAmount($expenses_graph, $totals, $expenses, $bills, 'bill', 'paid_at');
break;
}
// Payments
if ($status != 'upcoming') {
$payments = Payment::getMonthsOfYear('paid_at');
$this->setAmount($expenses_graph, $totals, $expenses, $payments, 'payment', 'paid_at');
}
// Expenses Graph
$expenses_graph = json_encode($expenses_graph);
return view('reports.expense_summary.index', compact('dates', 'categories', 'expenses', 'expenses_graph', 'totals'));
}
private function setAmount(&$graph, &$totals, &$expenses, $items, $type, $date_field)
{
foreach ($items as $item) {
$date = Date::parse($item->$date_field)->format('F');
if ($type == 'bill') {
$category_id = 0;
} else {
$category_id = $item->category_id;
}
if (!isset($expenses[$category_id])) {
continue;
}
$amount = $item->getConvertedAmount();
// Forecasting
if (($type == 'bill') && ($date_field == 'due_at')) {
foreach ($item->payments as $payment) {
$amount -= $payment->getConvertedAmount();
}
}
$expenses[$category_id][$date]['amount'] += $amount;
$expenses[$category_id][$date]['currency_code'] = $item->currency_code;
$expenses[$category_id][$date]['currency_rate'] = $item->currency_rate;
$graph[Date::parse($item->$date_field)->format('F-Y')] += $amount;
$totals[$date]['amount'] += $amount;
}
}
}

View File

@ -0,0 +1,190 @@
<?php
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
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\Setting\Category;
use Date;
class IncomeExpenseSummary extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$dates = $totals = $compares = $compares_graph = $categories = [];
$status = request('status');
//if ($filter != 'upcoming') {
$income_categories = Category::enabled()->type('income')->pluck('name', 'id')->toArray();
//}
// Add Invoice in Categories
$income_categories[0] = trans_choice('general.invoices', 2);
//if ($filter != 'upcoming') {
$expense_categories = Category::enabled()->type('expense')->pluck('name', 'id')->toArray();
//}
// Add Bill in Categories
$expense_categories[0] = trans_choice('general.bills', 2);
// 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('F');
$compares_graph[Date::parse($year . '-' . $j)->format('F-Y')] = 0;
// Totals
$totals[$dates[$j]] = array(
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
// Compares
$compares['income'][0][$dates[$j]] = array(
'category_id' => 0,
'name' => trans_choice('general.invoices', 1),
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
foreach ($income_categories as $category_id => $category_name) {
$compares['income'][$category_id][$dates[$j]] = array(
'category_id' => $category_id,
'name' => $category_name,
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
}
$compares['expense'][0][$dates[$j]] = array(
'category_id' => 0,
'name' => trans_choice('general.invoices', 1),
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
foreach ($expense_categories as $category_id => $category_name) {
$compares['expense'][$category_id][$dates[$j]] = array(
'category_id' => $category_id,
'name' => $category_name,
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
}
}
// Invoices
switch ($status) {
case 'all':
$invoices = Invoice::getMonthsOfYear('invoiced_at');
$this->setAmount($compares_graph, $totals, $compares, $invoices, 'invoice', 'invoiced_at');
break;
case 'upcoming':
$invoices = Invoice::getMonthsOfYear('due_at');
$this->setAmount($compares_graph, $totals, $compares, $invoices, 'invoice', 'due_at');
break;
default:
$invoices = InvoicePayment::getMonthsOfYear('paid_at');
$this->setAmount($compares_graph, $totals, $compares, $invoices, 'invoice', 'paid_at');
break;
}
// Revenues
if ($status != 'upcoming') {
$revenues = Revenue::getMonthsOfYear('paid_at');
$this->setAmount($compares_graph, $totals, $compares, $revenues, 'revenue', 'paid_at');
}
// Bills
switch ($status) {
case 'all':
$bills = Bill::getMonthsOfYear('billed_at');
$this->setAmount($compares_graph, $totals, $compares, $bills, 'bill', 'billed_at');
break;
case 'upcoming':
$bills = Bill::getMonthsOfYear('due_at');
$this->setAmount($compares_graph, $totals, $compares, $bills, 'bill', 'due_at');
break;
default:
$bills = BillPayment::getMonthsOfYear('paid_at');
$this->setAmount($compares_graph, $totals, $compares, $bills, 'bill', 'paid_at');
break;
}
// Payments
if ($status != 'upcoming') {
$payments = Payment::getMonthsOfYear('paid_at');
$this->setAmount($compares_graph, $totals, $compares, $payments, 'payment', 'paid_at');
}
// Incomes Graph
$compares_graph = json_encode($compares_graph);
return view('reports.income_expense_summary.index', compact('dates', 'income_categories', 'expense_categories', 'compares', 'compares_graph', 'totals'));
}
private function setAmount(&$graph, &$totals, &$compares, $items, $type, $date_field)
{
foreach ($items as $item) {
$date = Date::parse($item->$date_field)->format('F');
if (($type == 'invoice') || ($type == 'bill')) {
$category_id = 0;
} else {
$category_id = $item->category_id;
}
$group = (($type == 'invoice') || ($type == 'revenue')) ? 'income' : 'expense';
if (!isset($compares[$group][$category_id])) {
continue;
}
$amount = $item->getConvertedAmount();
// Forecasting
if ((($type == 'invoice') || ($type == 'bill')) && ($date_field == 'due_at')) {
foreach ($item->payments as $payment) {
$amount -= $payment->getConvertedAmount();
}
}
$compares[$group][$category_id][$date]['amount'] += $amount;
$compares[$group][$category_id][$date]['currency_code'] = $item->currency_code;
$compares[$group][$category_id][$date]['currency_rate'] = $item->currency_rate;
if ($group == 'income') {
$graph[Date::parse($item->$date_field)->format('F-Y')] += $amount;
$totals[$date]['amount'] += $amount;
} else {
$graph[Date::parse($item->$date_field)->format('F-Y')] -= $amount;
$totals[$date]['amount'] -= $amount;
}
}
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use App\Models\Income\Invoice;
use App\Models\Income\InvoicePayment;
use App\Models\Income\Revenue;
use App\Models\Setting\Category;
use Date;
class IncomeSummary extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$dates = $totals = $incomes = $incomes_graph = $categories = [];
$status = request('status');
//if ($filter != 'upcoming') {
$categories = Category::enabled()->type('income')->pluck('name', 'id')->toArray();
//}
// Add Invoice in Categories
$categories[0] = trans_choice('general.invoices', 2);
// 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('F');
$incomes_graph[Date::parse($year . '-' . $j)->format('F-Y')] = 0;
// Totals
$totals[$dates[$j]] = array(
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
// Invoice
$incomes[0][$dates[$j]] = array(
'category_id' => 0,
'name' => trans_choice('general.invoices', 1),
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
foreach ($categories as $category_id => $category_name) {
$incomes[$category_id][$dates[$j]] = array(
'category_id' => $category_id,
'name' => $category_name,
'amount' => 0,
'currency_code' => setting('general.default_currency'),
'currency_rate' => 1
);
}
}
// Invoices
switch ($status) {
case 'all':
$invoices = Invoice::getMonthsOfYear('invoiced_at');
$this->setAmount($incomes_graph, $totals, $incomes, $invoices, 'invoice', 'invoiced_at');
break;
case 'upcoming':
$invoices = Invoice::getMonthsOfYear('due_at');
$this->setAmount($incomes_graph, $totals, $incomes, $invoices, 'invoice', 'due_at');
break;
default:
$invoices = InvoicePayment::getMonthsOfYear('paid_at');
$this->setAmount($incomes_graph, $totals, $incomes, $invoices, 'invoice', 'paid_at');
break;
}
// Revenues
if ($status != 'upcoming') {
$revenues = Revenue::getMonthsOfYear('paid_at');
$this->setAmount($incomes_graph, $totals, $incomes, $revenues, 'revenue', 'paid_at');
}
// Incomes Graph
$incomes_graph = json_encode($incomes_graph);
return view('reports.income_summary.index', compact('dates', 'categories', 'incomes', 'incomes_graph', 'totals'));
}
private function setAmount(&$graph, &$totals, &$incomes, $items, $type, $date_field)
{
foreach ($items as $item) {
$date = Date::parse($item->$date_field)->format('F');
if ($type == 'invoice') {
$category_id = 0;
} else {
$category_id = $item->category_id;
}
if (!isset($incomes[$category_id])) {
continue;
}
$amount = $item->getConvertedAmount();
// Forecasting
if (($type == 'invoice') && ($date_field == 'due_at')) {
foreach ($item->payments as $payment) {
$amount -= $payment->getConvertedAmount();
}
}
$incomes[$category_id][$date]['amount'] += $amount;
$incomes[$category_id][$date]['currency_code'] = $item->currency_code;
$incomes[$category_id][$date]['currency_rate'] = $item->currency_rate;
$graph[Date::parse($item->$date_field)->format('F-Y')] += $amount;
$totals[$date]['amount'] += $amount;
}
}
}

View File

@ -0,0 +1,130 @@
<?php
namespace App\Http\Controllers\Search;
use App\Http\Controllers\Controller;
use App\Models\Banking\Account;
use App\Models\Expense\Bill;
use App\Models\Expense\Payment;
use App\Models\Expense\Vendor;
use App\Models\Income\Invoice;
use App\Models\Income\Revenue;
use App\Models\Income\Customer;
use App\Models\Item\Item;
class Search extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$items = Item::enabled()->with('category')->get()->sortBy('name');
return view('items.items.index', compact('items'));
}
/**
* Display a listing of the resource.
*
* @return Response
*/
public function search()
{
$results = array();
$keyword = request('keyword');
$accounts = Account::enabled()->search($keyword)->get();
if ($accounts->count()) {
foreach ($accounts as $account) {
$results[] = (object)[
'id' => $account->id,
'name' => $account->name,
'type' => trans_choice('general.accounts', 1),
'color' => '#337ab7',
'href' => url('banking/accounts/' . $account->id . '/edit'),
];
}
}
$items = Item::enabled()->search($keyword)->get();
if ($items->count()) {
foreach ($items as $item) {
$results[] = (object)[
'id' => $item->id,
'name' => $item->name,
'type' => trans_choice('general.items', 1),
'color' => '#f5bd65',
'href' => url('items/items/' . $item->id . '/edit'),
];
}
}
$invoices = Invoice::search($keyword)->get();
if ($invoices->count()) {
foreach ($invoices as $invoice) {
$results[] = (object)[
'id' => $invoice->id,
'name' => $invoice->invoice_number . ' - ' . $invoice->customer_name,
'type' => trans_choice('general.invoices', 1),
'color' => '#00c0ef',
'href' => url('incomes/invoices/' . $invoice->id),
];
}
}
//$revenues = Revenue::search($keyword)->get();
$customers = Customer::enabled()->search($keyword)->get();
if ($customers->count()) {
foreach ($customers as $customer) {
$results[] = (object)[
'id' => $customer->id,
'name' => $customer->name,
'type' => trans_choice('general.customers', 1),
'color' => '#03d876',
'href' => url('incomes/customers/' . $customer->id . '/edit'),
];
}
}
$bills = Bill::search($keyword)->get();
if ($bills->count()) {
foreach ($bills as $bill) {
$results[] = (object)[
'id' => $bill->id,
'name' => $bill->bill_number . ' - ' . $bill->vendor_name,
'type' => trans_choice('general.bills', 1),
'color' => '#dd4b39',
'href' => url('expenses/bills/' . $bill->id),
];
}
}
//$payments = Payment::search($keyword)->get();
$vendors = Vendor::enabled()->search($keyword)->get();
if ($vendors->count()) {
foreach ($vendors as $vendor) {
$results[] = (object)[
'id' => $vendor->id,
'name' => $vendor->name,
'type' => trans_choice('general.vendors', 1),
'color' => '#ff8373',
'href' => url('expenses/vendors/' . $vendor->id . '/edit'),
];
}
}
return response()->json((object) $results);
}
}

View File

@ -0,0 +1,125 @@
<?php
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Category as Request;
use App\Models\Setting\Category;
class Categories extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$categories = Category::collect();
$types = collect(['expense' => 'Expense', 'income' => 'Income', 'item' => 'Item', 'other' => 'Other'])
->prepend(trans('categories.all_types'), '');
return view('settings.categories.index', compact('categories', 'types'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('settings.categories.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
Category::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.categories', 1)]);
flash($message)->success();
return redirect('settings/categories');
}
/**
* Show the form for editing the specified resource.
*
* @param Category $category
*
* @return Response
*/
public function edit(Category $category)
{
return view('settings.categories.edit', compact('category'));
}
/**
* Update the specified resource in storage.
*
* @param Category $category
* @param Request $request
*
* @return Response
*/
public function update(Category $category, Request $request)
{
$category->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.categories', 1)]);
flash($message)->success();
return redirect('settings/categories');
}
/**
* Remove the specified resource from storage.
*
* @param Category $category
*
* @return Response
*/
public function destroy(Category $category)
{
$canDelete = $category->canDelete();
if ($canDelete === true) {
$category->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.categories', 1)]);
flash($message)->success();
} else {
$text = array();
if (isset($canDelete['items'])) {
$text[] = '<b>' . $canDelete['items'] . '</b> ' . trans_choice('general.items', ($canDelete['items'] > 1) ? 2 : 1);
}
if (isset($canDelete['payments'])) {
$text[] = '<b>' . $canDelete['payments'] . '</b> ' . trans_choice('general.payments', ($canDelete['payments'] > 1) ? 2 : 1);
}
if (isset($canDelete['revenues'])) {
$text[] = '<b>' . $canDelete['revenues'] . '</b> ' . trans_choice('general.items', ($canDelete['revenues'] > 1) ? 2 : 1);
}
$message = trans('messages.warning.deleted', ['type' => trans_choice('general.categories', 1), 'text' => implode(', ', $text)]);
flash($message)->warning();
}
return redirect('settings/categories');
}
}

View File

@ -0,0 +1,146 @@
<?php
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Currency as Request;
use App\Models\Banking\Account;
use App\Models\Setting\Currency;
use ClickNow\Money\Currency as MoneyCurrency;
class Currencies extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$currencies = Currency::collect();
return view('settings.currencies.index', compact('currencies', 'codes', 'rates'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
// Prepare codes
$codes = array();
$currencies = MoneyCurrency::getCurrencies();
foreach ($currencies as $key => $item) {
$codes[$key] = $key;
}
return view('settings.currencies.create', compact('codes'));
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
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)]);
flash($message)->success();
return redirect('settings/currencies');
}
/**
* Show the form for editing the specified resource.
*
* @param Currency $currency
*
* @return Response
*/
public function edit(Currency $currency)
{
// Prepare codes
$codes = array();
$currencies = MoneyCurrency::getCurrencies();
foreach ($currencies as $key => $item) {
$codes[$key] = $key;
}
// Set default currency
$currency->default_currency = ($currency->code == setting('general.default_currency')) ? 1 : 0;
return view('settings.currencies.edit', compact('currency', 'codes'));
}
/**
* Update the specified resource in storage.
*
* @param Currency $currency
* @param Request $request
*
* @return Response
*/
public function update(Currency $currency, Request $request)
{
$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)]);
flash($message)->success();
return redirect('settings/currencies');
}
/**
* Remove the specified resource from storage.
*
* @param Currency $currency
*
* @return Response
*/
public function destroy(Currency $currency)
{
$currency->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.currencies', 1)]);
flash($message)->success();
return redirect('settings/currencies');
}
public function currency()
{
$json = new \stdClass();
$account_id = request('account_id');
if ($account_id) {
$currencies = Currency::enabled()->pluck('name', 'code')->toArray();
$json->currency_code = Account::where('id', $account_id)->pluck('currency_code')->first();
$json->currency_name = $currencies[$json->currency_code];
}
return response()->json($json);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Models\Setting\Setting;
use File;
use Module;
class Modules extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @return Response
*/
public function edit($alias)
{
/*$setting = Setting::all($alias)->pluck('value', 'key');*/
$setting = Setting::all($alias)->map(function($s) use($alias) {
$s->key = str_replace($alias . '.', '', $s->key);
return $s;
})->pluck('value', 'key');
$module = Module::get($alias);
return view('settings.modules.edit', compact('setting', 'module'));
}
/**
* Update the specified resource in storage.
*
* @param $alias
*
* @return Response
*/
public function update($alias)
{
$fields = request()->all();
$skip_keys = ['company_id', '_method', '_token'];
foreach ($fields as $key => $value) {
// Don't process unwanted keys
if (in_array($key, $skip_keys)) {
continue;
}
setting()->set($alias . '.' . $key, $value);
}
// Save all settings
setting()->save();
$message = trans('messages.success.updated', ['type' => trans_choice('general.settings', 2)]);
flash($message)->success();
return redirect('settings/modules/' . $alias);
}
}

View File

@ -0,0 +1,118 @@
<?php
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Setting as Request;
use App\Models\Banking\Account;
use App\Models\Setting\Currency;
use App\Models\Setting\Tax;
use App\Models\Setting\Setting;
use App\Traits\DateTime;
use App\Traits\Uploads;
class Settings extends Controller
{
use DateTime, Uploads;
/**
* Show the form for editing the specified resource.
*
* @return Response
*/
public function edit()
{
/*$setting = Setting::all()->pluck('value', 'key');*/
$setting = Setting::all()->map(function($s) {
$s->key = str_replace('general.', '', $s->key);
return $s;
})->pluck('value', 'key');
$timezones = $this->getTimezones();
$accounts = Account::enabled()->pluck('name', 'id');
$currencies = Currency::enabled()->pluck('name', 'code');
$taxes = Tax::enabled()->pluck('name', 'id');
$date_formats = [
'd M Y' => '31 Dec 2017',
'd F Y' => '31 December 2017',
'd m Y' => '31 12 2017',
'm d Y' => '12 31 2017',
'Y m d' => '2017 12 31'
];
$date_separators = [
'dash' => trans('settings.localisation.date.dash'),
'slash' => trans('settings.localisation.date.slash'),
'dot' => trans('settings.localisation.date.dot'),
'comma' => trans('settings.localisation.date.comma'),
'space' => trans('settings.localisation.date.space'),
];
$email_protocols = [
'mail' => trans('settings.email.php'),
'smtp' => trans('settings.email.smtp.name'),
'sendmail' => trans('settings.email.sendmail'),
'log' => trans('settings.email.log')
];
return view('settings.settings.edit', compact(
'setting',
'timezones',
'accounts',
'currencies',
'taxes',
'date_formats',
'date_separators',
'email_protocols'
));
}
/**
* Update the specified resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function update(Request $request)
{
$fields = $request->all();
$company_id = $request->get('company_id');
$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)) {
$value = $this->getUploadedFilePath($request->file($key), 'settings');
// Prevent reset
if (empty($value)) {
continue;
}
}
setting()->set('general.' . $key, $value);
}
// Save all settings
setting()->save();
$message = trans('messages.success.updated', ['type' => trans_choice('general.settings', 2)]);
flash($message)->success();
return redirect('settings/settings');
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Http\Requests\Setting\Tax as Request;
use App\Models\Setting\Tax;
class Taxes extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$taxes = Tax::collect();
return view('settings.taxes.index', compact('taxes', 'rates'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('settings.taxes.create');
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return Response
*/
public function store(Request $request)
{
Tax::create($request->all());
$message = trans('messages.success.added', ['type' => trans_choice('general.tax_rates', 1)]);
flash($message)->success();
return redirect('settings/taxes');
}
/**
* Show the form for editing the specified resource.
*
* @param Tax $tax
*
* @return Response
*/
public function edit(Tax $tax)
{
return view('settings.taxes.edit', compact('tax'));
}
/**
* Update the specified resource in storage.
*
* @param Tax $tax
* @param Request $request
*
* @return Response
*/
public function update(Tax $tax, Request $request)
{
$tax->update($request->all());
$message = trans('messages.success.updated', ['type' => trans_choice('general.tax_rates', 1)]);
flash($message)->success();
return redirect('settings/taxes');
}
/**
* Remove the specified resource from storage.
*
* @param Tax $tax
*
* @return Response
*/
public function destroy(Tax $tax)
{
$canDelete = $tax->canDelete();
if ($canDelete === true) {
$tax->delete();
$message = trans('messages.success.deleted', ['type' => trans_choice('general.taxes', 1)]);
flash($message)->success();
} else {
$text = array();
if (isset($canDelete['items'])) {
$text[] = '<b>' . $canDelete['items'] . '</b> ' . trans_choice('general.items', ($canDelete['items'] > 1) ? 2 : 1);
}
if (isset($canDelete['bills'])) {
$text[] = '<b>' . $canDelete['bills'] . '</b> ' . trans_choice('general.bills', ($canDelete['bills'] > 1) ? 2 : 1);
}
if (isset($canDelete['invoices'])) {
$text[] = '<b>' . $canDelete['invoices'] . '</b> ' . trans_choice('general.items', ($canDelete['invoices'] > 1) ? 2 : 1);
}
$message = trans('messages.warning.deleted', ['type' => trans_choice('general.taxes', 1), 'text' => implode(', ', $text)]);
flash($message)->warning();
}
return redirect('settings/taxes');
}
}