v2 first commit

This commit is contained in:
denisdulici
2019-11-16 10:21:14 +03:00
parent 5b23e9c2c4
commit 6d50fa8442
3075 changed files with 3451681 additions and 65594 deletions

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use App\Models\Auth\Permission;
use Artisan;
class CreatePermission extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Permission
*/
public function handle()
{
$permission = Permission::create($this->request->all());
Artisan::call('cache:clear');
return $permission;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use App\Models\Auth\Role;
use Artisan;
class CreateRole extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Permission
*/
public function handle()
{
$role = Role::create($this->request->input());
if ($this->request->has('permissions')) {
$role->permissions()->attach($this->request->get('permissions'));
}
Artisan::call('cache:clear');
return $role;
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use App\Models\Auth\User;
use Artisan;
class CreateUser extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Permission
*/
public function handle()
{
$user = User::create($this->request->input());
if ($this->request->has('permissions')) {
$user->permissions()->attach($this->request->get('permissions'));
}
// Upload picture
if ($this->request->file('picture')) {
$media = $this->getMedia($this->request->file('picture'), 'users');
$user->attachMedia($media, 'picture');
}
// Attach roles
$user->roles()->attach($this->request->get('roles'));
// Attach companies
$user->companies()->attach($this->request->get('companies'));
Artisan::call('cache:clear');
// Add User Dashboard
foreach ($user->companies as $company) {
Artisan::call('user:seed', [
'user' => $user->id,
'company' => $company->id,
]);
}
Artisan::call('cache:clear');
return $user;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use Artisan;
class DeletePermission extends Job
{
protected $permission;
/**
* Create a new job instance.
*
* @param $permission
*/
public function __construct($permission)
{
$this->permission = $permission;
}
/**
* Execute the job.
*
* @return boolean
*/
public function handle()
{
$this->permission->delete();
Artisan::call('cache:clear');
return true;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use Artisan;
class DeleteRole extends Job
{
protected $role;
/**
* Create a new job instance.
*
* @param $role
*/
public function __construct($role)
{
$this->role = $role;
}
/**
* Execute the job.
*
* @return boolean
*/
public function handle()
{
$this->role->delete();
Artisan::call('cache:clear');
return true;
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use Artisan;
class DeleteUser extends Job
{
protected $user;
/**
* Create a new job instance.
*
* @param $user
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* @return boolean
*/
public function handle()
{
$this->authorize();
$this->user->delete();
Artisan::call('cache:clear');
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
// Can't delete yourself
if ($this->user->id == user()->id) {
$message = trans('auth.error.self_delete');
throw new \Exception($message);
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use App\Models\Auth\Permission;
use Artisan;
class UpdatePermission extends Job
{
protected $permission;
protected $request;
/**
* Create a new job instance.
*
* @param $permission
* @param $request
*/
public function __construct($permission, $request)
{
$this->permission = $permission;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Permission
*/
public function handle()
{
$this->permission->update($this->request->all());
Artisan::call('cache:clear');
return $this->permission;
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use App\Models\Auth\Role;
use Artisan;
class UpdateRole extends Job
{
protected $role;
protected $request;
/**
* Create a new job instance.
*
* @param $role
* @param $request
*/
public function __construct($role, $request)
{
$this->role = $role;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Role
*/
public function handle()
{
$this->role->update($this->request->all());
if ($this->request->has('permissions')) {
$this->role->permissions()->sync($this->request->get('permissions'));
}
Artisan::call('cache:clear');
return $this->role;
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\Job;
use App\Models\Auth\User;
use Artisan;
class UpdateUser extends Job
{
protected $user;
protected $request;
/**
* Create a new job instance.
*
* @param $user
* @param $request
*/
public function __construct($user, $request)
{
$this->user = $user;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return User
*/
public function handle()
{
$this->authorize();
// Do not reset password if not entered/changed
if (empty($this->request['password'])) {
unset($this->request['password']);
unset($this->request['password_confirmation']);
}
$this->user->update($this->request->input());
// Upload picture
if ($this->request->file('picture')) {
$media = $this->getMedia($this->request->file('picture'), 'users');
$this->user->attachMedia($media, 'picture');
}
// Sync roles
if ($this->request->has('roles')) {
$this->user->roles()->sync($this->request->get('roles'));
}
// Sync companies
if ($this->request->has('companies')) {
$this->user->companies()->sync($this->request->get('companies'));
}
Artisan::call('cache:clear');
return $this->user;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
// Can't disable yourself
if (($this->request->get('enabled', 1) == 0) && ($this->user->id == user()->id)) {
$message = trans('auth.error.self_disable');
throw new \Exception($message);
}
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Account;
class CreateAccount extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Account
*/
public function handle()
{
$account = Account::create($this->request->all());
// Set default account
if ($this->request['default_account']) {
setting()->set('default.account', $account->id);
setting()->save();
}
return $account;
}
}

View File

@@ -0,0 +1,213 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Jobs\Banking\CreateTransaction;
use App\Jobs\Expense\CreateBillHistory;
use App\Jobs\Income\CreateInvoiceHistory;
use App\Models\Banking\Transaction;
use App\Models\Income\Invoice;
use App\Models\Setting\Currency;
use Date;
class CreateDocumentTransaction extends Job
{
protected $model;
protected $request;
/**
* Create a new job instance.
*
* @param $model
* @param $request
*/
public function __construct($model, $request)
{
$this->model = $model;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Transaction
*/
public function handle()
{
$this->prepareRequest();
$this->checkAmount();
$transaction = $this->dispatch(new CreateTransaction($this->request));
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
$transaction->attachMedia($media, 'attachment');
}
$this->model->save();
$this->createHistory($transaction);
return $transaction;
}
protected function prepareRequest()
{
if ($this->request->missing('currency_code')) {
$this->request['currency_code'] = $this->model->currency_code;
}
$this->currency = Currency::where('code', $this->request['currency_code'])->first();
$this->request['type'] = ($this->model instanceof Invoice) ? 'income' : 'expense';
$this->request['currency_rate'] = $this->currency->rate;
$this->request['amount'] = isset($this->request['amount']) ? $this->request['amount'] : ($this->model->amount - $this->getPaidAmount());
$this->request['paid_at'] = isset($this->request['paid_at']) ? $this->request['paid_at'] : Date::now()->format('Y-m-d');
$this->request['company_id'] = isset($this->request['company_id']) ? $this->request['company_id'] : session('company_id');
$this->request['account_id'] = isset($this->request['account_id']) ? $this->request['account_id'] : setting('default.account');
$this->request['payment_method'] = isset($this->request['payment_method']) ? $this->request['payment_method'] : setting('default.payment_method');
$this->request['currency_code'] = isset($this->request['currency_code']) ? $this->request['currency_code'] : $this->model->currency_code;
$this->request['document_id'] = isset($this->request['document_id']) ? $this->request['document_id'] : $this->model->id;
$this->request['contact_id'] = isset($this->request['contact_id']) ? $this->request['contact_id'] : $this->model->contact_id;
$this->request['category_id'] = isset($this->request['category_id']) ? $this->request['category_id'] : $this->model->category_id;
$this->request['notify'] = isset($this->request['notify']) ? $this->request['notify'] : 0;
}
protected function checkAmount()
{
$currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
$total_amount = $this->model->amount;
$default_amount = (double) $this->request['amount'];
if ($this->model->currency_code == $this->request['currency_code']) {
$amount = $default_amount;
} else {
$default_amount_model = new Transaction();
$default_amount_model->default_currency_code = $this->model->currency_code;
$default_amount_model->amount = $default_amount;
$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();
$convert_amount_model = new Transaction();
$convert_amount_model->default_currency_code = $this->request['currency_code'];
$convert_amount_model->amount = $default_amount;
$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();
}
$total_amount -= $this->getPaidAmount();
// For amount cover integer
$multiplier = 1;
for ($i = 0; $i < $this->currency->precision; $i++) {
$multiplier *= 10;
}
$amount_check = (int) ($amount * $multiplier);
$total_amount_check = (int) (round($total_amount, $this->currency->precision) * $multiplier);
if ($amount_check > $total_amount_check) {
$error_amount = $total_amount;
if ($this->model->currency_code != $this->request['currency_code']) {
$error_amount_model = new Transaction();
$error_amount_model->default_currency_code = $this->request['currency_code'];
$error_amount_model->amount = $error_amount;
$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();
$convert_amount_model = new Transaction();
$convert_amount_model->default_currency_code = $this->model->currency_code;
$convert_amount_model->amount = $error_amount;
$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();
}
$message = trans('messages.error.over_payment', ['amount' => money($error_amount, $this->request['currency_code'], true)]);
throw new \Exception($message);
} else {
$this->setStatusCode($amount_check, $total_amount_check);
}
return true;
}
protected function getPaidAmount()
{
$paid = 0;
if (!$this->model->transactions->count()) {
return $paid;
}
$currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
foreach ($this->model->transactions as $item) {
$default_amount = $item->amount;
if ($this->model->currency_code == $item->currency_code) {
$amount = (double) $default_amount;
} else {
$default_amount_model = new Transaction();
$default_amount_model->default_currency_code = $this->model->currency_code;
$default_amount_model->amount = $default_amount;
$default_amount_model->currency_code = $item->currency_code;
$default_amount_model->currency_rate = $currencies[$item->currency_code];
$default_amount = (double) $default_amount_model->getDivideConvertedAmount();
$convert_amount_model = new Transaction();
$convert_amount_model->default_currency_code = $item->currency_code;
$convert_amount_model->amount = $default_amount;
$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();
}
$paid += $amount;
}
return $paid;
}
protected function setStatusCode($amount_check, $total_amount_check)
{
$column = ($this->model instanceof Invoice) ? 'invoice_status_code' : 'bill_status_code';
if ($amount_check == $total_amount_check) {
$this->model->$column = 'paid';
} else {
$this->model->$column = 'partial';
}
}
protected function createHistory($transaction)
{
$history_desc = money((double) $transaction->amount, (string) $transaction->currency_code, true)->format() . ' ' . trans_choice('general.payments', 1);
if ($this->model instanceof Invoice) {
$this->dispatch(new CreateInvoiceHistory($this->model, 0, $history_desc));
} else {
$this->dispatch(new CreateBillHistory($this->model, 0, $history_desc));
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Reconciliation;
class CreateReconciliation extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Reconciliation
*/
public function handle()
{
$reconcile = $this->request->get('reconcile');
$transactions = $this->request->get('transactions');
$reconciliation = Reconciliation::create([
'company_id' => session('company_id'),
'account_id' => $this->request->get('account_id'),
'started_at' => $this->request->get('started_at'),
'ended_at' => $this->request->get('ended_at'),
'closing_balance' => $this->request->get('closing_balance'),
'reconciled' => $reconcile ? 1 : 0,
]);
if ($transactions) {
foreach ($transactions as $key => $value) {
$t = explode('_', $key);
$m = '\\' . $t['1'];
$transaction = $m::find($t[0]);
$transaction->reconciled = 1;
$transaction->save();
}
}
return $reconciliation;
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Transaction;
class CreateTransaction extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Transaction
*/
public function handle()
{
$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');
}
// Recurring
$transaction->createRecurring();
return $transaction;
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Account;
use App\Models\Banking\Transaction;
use App\Models\Banking\Transfer;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
class CreateTransfer extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Transfer
*/
public function handle()
{
$currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
$expense_currency_code = Account::where('id', $this->request->get('from_account_id'))->pluck('currency_code')->first();
$income_currency_code = Account::where('id', $this->request->get('to_account_id'))->pluck('currency_code')->first();
$expense_transaction = Transaction::create([
'company_id' => $this->request['company_id'],
'type' => 'expense',
'account_id' => $this->request->get('from_account_id'),
'paid_at' => $this->request->get('transferred_at'),
'currency_code' => $expense_currency_code,
'currency_rate' => $currencies[$expense_currency_code],
'amount' => $this->request->get('amount'),
'contact_id' => 0,
'description' => $this->request->get('description'),
'category_id' => Category::transfer(), // Transfer Category ID
'payment_method' => $this->request->get('payment_method'),
'reference' => $this->request->get('reference'),
]);
// Convert amount if not same currency
if ($expense_currency_code != $income_currency_code) {
$default_currency = setting('default.currency', 'USD');
$default_amount = $this->request->get('amount');
if ($default_currency != $expense_currency_code) {
$default_amount_model = new Transfer();
$default_amount_model->default_currency_code = $default_currency;
$default_amount_model->amount = $this->request->get('amount');
$default_amount_model->currency_code = $expense_currency_code;
$default_amount_model->currency_rate = $currencies[$expense_currency_code];
$default_amount = $default_amount_model->getAmountDivided();
}
$transfer_amount = new Transfer();
$transfer_amount->default_currency_code = $expense_currency_code;
$transfer_amount->amount = $default_amount;
$transfer_amount->currency_code = $income_currency_code;
$transfer_amount->currency_rate = $currencies[$income_currency_code];
$amount = $transfer_amount->getAmountConvertedFromCustomDefault();
} else {
$amount = $this->request->get('amount');
}
$income_transaction = Transaction::create([
'company_id' => $this->request['company_id'],
'type' => 'income',
'account_id' => $this->request->get('to_account_id'),
'paid_at' => $this->request->get('transferred_at'),
'currency_code' => $income_currency_code,
'currency_rate' => $currencies[$income_currency_code],
'amount' => $amount,
'contact_id' => 0,
'description' => $this->request->get('description'),
'category_id' => Category::transfer(), // Transfer Category ID
'payment_method' => $this->request->get('payment_method'),
'reference' => $this->request->get('reference'),
]);
$transfer = Transfer::create([
'company_id' => $this->request['company_id'],
'expense_transaction_id' => $expense_transaction->id,
'income_transaction_id' => $income_transaction->id,
]);
return $transfer;
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
class DeleteAccount extends Job
{
protected $account;
/**
* Create a new job instance.
*
* @param $account
*/
public function __construct($account)
{
$this->account = $account;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->account->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if ($relationships = $this->getRelationships()) {
$message = trans('messages.warning.deleted', ['name' => $this->account->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'transactions' => 'transactions',
];
$relationships = $this->countRelationships($this->account, $rels);
if ($this->account->id == setting('default.account')) {
$relationships[] = strtolower(trans_choice('general.companies', 1));
}
return $relationships;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Transaction;
class DeleteReconciliation extends Job
{
protected $reconciliation;
/**
* Create a new job instance.
*
* @param $reconciliation
*/
public function __construct($reconciliation)
{
$this->reconciliation = $reconciliation;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->reconciliation->delete();
Transaction::where('account_id', $this->reconciliation->account_id)
->reconciled()
->whereBetween('paid_at', [$this->reconciliation->started_at, $this->reconciliation->ended_at])->each(function ($transaction) {
$transaction->reconciled = 0;
$transaction->save();
});
return true;
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Setting\Category;
class DeleteTransaction extends Job
{
protected $transaction;
/**
* Create a new job instance.
*
* @param $transaction
*/
public function __construct($transaction)
{
$this->transaction = $transaction;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->transaction->recurring()->delete();
$this->transaction->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if ($this->transaction->category->id == Category::transfer()) {
throw new \Exception('Unauthorized');
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
class DeleteTransfer extends Job
{
protected $transfer;
/**
* Create a new job instance.
*
* @param $transfer
*/
public function __construct($transfer)
{
$this->transfer = $transfer;
}
/**
* Execute the job.
*
* @return mixed
*/
public function handle()
{
$this->deleteRelationships($this->transfer, ['expense_transaction', 'income_transaction']);
$this->transfer->delete();
return true;
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Account;
class UpdateAccount extends Job
{
protected $account;
protected $request;
/**
* Create a new job instance.
*
* @param $account
* @param $request
*/
public function __construct($account, $request)
{
$this->account = $account;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Account
*/
public function handle()
{
$this->authorize();
$this->account->update($this->request->all());
// Set default account
if ($this->request['default_account']) {
setting()->set('default.account', $this->account->id);
setting()->save();
}
return $this->account;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if (!$relationships = $this->getRelationships()) {
return;
}
if ($this->account->currency_code != $this->request->get('currency_code')) {
$message = trans('messages.warning.disable_code', ['name' => $this->account->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
if (!$this->request->get('enabled') && ($this->account->id == setting('default.account'))) {
$relationships[] = strtolower(trans_choice('general.companies', 1));
$message = trans('messages.warning.disabled', ['name' => $this->account->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'transactions' => 'transactions',
];
return $this->countRelationships($this->account, $rels);
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Reconciliation;
class UpdateReconciliation extends Job
{
protected $reconciliation;
protected $request;
/**
* Create a new job instance.
*
* @param $reconciliation
* @param $request
*/
public function __construct($reconciliation, $request)
{
$this->reconciliation = $reconciliation;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Reconciliation
*/
public function handle()
{
$reconcile = $this->request->get('reconcile');
$transactions = $this->request->get('transactions');
$this->reconciliation->reconciled = $reconcile ? 1 : 0;
$this->reconciliation->save();
if ($transactions) {
foreach ($transactions as $key => $value) {
$t = explode('_', $key);
$m = '\\' . $t['1'];
$transaction = $m::find($t[0]);
$transaction->reconciled = 1;
$transaction->save();
}
}
return $this->reconciliation;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Transaction;
class UpdateTransaction extends Job
{
protected $transaction;
protected $request;
/**
* Create a new job instance.
*
* @param $transaction
* @param $request
*/
public function __construct($transaction, $request)
{
$this->transaction = $transaction;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Transaction
*/
public function handle()
{
$this->transaction->update($this->request->all());
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
$this->transaction->attachMedia($media, 'attachment');
}
// Recurring
$this->transaction->updateRecurring();
return $this->transaction;
}
}

View File

@@ -0,0 +1,112 @@
<?php
namespace App\Jobs\Banking;
use App\Abstracts\Job;
use App\Models\Banking\Account;
use App\Models\Banking\Transaction;
use App\Models\Banking\Transfer;
use App\Models\Setting\Category;
use App\Models\Setting\Currency;
class UpdateTransfer extends Job
{
protected $transfer;
protected $request;
/**
* Create a new job instance.
*
* @param $transfer
* @param $request
*/
public function __construct($transfer, $request)
{
$this->transfer = $transfer;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Transfer
*/
public function handle()
{
$currencies = Currency::enabled()->pluck('rate', 'code')->toArray();
$expense_currency_code = Account::where('id', $this->request->get('from_account_id'))->pluck('currency_code')->first();
$income_currency_code = Account::where('id', $this->request->get('to_account_id'))->pluck('currency_code')->first();
$expense_transaction = Transaction::findOrFail($this->transfer->expense_transaction_id);
$income_transaction = Transaction::findOrFail($this->transfer->income_transaction_id);
$expense_transaction->update([
'company_id' => $this->request['company_id'],
'type' => 'expense',
'account_id' => $this->request->get('from_account_id'),
'paid_at' => $this->request->get('transferred_at'),
'currency_code' => $expense_currency_code,
'currency_rate' => $currencies[$expense_currency_code],
'amount' => $this->request->get('amount'),
'contact_id' => 0,
'description' => $this->request->get('description'),
'category_id' => Category::transfer(), // Transfer Category ID
'payment_method' => $this->request->get('payment_method'),
'reference' => $this->request->get('reference'),
]);
// Convert amount if not same currency
if ($expense_currency_code != $income_currency_code) {
$default_currency = setting('default.currency', 'USD');
$default_amount = $this->request->get('amount');
if ($default_currency != $expense_currency_code) {
$default_amount_model = new Transfer();
$default_amount_model->default_currency_code = $default_currency;
$default_amount_model->amount = $this->request->get('amount');
$default_amount_model->currency_code = $expense_currency_code;
$default_amount_model->currency_rate = $currencies[$expense_currency_code];
$default_amount = $default_amount_model->getDivideConvertedAmount();
}
$transfer_amount = new Transfer();
$transfer_amount->default_currency_code = $expense_currency_code;
$transfer_amount->amount = $default_amount;
$transfer_amount->currency_code = $income_currency_code;
$transfer_amount->currency_rate = $currencies[$income_currency_code];
$amount = $transfer_amount->getAmountConvertedFromCustomDefault();
} else {
$amount = $this->request->get('amount');
}
$income_transaction->update([
'company_id' => $this->request['company_id'],
'type' => 'income',
'account_id' => $this->request->get('to_account_id'),
'paid_at' => $this->request->get('transferred_at'),
'currency_code' => $income_currency_code,
'currency_rate' => $currencies[$income_currency_code],
'amount' => $amount,
'contact_id' => 0,
'description' => $this->request->get('description'),
'category_id' => Category::transfer(), // Transfer Category ID
'payment_method' => $this->request->get('payment_method'),
'reference' => $this->request->get('reference'),
]);
$this->transfer->update([
'company_id' => $this->request['company_id'],
'expense_transaction_id' => $expense_transaction->id,
'income_transaction_id' => $income_transaction->id,
]);
return $this->transfer;
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Company;
use App\Traits\Users;
use Artisan;
class CreateCompany extends Job
{
use Users;
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Company
*/
public function handle()
{
// Clear settings
setting()->forgetAll();
$company = Company::create($this->request->all());
Artisan::call('user:seed', [
'user' => user()->id,
'company' => $company->id,
]);
setting()->setExtraColumns(['company_id' => $company->id]);
if ($this->request->file('logo')) {
$company_logo = $this->getMedia($this->request->file('logo'), 'settings', $company->id);
if ($company_logo) {
$company->attachMedia($company_logo, 'company_logo');
setting()->set('company.logo', $company_logo->id);
}
}
// Create settings
setting()->set([
'company.name' => $this->request->get('name'),
'company.email' => $this->request->get('email'),
'company.address' => $this->request->get('address'),
'default.currency' => $this->request->get('currency'),
'default.locale' => $this->request->get('locale', 'en-GB'),
]);
setting()->save();
setting()->forgetAll();
return $company;
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Auth\User;
use App\Models\Common\Contact;
class CreateContact extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Contact
*/
public function handle()
{
if (!empty($this->request->input('create_user'))) {
$this->createUser();
}
$contact = Contact::create($this->request->all());
return $contact;
}
public function createUser()
{
// Check if user exist
if ($user = User::where('email', $this->request['email'])->first()) {
$message = trans('messages.error.customer', ['name' => $user->name]);
throw new \Exception($message);
}
$data = $this->request->all();
$data['locale'] = setting('default.locale', 'en-GB');
$user = User::create($data);
$user->roles()->attach(['3']);
$user->companies()->attach([session('company_id')]);
// St user id to request
$this->request['user_id'] = $user->id;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Item;
class CreateItem extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Item
*/
public function handle()
{
$item = Item::create($this->request->all());
// Upload picture
if ($this->request->file('picture')) {
$media = $this->getMedia($this->request->file('picture'), 'items');
$item->attachMedia($media, 'picture');
}
return $item;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Report;
class CreateReport extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Report
*/
public function handle()
{
$report = Report::create($this->request->all());
return $report;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Company;
use App\Traits\Users;
class DeleteCompany extends Job
{
use Users;
protected $company;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($company)
{
$this->company = $company;
}
/**
* Execute the job.
*
* @return Company
*/
public function handle()
{
$this->authorize();
$this->company->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
// Can't delete active company
if ($this->company->id == session('company_id')) {
$message = trans('companies.error.delete_active');
throw new \Exception($message);
}
// Check if user can access company
if (!$this->isUserCompany($this->company->id)) {
$message = trans('companies.error.not_user_company');
throw new \Exception($message);
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
class DeleteContact extends Job
{
protected $contact;
/**
* Create a new job instance.
*
* @param $contact
*/
public function __construct($contact)
{
$this->contact = $contact;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->contact->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if ($relationships = $this->getRelationships()) {
$message = trans('messages.warning.deleted', ['name' => $this->contact->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'transactions' => 'transactions',
];
if ($this->contact->type == 'customer') {
$rels['invoices'] = 'invoices';
} else {
$rels['bills'] = 'bills';
}
return $this->countRelationships($this->contact, $rels);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
class DeleteItem extends Job
{
protected $item;
/**
* Create a new job instance.
*
* @param $item
*/
public function __construct($item)
{
$this->item = $item;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->item->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if ($relationships = $this->getRelationships()) {
$message = trans('messages.warning.deleted', ['name' => $this->item->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'invoice_items' => 'invoices',
'bill_items' => 'bills',
];
return $this->countRelationships($this->item, $rels);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
class DeleteReport extends Job
{
protected $report;
/**
* Create a new job instance.
*
* @param $report
*/
public function __construct($report)
{
$this->report = $report;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->report->delete();
return true;
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Company;
use App\Traits\Users;
class UpdateCompany extends Job
{
use Users;
protected $company;
protected $request;
/**
* Create a new job instance.
*
* @param $company
* @param $request
*/
public function __construct($company, $request)
{
$this->company = $company;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Company
*/
public function handle()
{
// Check if user can access company
$this->authorize();
// Update company
$this->company->update($this->request->all());
// Clear current settings
setting()->forgetAll();
// Load settings based on the given company
setting()->setExtraColumns(['company_id' => $this->company->id]);
setting()->load(true);
if ($this->request->has('name')) {
setting()->set('company.name', $this->request->get('name'));
}
if ($this->request->has('email')) {
setting()->set('company.email', $this->request->get('email'));
}
if ($this->request->has('address')) {
setting()->set('company.address', $this->request->get('address'));
}
if ($this->request->has('currency')) {
setting()->set('default.currency', $this->request->get('currency'));
}
if ($this->request->has('locale')) {
setting()->set('default.locale', $this->request->get('locale'));
}
if ($this->request->file('logo')) {
$company_logo = $this->getMedia($this->request->file('logo'), 'settings', $this->company->id);
if ($company_logo) {
$this->company->attachMedia($company_logo, 'company_logo');
setting()->set('company.logo', $company_logo->id);
}
}
setting()->save();
setting()->forgetAll();
return $this->company;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
// Check if user can access company
if (!$this->isUserCompany($this->company->id)) {
$message = trans('companies.error.not_user_company');
throw new \Exception($message);
}
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Contact;
class UpdateContact extends Job
{
protected $contact;
protected $request;
/**
* Create a new job instance.
*
* @param $contact
* @param $request
*/
public function __construct($contact, $request)
{
$this->contact = $contact;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Contact
*/
public function handle()
{
$this->authorize();
if (!empty($this->request->input('create_user'))) {
$this->createUser();
}
$this->contact->update($this->request->all());
return $this->contact;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if (($this->request['enabled'] == 0) && ($relationships = $this->getRelationships())) {
$message = trans('messages.warning.disabled', ['name' => $this->contact->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function createUser()
{
// Check if user exist
if ($user = User::where('email', $this->request['email'])->first()) {
$message = trans('messages.error.customer', ['name' => $user->name]);
throw new \Exception($message);
}
$data = $this->request->all();
$data['locale'] = setting('default.locale', 'en-GB');
$user = User::create($data);
$user->roles()->attach(['3']);
$user->companies()->attach([session('company_id')]);
// St user id to request
$this->request['user_id'] = $user->id;
}
public function getRelationships()
{
$rels = [
'transactions' => 'transactions',
];
if ($this->contact->type == 'customer') {
$rels['invoices'] = 'invoices';
} else {
$rels['bills'] = 'bills';
}
return $this->countRelationships($this->contact, $rels);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Item;
class UpdateItem extends Job
{
protected $item;
protected $request;
/**
* Create a new job instance.
*
* @param $item
* @param $request
*/
public function __construct($item, $request)
{
$this->item = $item;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Item
*/
public function handle()
{
$this->item->update($this->request->all());
// Upload picture
if ($this->request->file('picture')) {
$media = $this->getMedia($this->request->file('picture'), 'items');
$this->item->attachMedia($media, 'picture');
}
return $this->item;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Models\Common\Report;
class UpdateReport extends Job
{
protected $report;
protected $request;
/**
* Create a new job instance.
*
* @param $report
* @param $request
*/
public function __construct($report, $request)
{
$this->report = $report;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Report
*/
public function handle()
{
$this->report->update($this->request->all());
return $this->report;
}
}

View File

@@ -2,18 +2,16 @@
namespace App\Jobs\Expense;
use App\Events\BillCreated;
use App\Abstracts\Job;
use App\Events\Expense\BillCreated;
use App\Models\Expense\Bill;
use App\Models\Expense\BillHistory;
use App\Models\Expense\BillTotal;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use Illuminate\Foundation\Bus\Dispatchable;
class CreateBill
class CreateBill extends Job
{
use Currencies, DateTime, Dispatchable, Uploads;
use Currencies, DateTime;
protected $request;
@@ -24,7 +22,7 @@ class CreateBill
*/
public function __construct($request)
{
$this->request = $request;
$this->request = $this->getRequestInstance($request);
}
/**
@@ -34,7 +32,7 @@ class CreateBill
*/
public function handle()
{
$bill = Bill::create($this->request->input());
$bill = Bill::create($this->request->all());
// Upload attachment
if ($this->request->file('attachment')) {
@@ -50,9 +48,9 @@ class CreateBill
$discount_total = 0;
$discount = $this->request['discount'];
if ($this->request['item']) {
foreach ($this->request['item'] as $item) {
$bill_item = dispatch(new CreateBillItem($item, $bill, $discount));
if ($this->request['items']) {
foreach ($this->request['items'] as $item) {
$bill_item = $this->dispatch(new CreateBillItem($item, $bill, $discount));
// Calculate totals
$tax_total += $bill_item->tax;
@@ -92,15 +90,6 @@ class CreateBill
// Add bill totals
$this->addTotals($bill, $this->request, $taxes, $sub_total, $discount_total, $tax_total);
// Add bill history
BillHistory::create([
'company_id' => session('company_id'),
'bill_id' => $bill->id,
'status_code' => 'draft',
'notify' => 0,
'description' => trans('messages.success.added', ['type' => $bill->bill_number]),
]);
// Recurring
$bill->createRecurring();

View File

@@ -0,0 +1,49 @@
<?php
namespace App\Jobs\Expense;
use App\Abstracts\Job;
use App\Models\Expense\BillHistory;
class CreateBillHistory extends Job
{
protected $bill;
protected $notify;
protected $description;
/**
* Create a new job instance.
*
* @param $bill
* @param $notify
* @param $description
*/
public function __construct($bill, $notify = 0, $description = null)
{
$this->bill = $bill;
$this->notify = $notify;
$this->description = $description;
}
/**
* Execute the job.
*
* @return BillHistory
*/
public function handle()
{
$description = $this->description ?: trans_choice('general.payments', 1);
$bill_history = BillHistory::create([
'company_id' => $this->bill->company_id,
'bill_id' => $this->bill->id,
'status_code' => $this->bill->bill_status_code,
'notify' => $this->notify,
'description' => $description,
]);
return $bill_history;
}
}

View File

@@ -2,18 +2,14 @@
namespace App\Jobs\Expense;
use App\Models\Common\Item;
use App\Abstracts\Job;
use App\Models\Expense\BillItem;
use App\Models\Expense\BillItemTax;
use App\Models\Setting\Tax;
use App\Notifications\Common\Item as ItemNotification;
use App\Notifications\Common\ItemReminder as ItemReminderNotification;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Str;
class CreateBillItem
class CreateBillItem extends Job
{
use Dispatchable;
protected $data;
protected $bill;
@@ -41,8 +37,6 @@ class CreateBillItem
*/
public function handle()
{
$item_sku = '';
$item_id = !empty($this->data['item_id']) ? $this->data['item_id'] : 0;
$item_amount = (double) $this->data['price'] * (double) $this->data['quantity'];
@@ -53,19 +47,6 @@ class CreateBillItem
$item_discount_amount = $item_amount - ($item_amount * ($this->discount / 100));
}
if (!empty($item_id)) {
$item_object = Item::find($item_id);
$this->data['name'] = $item_object->name;
$item_sku = $item_object->sku;
// Increase stock (item bought)
$item_object->quantity += (double) $this->data['quantity'];
$item_object->save();
} elseif (!empty($this->data['sku'])) {
$item_sku = $this->data['sku'];
}
$tax_amount = 0;
$item_taxes = [];
$item_tax_total = 0;
@@ -83,6 +64,20 @@ class CreateBillItem
case 'compound':
$compounds[] = $tax;
break;
case 'fixed':
$fixed_taxes[] = $tax;
$tax_amount = $tax->rate;
$item_taxes[] = [
'company_id' => $this->invoice->company_id,
'invoice_id' => $this->invoice->id,
'tax_id' => $tax_id,
'name' => $tax->name,
'amount' => $tax_amount,
];
$item_tax_total += $tax_amount;
break;
case 'normal':
default:
$taxes[] = $tax;
@@ -105,7 +100,7 @@ class CreateBillItem
if ($inclusives) {
$item_amount = $item_discount_amount + $item_tax_total;
$item_base_rate = $item_amount / (1 + collect($inclusives)->sum('rate')/100);
$item_base_rate = $item_amount / (1 + collect($inclusives)->sum('rate') / 100);
foreach ($inclusives as $inclusive) {
$item_tax_total += $tax_amount = $item_base_rate * ($inclusive->rate / 100);
@@ -143,8 +138,7 @@ class CreateBillItem
'company_id' => $this->bill->company_id,
'bill_id' => $this->bill->id,
'item_id' => $item_id,
'name' => str_limit($this->data['name'], 180, ''),
'sku' => $item_sku,
'name' => Str::limit($this->data['name'], 180, ''),
'quantity' => (double) $this->data['quantity'],
'price' => (double) $this->data['price'],
'tax' => $item_tax_total,

View File

@@ -1,52 +0,0 @@
<?php
namespace App\Jobs\Expense;
use App\Models\Expense\BillHistory;
use App\Models\Expense\BillPayment;
use Illuminate\Foundation\Bus\Dispatchable;
class CreateBillPayment
{
use Dispatchable;
protected $request;
protected $bill;
/**
* Create a new job instance.
*
* @param $request
* @param $bill
*/
public function __construct($request, $bill)
{
$this->request = $request;
$this->bill = $bill;
}
/**
* Execute the job.
*
* @return BillPayment
*/
public function handle()
{
$bill_payment = BillPayment::create($this->request->input());
$desc_amount = money((float) $bill_payment->amount, (string) $bill_payment->currency_code, true)->format();
$history_data = [
'company_id' => $bill_payment->company_id,
'bill_id' => $bill_payment->bill_id,
'status_code' => $this->bill->bill_status_code,
'notify' => '0',
'description' => $desc_amount . ' ' . trans_choice('general.payments', 1),
];
BillHistory::create($history_data);
return $bill_payment;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Jobs\Expense;
use App\Abstracts\Job;
use App\Models\Expense\Bill;
class DeleteBill extends Job
{
protected $bill;
/**
* Create a new job instance.
*
* @param $bill
*/
public function __construct($bill)
{
$this->bill = $bill;
}
/**
* Execute the job.
*
* @return Bill
*/
public function handle()
{
$this->deleteRelationships($this->bill, [
'items', 'item_taxes', 'histories', 'transactions', 'recurring', 'totals'
]);
$this->bill->delete();
return true;
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Jobs\Expense;
use App\Abstracts\Job;
use App\Models\Expense\Bill;
use App\Models\Expense\BillHistory;
class DuplicateBill extends Job
{
protected $bill;
/**
* Create a new job instance.
*
* @param $bill
*/
public function __construct($bill)
{
$this->bill = $bill;
}
/**
* Execute the job.
*
* @return Bill
*/
public function handle()
{
$clone = $this->bill->duplicate();
// Add bill history
BillHistory::create([
'company_id' => session('company_id'),
'bill_id' => $clone->id,
'status_code' => 'draft',
'notify' => 0,
'description' => trans('messages.success.added', ['type' => $clone->bill_number]),
]);
return $clone;
}
}

View File

@@ -2,19 +2,17 @@
namespace App\Jobs\Expense;
use App\Events\BillUpdated;
use App\Abstracts\Job;
use App\Models\Common\Item;
use App\Models\Expense\Bill;
use App\Models\Expense\BillTotal;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Uploads;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Bus\Dispatchable;
class UpdateBill
class UpdateBill extends Job
{
use Currencies, DateTime, Dispatchable, Uploads;
use Currencies, DateTime;
protected $bill;
@@ -28,7 +26,7 @@ class UpdateBill
public function __construct($bill, $request)
{
$this->bill = $bill;
$this->request = $request;
$this->request = $this->getRequestInstance($request);
}
/**
@@ -52,27 +50,11 @@ class UpdateBill
$discount_total = 0;
$discount = $this->request['discount'];
if ($this->request['item']) {
$items = $this->bill->items;
if ($this->request['items']) {
$this->deleteRelationships($this->bill, ['items', 'item_taxes']);
if ($items) {
foreach ($items as $item) {
if (empty($item->item_id)) {
continue;
}
$item_object = Item::find($item->item_id);
// Decrease stock
$item_object->quantity -= (double) $item->quantity;
$item_object->save();
}
}
$this->deleteRelationships($this->bill, 'items');
foreach ($this->request['item'] as $item) {
$bill_item = dispatch(new CreateBillItem($item, $this->bill, $discount));
foreach ($this->request['items'] as $item) {
$bill_item = dispatch_now(new CreateBillItem($item, $this->bill, $discount));
// Calculate totals
$tax_total += $bill_item->tax;
@@ -127,7 +109,7 @@ class UpdateBill
$this->bill->updateRecurring();
// Fire the event to make it extensible
event(new BillUpdated($this->bill));
event(new \App\Events\Expense\BillUpdated($this->bill));
return $this->bill;
}

View File

@@ -2,19 +2,18 @@
namespace App\Jobs\Income;
use App\Events\InvoiceCreated;
use App\Abstracts\Job;
use App\Events\Income\InvoiceCreated;
use App\Events\Income\InvoiceCreating;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoiceTotal;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Incomes;
use App\Traits\Uploads;
use Illuminate\Foundation\Bus\Dispatchable;
class CreateInvoice
class CreateInvoice extends Job
{
use Currencies, DateTime, Dispatchable, Incomes, Uploads;
use Currencies, DateTime, Incomes;
protected $request;
@@ -25,7 +24,7 @@ class CreateInvoice
*/
public function __construct($request)
{
$this->request = $request;
$this->request = $this->getRequestInstance($request);
}
/**
@@ -35,7 +34,13 @@ class CreateInvoice
*/
public function handle()
{
$invoice = Invoice::create($this->request->input());
if (empty($this->request['amount'])) {
$this->request['amount'] = 0;
}
event(new InvoiceCreating($this->request));
$invoice = Invoice::create($this->request->all());
// Upload attachment
if ($this->request->file('attachment')) {
@@ -51,9 +56,9 @@ class CreateInvoice
$discount_total = 0;
$discount = $this->request['discount'];
if ($this->request['item']) {
foreach ($this->request['item'] as $item) {
$invoice_item = dispatch(new CreateInvoiceItem($item, $invoice, $discount));
if ($this->request['items']) {
foreach ($this->request['items'] as $item) {
$invoice_item = $this->dispatch(new CreateInvoiceItem($item, $invoice, $discount));
// Calculate totals
$tax_total += $invoice_item->tax;
@@ -88,27 +93,14 @@ class CreateInvoice
$this->request['amount'] = money($amount, $this->request['currency_code'])->getAmount();
$invoice->update($this->request->input());
$invoice->update($this->request->all());
// Add invoice totals
$this->addTotals($invoice, $this->request, $taxes, $sub_total, $discount_total, $tax_total);
// Add invoice history
InvoiceHistory::create([
'company_id' => session('company_id'),
'invoice_id' => $invoice->id,
'status_code' => 'draft',
'notify' => 0,
'description' => trans('messages.success.added', ['type' => $invoice->invoice_number]),
]);
// Update next invoice number
$this->increaseNextInvoiceNumber();
// Recurring
$invoice->createRecurring();
// Fire the event to make it extensible
event(new InvoiceCreated($invoice));
return $invoice;

View File

@@ -0,0 +1,49 @@
<?php
namespace App\Jobs\Income;
use App\Abstracts\Job;
use App\Models\Income\InvoiceHistory;
class CreateInvoiceHistory extends Job
{
protected $invoice;
protected $notify;
protected $description;
/**
* Create a new job instance.
*
* @param $invoice
* @param $notify
* @param $description
*/
public function __construct($invoice, $notify = 0, $description = null)
{
$this->invoice = $invoice;
$this->notify = $notify;
$this->description = $description;
}
/**
* Execute the job.
*
* @return InvoiceHistory
*/
public function handle()
{
$description = $this->description ?: trans_choice('general.payments', 1);
$invoice_history = InvoiceHistory::create([
'company_id' => $this->invoice->company_id,
'invoice_id' => $this->invoice->id,
'status_code' => $this->invoice->invoice_status_code,
'notify' => $this->notify,
'description' => $description,
]);
return $invoice_history;
}
}

View File

@@ -2,18 +2,14 @@
namespace App\Jobs\Income;
use App\Models\Common\Item;
use App\Abstracts\Job;
use App\Models\Income\InvoiceItem;
use App\Models\Income\InvoiceItemTax;
use App\Models\Setting\Tax;
use App\Notifications\Common\Item as ItemNotification;
use App\Notifications\Common\ItemReminder as ItemReminderNotification;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Str;
class CreateInvoiceItem
class CreateInvoiceItem extends Job
{
use Dispatchable;
protected $data;
protected $invoice;
@@ -41,8 +37,6 @@ class CreateInvoiceItem
*/
public function handle()
{
$item_sku = '';
$item_id = !empty($this->data['item_id']) ? $this->data['item_id'] : 0;
$item_amount = (double) $this->data['price'] * (double) $this->data['quantity'];
@@ -53,54 +47,14 @@ class CreateInvoiceItem
$item_discount_amount = $item_amount - ($item_amount * ($this->discount / 100));
}
if (!empty($item_id)) {
$item_object = Item::find($item_id);
$this->data['name'] = $item_object->name;
$item_sku = $item_object->sku;
// Decrease stock (item sold)
$item_object->quantity -= (double) $this->data['quantity'];
$item_object->save();
if (setting('general.send_item_reminder')) {
$item_stocks = explode(',', setting('general.schedule_item_stocks'));
foreach ($item_stocks as $item_stock) {
if ($item_object->quantity == $item_stock) {
foreach ($item_object->company->users as $user) {
if (!$user->can('read-notifications')) {
continue;
}
$user->notify(new ItemReminderNotification($item_object));
}
}
}
}
// Notify users if out of stock
if ($item_object->quantity == 0) {
foreach ($item_object->company->users as $user) {
if (!$user->can('read-notifications')) {
continue;
}
$user->notify(new ItemNotification($item_object));
}
}
} elseif (!empty($this->data['sku'])) {
$item_sku = $this->data['sku'];
}
$tax_amount = 0;
$item_taxes = [];
$item_tax_total = 0;
if (!empty($this->data['tax_id'])) {
$inclusives = $compounds = $taxes = [];
$inclusives = $compounds = $taxes = $fixed_taxes = [];
foreach ((array) $this->data['tax_id'] as $tax_id) {
foreach ((array)$this->data['tax_id'] as $tax_id) {
$tax = Tax::find($tax_id);
switch ($tax->type) {
@@ -110,6 +64,20 @@ class CreateInvoiceItem
case 'compound':
$compounds[] = $tax;
break;
case 'fixed':
$fixed_taxes[] = $tax;
$tax_amount = $tax->rate;
$item_taxes[] = [
'company_id' => $this->invoice->company_id,
'invoice_id' => $this->invoice->id,
'tax_id' => $tax_id,
'name' => $tax->name,
'amount' => $tax_amount,
];
$item_tax_total += $tax_amount;
break;
case 'normal':
default:
$taxes[] = $tax;
@@ -132,7 +100,7 @@ class CreateInvoiceItem
if ($inclusives) {
$item_amount = $item_discount_amount + $item_tax_total;
$item_base_rate = $item_amount / (1 + collect($inclusives)->sum('rate')/100);
$item_base_rate = $item_amount / (1 + collect($inclusives)->sum('rate') / 100);
foreach ($inclusives as $inclusive) {
$item_tax_total += $tax_amount = $item_base_rate * ($inclusive->rate / 100);
@@ -170,8 +138,7 @@ class CreateInvoiceItem
'company_id' => $this->invoice->company_id,
'invoice_id' => $this->invoice->id,
'item_id' => $item_id,
'name' => str_limit($this->data['name'], 180, ''),
'sku' => $item_sku,
'name' => Str::limit($this->data['name'], 180, ''),
'quantity' => (double) $this->data['quantity'],
'price' => (double) $this->data['price'],
'tax' => $item_tax_total,

View File

@@ -1,52 +0,0 @@
<?php
namespace App\Jobs\Income;
use App\Models\Income\InvoiceHistory;
use App\Models\Income\InvoicePayment;
use Illuminate\Foundation\Bus\Dispatchable;
class CreateInvoicePayment
{
use Dispatchable;
protected $request;
protected $invoice;
/**
* Create a new job instance.
*
* @param $request
* @param $invoice
*/
public function __construct($request, $invoice)
{
$this->request = $request;
$this->invoice = $invoice;
}
/**
* Execute the job.
*
* @return InvoicePayment
*/
public function handle()
{
$invoice_payment = InvoicePayment::create($this->request->input());
$desc_amount = money((float) $invoice_payment->amount, (string) $invoice_payment->currency_code, true)->format();
$history_data = [
'company_id' => $invoice_payment->company_id,
'invoice_id' => $invoice_payment->invoice_id,
'status_code' => $this->invoice->invoice_status_code,
'notify' => '0',
'description' => $desc_amount . ' ' . trans_choice('general.payments', 1),
];
InvoiceHistory::create($history_data);
return $invoice_payment;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Jobs\Income;
use App\Abstracts\Job;
use App\Models\Income\Invoice;
class DeleteInvoice extends Job
{
protected $invoice;
/**
* Create a new job instance.
*
* @param $invoice
*/
public function __construct($invoice)
{
$this->invoice = $invoice;
}
/**
* Execute the job.
*
* @return Invoice
*/
public function handle()
{
$this->deleteRelationships($this->invoice, [
'items', 'item_taxes', 'histories', 'transactions', 'recurring', 'totals'
]);
$this->invoice->delete();
return true;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Jobs\Income;
use App\Abstracts\Job;
use App\Events\Income\InvoiceCreated;
use App\Models\Income\Invoice;
class DuplicateInvoice extends Job
{
protected $invoice;
/**
* Create a new job instance.
*
* @param $invoice
*/
public function __construct($invoice)
{
$this->invoice = $invoice;
}
/**
* Execute the job.
*
* @return Invoice
*/
public function handle()
{
$clone = $this->invoice->duplicate();
event(new InvoiceCreated($clone));
return $clone;
}
}

View File

@@ -2,20 +2,18 @@
namespace App\Jobs\Income;
use App\Events\InvoiceUpdated;
use App\Abstracts\Job;
use App\Models\Common\Item;
use App\Models\Income\Invoice;
use App\Models\Income\InvoiceTotal;
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Incomes;
use App\Traits\Uploads;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Bus\Dispatchable;
class UpdateInvoice
class UpdateInvoice extends Job
{
use Currencies, DateTime, Dispatchable, Incomes, Uploads;
use Currencies, DateTime, Incomes;
protected $invoice;
@@ -29,7 +27,7 @@ class UpdateInvoice
public function __construct($invoice, $request)
{
$this->invoice = $invoice;
$this->request = $request;
$this->request = $this->getRequestInstance($request);
}
/**
@@ -39,6 +37,8 @@ class UpdateInvoice
*/
public function handle()
{
event(new \App\Events\Income\InvoiceUpdating($this->invoice, $this->request));
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'invoices');
@@ -53,27 +53,11 @@ class UpdateInvoice
$discount_total = 0;
$discount = $this->request['discount'];
if ($this->request['item']) {
$items = $this->invoice->items;
if ($this->request['items']) {
$this->deleteRelationships($this->invoice, ['items', 'item_taxes']);
if ($items) {
foreach ($items as $item) {
if (empty($item->item_id)) {
continue;
}
$item_object = Item::find($item->item_id);
// Increase stock
$item_object->quantity += (double) $item->quantity;
$item_object->save();
}
}
$this->deleteRelationships($this->invoice, 'items');
foreach ($this->request['item'] as $item) {
$invoice_item = dispatch(new CreateInvoiceItem($item, $this->invoice, $discount));
foreach ($this->request['items'] as $item) {
$invoice_item = dispatch_now(new CreateInvoiceItem($item, $this->invoice, $discount));
// Calculate totals
$tax_total += $invoice_item->tax;
@@ -127,8 +111,7 @@ class UpdateInvoice
// Recurring
$this->invoice->updateRecurring();
// Fire the event to make it extensible
event(new InvoiceUpdated($this->invoice));
event(new \App\Events\Income\InvoiceUpdated($this->invoice, $this->request));
return $this->invoice;
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
use App\Models\Setting\Category;
class CreateCategory extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Category
*/
public function handle()
{
$category = Category::create($this->request->all());
return $category;
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
use App\Models\Setting\Currency;
class CreateCurrency extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Currency
*/
public function handle()
{
// Force the rate to be 1 for default currency
if ($this->request->get('default_currency')) {
$this->request['rate'] = '1';
}
$currency = Currency::create($this->request->all());
// Update default currency setting
if ($this->request->get('default_currency')) {
setting()->set('default.currency', $this->request->get('code'));
setting()->save();
}
return $currency;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
use App\Models\Setting\Tax;
class CreateTax extends Job
{
protected $request;
/**
* Create a new job instance.
*
* @param $request
*/
public function __construct($request)
{
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Tax
*/
public function handle()
{
$tax = Tax::create($this->request->all());
return $tax;
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
class DeleteCategory extends Job
{
protected $category;
/**
* Create a new job instance.
*
* @param $category
*/
public function __construct($category)
{
$this->category = $category;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->category->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
// Can not delete the last category by type
if (Category::where('type', $this->category->type)->count() == 1) {
$message = trans('messages.error.last_category', ['type' => strtolower(trans_choice('general.' . $this->category->type . 's', 1))]);
throw new \Exception($message);
}
if ($relationships = $this->getRelationships()) {
$message = trans('messages.warning.deleted', ['name' => $this->category->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'items' => 'items',
'invoices' => 'invoices',
'bills' => 'bills',
'transactions' => 'transactions',
];
return $this->countRelationships($this->category, $rels);
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
class DeleteCurrency extends Job
{
protected $currency;
/**
* Create a new job instance.
*
* @param $currency
*/
public function __construct($currency)
{
$this->currency = $currency;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->currency->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if ($relationships = $this->getRelationships()) {
$message = trans('messages.warning.deleted', ['name' => $this->currency->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'accounts' => 'accounts',
'customers' => 'customers',
'invoices' => 'invoices',
'bills' => 'bills',
'transactions' => 'transactions',
];
return $this->countRelationships($this->currency, $rels);
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
class DeleteTax extends Job
{
protected $tax;
/**
* Create a new job instance.
*
* @param $tax
*/
public function __construct($tax)
{
$this->tax = $tax;
}
/**
* Execute the job.
*
* @return boolean|Exception
*/
public function handle()
{
$this->authorize();
$this->tax->delete();
return true;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if ($relationships = $this->getRelationships()) {
$message = trans('messages.warning.deleted', ['name' => $this->tax->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'items' => 'items',
'invoice_items' => 'invoices',
'bill_items' => 'bills',
];
return $this->countRelationships($this->tax, $rels);
}
}

View File

@@ -0,0 +1,75 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
use App\Models\Setting\Category;
class UpdateCategory extends Job
{
protected $category;
protected $request;
/**
* Create a new job instance.
*
* @param $category
* @param $request
*/
public function __construct($category, $request)
{
$this->category = $category;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Category
*/
public function handle()
{
$this->authorize();
$this->category->update($this->request->all());
return $this->category;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if (!$relationships = $this->getRelationships()) {
return;
}
if ($this->category->type != $this->request->get('type')) {
$message = trans('messages.error.change_type', ['text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
if (!$this->request->get('enabled')) {
$message = trans('messages.warning.disabled', ['name' => $this->category->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'items' => 'items',
'invoices' => 'invoices',
'bills' => 'bills',
'transactions' => 'transactions',
];
return $this->countRelationships($this->category, $rels);
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
use App\Models\Setting\Currency;
class UpdateCurrency extends Job
{
protected $currency;
protected $request;
/**
* Create a new job instance.
*
* @param $currency
* @param $request
*/
public function __construct($currency, $request)
{
$this->currency = $currency;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Currency
*/
public function handle()
{
$this->authorize();
$this->currency->update($this->request->all());
return $this->currency;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if (!$relationships = $this->getRelationships()) {
return;
}
if ($this->currency->code != $this->request->get('code')) {
$message = trans('messages.warning.disable_code', ['name' => $this->currency->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
if (!$this->request->get('enabled')) {
$message = trans('messages.warning.disable_code', ['name' => $this->currency->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'accounts' => 'accounts',
'customers' => 'customers',
'invoices' => 'invoices',
'bills' => 'bills',
'transactions' => 'transactions',
];
$relationships = $this->countRelationships($this->currency, $rels);
if ($this->currency->code == setting('default.currency')) {
$relationships[] = strtolower(trans_choice('general.companies', 1));
}
return $relationships;
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace App\Jobs\Setting;
use App\Abstracts\Job;
use App\Models\Setting\Tax;
class UpdateTax extends Job
{
protected $tax;
protected $request;
/**
* Create a new job instance.
*
* @param $tax
* @param $request
*/
public function __construct($tax, $request)
{
$this->tax = $tax;
$this->request = $this->getRequestInstance($request);
}
/**
* Execute the job.
*
* @return Tax
*/
public function handle()
{
$this->authorize();
$this->tax->update($this->request->all());
return $this->tax;
}
/**
* Determine if this action is applicable.
*
* @return void
*/
public function authorize()
{
if (!$relationships = $this->getRelationships()) {
return;
}
if ($this->tax->type != $this->request->get('type')) {
$message = trans('messages.error.type', ['text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
if (!$this->request->get('enabled')) {
$message = trans('messages.warning.disabled', ['name' => $this->tax->name, 'text' => implode(', ', $relationships)]);
throw new \Exception($message);
}
}
public function getRelationships()
{
$rels = [
'items' => 'items',
'invoice_items' => 'invoices',
'bill_items' => 'bills',
];
return $this->countRelationships($this->tax, $rels);
}
}