Merge branch 'master' into laravel-7
This commit is contained in:
@ -98,7 +98,7 @@ abstract class DocumentModel extends Model
|
||||
$default_model->currency_code = $item->currency_code;
|
||||
$default_model->currency_rate = $currencies[$item->currency_code];
|
||||
|
||||
$default_amount = (double) $default_model->getDivideConvertedAmount();
|
||||
$default_amount = (double) $default_model->getAmountConvertedToDefault();
|
||||
|
||||
$convert_model = new Transaction();
|
||||
$convert_model->default_currency_code = $item->currency_code;
|
||||
@ -106,7 +106,7 @@ abstract class DocumentModel extends Model
|
||||
$convert_model->currency_code = $this->currency_code;
|
||||
$convert_model->currency_rate = $currencies[$this->currency_code];
|
||||
|
||||
$amount = (double) $convert_model->getAmountConvertedFromCustomDefault();
|
||||
$amount = (double) $convert_model->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
|
@ -30,7 +30,7 @@ abstract class Controller extends BaseController
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setPermissions()
|
||||
public function setPermissions()
|
||||
{
|
||||
// No need to check for permission in console
|
||||
if (app()->runningInConsole()) {
|
||||
@ -90,33 +90,4 @@ abstract class Controller extends BaseController
|
||||
|
||||
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a job to its appropriate handler and return a response array for ajax calls.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @return mixed
|
||||
*/
|
||||
public function ajaxDispatch($job)
|
||||
{
|
||||
try {
|
||||
$data = $this->dispatch($job);
|
||||
|
||||
$response = [
|
||||
'success' => true,
|
||||
'error' => false,
|
||||
'data' => $data,
|
||||
'message' => '',
|
||||
];
|
||||
} catch(\Exception $e) {
|
||||
$response = [
|
||||
'success' => false,
|
||||
'error' => true,
|
||||
'data' => null,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
10
app/Abstracts/Observer.php
Normal file
10
app/Abstracts/Observer.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts;
|
||||
|
||||
use Monooso\Unobserve\CanMute;
|
||||
|
||||
abstract class Observer
|
||||
{
|
||||
use CanMute;
|
||||
}
|
@ -67,6 +67,9 @@ abstract class Report
|
||||
'datasets' => [],
|
||||
];
|
||||
|
||||
public $column_name_width = 'report-column-name';
|
||||
public $column_value_width = 'report-column-value';
|
||||
|
||||
public function __construct(Model $model = null, $load_data = true)
|
||||
{
|
||||
$this->setGroups();
|
||||
@ -95,6 +98,7 @@ abstract class Report
|
||||
$this->setFilters();
|
||||
$this->setRows();
|
||||
$this->setData();
|
||||
$this->setColumnWidth();
|
||||
|
||||
$this->loaded = true;
|
||||
}
|
||||
@ -198,6 +202,30 @@ abstract class Report
|
||||
return \Excel::download(new Export($this->views['content'], $this), \Str::filename($this->model->name) . '.xlsx');
|
||||
}
|
||||
|
||||
public function setColumnWidth()
|
||||
{
|
||||
if (empty($this->model->settings->period)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$width = '';
|
||||
|
||||
switch ($this->model->settings->period) {
|
||||
case 'quarterly':
|
||||
$width = 'col-sm-2';
|
||||
break;
|
||||
case 'yearly':
|
||||
$width = 'col-sm-4';
|
||||
break;
|
||||
}
|
||||
|
||||
if (empty($width)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->column_name_width = $this->column_value_width = $width;
|
||||
}
|
||||
|
||||
public function setYear()
|
||||
{
|
||||
$this->year = request('year', Date::now()->year);
|
||||
|
@ -32,6 +32,9 @@ class BillReminder extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Disable model cache
|
||||
config(['laravel-model-caching.enabled' => false]);
|
||||
|
||||
// Get all companies
|
||||
$companies = Company::enabled()->cursor();
|
||||
|
||||
|
@ -32,6 +32,9 @@ class InvoiceReminder extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Disable model cache
|
||||
config(['laravel-model-caching.enabled' => false]);
|
||||
|
||||
// Get all companies
|
||||
$companies = Company::enabled()->cursor();
|
||||
|
||||
|
@ -45,6 +45,9 @@ class RecurringCheck extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Disable model cache
|
||||
config(['laravel-model-caching.enabled' => false]);
|
||||
|
||||
// Get all companies
|
||||
$companies = Company::enabled()->cursor();
|
||||
|
||||
|
22
app/Events/Banking/TransactionCreated.php
Normal file
22
app/Events/Banking/TransactionCreated.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Banking;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class TransactionCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $transaction;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $transaction
|
||||
*/
|
||||
public function __construct($transaction)
|
||||
{
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
}
|
22
app/Events/Banking/TransactionCreating.php
Normal file
22
app/Events/Banking/TransactionCreating.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Banking;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class TransactionCreating
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
@ -198,7 +198,7 @@ class Reconciliations extends Controller
|
||||
$total = $account->opening_balance;
|
||||
|
||||
// Sum income transactions
|
||||
$transactions = $account->income_transacions()->whereDate('paid_at', '<', $started_at)->get();
|
||||
$transactions = $account->income_transactions()->whereDate('paid_at', '<', $started_at)->get();
|
||||
foreach ($transactions as $item) {
|
||||
$total += $item->amount;
|
||||
}
|
||||
|
65
app/Http/Controllers/Modals/Accounts.php
Normal file
65
app/Http/Controllers/Modals/Accounts.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Modals;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use App\Http\Requests\Banking\Account as Request;
|
||||
use App\Jobs\Banking\CreateAccount;
|
||||
use App\Models\Banking\Account;
|
||||
use App\Models\Setting\Currency;
|
||||
|
||||
class Accounts extends Controller
|
||||
{
|
||||
/**
|
||||
* Instantiate a new controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Add CRUD permission check
|
||||
$this->middleware('permission:create-banking-accounts')->only(['create', 'store', 'duplicate', 'import']);
|
||||
$this->middleware('permission:read-banking-accounts')->only(['index', 'show', 'edit', 'export']);
|
||||
$this->middleware('permission:update-banking-accounts')->only(['update', 'enable', 'disable']);
|
||||
$this->middleware('permission:delete-banking-accounts')->only('destroy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$currencies = Currency::enabled()->pluck('name', 'code');
|
||||
|
||||
$currency = Currency::where('code', '=', setting('default.currency'))->first();
|
||||
|
||||
$html = view('modals.accounts.create', compact('currencies', 'currency'))->render();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'error' => false,
|
||||
'message' => 'null',
|
||||
'html' => $html,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request['enabled'] = 1;
|
||||
|
||||
$response = $this->ajaxDispatch(new CreateAccount($request));
|
||||
|
||||
if ($response['success']) {
|
||||
$response['message'] = trans('messages.success.added', ['type' => trans_choice('general.accounts', 1)]);
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
}
|
||||
}
|
@ -100,7 +100,7 @@ class Invoices extends Controller
|
||||
if ($invoice->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $invoice->currency_code;
|
||||
|
||||
$amount = $item->getAmountConvertedFromCustomDefault();
|
||||
$amount = $item->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
@ -129,7 +129,7 @@ class Invoices extends Controller
|
||||
if ($invoice->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $invoice->currency_code;
|
||||
|
||||
$amount = $item->getAmountConvertedFromCustomDefault();
|
||||
$amount = $item->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
|
@ -108,7 +108,9 @@ class Bills extends Controller
|
||||
|
||||
$categories = Category::type('expense')->enabled()->orderBy('name')->pluck('name', 'id');
|
||||
|
||||
return view('purchases.bills.create', compact('vendors', 'currencies', 'currency', 'items', 'taxes', 'categories'));
|
||||
$number = $this->getNextBillNumber();
|
||||
|
||||
return view('purchases.bills.create', compact('vendors', 'currencies', 'currency', 'items', 'taxes', 'categories', 'number'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,7 +371,7 @@ class Bills extends Controller
|
||||
if ($bill->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $bill->currency_code;
|
||||
|
||||
$amount = $item->getAmountConvertedFromCustomDefault();
|
||||
$amount = $item->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
|
@ -447,7 +447,7 @@ class Invoices extends Controller
|
||||
if ($invoice->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $invoice->currency_code;
|
||||
|
||||
$amount = $item->getAmountConvertedFromCustomDefault();
|
||||
$amount = $item->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
|
@ -22,15 +22,10 @@ class Money
|
||||
$sale_price = $request->get('sale_price');
|
||||
$purchase_price = $request->get('purchase_price');
|
||||
$opening_balance = $request->get('opening_balance');
|
||||
$currency_code = $request->get('currency_code');
|
||||
$items = $request->get('items');
|
||||
|
||||
if (empty($currency_code)) {
|
||||
$currency_code = setting('default.currency');
|
||||
}
|
||||
|
||||
if (!empty($amount)) {
|
||||
$amount = money($request->get('amount'), $currency_code)->getAmount();
|
||||
$amount = money($amount)->getAmount();
|
||||
|
||||
$request->request->set('amount', $amount);
|
||||
}
|
||||
@ -42,11 +37,7 @@ class Money
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($item['currency']) && $item['currency'] != $currency_code) {
|
||||
$items[$key]['price'] = money($item['price'], $item['currency'])->getAmount();
|
||||
} else {
|
||||
$items[$key]['price'] = money($item['price'], $currency_code)->getAmount();
|
||||
}
|
||||
$items[$key]['price'] = money($item['price'])->getAmount();
|
||||
}
|
||||
|
||||
$request->request->set('items', $items);
|
||||
@ -54,24 +45,10 @@ class Money
|
||||
}
|
||||
|
||||
if (isset($opening_balance)) {
|
||||
$opening_balance = money($opening_balance, $currency_code)->getAmount();
|
||||
$opening_balance = money($opening_balance)->getAmount();
|
||||
|
||||
$request->request->set('opening_balance', $opening_balance);
|
||||
}
|
||||
|
||||
/* check item price use money
|
||||
if (isset($sale_price)) {
|
||||
$sale_price = money($sale_price, $currency_code)->getAmount();
|
||||
|
||||
$request->request->set('sale_price', $sale_price);
|
||||
}
|
||||
|
||||
if (isset($purchase_price)) {
|
||||
$purchase_price = money($purchase_price, $currency_code)->getAmount();
|
||||
|
||||
$request->request->set('purchase_price', $purchase_price);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
@ -37,7 +37,7 @@ class Contact extends FormRequest
|
||||
$id = null;
|
||||
}
|
||||
|
||||
if (!empty($this->request->get('create_user')) && empty($this->request->get('user_id'))) {
|
||||
if (($this->request->get('create_user', 'false') === 'true') && empty($this->request->get('user_id'))) {
|
||||
$required = 'required|';
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ class CreateDocumentTransaction extends Job
|
||||
$default_amount_model->currency_code = $this->request['currency_code'];
|
||||
$default_amount_model->currency_rate = $currencies[$this->request['currency_code']];
|
||||
|
||||
$default_amount = (double) $default_amount_model->getDivideConvertedAmount();
|
||||
$default_amount = (double) $default_amount_model->getAmountConvertedToDefault();
|
||||
|
||||
$convert_amount_model = new Transaction();
|
||||
$convert_amount_model->default_currency_code = $this->request['currency_code'];
|
||||
@ -100,7 +100,7 @@ class CreateDocumentTransaction extends Job
|
||||
$convert_amount_model->currency_code = $this->model->currency_code;
|
||||
$convert_amount_model->currency_rate = $currencies[$this->model->currency_code];
|
||||
|
||||
$amount = (double) $convert_amount_model->getAmountConvertedFromCustomDefault();
|
||||
$amount = (double) $convert_amount_model->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$total_amount -= $this->model->paid;
|
||||
@ -126,7 +126,7 @@ class CreateDocumentTransaction extends Job
|
||||
$error_amount_model->currency_code = $this->model->currency_code;
|
||||
$error_amount_model->currency_rate = $currencies[$this->model->currency_code];
|
||||
|
||||
$error_amount = (double) $error_amount_model->getDivideConvertedAmount();
|
||||
$error_amount = (double) $error_amount_model->getAmountConvertedToDefault();
|
||||
|
||||
$convert_amount_model = new Transaction();
|
||||
$convert_amount_model->default_currency_code = $this->model->currency_code;
|
||||
@ -134,7 +134,7 @@ class CreateDocumentTransaction extends Job
|
||||
$convert_amount_model->currency_code = $this->request['currency_code'];
|
||||
$convert_amount_model->currency_rate = $currencies[$this->request['currency_code']];
|
||||
|
||||
$error_amount = (double) $convert_amount_model->getAmountConvertedFromCustomDefault();
|
||||
$error_amount = (double) $convert_amount_model->getAmountConvertedFromDefault();
|
||||
}
|
||||
|
||||
$message = trans('messages.error.over_payment', ['amount' => money($error_amount, $this->request['currency_code'], true)]);
|
||||
|
@ -3,12 +3,16 @@
|
||||
namespace App\Jobs\Banking;
|
||||
|
||||
use App\Abstracts\Job;
|
||||
use App\Events\Banking\TransactionCreated;
|
||||
use App\Events\Banking\TransactionCreating;
|
||||
use App\Models\Banking\Transaction;
|
||||
|
||||
class CreateTransaction extends Job
|
||||
{
|
||||
protected $request;
|
||||
|
||||
protected $transaction;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
@ -26,18 +30,22 @@ class CreateTransaction extends Job
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$transaction = Transaction::create($this->request->all());
|
||||
event(new TransactionCreating($this->request));
|
||||
|
||||
$this->transaction = Transaction::create($this->request->all());
|
||||
|
||||
// Upload attachment
|
||||
if ($this->request->file('attachment')) {
|
||||
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
|
||||
|
||||
$transaction->attachMedia($media, 'attachment');
|
||||
$this->transaction->attachMedia($media, 'attachment');
|
||||
}
|
||||
|
||||
// Recurring
|
||||
$transaction->createRecurring();
|
||||
$this->transaction->createRecurring();
|
||||
|
||||
return $transaction;
|
||||
event(new TransactionCreated($this->transaction));
|
||||
|
||||
return $this->transaction;
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class CreateTransfer extends Job
|
||||
$default_amount_model->currency_code = $expense_currency_code;
|
||||
$default_amount_model->currency_rate = $currencies[$expense_currency_code];
|
||||
|
||||
$default_amount = $default_amount_model->getAmountDivided();
|
||||
$default_amount = $default_amount_model->getAmountConvertedToDefault();
|
||||
}
|
||||
|
||||
$transfer_amount = new Transfer();
|
||||
@ -74,7 +74,7 @@ class CreateTransfer extends Job
|
||||
$transfer_amount->currency_code = $income_currency_code;
|
||||
$transfer_amount->currency_rate = $currencies[$income_currency_code];
|
||||
|
||||
$amount = $transfer_amount->getAmountConvertedFromCustomDefault();
|
||||
$amount = $transfer_amount->getAmountConvertedFromDefault();
|
||||
} else {
|
||||
$amount = $this->request->get('amount');
|
||||
}
|
||||
|
@ -41,6 +41,12 @@ class DeleteTransaction extends Job
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
if ($this->transaction->reconciled) {
|
||||
$message = trans('messages.warning.reconciled_tran');
|
||||
|
||||
throw new \Exception($message);
|
||||
}
|
||||
|
||||
if ($this->transaction->category->id == Category::transfer()) {
|
||||
throw new \Exception('Unauthorized');
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ class UpdateTransaction extends Job
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->authorize();
|
||||
|
||||
$this->transaction->update($this->request->all());
|
||||
|
||||
// Upload attachment
|
||||
@ -44,4 +46,18 @@ class UpdateTransaction extends Job
|
||||
|
||||
return $this->transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this action is applicable.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
if ($this->transaction->reconciled) {
|
||||
$message = trans('messages.warning.reconciled_tran');
|
||||
|
||||
throw new \Exception($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ class UpdateTransfer extends Job
|
||||
$default_amount_model->currency_code = $expense_currency_code;
|
||||
$default_amount_model->currency_rate = $currencies[$expense_currency_code];
|
||||
|
||||
$default_amount = $default_amount_model->getDivideConvertedAmount();
|
||||
$default_amount = $default_amount_model->getAmountConvertedToDefault();
|
||||
}
|
||||
|
||||
$transfer_amount = new Transfer();
|
||||
@ -81,7 +81,7 @@ class UpdateTransfer extends Job
|
||||
$transfer_amount->currency_code = $income_currency_code;
|
||||
$transfer_amount->currency_rate = $currencies[$income_currency_code];
|
||||
|
||||
$amount = $transfer_amount->getAmountConvertedFromCustomDefault();
|
||||
$amount = $transfer_amount->getAmountConvertedFromDefault();
|
||||
} else {
|
||||
$amount = $this->request->get('amount');
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class CreateContact extends Job
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (!empty($this->request->input('create_user'))) {
|
||||
if ($this->request->get('create_user', 'false') === 'true') {
|
||||
$this->createUser();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ class UpdateContact extends Job
|
||||
{
|
||||
$this->authorize();
|
||||
|
||||
if (!empty($this->request->input('create_user'))) {
|
||||
if ($this->request->get('create_user', 'false') === 'true') {
|
||||
$this->createUser();
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ namespace App\Jobs\Purchase;
|
||||
|
||||
use App\Abstracts\Job;
|
||||
use App\Models\Purchase\Bill;
|
||||
use App\Observers\Transaction;
|
||||
|
||||
class DeleteBill extends Job
|
||||
{
|
||||
@ -26,7 +27,9 @@ class DeleteBill extends Job
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
session(['deleting_bill' => true]);
|
||||
$this->authorize();
|
||||
|
||||
Transaction::mute();
|
||||
|
||||
$this->deleteRelationships($this->bill, [
|
||||
'items', 'item_taxes', 'histories', 'transactions', 'recurring', 'totals'
|
||||
@ -34,8 +37,22 @@ class DeleteBill extends Job
|
||||
|
||||
$this->bill->delete();
|
||||
|
||||
session()->forget('deleting_bill');
|
||||
Transaction::unmute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this action is applicable.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
if ($this->bill->transactions()->isReconciled()->count()) {
|
||||
$message = trans('messages.warning.reconciled_doc', ['type' => trans_choice('general.bills', 1)]);
|
||||
|
||||
throw new \Exception($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace App\Jobs\Sale;
|
||||
|
||||
use App\Abstracts\Job;
|
||||
use App\Models\Sale\Invoice;
|
||||
use App\Observers\Transaction;
|
||||
|
||||
class DeleteInvoice extends Job
|
||||
{
|
||||
@ -26,7 +27,9 @@ class DeleteInvoice extends Job
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
session(['deleting_invoice' => true]);
|
||||
$this->authorize();
|
||||
|
||||
Transaction::mute();
|
||||
|
||||
$this->deleteRelationships($this->invoice, [
|
||||
'items', 'item_taxes', 'histories', 'transactions', 'recurring', 'totals'
|
||||
@ -34,8 +37,22 @@ class DeleteInvoice extends Job
|
||||
|
||||
$this->invoice->delete();
|
||||
|
||||
session()->forget('deleting_invoice');
|
||||
Transaction::unmute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this action is applicable.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
if ($this->invoice->transactions()->isReconciled()->count()) {
|
||||
$message = trans('messages.warning.reconciled_doc', ['type' => trans_choice('general.invoices', 1)]);
|
||||
|
||||
throw new \Exception($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
23
app/Listeners/Purchase/IncreaseNextBillNumber.php
Normal file
23
app/Listeners/Purchase/IncreaseNextBillNumber.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners\Purchase;
|
||||
|
||||
use App\Events\Purchase\BillCreated as Event;
|
||||
use App\Traits\Purchases;
|
||||
|
||||
class IncreaseNextBillNumber
|
||||
{
|
||||
use Purchases;
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Event $event)
|
||||
{
|
||||
// Update next bill number
|
||||
$this->increaseNextBillNumber();
|
||||
}
|
||||
}
|
100
app/Listeners/Update/V20/Version205.php
Normal file
100
app/Listeners/Update/V20/Version205.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners\Update\V20;
|
||||
|
||||
use App\Abstracts\Listeners\Update as Listener;
|
||||
use App\Events\Install\UpdateFinished as Event;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Version205 extends Listener
|
||||
{
|
||||
const ALIAS = 'core';
|
||||
|
||||
const VERSION = '2.0.5';
|
||||
|
||||
protected $items;
|
||||
|
||||
protected $categories;
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Event $event)
|
||||
{
|
||||
if ($this->skipThisUpdate($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->items = [];
|
||||
|
||||
$this->updateBillItems();
|
||||
|
||||
$this->updateInvoiceItems();
|
||||
}
|
||||
|
||||
protected function updateBillItems()
|
||||
{
|
||||
$bill_items = DB::table('bill_items')->whereNull('deleted_at')->where('item_id', 0)->cursor();
|
||||
|
||||
foreach ($bill_items as $bill_item) {
|
||||
$item_id = $this->getItemId($bill_item);
|
||||
|
||||
DB::table('bill_items')
|
||||
->where('id', $bill_item->id)
|
||||
->update(['item_id' => $item_id]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateInvoiceItems()
|
||||
{
|
||||
$invoice_items = DB::table('invoice_items')->whereNull('deleted_at')->where('item_id', 0)->cursor();
|
||||
|
||||
foreach ($invoice_items as $invoice_item) {
|
||||
$item_id = $this->getItemId($invoice_item);
|
||||
|
||||
DB::table('invoice_items')
|
||||
->where('id', $invoice_item->id)
|
||||
->update(['item_id' => $item_id]);
|
||||
|
||||
DB::table('items')
|
||||
->where('id', $item_id)
|
||||
->update(['sale_price' => $invoice_item->price]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getItemId($item)
|
||||
{
|
||||
// Set category_id for company.
|
||||
if (!isset($this->categories[$item->company_id])) {
|
||||
$this->categories[$item->company_id] = DB::table('categories')->where('company_id', $item->company_id)->where('type', 'item')->first()->id;
|
||||
}
|
||||
|
||||
// Return set item_id for item name.
|
||||
if (isset($this->items[$item->company_id]) && in_array($item->name, $this->items[$item->company_id])) {
|
||||
return array_search($item->name, $this->items[$item->company_id]);
|
||||
}
|
||||
|
||||
// Insert new item.
|
||||
$item_id = DB::table('items')->insertGetId([
|
||||
'company_id' => $item->company_id,
|
||||
'name' => $item->name,
|
||||
'description' => null,
|
||||
'sale_price' => $item->price,
|
||||
'purchase_price' => $item->price,
|
||||
'category_id' => $this->categories[$item->company_id],
|
||||
'tax_id' => null,
|
||||
'enabled' => 1,
|
||||
'created_at' => $item->created_at,
|
||||
'updated_at' => $item->updated_at,
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
|
||||
// Set item_id for item name.
|
||||
$this->items[$item->company_id][$item_id] = $item->name;
|
||||
|
||||
return $item_id;
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ class Account extends Model
|
||||
return $this->transactions()->where('type', 'expense');
|
||||
}
|
||||
|
||||
public function income_transacions()
|
||||
public function income_transactions()
|
||||
{
|
||||
return $this->transactions()->where('type', 'income');
|
||||
}
|
||||
@ -81,7 +81,7 @@ class Account extends Model
|
||||
$total = $this->opening_balance;
|
||||
|
||||
// Sum Incomes
|
||||
$total += $this->income_transacions->sum('amount');
|
||||
$total += $this->income_transactions->sum('amount');
|
||||
|
||||
// Subtract Expenses
|
||||
$total -= $this->expense_transactions->sum('amount');
|
||||
|
@ -174,6 +174,28 @@ class Transaction extends Model
|
||||
return $query->sum('amount');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only reconciled.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopeIsReconciled($query)
|
||||
{
|
||||
return $query->where('reconciled', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only not reconciled.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopeIsNotReconciled($query)
|
||||
{
|
||||
return $query->where('reconciled', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert amount to double.
|
||||
*
|
||||
@ -211,9 +233,4 @@ class Transaction extends Model
|
||||
|
||||
return $this->getMedia('attachment')->last();
|
||||
}
|
||||
|
||||
public function getDivideConvertedAmount($format = false)
|
||||
{
|
||||
return $this->divide($this->amount, $this->currency_code, $this->currency_rate, $format);
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ class Contact extends Model
|
||||
$this->$collection()->accrued()->notPaid()->each(function ($item) use (&$amount) {
|
||||
$unpaid = $item->amount - $item->paid;
|
||||
|
||||
$amount += $this->convertFromDefault($unpaid, $item->currency_code, $item->currency_rate, false);
|
||||
$amount += $this->convertFromDefault($unpaid, $item->currency_code, $item->currency_rate);
|
||||
});
|
||||
|
||||
return $amount;
|
||||
|
@ -99,5 +99,6 @@ class Bill extends DocumentModel
|
||||
public function onCloning($src, $child = null)
|
||||
{
|
||||
$this->status = 'draft';
|
||||
$this->bill_number = $this->getNextBillNumber();
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,15 @@ class BillItem extends Model
|
||||
*/
|
||||
public $cloneable_relations = ['taxes'];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::retrieved(function($model) {
|
||||
$model->setTaxIds();
|
||||
});
|
||||
}
|
||||
|
||||
public function bill()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Purchase\Bill');
|
||||
@ -74,4 +83,20 @@ class BillItem extends Model
|
||||
{
|
||||
$this->attributes['tax'] = (double) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert tax to Array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTaxIds()
|
||||
{
|
||||
$tax_ids = [];
|
||||
|
||||
foreach ($this->taxes as $tax) {
|
||||
$tax_ids[] = (string) $tax->tax_id;
|
||||
}
|
||||
|
||||
$this->setAttribute('tax_id', $tax_ids);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,15 @@ class InvoiceItem extends Model
|
||||
*/
|
||||
public $cloneable_relations = ['taxes'];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::retrieved(function($model) {
|
||||
$model->setTaxIds();
|
||||
});
|
||||
}
|
||||
|
||||
public function invoice()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Sale\Invoice');
|
||||
@ -73,4 +82,20 @@ class InvoiceItem extends Model
|
||||
{
|
||||
$this->attributes['tax'] = (double) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert tax to Array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTaxIds()
|
||||
{
|
||||
$tax_ids = [];
|
||||
|
||||
foreach ($this->taxes as $tax) {
|
||||
$tax_ids[] = (string) $tax->tax_id;
|
||||
}
|
||||
|
||||
$this->setAttribute('tax_id', $tax_ids);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class Category extends Model
|
||||
return $this->transactions()->where('type', 'expense');
|
||||
}
|
||||
|
||||
public function income_transacions()
|
||||
public function income_transactions()
|
||||
{
|
||||
return $this->transactions()->where('type', 'income');
|
||||
}
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Abstracts\Observer;
|
||||
use App\Jobs\Purchase\CreateBillHistory;
|
||||
use App\Jobs\Sale\CreateInvoiceHistory;
|
||||
use App\Models\Banking\Transaction as Model;
|
||||
use App\Traits\Jobs;
|
||||
|
||||
class Transaction
|
||||
class Transaction extends Observer
|
||||
{
|
||||
use Jobs;
|
||||
|
||||
@ -30,10 +31,6 @@ class Transaction
|
||||
|
||||
protected function updateInvoice($transaction)
|
||||
{
|
||||
if (session('deleting_invoice')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$invoice = $transaction->invoice;
|
||||
|
||||
$invoice->status = ($invoice->transactions->count() > 1) ? 'partial' : 'sent';
|
||||
@ -45,10 +42,6 @@ class Transaction
|
||||
|
||||
protected function updateBill($transaction)
|
||||
{
|
||||
if (session('deleting_bill')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bill = $transaction->bill;
|
||||
|
||||
$bill->status = ($bill->transactions->count() > 1) ? 'partial' : 'received';
|
||||
|
@ -16,6 +16,7 @@ class Event extends Provider
|
||||
'App\Listeners\Update\CreateModuleUpdatedHistory',
|
||||
'App\Listeners\Update\V20\Version200',
|
||||
'App\Listeners\Update\V20\Version203',
|
||||
'App\Listeners\Update\V20\Version205',
|
||||
],
|
||||
'Illuminate\Auth\Events\Login' => [
|
||||
'App\Listeners\Auth\Login',
|
||||
@ -25,6 +26,7 @@ class Event extends Provider
|
||||
],
|
||||
'App\Events\Purchase\BillCreated' => [
|
||||
'App\Listeners\Purchase\CreateBillCreatedHistory',
|
||||
'App\Listeners\Purchase\IncreaseNextBillNumber',
|
||||
],
|
||||
'App\Events\Purchase\BillReceived' => [
|
||||
'App\Listeners\Purchase\MarkBillReceived',
|
||||
|
@ -3,46 +3,31 @@
|
||||
namespace App\Traits;
|
||||
|
||||
use Akaunting\Money\Money;
|
||||
use Akaunting\Money\Currency;
|
||||
|
||||
trait Currencies
|
||||
{
|
||||
public function convert($amount, $from, $to, $rate, $format = false)
|
||||
public function convert($method, $amount, $from, $to, $rate, $format = false)
|
||||
{
|
||||
$money = Money::$from($amount, $format);
|
||||
$money = Money::$to($amount, $format);
|
||||
|
||||
// No need to convert same currency
|
||||
if ($from == $to) {
|
||||
return $format ? $money->format() : $money->getAmount();
|
||||
}
|
||||
|
||||
$money = $money->convert(new Currency($to), (double) $rate);
|
||||
$money = $money->$method((double) $rate);
|
||||
|
||||
return $format ? $money->format() : $money->getAmount();
|
||||
}
|
||||
|
||||
public function divide($amount, $code, $rate, $format = false)
|
||||
{
|
||||
$money = Money::$code($amount, $format);
|
||||
|
||||
$money = $money->divide((double) $rate);
|
||||
|
||||
return $format ? $money->format() : $money->getAmount();
|
||||
}
|
||||
|
||||
public function getAmount($with_tax = true)
|
||||
{
|
||||
return $with_tax ? $this->amount : (isset($this->amount_without_tax) ? $this->amount_without_tax : $this->amount);
|
||||
}
|
||||
|
||||
public function convertToDefault($amount, $from, $rate, $format = false)
|
||||
{
|
||||
return $this->convert($amount, $from, $this->getDefaultCurrency(), $rate, $format);
|
||||
return $this->convert('divide', $amount, $from, $this->getDefaultCurrency(), $rate, $format);
|
||||
}
|
||||
|
||||
public function convertFromDefault($amount, $to, $rate, $format = false)
|
||||
{
|
||||
return $this->convert($amount, $this->getDefaultCurrency(), $to, $rate, $format);
|
||||
return $this->convert('multiply', $amount, $this->getDefaultCurrency(), $to, $rate, $format);
|
||||
}
|
||||
|
||||
public function getAmountConvertedToDefault($format = false, $with_tax = true)
|
||||
@ -55,18 +40,13 @@ trait Currencies
|
||||
return $this->convertFromDefault($this->getAmount($with_tax), $this->currency_code, $this->currency_rate, $format);
|
||||
}
|
||||
|
||||
public function getAmountConvertedFromCustomDefault($format = false, $with_tax = true)
|
||||
public function getAmount($with_tax = true)
|
||||
{
|
||||
return $this->convert($this->getAmount($with_tax), $this->default_currency_code, $this->currency_code, $this->currency_rate, $format);
|
||||
return $with_tax ? $this->amount : (isset($this->amount_without_tax) ? $this->amount_without_tax : $this->amount);
|
||||
}
|
||||
|
||||
public function getAmountDivided($format = false, $with_tax = true)
|
||||
public function getDefaultCurrency()
|
||||
{
|
||||
return $this->divide($this->getAmount($with_tax), $this->currency_code, $this->currency_rate, $format);
|
||||
}
|
||||
|
||||
protected function getDefaultCurrency()
|
||||
{
|
||||
return setting('default.currency', 'USD');
|
||||
return !empty($this->default_currency_code) ? $this->default_currency_code : setting('default.currency', 'USD');
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,35 @@ trait Jobs
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a job to its appropriate handler and return a response array for ajax calls.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @return mixed
|
||||
*/
|
||||
public function ajaxDispatch($job)
|
||||
{
|
||||
try {
|
||||
$data = $this->dispatch($job);
|
||||
|
||||
$response = [
|
||||
'success' => true,
|
||||
'error' => false,
|
||||
'data' => $data,
|
||||
'message' => '',
|
||||
];
|
||||
} catch(\Exception $e) {
|
||||
$response = [
|
||||
'success' => false,
|
||||
'error' => true,
|
||||
'data' => null,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function getDispatchFunction()
|
||||
{
|
||||
$config = config('queue.default');
|
||||
|
@ -4,6 +4,33 @@ namespace App\Traits;
|
||||
|
||||
trait Purchases
|
||||
{
|
||||
/**
|
||||
* Generate next bill number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNextBillNumber()
|
||||
{
|
||||
$prefix = setting('bill.number_prefix', 'BIL-');
|
||||
$next = setting('bill.number_next', '1');
|
||||
$digit = setting('bill.number_digit', '5');
|
||||
|
||||
$number = $prefix . str_pad($next, $digit, '0', STR_PAD_LEFT);
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the next bill number
|
||||
*/
|
||||
public function increaseNextBillNumber()
|
||||
{
|
||||
$next = setting('bill.number_next', 1) + 1;
|
||||
|
||||
setting(['bill.number_next' => $next]);
|
||||
setting()->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of bill statuses
|
||||
*
|
||||
|
@ -17,7 +17,7 @@ trait Recurring
|
||||
}
|
||||
|
||||
$frequency = ($request['recurring_frequency'] != 'custom') ? $request['recurring_frequency'] : $request['recurring_custom_frequency'];
|
||||
$interval = ($request['recurring_frequency'] != 'custom') ? 1 : (int) $request['recurring_interval'];
|
||||
$interval = (($request['recurring_frequency'] != 'custom') || ($request['recurring_interval'] < 1)) ? 1 : (int) $request['recurring_interval'];
|
||||
$started_at = $request->get('paid_at') ?: ($request->get('invoiced_at') ?: $request->get('billed_at'));
|
||||
|
||||
$this->recurring()->create([
|
||||
@ -39,7 +39,7 @@ trait Recurring
|
||||
}
|
||||
|
||||
$frequency = ($request['recurring_frequency'] != 'custom') ? $request['recurring_frequency'] : $request['recurring_custom_frequency'];
|
||||
$interval = ($request['recurring_frequency'] != 'custom') ? 1 : (int) $request['recurring_interval'];
|
||||
$interval = (($request['recurring_frequency'] != 'custom') || ($request['recurring_interval'] < 1)) ? 1 : (int) $request['recurring_interval'];
|
||||
$started_at = $request->get('paid_at') ?: ($request->get('invoiced_at') ?: $request->get('billed_at'));
|
||||
|
||||
$recurring = $this->recurring();
|
||||
|
@ -6,8 +6,8 @@ use Akaunting\Module\Module;
|
||||
use App\Traits\SiteApi;
|
||||
use Cache;
|
||||
use Date;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Support\Arr;
|
||||
use Parsedown;
|
||||
|
||||
class Versions
|
||||
{
|
||||
@ -27,8 +27,6 @@ class Versions
|
||||
return $output;
|
||||
}
|
||||
|
||||
$parsedown = new Parsedown();
|
||||
|
||||
$releases = json_decode($json);
|
||||
|
||||
foreach ($releases as $release) {
|
||||
@ -46,7 +44,7 @@ class Versions
|
||||
|
||||
$output .= '<h2><span class="badge badge-pill badge-success">' . $release->tag_name . '</span></h2>';
|
||||
|
||||
$output .= $parsedown->text($release->body);
|
||||
$output .= Markdown::convertToHtml($release->body);
|
||||
|
||||
$output .= '<hr>';
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ class IncomeByCategory extends Widget
|
||||
|
||||
public function show()
|
||||
{
|
||||
Category::with('income_transacions')->type('income')->each(function ($category) {
|
||||
Category::with('income_transactions')->type('income')->each(function ($category) {
|
||||
$amount = 0;
|
||||
|
||||
$this->applyFilters($category->income_transacions())->each(function ($transaction) use (&$amount) {
|
||||
$this->applyFilters($category->income_transactions())->each(function ($transaction) use (&$amount) {
|
||||
$amount += $transaction->getAmountConvertedToDefault();
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user