improved tenant identification

This commit is contained in:
Denis Duliçi 2021-04-16 00:59:43 +03:00
parent 9635e6be5d
commit 2b07442260
126 changed files with 1719 additions and 999 deletions

View File

@ -21,9 +21,9 @@ abstract class Module extends Command
protected function changeRuntime()
{
$this->old_company_id = session('company_id');
$this->old_company_id = company_id();
session(['company_id' => $this->company_id]);
company($this->company_id)->makeCurrent();
app()->setLocale($this->locale);
@ -36,7 +36,7 @@ abstract class Module extends Command
session()->forget('company_id');
if (!empty($this->old_company_id)) {
session(['company_id' => $this->old_company_id]);
company($this->old_company_id)->makeCurrent();
}
}

View File

@ -4,8 +4,12 @@ namespace App\Abstracts;
use App\Events\Export\HeadingsPreparing;
use App\Events\Export\RowsPreparing;
use App\Notifications\Common\ExportFailed;
use App\Utilities\Date;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadings;
@ -13,16 +17,21 @@ use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithTitle;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
abstract class Export implements FromCollection, ShouldAutoSize, WithHeadings, WithMapping, WithTitle
abstract class Export implements FromCollection, HasLocalePreference, ShouldAutoSize, ShouldQueue, WithHeadings, WithMapping, WithTitle
{
use Exportable;
public $ids;
public $fields;
public $user;
public function __construct($ids = null)
{
$this->ids = $ids;
$this->fields = $this->fields();
$this->user = user();
}
public function title(): string
@ -74,4 +83,14 @@ abstract class Export implements FromCollection, ShouldAutoSize, WithHeadings, W
return $rows;
}
public function preferredLocale()
{
return $this->user->locale;
}
public function failed(\Throwable $exception): void
{
$this->user->notify(new ExportFailed($exception));
}
}

View File

@ -29,8 +29,7 @@ abstract class Factory extends BaseFactory
$this->user = User::first();
$this->company = $this->user->companies()->first();
session(['company_id' => $this->company->id]);
setting()->setExtraColumns(['company_id' => $this->company->id]);
company($this->company->id)->makeCurrent();
}
public function getCompanyUsers()

View File

@ -3,11 +3,12 @@
namespace App\Abstracts\Http;
use App\Abstracts\Http\Response;
use App\Jobs\Auth\NotifyUser;
use App\Jobs\Common\CreateMediableForExport;
use App\Notifications\Common\ImportCompleted;
use App\Traits\Jobs;
use App\Traits\Permissions;
use App\Traits\Relationships;
use Exception;
use ErrorException;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
@ -15,9 +16,6 @@ use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Exceptions\SheetNotFoundException;
use Maatwebsite\Excel\Facades\Excel;
use Throwable;
abstract class Controller extends BaseController
{
@ -78,23 +76,49 @@ abstract class Controller extends BaseController
*
* @param $class
* @param $request
* @param $url
* @param $translation
*
* @return mixed
*/
public function importExcel($class, $request)
public function importExcel($class, $request, $translation)
{
try {
Excel::import($class, $request->file('import'));
$file = $request->file('import');
if (should_queue()) {
$class->queue($file)->onQueue('imports')->chain([
new NotifyUser(user(), new ImportCompleted),
]);
$message = trans('messages.success.import_queued', ['type' => $translation]);
} else {
$class->import($file);
$message = trans('messages.success.imported', ['type' => $translation]);
}
$response = [
'success' => true,
'error' => false,
'data' => null,
'message' => '',
'message' => $message,
];
} catch (SheetNotFoundException | ErrorException | Exception | Throwable $e) {
$message = $e->getMessage();
} catch (\Throwable $e) {
if ($e instanceof \Maatwebsite\Excel\Validators\ValidationException) {
foreach ($e->failures() as $failure) {
$message = trans('messages.error.import_column', [
'message' => collect($failure->errors())->first(),
'column' => $failure->attribute(),
'line' => $failure->row(),
]);
flash($message)->error()->important();
}
$message = '';
} else {
$message = $e->getMessage();
}
$response = [
'success' => false,
@ -111,15 +135,30 @@ abstract class Controller extends BaseController
* Export the excel file or catch errors
*
* @param $class
* @param $file_name
* @param $translation
* @param $extension
*
* @return mixed
*/
public function exportExcel($class, $file_name, $extension = 'xlsx')
public function exportExcel($class, $translation, $extension = 'xlsx')
{
try {
return Excel::download($class, Str::filename($file_name) . '.' . $extension);
} catch (ErrorException | Exception | Throwable $e) {
$file_name = Str::filename($translation) . '.' . $extension;
if (should_queue()) {
$class->queue($file_name)->onQueue('exports')->chain([
new CreateMediableForExport(user(), $file_name),
]);
$message = trans('messages.success.export_queued', ['type' => $translation]);
flash($message)->success();
return back();
} else {
return $class->download($file_name);
}
} catch (\Throwable $e) {
flash($e->getMessage())->error()->important();
return back();

View File

@ -15,7 +15,7 @@ abstract class FormRequest extends BaseFormRequest
protected function prepareForValidation()
{
$this->merge([
'company_id' => session('company_id'),
'company_id' => company_id(),
]);
}

View File

@ -5,30 +5,34 @@ namespace App\Abstracts;
use App\Traits\Import as ImportHelper;
use App\Utilities\Date;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Validators\Failure;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
abstract class Import implements ToModel, SkipsOnError, SkipsOnFailure, WithChunkReading, WithHeadingRow, WithMapping, WithValidation
abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRows, WithChunkReading, WithHeadingRow, WithMapping, WithValidation, ToModel
{
use Importable, ImportHelper;
public $empty_field = 'empty---';
public $user;
public function __construct()
{
$this->user = user();
}
public function map($row): array
{
$row['company_id'] = session('company_id');
$row['company_id'] = company_id();
// Make enabled field integer
if (isset($row['enabled'])) {
@ -67,31 +71,6 @@ abstract class Import implements ToModel, SkipsOnError, SkipsOnFailure, WithChun
return 100;
}
public function onFailure(Failure ...$failures)
{
$sheet = Str::snake((new \ReflectionClass($this))->getShortName());
foreach ($failures as $failure) {
// @todo remove after 3.2 release https://github.com/Maatwebsite/Laravel-Excel/issues/1834#issuecomment-474340743
if (collect($failure->values())->first() == $this->empty_field) {
continue;
}
$message = trans('messages.error.import_column', [
'message' => collect($failure->errors())->first(),
'sheet' => $sheet,
'line' => $failure->row(),
]);
flash($message)->error()->important();
}
}
public function onError(\Throwable $e)
{
flash($e->getMessage())->error()->important();
}
public function isNotValid($row)
{
return Validator::make($row, $this->rules())->fails();
@ -111,4 +90,9 @@ abstract class Import implements ToModel, SkipsOnError, SkipsOnFailure, WithChun
return false;
}
public function preferredLocale()
{
return $this->user->locale;
}
}

View File

@ -6,14 +6,10 @@ use App\Abstracts\Http\FormRequest;
use App\Traits\Jobs;
use App\Traits\Relationships;
use App\Traits\Uploads;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
abstract class Job implements ShouldQueue
abstract class Job
{
use InteractsWithQueue, Jobs, Queueable, Relationships, SerializesModels, Uploads;
use Jobs, Relationships, Uploads;
public function getRequestInstance($request)
{

View File

@ -0,0 +1,49 @@
<?php
namespace App\Abstracts;
use App\Abstracts\Http\FormRequest;
use App\Traits\Jobs;
use App\Traits\Relationships;
use App\Traits\Uploads;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
abstract class JobShouldQueue implements ShouldQueue
{
use InteractsWithQueue, Jobs, Queueable, Relationships, SerializesModels, Uploads;
/**
* Check if request is array and if so, convert to a request class.
*
* @param mixed $request
* @return \Illuminate\Foundation\Http\FormRequest
*
* @deprecated Request is not serializable so can't use it with queues.
*/
public function getRequestInstance($request)
{
return $this->getRequestAsCollection($request);
}
/**
* Covert the request to collection.
*
* @param mixed $request
* @return \Illuminate\Support\Collection
*/
public function getRequestAsCollection($request)
{
if (is_array($request)) {
$data = $request;
$request = new class() extends FormRequest {};
$request->merge($data);
}
return collect($request->all());
}
}

View File

@ -2,19 +2,21 @@
namespace App\Abstracts;
use App\Models\Common\EmailTemplate;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification as BaseNotification;
abstract class Notification extends BaseNotification
abstract class Notification extends BaseNotification implements ShouldQueue
{
use Queueable;
/**
* Create a notification instance.
*/
public function __construct()
{
$this->queue = 'high';
$this->delay = config('queue.connections.database.delay');
$this->onQueue('notifications');
}
/**
@ -35,24 +37,24 @@ abstract class Notification extends BaseNotification
*/
public function initMessage()
{
$template = EmailTemplate::alias($this->template)->first();
app('url')->defaults(['company_id' => company_id()]);
$message = (new MailMessage)
->from(config('mail.from.address'), config('mail.from.name'))
->subject($this->getSubject($template))
->view('partials.email.body', ['body' => $this->getBody($template)]);
->subject($this->getSubject())
->view('partials.email.body', ['body' => $this->getBody()]);
return $message;
}
public function getSubject($template)
public function getSubject()
{
return $this->replaceTags($template->subject);
return $this->replaceTags($this->template->subject);
}
public function getBody($template)
public function getBody()
{
return $this->replaceTags($template->body);
return $this->replaceTags($this->template->body);
}
public function replaceTags($content)

View File

@ -611,7 +611,7 @@ abstract class DocumentShow extends Base
$image->make($path)->resize($width, $height)->encode();
});
} catch (NotReadableException | \Exception $e) {
Log::info('Company ID: ' . session('company_id') . ' components/documentshow.php exception.');
Log::info('Company ID: ' . company_id() . ' components/documentshow.php exception.');
Log::info($e->getMessage());
$path = base_path('public/img/company.png');
@ -651,11 +651,11 @@ abstract class DocumentShow extends Base
$route .= 'signed.' . $page . '.show';
try {
route($route, [$this->document->id, 'company_id' => session('company_id')]);
route($route, [$this->document->id, 'company_id' => company_id()]);
$signedUrl = URL::signedRoute($route, [$this->document->id, 'company_id' => session('company_id')]);
$signedUrl = URL::signedRoute($route, [$this->document->id]);
} catch (\Exception $e) {
$signedUrl = URL::signedRoute('signed.invoices.show', [$this->document->id, 'company_id' => session('company_id')]);
$signedUrl = URL::signedRoute('signed.invoices.show', [$this->document->id]);
}
return $signedUrl;

View File

@ -213,7 +213,7 @@ abstract class DocumentTemplate extends Base
$image->make($path)->resize($width, $height)->encode();
});
} catch (NotReadableException | \Exception $e) {
Log::info('Company ID: ' . session('company_id') . ' components/documentshow.php exception.');
Log::info('Company ID: ' . company_id() . ' components/documentshow.php exception.');
Log::info($e->getMessage());
$path = base_path('public/img/company.png');

View File

@ -35,7 +35,7 @@ class Companies extends BulkAction
foreach ($companies as $company) {
try {
$this->dispatch(new UpdateCompany($company, $request->merge(['enabled' => 1]), session('company_id')));
$this->dispatch(new UpdateCompany($company, $request->merge(['enabled' => 1])));
} catch (\Exception $e) {
flash($e->getMessage())->error()->important();
}
@ -48,7 +48,7 @@ class Companies extends BulkAction
foreach ($companies as $company) {
try {
$this->dispatch(new UpdateCompany($company, $request->merge(['enabled' => 0]), session('company_id')));
$this->dispatch(new UpdateCompany($company, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error()->important();
}
@ -61,7 +61,7 @@ class Companies extends BulkAction
foreach ($companies as $company) {
try {
$this->dispatch(new DeleteCompany($company, session('company_id')));
$this->dispatch(new DeleteCompany($company));
} catch (\Exception $e) {
flash($e->getMessage())->error()->important();
}

View File

@ -47,12 +47,8 @@ class BillReminder extends Command
$this->info('Sending bill reminders for ' . $company->name . ' company.');
// Set company id
session(['company_id' => $company->id]);
// Override settings and currencies
Overrider::load('settings');
Overrider::load('currencies');
// Set company
$company->makeCurrent();
// Don't send reminders if disabled
if (!setting('schedule.send_bill_reminder')) {
@ -70,9 +66,7 @@ class BillReminder extends Command
}
}
// Unset company_id
session()->forget('company_id');
setting()->forgetAll();
Company::forgetCurrent();
}
protected function remind($day)

View File

@ -47,8 +47,7 @@ class DownloadModule extends Command
$this->alias = $this->argument('alias');
$this->company = $this->argument('company');
session(['company_id' => $this->company]);
setting()->setExtraColumns(['company_id' => $this->company]);
company($this->company)->makeCurrent();
if (!$path = $this->download()) {
return self::CMD_ERROR;

View File

@ -57,8 +57,7 @@ class FinishUpdate extends Command
}
}
session(['company_id' => $company_id]);
setting()->setExtraColumns(['company_id' => $company_id]);
company($company_id)->makeCurrent();
// Disable model cache during update
config(['laravel-model-caching.enabled' => false]);

View File

@ -47,12 +47,8 @@ class InvoiceReminder extends Command
$this->info('Sending invoice reminders for ' . $company->name . ' company.');
// Set company id
session(['company_id' => $company->id]);
// Override settings and currencies
Overrider::load('settings');
Overrider::load('currencies');
// Set company
$company->makeCurrent();
// Don't send reminders if disabled
if (!setting('schedule.send_invoice_reminder')) {
@ -70,9 +66,7 @@ class InvoiceReminder extends Command
}
}
// Unset company_id
session()->forget('company_id');
setting()->forgetAll();
Company::forgetCurrent();
}
protected function remind($day)

View File

@ -7,10 +7,10 @@ use App\Events\Banking\TransactionRecurring;
use App\Events\Document\DocumentCreated;
use App\Events\Document\DocumentRecurring;
use App\Models\Banking\Transaction;
use App\Models\Common\Company;
use App\Models\Common\Recurring;
use App\Models\Document\Document;
use App\Utilities\Date;
use App\Utilities\Overrider;
use Illuminate\Console\Command;
class RecurringCheck extends Command
@ -83,12 +83,7 @@ class RecurringCheck extends Command
continue;
}
// Set company id
session(['company_id' => $recur->company_id]);
// Override settings and currencies
Overrider::load('settings');
Overrider::load('currencies');
company($recur->company_id)->makeCurrent();
$today = Date::today();
@ -121,9 +116,7 @@ class RecurringCheck extends Command
}
}
// Unset company_id
session()->forget('company_id');
setting()->forgetAll();
Company::forgetCurrent();
}
protected function recur($model, $type, $schedule_date)

View File

@ -68,8 +68,7 @@ class Update extends Command
$this->old = $this->getOldVersion();
session(['company_id' => $this->company]);
setting()->setExtraColumns(['company_id' => $this->company]);
company($this->company)->makeCurrent();
if (!$path = $this->download()) {
return self::CMD_ERROR;

View File

@ -40,7 +40,7 @@ class FinishInstallation
protected function callSeeds()
{
Artisan::call('company:seed', [
'company' => session('company_id'),
'company' => company_id(),
'--class' => 'Modules\$STUDLY_NAME$\Database\Seeds\$STUDLY_NAME$DatabaseSeeder',
]);
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Events\Common;
use App\Abstracts\Event;
class CompanyForgettingCurrent extends Event
{
public $company;
/**
* Create a new event instance.
*
* @param $company
*/
public function __construct($company)
{
$this->company = $company;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Events\Common;
use App\Abstracts\Event;
class CompanyForgotCurrent extends Event
{
public $company;
/**
* Create a new event instance.
*
* @param $company
*/
public function __construct($company)
{
$this->company = $company;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Events\Common;
use App\Abstracts\Event;
class CompanyMadeCurrent extends Event
{
public $company;
/**
* Create a new event instance.
*
* @param $company
*/
public function __construct($company)
{
$this->company = $company;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Events\Common;
use App\Abstracts\Event;
class CompanyMakingCurrent extends Event
{
public $company;
/**
* Create a new event instance.
*
* @param $company
*/
public function __construct($company)
{
$this->company = $company;
}
}

View File

@ -69,7 +69,7 @@ class Companies extends ApiController
public function update(Company $company, Request $request)
{
try {
$company = $this->dispatch(new UpdateCompany($company, $request, session('company_id')));
$company = $this->dispatch(new UpdateCompany($company, $request));
return $this->item($company->fresh(), new Transformer());
} catch (\Exception $e) {
@ -86,7 +86,7 @@ class Companies extends ApiController
public function enable(Company $company)
{
try {
$company = $this->dispatch(new UpdateCompany($company, request()->merge(['enabled' => 1]), session('company_id')));
$company = $this->dispatch(new UpdateCompany($company, request()->merge(['enabled' => 1])));
return $this->item($company->fresh(), new Transformer());
} catch (\Exception $e) {
@ -103,7 +103,7 @@ class Companies extends ApiController
public function disable(Company $company)
{
try {
$company = $this->dispatch(new UpdateCompany($company, request()->merge(['enabled' => 0]), session('company_id')));
$company = $this->dispatch(new UpdateCompany($company, request()->merge(['enabled' => 0])));
return $this->item($company->fresh(), new Transformer());
} catch (\Exception $e) {
@ -120,7 +120,7 @@ class Companies extends ApiController
public function destroy(Company $company)
{
try {
$this->dispatch(new DeleteCompany($company, session('company_id')));
$this->dispatch(new DeleteCompany($company));
return $this->response->noContent();
} catch (\Exception $e) {

View File

@ -37,16 +37,14 @@ class Login extends Controller
{
// Attempt to login
if (!auth()->attempt($request->only('email', 'password'), $request->get('remember', false))) {
$response = [
return response()->json([
'status' => null,
'success' => false,
'error' => true,
'message' => trans('auth.failed'),
'data' => null,
'redirect' => null,
];
return response()->json($response);
]);
}
// Get user object
@ -56,49 +54,64 @@ class Login extends Controller
if (!$user->enabled) {
$this->logout();
$response = [
return response()->json([
'status' => null,
'success' => false,
'error' => true,
'message' => trans('auth.disabled'),
'data' => null,
'redirect' => null,
];
return response()->json($response);
]);
}
// Check if is customer
if ($user->can('read-client-portal')) {
$path = session('url.intended', 'portal');
$company = $user->withoutEvents(function () use ($user) {
return $user->companies()->enabled()->first();
});
// Path must start with 'portal' prefix
if (!Str::startsWith($path, 'portal')) {
$path = 'portal';
// Logout if no company assigned
if (!$company) {
$this->logout();
return response()->json([
'status' => null,
'success' => false,
'error' => true,
'message' => trans('auth.error.no_company'),
'data' => null,
'redirect' => null,
]);
}
// Redirect to portal if is customer
if ($user->can('read-client-portal')) {
$path = session('url.intended', '');
// Path must start with company id and 'portal' prefix
if (!Str::startsWith($path, $company->id . '/portal')) {
$path = route('portal.dashboard', ['company_id' => $company->id]);
}
$response = [
return response()->json([
'status' => null,
'success' => true,
'error' => false,
'message' => null,
'data' => null,
'redirect' => url($path),
];
return response()->json($response);
]);
}
$response = [
// Redirect to landing page if is user
$url = route($user->landing_page, ['company_id' => $company->id]);
return response()->json([
'status' => null,
'success' => true,
'error' => false,
'message' => null,
'data' => null,
'redirect' => redirect()->intended(route($user->landing_page))->getTargetUrl(),
];
return response()->json($response);
'redirect' => redirect()->intended($url)->getTargetUrl(),
]);
}
public function destroy()

View File

@ -42,20 +42,16 @@ class Transactions extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.transactions', 2));
if ($response['success']) {
$response['redirect'] = route('transactions.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.transactions', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['banking', 'transactions']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -97,20 +97,16 @@ class Transfers extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.transfers', 2));
if ($response['success']) {
$response['redirect'] = route('transfers.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.transfers', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['banking', 'transfers']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -11,7 +11,6 @@ use App\Models\Common\Company;
use App\Models\Setting\Currency;
use App\Traits\Uploads;
use App\Traits\Users;
use App\Utilities\Overrider;
class Companies extends Controller
{
@ -60,7 +59,7 @@ class Companies extends Controller
*/
public function store(Request $request)
{
$company_id = session('company_id');
$current_company_id = company_id();
$response = $this->ajaxDispatch(new CreateCompany($request));
@ -78,9 +77,7 @@ class Companies extends Controller
flash($message)->error()->important();
}
session(['company_id' => $company_id]);
Overrider::load('settings');
company($current_company_id)->makeCurrent();
return response()->json($response);
}
@ -94,7 +91,7 @@ class Companies extends Controller
*/
public function edit(Company $company)
{
if (!$this->isUserCompany($company->id)) {
if ($this->isNotUserCompany($company->id)) {
return redirect()->route('companies.index');
}
@ -113,9 +110,9 @@ class Companies extends Controller
*/
public function update(Company $company, Request $request)
{
$company_id = session('company_id');
$current_company_id = company_id();
$response = $this->ajaxDispatch(new UpdateCompany($company, $request, session('company_id')));
$response = $this->ajaxDispatch(new UpdateCompany($company, $request, company_id()));
if ($response['success']) {
$response['redirect'] = route('companies.index');
@ -131,9 +128,7 @@ class Companies extends Controller
flash($message)->error()->important();
}
session(['company_id' => $company_id]);
Overrider::load('settings');
company($current_company_id)->makeCurrent();
return response()->json($response);
}
@ -147,7 +142,7 @@ class Companies extends Controller
*/
public function enable(Company $company)
{
$response = $this->ajaxDispatch(new UpdateCompany($company, request()->merge(['enabled' => 1]), session('company_id')));
$response = $this->ajaxDispatch(new UpdateCompany($company, request()->merge(['enabled' => 1])));
if ($response['success']) {
$response['message'] = trans('messages.success.enabled', ['type' => trans_choice('general.companies', 1)]);
@ -165,7 +160,7 @@ class Companies extends Controller
*/
public function disable(Company $company)
{
$response = $this->ajaxDispatch(new UpdateCompany($company, request()->merge(['enabled' => 0]), session('company_id')));
$response = $this->ajaxDispatch(new UpdateCompany($company, request()->merge(['enabled' => 0])));
if ($response['success']) {
$response['message'] = trans('messages.success.disabled', ['type' => trans_choice('general.companies', 1)]);
@ -183,7 +178,7 @@ class Companies extends Controller
*/
public function destroy(Company $company)
{
$response = $this->ajaxDispatch(new DeleteCompany($company, session('company_id')));
$response = $this->ajaxDispatch(new DeleteCompany($company));
$response['redirect'] = route('companies.index');
@ -210,22 +205,21 @@ class Companies extends Controller
public function switch(Company $company)
{
if ($this->isUserCompany($company->id)) {
$old_company_id = session('company_id');
$old_company_id = company_id();
$company->makeCurrent();
session(['company_id' => $company->id]);
session(['dashboard_id' => user()->dashboards()->enabled()->pluck('id')->first()]);
Overrider::load('settings');
event(new \App\Events\Common\CompanySwitched($company, $old_company_id));
// Check wizard
if (!setting('wizard.completed', false)) {
return redirect()->route('wizard.edit');
return redirect()->route('wizard.edit', ['company_id' => $company->id]);
}
}
return redirect()->route('dashboard');
return redirect()->route('dashboard', ['company_id' => $company->id]);
}
public function autocomplete()

View File

@ -7,7 +7,6 @@ use App\Http\Requests\Common\Dashboard as Request;
use App\Jobs\Common\CreateDashboard;
use App\Jobs\Common\DeleteDashboard;
use App\Jobs\Common\UpdateDashboard;
use App\Models\Common\Company;
use App\Models\Common\Dashboard;
use App\Models\Common\Widget;
use App\Traits\DateTime;
@ -60,7 +59,7 @@ class Dashboards extends Controller
if (empty($dashboard)) {
$dashboard = $this->dispatch(new CreateDashboard([
'company_id' => session('company_id'),
'company_id' => company_id(),
'name' => trans_choice('general.dashboards', 1),
'default_widgets' => 'core',
]));
@ -89,7 +88,7 @@ class Dashboards extends Controller
*/
public function create()
{
$users = Company::find(session('company_id'))->users()->get()->sortBy('name');
$users = company()->users()->get()->sortBy('name');
return view('common.dashboards.create', compact('users'));
}
@ -130,11 +129,11 @@ class Dashboards extends Controller
*/
public function edit(Dashboard $dashboard)
{
if (!$this->isUserDashboard($dashboard->id)) {
if ($this->isNotUserDashboard($dashboard->id)) {
return redirect()->route('dashboards.index');
}
$users = Company::find(session('company_id'))->users()->get()->sortBy('name');
$users = company()->users()->get()->sortBy('name');
return view('common.dashboards.edit', compact('dashboard', 'users'));
}

View File

@ -16,7 +16,7 @@ class Import extends Controller
*/
public function create($group, $type, $route = null)
{
$path = $group . '/' . $type;
$path = company_id() . '/' . $group . '/' . $type;
if (module($group) instanceof \Akaunting\Module\Module) {
$namespace = $group . '::';

View File

@ -111,20 +111,16 @@ class Items extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.items', 2));
if ($response['success']) {
$response['redirect'] = route('items.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.items', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['common', 'items']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -182,7 +182,7 @@ class Uploads extends Controller
$folders = explode('/', $media->directory);
// Check if company can access media
if ($folders[0] != session('company_id')) {
if ($folders[0] != company_id()) {
return false;
}

View File

@ -73,7 +73,7 @@ class Updates extends Controller
Cache::forget('updates');
Cache::forget('versions');
event(new UpdateCacheCleared(session('company_id')));
event(new UpdateCacheCleared(company_id()));
return redirect()->back();
}
@ -274,7 +274,7 @@ class Updates extends Controller
set_time_limit(900); // 15 minutes
try {
$this->dispatch(new FinishUpdate($request['alias'], $request['version'], $request['installed'], session('company_id')));
$this->dispatch(new FinishUpdate($request['alias'], $request['version'], $request['installed'], company_id()));
$json = [
'success' => true,

View File

@ -110,7 +110,7 @@ class DocumentItemColumns extends Controller
$company_id = $request->get('company_id');
if (empty($company_id)) {
$company_id = session('company_id');
$company_id = company_id();
}
foreach ($fields as $key => $value) {

View File

@ -32,7 +32,7 @@ class InvoiceTemplates extends Controller
$company_id = $request->get('company_id');
if (empty($company_id)) {
$company_id = session('company_id');
$company_id = company_id();
}
foreach ($fields as $key => $value) {

View File

@ -56,7 +56,7 @@ class Items extends Controller
{
if ($request->get('type', false) == 'inline') {
$data = [
'company_id' => session('company_id'),
'company_id' => company_id(),
'name' => '',
'sale_price' => 0,
'purchase_price' => 0,

View File

@ -204,7 +204,7 @@ class Item extends Controller
try {
$this->dispatch(new CopyFiles($request['alias'], $request['path']));
event(new \App\Events\Module\Copied($request['alias'], session('company_id')));
event(new \App\Events\Module\Copied($request['alias'], company_id()));
$json = [
'success' => true,
@ -236,9 +236,9 @@ class Item extends Controller
public function install(Request $request)
{
try {
event(new \App\Events\Module\Installing($request['alias'], session('company_id')));
event(new \App\Events\Module\Installing($request['alias'], company_id()));
$this->dispatch(new InstallModule($request['alias'], session('company_id')));
$this->dispatch(new InstallModule($request['alias'], company_id()));
$name = module($request['alias'])->getName();
@ -277,7 +277,7 @@ class Item extends Controller
try {
$name = module($alias)->getName();
$this->dispatch(new UninstallModule($alias, session('company_id')));
$this->dispatch(new UninstallModule($alias, company_id()));
$message = trans('modules.uninstalled', ['module' => $name]);
@ -296,7 +296,7 @@ class Item extends Controller
try {
$name = module($alias)->getName();
$this->dispatch(new EnableModule($alias, session('company_id')));
$this->dispatch(new EnableModule($alias, company_id()));
$message = trans('modules.enabled', ['module' => $name]);
@ -315,7 +315,7 @@ class Item extends Controller
try {
$name = module($alias)->getName();
$this->dispatch(new DisableModule($alias, session('company_id')));
$this->dispatch(new DisableModule($alias, company_id()));
$message = trans('modules.disabled', ['module' => $name]);

View File

@ -19,7 +19,7 @@ class My extends Controller
{
$purchased = $this->getMyModules();
$modules = $this->getInstalledModules();
$installed = Module::where('company_id', '=', session('company_id'))->pluck('enabled', 'alias')->toArray();
$installed = Module::where('company_id', '=', company_id())->pluck('enabled', 'alias')->toArray();
return $this->response('modules.my.index', compact('purchased', 'modules', 'installed'));
}

View File

@ -119,12 +119,12 @@ class Invoices extends Controller
$codes = explode('.', $payment_method_key);
if (!isset($payment_actions[$codes[0]])) {
$payment_actions[$codes[0]] = URL::signedRoute('signed.invoices.' . $codes[0] . '.show', [$invoice->id, 'company_id' => session('company_id')]);
$payment_actions[$codes[0]] = URL::signedRoute('signed.invoices.' . $codes[0] . '.show', [$invoice->id]);
}
}
$print_action = URL::signedRoute('signed.invoices.print', [$invoice->id, 'company_id' => session('company_id')]);
$pdf_action = URL::signedRoute('signed.invoices.pdf', [$invoice->id, 'company_id' => session('company_id')]);
$print_action = URL::signedRoute('signed.invoices.print', [$invoice->id]);
$pdf_action = URL::signedRoute('signed.invoices.pdf', [$invoice->id]);
event(new \App\Events\Document\DocumentViewed($invoice));

View File

@ -128,20 +128,16 @@ class Bills extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.bills', 2));
if ($response['success']) {
$response['redirect'] = route('bills.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['purchases', 'bills']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -134,20 +134,16 @@ class Payments extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.payments', 2));
if ($response['success']) {
$response['redirect'] = route('payments.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.payments', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['purchases', 'payments']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -161,20 +161,16 @@ class Vendors extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.vendors', 2));
if ($response['success']) {
$response['redirect'] = route('vendors.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.vendors', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['purchases', 'vendors']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -159,20 +159,16 @@ class Customers extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.customers', 2));
if ($response['success']) {
$response['redirect'] = route('customers.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.customers', 1)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['sales', 'customers']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -127,20 +127,16 @@ class Invoices extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.invoices', 2));
if ($response['success']) {
$response['redirect'] = route('invoices.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.invoices', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['sales', 'invoices']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -134,20 +134,16 @@ class Revenues extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.revenues', 2));
if ($response['success']) {
$response['redirect'] = route('revenues.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.revenues', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['sales', 'revenues']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -92,20 +92,16 @@ class Categories extends Controller
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
$response = $this->importExcel(new Import, $request, trans_choice('general.categories', 2));
if ($response['success']) {
$response['redirect'] = route('categories.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.categories', 2)]);
flash($message)->success();
flash($response['message'])->success();
} else {
$response['redirect'] = route('import.create', ['settings', 'categories']);
$message = $response['message'];
flash($message)->error()->important();
flash($response['message'])->error()->important();
}
return response()->json($response);

View File

@ -16,7 +16,7 @@ class Modules extends Controller
*/
public function __construct()
{
$alias = request()->segment(1);
$alias = request()->segment(2);
// Add CRUD permission check
$this->middleware('permission:create-' . $alias . '-settings')->only('create', 'store', 'duplicate', 'import');

View File

@ -80,7 +80,7 @@ class Settings extends Controller
$company_id = $request->get('company_id');
if (empty($company_id)) {
$company_id = session('company_id');
$company_id = company_id();
}
$company = Company::find($company_id);

View File

@ -31,7 +31,7 @@ class Companies extends Controller
*/
public function edit()
{
$company = Company::find(session('company_id'));
$company = Company::find(company_id());
return view('wizard.companies.edit', compact('company'));
}
@ -46,7 +46,7 @@ class Companies extends Controller
public function update(Request $request)
{
// Company
$company = Company::find(session('company_id'));
$company = Company::find(company_id());
$fields = $request->all();

View File

@ -36,11 +36,8 @@ class Kernel extends HttpKernel
// 'session.auth',
'session.errors',
'csrf',
'bindings',
'install.redirect',
'header.x',
'company.settings',
'company.currencies',
'language',
'firewall.all',
],
@ -55,16 +52,16 @@ class Kernel extends HttpKernel
'auth.disabled',
'throttle:api',
'permission:read-api',
'api.company',
'company.identify',
'bindings',
'company.settings',
'company.currencies',
'language',
'firewall.all',
],
'common' => [
'web',
'company.identify',
'bindings',
'wizard.redirect',
],
@ -77,6 +74,8 @@ class Kernel extends HttpKernel
'web',
'auth',
'auth.disabled',
'company.identify',
'bindings',
'wizard.redirect',
'menu.admin',
'permission:read-admin-panel',
@ -86,6 +85,8 @@ class Kernel extends HttpKernel
'web',
'auth',
'auth.disabled',
'company.identify',
'bindings',
'permission:read-admin-panel',
],
@ -93,6 +94,8 @@ class Kernel extends HttpKernel
'web',
'auth',
'auth.disabled',
'company.identify',
'bindings',
'menu.portal',
'permission:read-client-portal',
],
@ -105,11 +108,9 @@ class Kernel extends HttpKernel
'csrf',
'signature',
'signed.redirect',
'company.signed',
'company.identify',
'bindings',
'header.x',
'company.settings',
'company.currencies',
'language',
'firewall.all',
],
@ -141,13 +142,10 @@ class Kernel extends HttpKernel
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
// Akaunting
'api.company' => \App\Http\Middleware\ApiCompany::class,
'api.key' => \App\Http\Middleware\CanApiKey::class,
'api.key' => \App\Http\Middleware\RedirectIfNoApiKey::class,
'auth.disabled' => \App\Http\Middleware\LogoutIfUserDisabled::class,
'auth.redirect' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'company.currencies' => \App\Http\Middleware\LoadCurrencies::class,
'company.settings' => \App\Http\Middleware\LoadSettings::class,
'company.signed' => \App\Http\Middleware\SignedCompany::class,
'company.identify' => \App\Http\Middleware\IdentifyCompany::class,
'dropzone' => \App\Http\Middleware\Dropzone::class,
'header.x' => \App\Http\Middleware\AddXHeader::class,
'menu.admin' => \App\Http\Middleware\AdminMenu::class,

View File

@ -1,41 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Traits\Users;
class ApiCompany
{
use Users;
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$company_id = $request->get('company_id');
if (empty($company_id)) {
return $next($request);
}
// Check if user can access company
if (!$this->isUserCompany($company_id)) {
return $next($request);
}
// Set company id
session(['company_id' => $company_id]);
// Set the company settings
setting()->setExtraColumns(['company_id' => $company_id]);
setting()->load(true);
return $next($request);
}
}

View File

@ -10,7 +10,7 @@ class Authenticate extends Middleware
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string
* @return string|null
*/
protected function redirectTo($request)
{
@ -18,4 +18,4 @@ class Authenticate extends Middleware
return route('login');
}
}
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace App\Http\Middleware;
use App\Traits\Users;
use Closure;
use Illuminate\Auth\AuthenticationException;
class IdentifyCompany
{
use Users;
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string[] ...$guards
* @return mixed
*
* @throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$guards)
{
$company_id = $request->isApi()
? $this->getCompanyIdFromApi($request)
: $this->getCompanyIdFromWeb($request);
if (empty($company_id)) {
abort(500, 'Missing company');
}
// Check if user can access company
if ($request->isNotSigned($company_id) && $this->isNotUserCompany($company_id)) {
throw new AuthenticationException('Unauthenticated.', $guards);
}
// Set company as current
company($company_id)->makeCurrent();
// Fix routes
app('url')->defaults(['company_id' => $company_id]);
$request->route()->forgetParameter('company_id');
return $next($request);
}
protected function getCompanyIdFromWeb($request)
{
return (int) $request->route('company_id');
}
protected function getCompanyIdFromApi($request)
{
$company_id = $request->get('company_id', $request->header('X-Company'));
return $company_id ?: optional($this->getFirstCompanyOfUser())->id;
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Utilities\Overrider;
use Closure;
class LoadCurrencies
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$company_id = session('company_id');
if (empty($company_id)) {
return $next($request);
}
Overrider::load('currencies');
return $next($request);
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Utilities\Overrider;
use Closure;
class LoadSettings
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$company_id = session('company_id');
if (empty($company_id)) {
return $next($request);
}
Overrider::load('settings');
return $next($request);
}
}

View File

@ -20,15 +20,11 @@ class RedirectIfAuthenticated
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (auth()->guard($guard)->check()) {
$user = user();
if ($user->contact) {
return redirect()->route('portal.dashboard');
}
return redirect()->route($user->landing_page);
if (!auth()->guard($guard)->check()) {
continue;
}
return redirect(user()->getLandingPageOfUser());
}
return $next($request);

View File

@ -4,7 +4,7 @@ namespace App\Http\Middleware;
use Closure;
class CanApiKey
class RedirectIfNoApiKey
{
/**
* Handle an incoming request.
@ -14,15 +14,15 @@ class CanApiKey
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request['alias'] != 'core') {
if (setting('apps.api_key')) {
return $next($request);
} else {
redirect('apps/api-key/create')->send();
}
} else {
{
if ($request->get('alias') == 'core') {
return $next($request);
}
if (setting('apps.api_key')) {
return $next($request);
}
return redirect()->route('apps.api-key.create');
}
}
}

View File

@ -3,7 +3,6 @@
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
class RedirectIfNotInstalled
{
@ -22,11 +21,11 @@ class RedirectIfNotInstalled
}
// Already in the installation wizard
if (Str::startsWith($request->getPathInfo(), '/install')) {
if ($request->isInstall()) {
return $next($request);
}
// Not installed, redirect to installation wizard
redirect()->route('install.requirements')->send();
return redirect()->route('install.requirements');
}
}

View File

@ -3,7 +3,6 @@
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
class RedirectIfWizardNotCompleted
{
@ -22,11 +21,11 @@ class RedirectIfWizardNotCompleted
}
// Check url
if (Str::startsWith($request->getPathInfo(), '/wizard') || Str::startsWith($request->getPathInfo(), '/settings')) {
if ($request->isWizard(company_id()) || $request->is(company_id() . '/settings/*')) {
return $next($request);
}
// Redirect to wizard
redirect()->route('wizard.edit')->send();
return redirect()->route('wizard.edit');
}
}

View File

@ -24,14 +24,14 @@ class RedirectSignedIfAuthenticated
$page = 'dashboard';
$params = [];
if ($request->segment(2) == 'invoices') {
if ($request->segment(3) == 'invoices') {
$page = 'invoices.show';
$invoice = Document::find($request->segment(3));
$invoice = Document::find($request->segment(4));
$params = [$invoice->id];
}
redirect()->route($prefix . $page, $params)->send();
return redirect()->route($prefix . $page, $params);
}
}

View File

@ -1,33 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
class SignedCompany
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$company_id = $request->get('company_id');
if (empty($company_id)) {
return $next($request);
}
// Set company id
session(['company_id' => $company_id]);
// Set the company settings
setting()->setExtraColumns(['company_id' => $company_id]);
setting()->load(true);
return $next($request);
}
}

View File

@ -9,7 +9,6 @@ use Illuminate\View\View;
class DocumentType
{
/**
* Bind data to the view.
*
@ -18,14 +17,15 @@ class DocumentType
*/
public function compose(View $view)
{
if (!empty(request()->route())) {
$route = request()->route();
$route = request()->route();
/** @var Invoices|Bills|PortalInvoices $controller */
$controller = $route->getController();
$view->with(['type' => $controller->type ?? '']);
if (empty($route)) {
return;
}
}
/** @var Invoices|Bills|PortalInvoices $controller */
$controller = $route->getController();
$view->with(['type' => $controller->type ?? '']);
}
}

View File

@ -6,7 +6,6 @@ use Illuminate\View\View;
class InvoiceText
{
/**
* Bind data to the view.
*
@ -41,5 +40,4 @@ class InvoiceText
$view->with(['text_override' => $text_override]);
}
}
}

View File

@ -42,7 +42,7 @@ class Logo
$image->make($path)->resize($width, $height)->encode();
});
} catch (NotReadableException | \Exception $e) {
Log::info('Company ID: ' . session('company_id') . ' viewcomposer/logo.php exception.');
Log::info('Company ID: ' . company_id() . ' viewcomposer/logo.php exception.');
Log::info($e->getMessage());
$path = base_path('public/img/company.png');

View File

@ -27,6 +27,8 @@ class Notifications
return;
}
$path = str_replace('{company_id}/', '', $path);
if (!$notifications = $this->getNotifications($path)) {
return;
}

View File

@ -31,6 +31,8 @@ class Suggestions
return;
}
$path = str_replace('{company_id}/', '', $path);
if (!$suggestions = $this->getSuggestions($path)) {
return;
}

View File

@ -49,7 +49,7 @@ class Transfers extends Import
private function getExpenseTransactionId($row)
{
$expense_transaction = Transaction::create([
'company_id' => session('company_id'),
'company_id' => company_id(),
'type' => 'expense',
'account_id' => $row['from_account_id'],
'paid_at' => $row['transferred_at'],
@ -81,7 +81,7 @@ class Transfers extends Import
}
$income_transaction = Transaction::create([
'company_id' => session('company_id'),
'company_id' => company_id(),
'type' => 'income',
'account_id' => $row['to_account_id'],
'paid_at' => $row['transferred_at'],

View File

@ -0,0 +1,36 @@
<?php
namespace App\Jobs\Auth;
use App\Abstracts\JobShouldQueue;
class NotifyUser extends JobShouldQueue
{
protected $user;
protected $notification;
/**
* Create a new job instance.
*
* @param $user
* @param $notification
*/
public function __construct($user, $notification)
{
$this->user = $user;
$this->notification = $notification;
$this->onQueue('jobs');
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$this->user->notify($this->notification);
}
}

View File

@ -31,14 +31,14 @@ class CreateCompany extends Job
*/
public function handle()
{
$current_company_id = company_id();
event(new CompanyCreating($this->request));
\DB::transaction(function () {
$this->company = Company::create($this->request->all());
// Clear settings
setting()->setExtraColumns(['company_id' => $this->company->id]);
setting()->forgetAll();
$this->company->makeCurrent();
$this->callSeeds();
@ -47,6 +47,10 @@ class CreateCompany extends Job
event(new CompanyCreated($this->company));
if (!empty($current_company_id)) {
company($current_company_id)->makeCurrent();
}
return $this->company;
}
@ -106,6 +110,5 @@ class CreateCompany extends Job
}
setting()->save();
setting()->forgetAll();
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\JobShouldQueue;
use App\Notifications\Common\ExportCompleted;
use Illuminate\Support\Facades\File;
class CreateMediableForExport extends JobShouldQueue
{
protected $user;
protected $file_name;
/**
* Create a new job instance.
*
* @param $user
* @param $file_name
*/
public function __construct($user, $file_name)
{
$this->user = $user;
$this->file_name = $file_name;
$this->onQueue('jobs');
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$source = storage_path('app/uploads/' . $this->file_name);
$destination = storage_path('app/uploads/' . company_id() . '/exports/');
// Create exports directory
if (!File::isDirectory($destination)) {
File::makeDirectory($destination);
}
File::move($source, $destination . $this->file_name);
// Create the media record
$media = $this->importMedia($this->file_name, 'exports');
$this->user->attachMedia($media, 'export');
$download_url = route('uploads.download', ['id' => $media->id, 'company_id' => company_id()]);
$this->user->notify(new ExportCompleted($download_url));
}
}

View File

@ -11,17 +11,17 @@ class DeleteCompany extends Job
protected $company;
protected $active_company_id;
protected $current_company_id;
/**
* Create a new job instance.
*
* @param $request
* @param $company
*/
public function __construct($company, $active_company_id)
public function __construct($company)
{
$this->company = $company;
$this->active_company_id = $active_company_id;
$this->current_company_id = company_id();
}
/**
@ -56,14 +56,14 @@ class DeleteCompany extends Job
public function authorize()
{
// Can't delete active company
if ($this->company->id == $this->active_company_id) {
if ($this->company->id == $this->current_company_id) {
$message = trans('companies.error.delete_active');
throw new \Exception($message);
}
// Check if user can access company
if (!$this->isUserCompany($this->company->id)) {
if ($this->isNotUserCompany($this->company->id)) {
$message = trans('companies.error.not_user_company');
throw new \Exception($message);

View File

@ -60,7 +60,7 @@ class DeleteDashboard extends Job
}
// Check if user can access dashboard
if (!$this->isUserDashboard($this->dashboard->id)) {
if ($this->isNotUserDashboard($this->dashboard->id)) {
$message = trans('dashboards.error.not_user_dashboard');
throw new \Exception($message);

View File

@ -16,7 +16,7 @@ class UpdateCompany extends Job
protected $request;
protected $active_company_id;
protected $current_company_id;
/**
* Create a new job instance.
@ -24,11 +24,11 @@ class UpdateCompany extends Job
* @param $company
* @param $request
*/
public function __construct($company, $request, $active_company_id)
public function __construct($company, $request)
{
$this->company = $company;
$this->request = $this->getRequestInstance($request);
$this->active_company_id = $active_company_id;
$this->current_company_id = company_id();
}
/**
@ -45,10 +45,7 @@ class UpdateCompany extends Job
\DB::transaction(function () {
$this->company->update($this->request->all());
// Clear current and load given company settings
setting()->setExtraColumns(['company_id' => $this->company->id]);
setting()->forgetAll();
setting()->load(true);
$this->company->makeCurrent();
if ($this->request->has('name')) {
setting()->set('company.name', $this->request->get('name'));
@ -89,11 +86,14 @@ class UpdateCompany extends Job
}
setting()->save();
setting()->forgetAll();
});
event(new CompanyUpdated($this->company, $this->request));
if (!empty($this->current_company_id)) {
company($this->current_company_id)->makeCurrent();
}
return $this->company;
}
@ -105,14 +105,14 @@ class UpdateCompany extends Job
public function authorize()
{
// Can't disable active company
if (($this->request->get('enabled', 1) == 0) && ($this->company->id == $this->active_company_id)) {
if (($this->request->get('enabled', 1) == 0) && ($this->company->id == $this->current_company_id)) {
$message = trans('companies.error.disable_active');
throw new \Exception($message);
}
// Check if user can access company
if (!$this->isUserCompany($this->company->id)) {
if ($this->isNotUserCompany($this->company->id)) {
$message = trans('companies.error.not_user_company');
throw new \Exception($message);

View File

@ -77,7 +77,7 @@ class UpdateDashboard extends Job
}
// Check if user can access dashboard
if (!$this->isUserDashboard($this->dashboard->id)) {
if ($this->isNotUserDashboard($this->dashboard->id)) {
$message = trans('dashboards.error.not_user_dashboard');
throw new \Exception($message);

View File

@ -15,21 +15,6 @@ class Login
*/
public function handle(Event $event)
{
// Get first company
$company = $event->user->companies()->enabled()->first();
// Logout if no company assigned
if (!$company) {
app('App\Http\Controllers\Auth\Login')->logout();
flash(trans('auth.error.no_company'))->error()->important();
return;
}
// Set company id
session(['company_id' => $company->id]);
// Save user login time
$event->user->last_logged_in_at = Date::now();

View File

@ -29,17 +29,17 @@ class AddAdminItems
if (session('dashboard_id') != $dashboard->id) {
$sub->route('dashboards.switch', $dashboard->name, ['dashboard' => $dashboard->id], $key, $attr);
} else {
$sub->url('/', $dashboard->name, $key, $attr);
$sub->url('/' . company_id(), $dashboard->name, $key, $attr);
}
}
}, 10, [
'url' => '/',
'url' => '/' . company_id(),
'title' => trans_choice('general.dashboards', 2),
'icon' => 'fa fa-tachometer-alt',
]);
} else {
$menu->add([
'url' => '/',
'url' => '/' . company_id(),
'title' => trans_choice('general.dashboards', 1),
'icon' => 'fa fa-tachometer-alt',
'order' => 10,

View File

@ -51,7 +51,7 @@ class UpdateExtraModules
continue;
}
$company_id = session('company_id');
$company_id = company_id();
$command = "update {$alias} {$company_id} {$latest_version}";

View File

@ -70,34 +70,25 @@ class Version200 extends Listener
protected function updateCompanies()
{
$company_id = session('company_id');
$company_id = company_id();
$companies = Company::cursor();
foreach ($companies as $company) {
session(['company_id' => $company->id]);
$company->makeCurrent();
$this->updateSettings($company);
$this->updateSettings();
$this->createEmailTemplates($company);
$this->createReports($company);
}
setting()->forgetAll();
session(['company_id' => $company_id]);
Overrider::load('settings');
company($company_id)->makeCurrent();
}
public function updateSettings($company)
public function updateSettings()
{
// Set the active company settings
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->forgetAll();
setting()->load(true);
// Override settings
config(['app.url' => route('dashboard')]);
config(['app.timezone' => setting('general.timezone', 'UTC')]);

View File

@ -30,30 +30,21 @@ class Version203 extends Listener
protected function updateCompanies()
{
$company_id = session('company_id');
$company_id = company_id();
$companies = Company::cursor();
foreach ($companies as $company) {
session(['company_id' => $company->id]);
$company->makeCurrent();
$this->updateSettings($company);
}
setting()->forgetAll();
session(['company_id' => $company_id]);
Overrider::load('settings');
company($company_id)->makeCurrent();
}
public function updateSettings($company)
{
// Set the active company settings
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->forgetAll();
setting()->load(true);
setting()->set(['invoice.payment_terms' => setting('invoice.payment_terms', 0)]);
setting()->save();

View File

@ -1031,24 +1031,20 @@ class Version210 extends Listener
protected function updateCompanies()
{
$company_id = session('company_id');
$company_id = company_id();
$companies = Company::cursor();
foreach ($companies as $company) {
session(['company_id' => $company->id]);
$company->makeCurrent();
$this->updateSettings($company);
$this->updateSettings();
}
setting()->forgetAll();
session(['company_id' => $company_id]);
Overrider::load('settings');
company($company_id)->makeCurrent();
}
public function updateSettings($company)
public function updateSettings()
{
$income_category = Category::income()->enabled()->first();
$expense_category = Category::expense()->enabled()->first();
@ -1057,11 +1053,6 @@ class Version210 extends Listener
return;
}
// Set the active company settings
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->forgetAll();
setting()->load(true);
setting()->set(['default.income_category' => setting('default.income_category', $income_category->id)]);
setting()->set(['default.expense_category' => setting('default.expense_category', $expense_category->id)]);

View File

@ -30,30 +30,21 @@ class Version213 extends Listener
protected function updateCompanies()
{
$company_id = session('company_id');
$company_id = company_id();
$companies = Company::cursor();
foreach ($companies as $company) {
session(['company_id' => $company->id]);
$company->makeCurrent();
$this->updateSettings($company);
$this->updateSettings();
}
setting()->forgetAll();
session(['company_id' => $company_id]);
Overrider::load('settings');
company($company_id)->makeCurrent();
}
public function updateSettings($company)
public function updateSettings()
{
// Set the active company settings
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->forgetAll();
setting()->load(true);
$company_logo = setting('company.logo');
if (is_array($company_logo)) {

View File

@ -5,7 +5,9 @@ namespace App\Models\Auth;
use App\Traits\Tenants;
use App\Notifications\Auth\Reset;
use App\Traits\Media;
use App\Traits\Users;
use Date;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
@ -14,9 +16,9 @@ use Kyslik\ColumnSortable\Sortable;
use Laratrust\Traits\LaratrustUserTrait;
use Lorisleiva\LaravelSearchString\Concerns\SearchString;
class User extends Authenticatable
class User extends Authenticatable implements HasLocalePreference
{
use HasFactory, LaratrustUserTrait, Notifiable, SearchString, SoftDeletes, Sortable, Media, Tenants;
use HasFactory, LaratrustUserTrait, Notifiable, SearchString, SoftDeletes, Sortable, Media, Tenants, Users;
protected $table = 'users';
@ -193,20 +195,39 @@ class User extends Authenticatable
}
/**
* Convert tax to Array.
* Attach company_ids attribute to model.
*
* @return void
*/
public function setCompanyIds()
{
$this->setAttribute('company_ids', $this->companies->pluck('id')->toArray());
$company_ids = $this->withoutEvents(function () {
return $this->companies->pluck('id')->toArray();
});
$this->setAttribute('company_ids', $company_ids);
}
/**
* Detach company_ids attribute from model.
*
* @return void
*/
public function unsetCompanyIds()
{
$this->offsetUnset('company_ids');
}
/**
* Get the user's preferred locale.
*
* @return string
*/
public function preferredLocale()
{
return $this->locale;
}
/**
* Create a new factory instance for the model.
*

View File

@ -2,11 +2,16 @@
namespace App\Models\Common;
use App\Events\Common\CompanyForgettingCurrent;
use App\Events\Common\CompanyForgotCurrent;
use App\Events\Common\CompanyMadeCurrent;
use App\Events\Common\CompanyMakingCurrent;
use App\Models\Document\Document;
use App\Traits\Contacts;
use App\Traits\Media;
use App\Traits\Tenants;
use App\Traits\Transactions;
use App\Utilities\Overrider;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Database\Eloquent\SoftDeletes;
use Kyslik\ColumnSortable\Sortable;
@ -435,4 +440,82 @@ class Company extends Eloquent
{
return $this->getMedia('company_logo')->last();
}
public function makeCurrent()
{
if ($this->isCurrent()) {
return $this;
}
static::forgetCurrent();
event(new CompanyMakingCurrent($this));
// Bind to container
app()->instance(static::class, $this);
// Set session for backward compatibility @deprecated
//session(['company_id' => $this->id]);
// Load settings
setting()->setExtraColumns(['company_id' => $this->id]);
setting()->forgetAll();
setting()->load(true);
// Override settings and currencies
Overrider::load('settings');
Overrider::load('currencies');
event(new CompanyMadeCurrent($this));
return $this;
}
public function isCurrent()
{
return optional(static::getCurrent())->id === $this->id;
}
public function isNotCurrent()
{
return !$this->isCurrent();
}
public static function getCurrent()
{
if (!app()->has(static::class)) {
return null;
}
return app(static::class);
}
public static function forgetCurrent()
{
$current = static::getCurrent();
if (is_null($current)) {
return null;
}
event(new CompanyForgettingCurrent($current));
// Remove from container
app()->forgetInstance(static::class);
// Unset session for backward compatibility @deprecated
//session()->forget('company_id');
// Remove settings
setting()->forgetAll();
event(new CompanyForgotCurrent($current));
return $current;
}
public static function hasCurrent()
{
return static::getCurrent() !== null;
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace App\Notifications\Common;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class ExportCompleted extends Notification implements ShouldQueue
{
use Queueable;
protected $download_url;
/**
* Create a notification instance.
*
* @param string $download_url
*/
public function __construct($download_url)
{
$this->download_url = $download_url;
$this->onQueue('notifications');
}
/**
* Get the notification's channels.
*
* @param mixed $notifiable
* @return array|string
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Build the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject(trans('notifications.export.completed.subject'))
->line(trans('notifications.export.completed.description'))
->action(trans('general.download'), $this->download_url);
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Notifications\Common;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class ExportFailed extends Notification implements ShouldQueue
{
use Queueable;
/**
* The error exception.
*
* @var object
*/
public $exception;
/**
* Create a notification instance.
*
* @param object $exception
*/
public function __construct($exception)
{
$this->exception = $exception;
$this->onQueue('notifications');
}
/**
* Get the notification's channels.
*
* @param mixed $notifiable
* @return array|string
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Build the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject(trans('notifications.export.failed.subject'))
->line(trans('notifications.export.failed.description'))
->line($this->exception->getMessage());
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Notifications\Common;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class ImportCompleted extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a notification instance.
*/
public function __construct()
{
$this->onQueue('notifications');
}
/**
* Get the notification's channels.
*
* @param mixed $notifiable
* @return array|string
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Build the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$dashboard_url = route('dashboard', ['company_id' => company_id()]);
return (new MailMessage)
->subject(trans('notifications.import.completed.subject'))
->line(trans('notifications.import.completed.description'))
->action(trans_choice('general.dashboards', 1), $dashboard_url);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace App\Notifications\Common;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class ImportFailed extends Notification implements ShouldQueue
{
use Queueable;
/**
* The error messages.
*
* @var array
*/
public $errors;
/**
* Create a notification instance.
*
* @param object $errors
*/
public function __construct($errors)
{
$this->errors = $errors;
$this->onQueue('notifications');
}
/**
* Get the notification's channels.
*
* @param mixed $notifiable
* @return array|string
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Build the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$message = (new MailMessage)
->subject(trans('notifications.import.failed.subject'))
->line(trans('notifications.import.failed.description'));
foreach ($this->errors as $error) {
$message->line($error);
}
return $message;
}
}

View File

@ -3,6 +3,7 @@
namespace App\Notifications\Portal;
use App\Abstracts\Notification;
use App\Models\Common\EmailTemplate;
use Illuminate\Support\Facades\URL;
class PaymentReceived extends Notification
@ -39,7 +40,7 @@ class PaymentReceived extends Notification
$this->invoice = $invoice;
$this->transaction = $transaction;
$this->template = $template;
$this->template = EmailTemplate::alias($template)->first();
}
/**
@ -105,7 +106,7 @@ class PaymentReceived extends Notification
money($this->invoice->amount, $this->invoice->currency_code, true),
company_date($this->invoice->due_at),
trans('documents.statuses.' . $this->invoice->status),
URL::signedRoute('signed.invoices.show', [$this->invoice->id, 'company_id' => $this->invoice->company_id]),
URL::signedRoute('signed.invoices.show', [$this->invoice->id]),
route('invoices.show', $this->invoice->id),
route('portal.invoices.show', $this->invoice->id),
money($this->transaction->amount, $this->transaction->currency_code, true),

View File

@ -3,6 +3,7 @@
namespace App\Notifications\Purchase;
use App\Abstracts\Notification;
use App\Models\Common\EmailTemplate;
class Bill extends Notification
{
@ -31,7 +32,7 @@ class Bill extends Notification
parent::__construct();
$this->bill = $bill;
$this->template = $template;
$this->template = EmailTemplate::alias($template)->first();
}
/**

View File

@ -3,6 +3,7 @@
namespace App\Notifications\Sale;
use App\Abstracts\Notification;
use App\Models\Common\EmailTemplate;
use Illuminate\Support\Facades\URL;
class Invoice extends Notification
@ -32,7 +33,7 @@ class Invoice extends Notification
parent::__construct();
$this->invoice = $invoice;
$this->template = $template;
$this->template = EmailTemplate::alias($template)->first();
}
/**
@ -95,7 +96,7 @@ class Invoice extends Notification
money($this->invoice->amount, $this->invoice->currency_code, true),
money($this->invoice->amount_due, $this->invoice->currency_code, true),
company_date($this->invoice->due_at),
URL::signedRoute('signed.invoices.show', [$this->invoice->id, 'company_id' => $this->invoice->company_id]),
URL::signedRoute('signed.invoices.show', [$this->invoice->id]),
route('invoices.show', $this->invoice->id),
route('portal.invoices.show', $this->invoice->id),
$this->invoice->contact_name,

View File

@ -9,6 +9,16 @@ use Illuminate\View\Factory as ViewFactory;
class Macro extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
@ -24,6 +34,59 @@ class Macro extends ServiceProvider
return !$this->isApi();
});
Request::macro('isAuth', function () {
return $this->is('auth/*');
});
Request::macro('isNotAuth', function () {
return !$this->isAuth();
});
Request::macro('isInstall', function () {
return $this->is('install/*');
});
Request::macro('isNotInstall', function () {
return !$this->isInstall();
});
Request::macro('isSigned', function ($company_id) {
return $this->is($company_id . '/signed/*');
});
Request::macro('isNotSigned', function ($company_id) {
return !$this->isSigned($company_id);
});
Request::macro('isPortal', function ($company_id) {
return $this->is($company_id . '/portal') || $this->is($company_id . '/portal/*');
});
Request::macro('isNotPortal', function ($company_id) {
return !$this->isPortal($company_id);
});
Request::macro('isWizard', function ($company_id) {
return $this->is($company_id . '/wizard') || $this->is($company_id . '/wizard/*');
});
Request::macro('isNotWizard', function ($company_id) {
return !$this->isWizard($company_id);
});
Request::macro('isAdmin', function ($company_id) {
return $this->isNotApi()
&& $this->isNotAuth()
&& $this->isNotInstall()
&& $this->isNotSigned($company_id)
&& $this->isNotPortal($company_id)
&& $this->isNotWizard($company_id);
});
Request::macro('isNotAdmin', function ($company_id) {
return !$this->isAdmin($company_id);
});
Str::macro('filename', function ($string, $separator = '-') {
// Replace @ with the word 'at'
$string = str_replace('@', $separator.'at'.$separator, $string);
@ -47,14 +110,4 @@ class Macro extends ServiceProvider
return false;
});
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}

View File

@ -8,17 +8,7 @@ use Illuminate\Support\ServiceProvider as Provider;
class Observer extends Provider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function boot()
{
Transaction::observe('App\Observers\Transaction');
}
/**
* Register the service provider.
* Register any application services.
*
* @return void
*/
@ -26,4 +16,14 @@ class Observer extends Provider
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Transaction::observe('App\Observers\Transaction');
}
}

102
app/Providers/Queue.php Normal file
View File

@ -0,0 +1,102 @@
<?php
namespace App\Providers;
use App\Notifications\Common\ImportFailed;
use Illuminate\Queue\Events\JobFailed;
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Support\ServiceProvider as Provider;
class Queue extends Provider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
app('queue')->createPayloadUsing(function ($connection, $queue, $payload) {
$company_id = company_id();
if (empty($company_id)) {
return [];
}
return ['company_id' => $company_id];
});
app('events')->listen(JobProcessing::class, function ($event) {
$payload = $event->job->payload();
if (!array_key_exists('company_id', $payload)) {
return;
}
$company = company($payload['company_id']);
if (empty($company)) {
$event->job->delete();
}
$company->makeCurrent();
});
app('events')->listen(JobFailed::class, function ($event) {
if (!$event->exception instanceof \Maatwebsite\Excel\Validators\ValidationException) {
return;
}
$body = $event->job->getRawBody();
if (empty($body) || !is_string($body)) {
return;
}
$payload = json_decode($body);
if (empty($payload) || empty($payload->data) || empty($payload->data->command)) {
return;
}
$excel_job = unserialize($payload->data->command);
if (!$excel_job instanceof \Maatwebsite\Excel\Jobs\ReadChunk) {
return;
}
$ref = new \ReflectionProperty($excel_job, 'import');
$ref->setAccessible(true);
// Get import class
$class = $ref->getValue($excel_job);
if (!$class instanceof \App\Abstracts\Import) {
return;
}
$errors = [];
foreach ($event->exception->failures() as $failure) {
$message = trans('messages.error.import_column', [
'message' => collect($failure->errors())->first(),
'column' => $failure->attribute(),
'line' => $failure->row(),
]);
$errors[] = $message;
}
if (!empty($errors)) {
$class->user->notify(new ImportFailed($errors));
}
});
}
}

View File

@ -92,7 +92,8 @@ class Route extends Provider
*/
protected function mapCommonRoutes()
{
Facade::middleware('common')
Facade::prefix('{company_id}')
->middleware('common')
->namespace($this->namespace)
->group(base_path('routes/common.php'));
}
@ -120,7 +121,7 @@ class Route extends Provider
*/
protected function mapWizardRoutes()
{
Facade::prefix('wizard')
Facade::prefix('{company_id}/wizard')
->middleware('wizard')
->namespace($this->namespace)
->group(base_path('routes/wizard.php'));
@ -135,7 +136,8 @@ class Route extends Provider
*/
protected function mapAdminRoutes()
{
Facade::middleware('admin')
Facade::prefix('{company_id}')
->middleware('admin')
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
}
@ -149,7 +151,7 @@ class Route extends Provider
*/
protected function mapPortalRoutes()
{
Facade::prefix('portal')
Facade::prefix('{company_id}/portal')
->middleware('portal')
->namespace($this->namespace)
->group(base_path('routes/portal.php'));
@ -164,7 +166,7 @@ class Route extends Provider
*/
protected function mapSignedRoutes()
{
Facade::prefix('signed')
Facade::prefix('{company_id}/signed')
->middleware('signed')
->namespace($this->namespace)
->group(base_path('routes/signed.php'));

View File

@ -42,6 +42,6 @@ class Company implements Scope
}
// Apply company scope
$builder->where($table . '.company_id', '=', session('company_id'));
$builder->where($table . '.company_id', '=', company_id());
}
}

View File

@ -116,9 +116,9 @@ trait Import
public function getAccountIdFromCurrency($row)
{
return Account::firstOrCreate([
'company_id' => company_id(),
'currency_code' => $row['currency_code'],
], [
'company_id' => session('company_id'),
'name' => !empty($row['account_name']) ? $row['account_name'] : $row['currency_code'],
'number' => !empty($row['account_number']) ? $row['account_number'] : rand(1, 10000),
'opening_balance' => !empty($row['opening_balance']) ? $row['opening_balance'] : 0,
@ -129,9 +129,9 @@ trait Import
public function getAccountIdFromName($row)
{
return Account::firstOrCreate([
'company_id' => company_id(),
'name' => $row['account_name'],
], [
'company_id' => session('company_id'),
'number' => !empty($row['account_number']) ? $row['account_number'] : rand(1, 10000),
'currency_code' => !empty($row['currency_code']) ? $row['currency_code'] : setting('default.currency'),
'opening_balance' => !empty($row['opening_balance']) ? $row['opening_balance'] : 0,
@ -142,9 +142,9 @@ trait Import
public function getAccountIdFromNumber($row)
{
return Account::firstOrCreate([
'company_id' => company_id(),
'number' => $row['account_number'],
], [
'company_id' => session('company_id'),
'name' => !empty($row['account_name']) ? $row['account_name'] : $row['account_number'],
'currency_code' => !empty($row['currency_code']) ? $row['currency_code'] : setting('default.currency'),
'opening_balance' => !empty($row['opening_balance']) ? $row['opening_balance'] : 0,
@ -155,9 +155,9 @@ trait Import
public function getCategoryIdFromName($row, $type)
{
return Category::firstOrCreate([
'company_id' => company_id(),
'name' => $row['category_name'],
], [
'company_id' => session('company_id'),
'type' => $type,
'color' => !empty($row['category_color']) ? $row['category_color'] : '#' . dechex(rand(0x000000, 0xFFFFFF)),
'enabled' => 1,
@ -167,9 +167,9 @@ trait Import
public function getContactIdFromEmail($row, $type)
{
return Contact::firstOrCreate([
'company_id' => company_id(),
'email' => $row['contact_email'],
], [
'company_id' => session('company_id'),
'type' => $type,
'name' => !empty($row['contact_name']) ? $row['contact_name'] : $row['contact_email'],
'currency_code' => !empty($row['contact_currency']) ? $row['contact_currency'] : setting('default.currency'),
@ -180,9 +180,9 @@ trait Import
public function getContactIdFromName($row, $type)
{
return Contact::firstOrCreate([
'company_id' => company_id(),
'name' => $row['contact_name'],
], [
'company_id' => session('company_id'),
'type' => $type,
'currency_code' => !empty($row['contact_currency']) ? $row['contact_currency'] : setting('default.currency'),
'enabled' => 1,
@ -192,9 +192,9 @@ trait Import
public function getItemIdFromName($row)
{
return Item::firstOrCreate([
'company_id' => company_id(),
'name' => $row['item_name'],
], [
'company_id' => session('company_id'),
'sale_price' => !empty($row['sale_price']) ? $row['sale_price'] : (!empty($row['price']) ? $row['price'] : 0),
'purchase_price' => !empty($row['purchase_price']) ? $row['purchase_price'] : (!empty($row['price']) ? $row['price'] : 0),
'enabled' => 1,
@ -204,9 +204,9 @@ trait Import
public function getTaxIdFromRate($row, $type = 'normal')
{
return Tax::firstOrCreate([
'company_id' => company_id(),
'rate' => $row['tax_rate'],
], [
'company_id' => session('company_id'),
'type' => $type,
'name' => !empty($row['tax_name']) ? $row['tax_name'] : $row['tax_rate'],
'enabled' => 1,

View File

@ -3,6 +3,7 @@
namespace App\Traits;
use Exception;
use Illuminate\Bus\Dispatcher;
use Throwable;
trait Jobs
@ -17,7 +18,32 @@ trait Jobs
{
$function = $this->getDispatchFunction();
return $function($job);
return $this->$function($job);
}
/**
* Dispatch a job to its appropriate handler.
*
* @param mixed $command
* @return mixed
*/
public function dispatchQueue($job)
{
return app(Dispatcher::class)->dispatch($job);
}
/**
* Dispatch a command to its appropriate handler in the current process.
*
* Queuable jobs will be dispatched to the "sync" queue.
*
* @param mixed $command
* @param mixed $handler
* @return mixed
*/
public function dispatchSync($job, $handler = null)
{
return app(Dispatcher::class)->dispatchSync($job, $handler);
}
/**
@ -26,12 +52,12 @@ trait Jobs
* @param mixed $job
* @param mixed $handler
* @return mixed
*
* @deprecated Will be removed in a future Laravel version.
*/
public function dispatchNow($job, $handler = null)
{
$result = dispatch_now($job, $handler);
return $result;
return app(Dispatcher::class)->dispatchNow($job, $handler);
}
/**
@ -65,8 +91,6 @@ trait Jobs
public function getDispatchFunction()
{
$config = config('queue.default');
return ($config == 'sync') ? 'dispatch_now' : 'dispatch';
return should_queue() ? 'dispatchQueue' : 'dispatchSync';
}
}

View File

@ -164,7 +164,7 @@ trait Modules
public function getInstalledModules()
{
$key = 'apps.installed.' . session('company_id');
$key = 'apps.installed.' . company_id();
if ($installed = Cache::get($key)) {
return $installed;

View File

@ -83,7 +83,7 @@ trait Scopes
return $type;
}
$type = $request->get('type') ?: Str::singular((string) $request->segment(2));
$type = $request->get('type') ?: Str::singular((string) $request->segment(3));
if ($type == 'revenue') {
$type = 'income';

View File

@ -19,7 +19,7 @@ trait SiteApi
$headers['headers'] = [
'Authorization' => 'Bearer ' . setting('apps.api_key'),
'Accept' => 'application/json',
'Referer' => app()->runningInConsole() ? config('app.url') : route('dashboard'),
'Referer' => app()->runningInConsole() ? config('app.url') : url('/'),
'Akaunting' => version('short'),
'Language' => language()->getShortCode(),
'Information' => json_encode(Info::all()),

Some files were not shown because too many files have changed in this diff Show More