mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
49aeb4c2a1
@ -1 +1 @@
|
|||||||
5.5.41
|
5.5.42
|
@ -22,6 +22,8 @@ use App\Jobs\Company\CreateCompanyTaskStatuses;
|
|||||||
use App\Jobs\Ninja\CompanySizeCheck;
|
use App\Jobs\Ninja\CompanySizeCheck;
|
||||||
use App\Jobs\Util\VersionCheck;
|
use App\Jobs\Util\VersionCheck;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
|
use App\Models\BankIntegration;
|
||||||
|
use App\Models\BankTransaction;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
@ -223,6 +225,18 @@ class DemoMode extends Command
|
|||||||
'company_id' => $company->id,
|
'company_id' => $company->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$bi = BankIntegration::factory()->create([
|
||||||
|
'account_id' => $account->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
BankTransaction::factory()->count(50)->create([
|
||||||
|
'bank_integration_id' => $bi->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
]);
|
||||||
|
|
||||||
$this->info('Creating '.$this->count.' clients');
|
$this->info('Creating '.$this->count.' clients');
|
||||||
|
|
||||||
for ($x = 0; $x < $this->count; $x++) {
|
for ($x = 0; $x < $this->count; $x++) {
|
||||||
|
@ -48,7 +48,7 @@ class Kernel extends ConsoleKernel
|
|||||||
$schedule->job(new VersionCheck)->daily();
|
$schedule->job(new VersionCheck)->daily();
|
||||||
|
|
||||||
/* Checks and cleans redundant files */
|
/* Checks and cleans redundant files */
|
||||||
$schedule->job(new DiskCleanup)->daily()->withoutOverlapping();
|
$schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping();
|
||||||
|
|
||||||
/* Send reminders */
|
/* Send reminders */
|
||||||
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping();
|
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping();
|
||||||
@ -63,7 +63,7 @@ class Kernel extends ConsoleKernel
|
|||||||
$schedule->job(new UpdateExchangeRates)->dailyAt('23:30')->withoutOverlapping();
|
$schedule->job(new UpdateExchangeRates)->dailyAt('23:30')->withoutOverlapping();
|
||||||
|
|
||||||
/* Runs cleanup code for subscriptions */
|
/* Runs cleanup code for subscriptions */
|
||||||
$schedule->job(new SubscriptionCron)->daily()->withoutOverlapping();
|
$schedule->job(new SubscriptionCron)->dailyAt('00:01')->withoutOverlapping();
|
||||||
|
|
||||||
/* Sends recurring invoices*/
|
/* Sends recurring invoices*/
|
||||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping();
|
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping();
|
||||||
@ -72,22 +72,22 @@ class Kernel extends ConsoleKernel
|
|||||||
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping();
|
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping();
|
||||||
|
|
||||||
/* Fires notifications for expired Quotes */
|
/* Fires notifications for expired Quotes */
|
||||||
$schedule->job(new QuoteCheckExpired)->dailyAt('05:00')->withoutOverlapping();
|
$schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping();
|
||||||
|
|
||||||
/* Performs auto billing */
|
/* Performs auto billing */
|
||||||
$schedule->job(new AutoBillCron)->dailyAt('06:00')->withoutOverlapping();
|
$schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping();
|
||||||
|
|
||||||
/* Checks the status of the scheduler */
|
/* Checks the status of the scheduler */
|
||||||
$schedule->job(new SchedulerCheck)->daily()->withoutOverlapping();
|
$schedule->job(new SchedulerCheck)->dailyAt('01:10')->withoutOverlapping();
|
||||||
|
|
||||||
/* Checks for scheduled tasks */
|
/* Checks for scheduled tasks */
|
||||||
$schedule->job(new TaskScheduler())->daily()->withoutOverlapping();
|
$schedule->job(new TaskScheduler())->dailyAt('06:50')->withoutOverlapping();
|
||||||
|
|
||||||
/* Performs system maintenance such as pruning the backup table */
|
/* Performs system maintenance such as pruning the backup table */
|
||||||
$schedule->job(new SystemMaintenance)->weekly()->withoutOverlapping();
|
$schedule->job(new SystemMaintenance)->weekly()->withoutOverlapping();
|
||||||
|
|
||||||
/* Pulls in bank transactions from third party services */
|
/* Pulls in bank transactions from third party services */
|
||||||
$schedule->job(new BankTransactionSync)->dailyAt('04:00')->withoutOverlapping();
|
$schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping();
|
||||||
|
|
||||||
if (Ninja::isSelfHost()) {
|
if (Ninja::isSelfHost()) {
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ class Handler extends ExceptionHandler
|
|||||||
} elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
|
} elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
|
||||||
return response()->json(['message'=>'Fatal error'], 500);
|
return response()->json(['message'=>'Fatal error'], 500);
|
||||||
} elseif ($exception instanceof AuthorizationException) {
|
} elseif ($exception instanceof AuthorizationException) {
|
||||||
return response()->json(['message'=>'You are not authorized to view or perform this action'], 401);
|
return response()->json(['message'=> $exception->getMessage()], 401);
|
||||||
} elseif ($exception instanceof TokenMismatchException) {
|
} elseif ($exception instanceof TokenMismatchException) {
|
||||||
return redirect()
|
return redirect()
|
||||||
->back()
|
->back()
|
||||||
|
30
app/Factory/BankTransactionRuleFactory.php
Normal file
30
app/Factory/BankTransactionRuleFactory.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Factory;
|
||||||
|
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class BankTransactionRuleFactory
|
||||||
|
{
|
||||||
|
public static function create(int $company_id, int $user_id) :BankTransactionRule
|
||||||
|
{
|
||||||
|
$bank_transaction_rule = new BankTransactionRule;
|
||||||
|
$bank_transaction_rule->user_id = $user_id;
|
||||||
|
$bank_transaction_rule->company_id = $company_id;
|
||||||
|
|
||||||
|
$bank_transaction_rule->name = '';
|
||||||
|
$bank_transaction_rule->rules = [];
|
||||||
|
|
||||||
|
return $bank_transaction_rule;
|
||||||
|
}
|
||||||
|
}
|
133
app/Filters/BankTransactionRuleFilters.php
Normal file
133
app/Filters/BankTransactionRuleFilters.php
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BankTransactionRuleilters.
|
||||||
|
*/
|
||||||
|
class BankTransactionRuleFilters extends QueryFilters
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Filter by name.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return Builder
|
||||||
|
*/
|
||||||
|
public function name(string $name = ''): Builder
|
||||||
|
{
|
||||||
|
if(strlen($name) >=1)
|
||||||
|
return $this->builder->where('name', 'like', '%'.$name.'%');
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter based on search text.
|
||||||
|
*
|
||||||
|
* @param string query filter
|
||||||
|
* @return Builder
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public function filter(string $filter = '') : Builder
|
||||||
|
{
|
||||||
|
if (strlen($filter) == 0) {
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->builder->where(function ($query) use ($filter) {
|
||||||
|
$query->where('bank_transaction_rules.name', 'like', '%'.$filter.'%');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the list based on the status
|
||||||
|
* archived, active, deleted.
|
||||||
|
*
|
||||||
|
* @param string filter
|
||||||
|
* @return Builder
|
||||||
|
*/
|
||||||
|
public function status(string $filter = '') : Builder
|
||||||
|
{
|
||||||
|
if (strlen($filter) == 0) {
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = 'bank_transaction_rules';
|
||||||
|
$filters = explode(',', $filter);
|
||||||
|
|
||||||
|
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||||
|
$query->whereNull($table.'.id');
|
||||||
|
|
||||||
|
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||||
|
$query->orWhereNull($table.'.deleted_at');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||||
|
$query->orWhere(function ($query) use ($table) {
|
||||||
|
$query->whereNotNull($table.'.deleted_at');
|
||||||
|
|
||||||
|
if (! in_array($table, ['users'])) {
|
||||||
|
$query->where($table.'.is_deleted', '=', 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||||
|
$query->orWhere($table.'.is_deleted', '=', 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the list based on $sort.
|
||||||
|
*
|
||||||
|
* @param string sort formatted as column|asc
|
||||||
|
* @return Builder
|
||||||
|
*/
|
||||||
|
public function sort(string $sort) : Builder
|
||||||
|
{
|
||||||
|
$sort_col = explode('|', $sort);
|
||||||
|
|
||||||
|
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base query.
|
||||||
|
*
|
||||||
|
* @param int company_id
|
||||||
|
* @param User $user
|
||||||
|
* @return Builder
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public function baseQuery(int $company_id, User $user) : Builder
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the query by the users company ID.
|
||||||
|
*
|
||||||
|
* @return Illuminate\Database\Query\Builder
|
||||||
|
*/
|
||||||
|
public function entityFilter()
|
||||||
|
{
|
||||||
|
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||||
|
return $this->builder->company();
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@
|
|||||||
namespace App\Filters;
|
namespace App\Filters;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,6 +20,8 @@ use Illuminate\Database\Eloquent\Builder;
|
|||||||
*/
|
*/
|
||||||
class TaskFilters extends QueryFilters
|
class TaskFilters extends QueryFilters
|
||||||
{
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter based on search text.
|
* Filter based on search text.
|
||||||
*
|
*
|
||||||
@ -111,6 +114,16 @@ class TaskFilters extends QueryFilters
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function project_tasks($project)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (strlen($project) == 0) {
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->builder->where('project_id', $this->decodePrimaryKey($project));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the list based on $sort.
|
* Sorts the list based on $sort.
|
||||||
*
|
*
|
||||||
|
@ -87,7 +87,8 @@ class AccountTransformer implements AccountTransformerInterface
|
|||||||
return [
|
return [
|
||||||
'id' => $account->id,
|
'id' => $account->id,
|
||||||
'account_type' => $account->CONTAINER,
|
'account_type' => $account->CONTAINER,
|
||||||
'account_name' => $account->accountName,
|
// 'account_name' => $account->accountName,
|
||||||
|
'account_name' => property_exists($account, 'accountName') ? $account->accountName : $account->nickname,
|
||||||
'account_status' => $account->accountStatus,
|
'account_status' => $account->accountStatus,
|
||||||
'account_number' => property_exists($account, 'accountNumber') ? '**** ' . substr($account?->accountNumber, -7) : '',
|
'account_number' => property_exists($account, 'accountNumber') ? '**** ' . substr($account?->accountNumber, -7) : '',
|
||||||
'provider_account_id' => $account->providerAccountId,
|
'provider_account_id' => $account->providerAccountId,
|
||||||
|
@ -48,8 +48,15 @@ class EpcQrGenerator
|
|||||||
|
|
||||||
$this->validateFields();
|
$this->validateFields();
|
||||||
|
|
||||||
$qr = $writer->writeString($this->encodeMessage());
|
try {
|
||||||
|
$qr = $writer->writeString($this->encodeMessage(), 'utf-8');
|
||||||
|
}
|
||||||
|
catch(\Throwable $e){
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
return '';
|
||||||
|
}
|
||||||
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
||||||
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
||||||
|
|
||||||
@ -69,7 +76,7 @@ class EpcQrGenerator
|
|||||||
$this->formatMoney($this->amount),
|
$this->formatMoney($this->amount),
|
||||||
$this->sepa['purpose'],
|
$this->sepa['purpose'],
|
||||||
substr($this->invoice->number,0,34),
|
substr($this->invoice->number,0,34),
|
||||||
substr($this->invoice->public_notes,0,139),
|
'',
|
||||||
''
|
''
|
||||||
)), "\n");
|
)), "\n");
|
||||||
|
|
||||||
|
@ -87,10 +87,10 @@ class SwissQrGenerator
|
|||||||
$qrBill->setUltimateDebtor(
|
$qrBill->setUltimateDebtor(
|
||||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
||||||
substr($this->client->present()->name(), 0 , 70),
|
substr($this->client->present()->name(), 0 , 70),
|
||||||
$this->client->address1 ? substr($this->client->address1, 0 , 70) : '',
|
$this->client->address1 ? substr($this->client->address1, 0 , 70) : '_',
|
||||||
$this->client->address2 ? substr($this->client->address2, 0 , 16) : '',
|
$this->client->address2 ? substr($this->client->address2, 0 , 16) : '_',
|
||||||
$this->client->postal_code ? substr($this->client->postal_code, 0, 16) : '',
|
$this->client->postal_code ? substr($this->client->postal_code, 0, 16) : '_',
|
||||||
$this->client->city ? substr($this->client->city, 0, 35) : '',
|
$this->client->city ? substr($this->client->city, 0, 35) : '_',
|
||||||
'CH'
|
'CH'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -110,6 +110,8 @@ class ActivityController extends BaseController
|
|||||||
'vendor' => $activity->vendor ? $activity->vendor : '',
|
'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||||
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||||
'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
||||||
|
'subscription' => $activity->subscription ? $activity->subscription : '',
|
||||||
|
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||||
];
|
];
|
||||||
|
|
||||||
return array_merge($arr, $activity->toArray());
|
return array_merge($arr, $activity->toArray());
|
||||||
|
@ -481,19 +481,32 @@ class BankTransactionController extends BaseController
|
|||||||
{
|
{
|
||||||
$action = request()->input('action');
|
$action = request()->input('action');
|
||||||
|
|
||||||
if(!in_array($action, ['archive', 'restore', 'delete']))
|
if(!in_array($action, ['archive', 'restore', 'delete', 'convert_matched']))
|
||||||
return response()->json(['message' => 'Unsupported action.'], 400);
|
return response()->json(['message' => 'Unsupported action.'], 400);
|
||||||
|
|
||||||
$ids = request()->input('ids');
|
$ids = request()->input('ids');
|
||||||
|
|
||||||
$bank_transactions = BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
$bank_transactions = BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||||
|
|
||||||
|
if($action == 'convert_matched') //catch this action
|
||||||
|
{
|
||||||
|
if(auth()->user()->isAdmin())
|
||||||
|
{
|
||||||
|
$this->bank_transaction_repo->convert_matched($bank_transactions);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
$bank_transactions->each(function ($bank_transaction, $key) use ($action) {
|
$bank_transactions->each(function ($bank_transaction, $key) use ($action) {
|
||||||
if (auth()->user()->can('edit', $bank_transaction)) {
|
if (auth()->user()->can('edit', $bank_transaction)) {
|
||||||
$this->bank_transaction_repo->{$action}($bank_transaction);
|
$this->bank_transaction_repo->{$action}($bank_transaction);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||||
|
|
||||||
return $this->listResponse(BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
return $this->listResponse(BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||||
|
505
app/Http/Controllers/BankTransactionRuleController.php
Normal file
505
app/Http/Controllers/BankTransactionRuleController.php
Normal file
@ -0,0 +1,505 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Factory\BankTransactionFactory;
|
||||||
|
use App\Factory\BankTransactionRuleFactory;
|
||||||
|
use App\Filters\BankTransactionFilters;
|
||||||
|
use App\Filters\BankTransactionRuleFilters;
|
||||||
|
use App\Helpers\Bank\Yodlee\Yodlee;
|
||||||
|
use App\Http\Requests\BankTransactionRule\CreateBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\BankTransactionRule\DestroyBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\BankTransactionRule\EditBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\BankTransactionRule\ShowBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\BankTransactionRule\StoreBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\BankTransactionRule\UpdateBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\BankTransaction\AdminBankTransactionRuleRequest;
|
||||||
|
use App\Http\Requests\Import\PreImportRequest;
|
||||||
|
use App\Jobs\Bank\MatchBankTransactionRules;
|
||||||
|
use App\Models\BankTransaction;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use App\Repositories\BankTransactionRepository;
|
||||||
|
use App\Repositories\BankTransactionRuleRepository;
|
||||||
|
use App\Services\Bank\BankMatchingService;
|
||||||
|
use App\Transformers\BankTransactionRuleTransformer;
|
||||||
|
use App\Transformers\BankTransactionTransformer;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class BankTransactionRuleController extends BaseController
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
protected $entity_type = BankTransactionRule::class;
|
||||||
|
|
||||||
|
protected $entity_transformer = BankTransactionRuleTransformer::class;
|
||||||
|
|
||||||
|
protected $bank_transaction_repo;
|
||||||
|
|
||||||
|
public function __construct(BankTransactionRuleRepository $bank_transaction_repo)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->bank_transaction_repo = $bank_transaction_repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/api/v1/bank_transaction_rules",
|
||||||
|
* operationId="getBankTransactionRules",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Gets a list of bank_transaction_rules",
|
||||||
|
* description="Lists all bank transaction rules",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="rows",
|
||||||
|
* in="query",
|
||||||
|
* description="The number of bank integrations to return",
|
||||||
|
* example="50",
|
||||||
|
* required=false,
|
||||||
|
* @OA\Schema(
|
||||||
|
* type="number",
|
||||||
|
* format="integer",
|
||||||
|
* ),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="A list of bank integrations",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
* @param BankTransactionFilters $filter
|
||||||
|
* @return Response|mixed
|
||||||
|
*/
|
||||||
|
public function index(BankTransactionRuleFilters $filters)
|
||||||
|
{
|
||||||
|
|
||||||
|
$bank_transaction_rules = BankTransactionRule::filter($filters);
|
||||||
|
|
||||||
|
return $this->listResponse($bank_transaction_rules);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param ShowBankTransactionRuleRequest $request
|
||||||
|
* @param BankTransactionRule $bank_transaction_rule
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/api/v1/bank_transaction_rules/{id}",
|
||||||
|
* operationId="showBankTransactionRule",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Shows a bank_transaction",
|
||||||
|
* description="Displays a bank_transaction by id",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="id",
|
||||||
|
* in="path",
|
||||||
|
* description="The Bank Transaction RuleHashed ID",
|
||||||
|
* example="D2J234DFA",
|
||||||
|
* required=true,
|
||||||
|
* @OA\Schema(
|
||||||
|
* type="string",
|
||||||
|
* format="string",
|
||||||
|
* ),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns the bank_transaction rule object",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function show(ShowBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
return $this->itemResponse($bank_transaction_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param EditBankTransactionRuleRequest $request
|
||||||
|
* @param BankTransactionRule $bank_transaction_rule
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/api/v1/bank_transaction_rules/{id}/edit",
|
||||||
|
* operationId="editBankTransactionRule",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Shows a bank_transaction for editing",
|
||||||
|
* description="Displays a bank_transaction by id",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="id",
|
||||||
|
* in="path",
|
||||||
|
* description="The Bank Transaction Rule Hashed ID",
|
||||||
|
* example="D2J234DFA",
|
||||||
|
* required=true,
|
||||||
|
* @OA\Schema(
|
||||||
|
* type="string",
|
||||||
|
* format="string",
|
||||||
|
* ),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns the bank_transaction rule object",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function edit(EditBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
return $this->itemResponse($bank_transaction_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param UpdateBankTransactionRuleRequest $request
|
||||||
|
* @param BankTransactionRule $bank_transaction_rule
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @OA\Put(
|
||||||
|
* path="/api/v1/bank_transaction_rules/{id}",
|
||||||
|
* operationId="updateBankTransactionRule",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Updates a bank_transaction Rule",
|
||||||
|
* description="Handles the updating of a bank_transaction rule by id",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="id",
|
||||||
|
* in="path",
|
||||||
|
* description="The Bank Transaction Rule Hashed ID",
|
||||||
|
* example="D2J234DFA",
|
||||||
|
* required=true,
|
||||||
|
* @OA\Schema(
|
||||||
|
* type="string",
|
||||||
|
* format="string",
|
||||||
|
* ),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns the bank_transaction rule object",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function update(UpdateBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
|
||||||
|
//stubs for updating the model
|
||||||
|
$bank_transaction = $this->bank_transaction_repo->save($request->all(), $bank_transaction_rule);
|
||||||
|
|
||||||
|
return $this->itemResponse($bank_transaction_rule->fresh());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @param CreateBankTransactionRuleRequest $request
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/api/v1/bank_transaction_rules/create",
|
||||||
|
* operationId="getBankTransactionRulesCreate",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Gets a new blank bank_transaction rule object",
|
||||||
|
* description="Returns a blank object with default values",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="A blank bank_transaction rule object",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function create(CreateBankTransactionRuleRequest $request)
|
||||||
|
{
|
||||||
|
$bank_transaction_rule = BankTransactionRuleFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id);
|
||||||
|
|
||||||
|
return $this->itemResponse($bank_transaction_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param StoreBankTransactionRuleRequest $request
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @OA\Post(
|
||||||
|
* path="/api/v1/bank_transaction_rules",
|
||||||
|
* operationId="storeBankTransaction",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Adds a bank_transaction rule",
|
||||||
|
* description="Adds an bank_transaction to a company",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns the saved bank_transaction rule object",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function store(StoreBankTransactionRuleRequest $request)
|
||||||
|
{
|
||||||
|
//stub to store the model
|
||||||
|
$bank_transaction_rule = $this->bank_transaction_repo->save($request->all(), BankTransactionRuleFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id));
|
||||||
|
|
||||||
|
return $this->itemResponse($bank_transaction_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param DestroyBankTransactionRuleRequest $request
|
||||||
|
* @param BankTransactionRule $bank_transaction_rule
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
* @OA\Delete(
|
||||||
|
* path="/api/v1/bank_transaction_rules/{id}",
|
||||||
|
* operationId="deleteBankTransactionRule",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Deletes a bank_transaction rule",
|
||||||
|
* description="Handles the deletion of a bank_transaction rule by id",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="id",
|
||||||
|
* in="path",
|
||||||
|
* description="The Bank Transaction Rule Hashed ID",
|
||||||
|
* example="D2J234DFA",
|
||||||
|
* required=true,
|
||||||
|
* @OA\Schema(
|
||||||
|
* type="string",
|
||||||
|
* format="string",
|
||||||
|
* ),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns a HTTP status",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function destroy(DestroyBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
$this->bank_transaction_repo->delete($bank_transaction_rule);
|
||||||
|
|
||||||
|
return $this->itemResponse($bank_transaction_rule->fresh());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform bulk actions on the list view.
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*
|
||||||
|
* @OA\Post(
|
||||||
|
* path="/api/v1/bank_transation_rules/bulk",
|
||||||
|
* operationId="bulkBankTransactionRules",
|
||||||
|
* tags={"bank_transaction_rules"},
|
||||||
|
* summary="Performs bulk actions on an array of bank_transation rules",
|
||||||
|
* description="",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||||
|
* @OA\RequestBody(
|
||||||
|
* description="Action paramters",
|
||||||
|
* required=true,
|
||||||
|
* @OA\MediaType(
|
||||||
|
* mediaType="application/json",
|
||||||
|
* @OA\Schema(
|
||||||
|
* type="array",
|
||||||
|
* @OA\Items(
|
||||||
|
* type="integer",
|
||||||
|
* description="Array of hashed IDs to be bulk 'actioned",
|
||||||
|
* example="[0,1,2,3]",
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="The Bulk Action response",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function bulk()
|
||||||
|
{
|
||||||
|
$action = request()->input('action');
|
||||||
|
|
||||||
|
if(!in_array($action, ['archive', 'restore', 'delete']))
|
||||||
|
return response()->json(['message' => 'Unsupported action.'], 400);
|
||||||
|
|
||||||
|
$ids = request()->input('ids');
|
||||||
|
|
||||||
|
$bank_transaction_rules = BankTransactionRule::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||||
|
|
||||||
|
$bank_transaction_rules->each(function ($bank_transaction_rule, $key) use ($action) {
|
||||||
|
if (auth()->user()->can('edit', $bank_transaction_rule)) {
|
||||||
|
$this->bank_transaction_repo->{$action}($bank_transaction_rule);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||||
|
|
||||||
|
return $this->listResponse(BankTransactionRule::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -108,6 +108,7 @@ class BaseController extends Controller
|
|||||||
'company.system_logs',
|
'company.system_logs',
|
||||||
'company.bank_integrations',
|
'company.bank_integrations',
|
||||||
'company.bank_transactions',
|
'company.bank_transactions',
|
||||||
|
'company.bank_transaction_rules',
|
||||||
];
|
];
|
||||||
|
|
||||||
private $mini_load = [
|
private $mini_load = [
|
||||||
@ -126,6 +127,7 @@ class BaseController extends Controller
|
|||||||
'company.expense_categories',
|
'company.expense_categories',
|
||||||
'company.subscriptions',
|
'company.subscriptions',
|
||||||
'company.bank_integrations',
|
'company.bank_integrations',
|
||||||
|
'company.bank_transaction_rules',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@ -456,6 +458,13 @@ class BaseController extends Controller
|
|||||||
$query->where('bank_transactions.user_id', $user->id);
|
$query->where('bank_transactions.user_id', $user->id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'company.bank_transaction_rules'=> function ($query) use ($updated_at, $user) {
|
||||||
|
$query->where('updated_at', '>=', $updated_at);
|
||||||
|
|
||||||
|
if (! $user->isAdmin()) {
|
||||||
|
$query->where('bank_transaction_rules.user_id', $user->id);
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -530,6 +539,12 @@ class BaseController extends Controller
|
|||||||
$query->where('bank_integrations.user_id', $user->id);
|
$query->where('bank_integrations.user_id', $user->id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'company.bank_transaction_rules'=> function ($query) use ($updated_at, $user) {
|
||||||
|
|
||||||
|
if (! $user->isAdmin()) {
|
||||||
|
$query->where('bank_transaction_rules.user_id', $user->id);
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -41,6 +41,25 @@ class SubscriptionPurchaseController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function upgrade(Subscription $subscription, Request $request)
|
||||||
|
{
|
||||||
|
/* Make sure the contact is logged into the correct company for this subscription */
|
||||||
|
if (auth()->guard('contact')->user() && auth()->guard('contact')->user()->company_id != $subscription->company_id) {
|
||||||
|
auth()->guard('contact')->logout();
|
||||||
|
$request->session()->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('locale')) {
|
||||||
|
$this->setLocale($request->query('locale'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('billing-portal.purchasev2', [
|
||||||
|
'subscription' => $subscription,
|
||||||
|
'hash' => Str::uuid()->toString(),
|
||||||
|
'request_data' => $request->all(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set locale for incoming request.
|
* Set locale for incoming request.
|
||||||
*
|
*
|
||||||
@ -56,4 +75,7 @@ class SubscriptionPurchaseController extends Controller
|
|||||||
App::setLocale($record->locale);
|
App::setLocale($record->locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,8 @@ class CompanyController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function create(CreateCompanyRequest $request)
|
public function create(CreateCompanyRequest $request)
|
||||||
{
|
{
|
||||||
$company = CompanyFactory::create(auth()->user()->company()->account->id);
|
$cf = new \App\Factory\CompanyFactory;
|
||||||
|
$company = $cf->create(auth()->user()->company()->account->id);
|
||||||
|
|
||||||
return $this->itemResponse($company);
|
return $this->itemResponse($company);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
|||||||
use App\Http\Requests\Invoice\UpdateInvoiceRequest;
|
use App\Http\Requests\Invoice\UpdateInvoiceRequest;
|
||||||
use App\Http\Requests\Invoice\UpdateReminderRequest;
|
use App\Http\Requests\Invoice\UpdateReminderRequest;
|
||||||
use App\Http\Requests\Invoice\UploadInvoiceRequest;
|
use App\Http\Requests\Invoice\UploadInvoiceRequest;
|
||||||
|
use App\Jobs\Cron\AutoBill;
|
||||||
use App\Jobs\Entity\EmailEntity;
|
use App\Jobs\Entity\EmailEntity;
|
||||||
use App\Jobs\Invoice\BulkInvoiceJob;
|
use App\Jobs\Invoice\BulkInvoiceJob;
|
||||||
use App\Jobs\Invoice\StoreInvoice;
|
use App\Jobs\Invoice\StoreInvoice;
|
||||||
@ -696,11 +697,14 @@ class InvoiceController extends BaseController
|
|||||||
{
|
{
|
||||||
/*If we are using bulk actions, we don't want to return anything */
|
/*If we are using bulk actions, we don't want to return anything */
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
|
case 'auto_bill':
|
||||||
|
AutoBill::dispatch($invoice->id, $invoice->company->db);
|
||||||
|
return $this->itemResponse($invoice);
|
||||||
|
|
||||||
case 'clone_to_invoice':
|
case 'clone_to_invoice':
|
||||||
$invoice = CloneInvoiceFactory::create($invoice, auth()->user()->id);
|
$invoice = CloneInvoiceFactory::create($invoice, auth()->user()->id);
|
||||||
|
|
||||||
return $this->itemResponse($invoice);
|
return $this->itemResponse($invoice);
|
||||||
break;
|
|
||||||
case 'clone_to_quote':
|
case 'clone_to_quote':
|
||||||
$quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id);
|
$quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id);
|
||||||
|
|
||||||
@ -767,7 +771,7 @@ class InvoiceController extends BaseController
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'cancel':
|
case 'cancel':
|
||||||
$invoice = $invoice->service()->handleCancellation()->deletePdf()->touchPdf()->save();
|
$invoice = $invoice->service()->handleCancellation()->touchPdf()->save();
|
||||||
|
|
||||||
if (! $bulk) {
|
if (! $bulk) {
|
||||||
$this->itemResponse($invoice);
|
$this->itemResponse($invoice);
|
||||||
@ -777,7 +781,7 @@ class InvoiceController extends BaseController
|
|||||||
case 'email':
|
case 'email':
|
||||||
//check query parameter for email_type and set the template else use calculateTemplate
|
//check query parameter for email_type and set the template else use calculateTemplate
|
||||||
|
|
||||||
if (request()->has('email_type') && property_exists($invoice->company->settings, request()->input('email_type'))) {
|
if (request()->has('email_type') && in_array(request()->input('email_type'), ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'custom1', 'custom2', 'custom3'])) {
|
||||||
$this->reminder_template = $invoice->client->getSetting(request()->input('email_type'));
|
$this->reminder_template = $invoice->client->getSetting(request()->input('email_type'));
|
||||||
} else {
|
} else {
|
||||||
$this->reminder_template = $invoice->calculateTemplate('invoice');
|
$this->reminder_template = $invoice->calculateTemplate('invoice');
|
||||||
|
@ -181,7 +181,10 @@ class MigrationController extends BaseController
|
|||||||
$company->tasks()->forceDelete();
|
$company->tasks()->forceDelete();
|
||||||
$company->vendors()->forceDelete();
|
$company->vendors()->forceDelete();
|
||||||
$company->expenses()->forceDelete();
|
$company->expenses()->forceDelete();
|
||||||
$company->purchase_orders()->forceDelete();
|
$company->bank_transaction_rules()->forceDelete();
|
||||||
|
$company->bank_transactions()->forceDelete();
|
||||||
|
$company->bank_integrations()->forceDelete();
|
||||||
|
|
||||||
$company->all_activities()->forceDelete();
|
$company->all_activities()->forceDelete();
|
||||||
|
|
||||||
$settings = $company->settings;
|
$settings = $company->settings;
|
||||||
|
10
app/Http/Controllers/OpenAPI/BTRulesSchema.php
Normal file
10
app/Http/Controllers/OpenAPI/BTRulesSchema.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @OA\Schema(
|
||||||
|
* schema="BTRules",
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="data_key", type="string", example="description,amount", description="The key to search"),
|
||||||
|
* @OA\Property(property="operator", type="string", example=">", description="The operator flag of the search"),
|
||||||
|
* @OA\Property(property="value", type="string" ,example="bob", description="The value to search for"),
|
||||||
|
* )
|
||||||
|
*/
|
@ -6,7 +6,7 @@
|
|||||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The bank integration hashed id"),
|
* @OA\Property(property="id", type="string", example="AS3df3A", description="The bank integration hashed id"),
|
||||||
* @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"),
|
* @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"),
|
||||||
* @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user hashed id"),
|
* @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user hashed id"),
|
||||||
* @OA\Property(property="transaction_id", type="integer", example=343434, description="The id of the transaction"),
|
* @OA\Property(property="transaction_id", type="integer", example=343434, description="The id of the transaction rule"),
|
||||||
* @OA\Property(property="amount", type="number", example=10.00, description="The transaction amount"),
|
* @OA\Property(property="amount", type="number", example=10.00, description="The transaction amount"),
|
||||||
* @OA\Property(property="currency_id", type="string", example="1", description="The currency ID of the currency"),
|
* @OA\Property(property="currency_id", type="string", example="1", description="The currency ID of the currency"),
|
||||||
* @OA\Property(property="account_type", type="string", example="creditCard", description="The account type"),
|
* @OA\Property(property="account_type", type="string", example="creditCard", description="The account type"),
|
||||||
|
25
app/Http/Controllers/OpenAPI/BankTransactionRule.php
Normal file
25
app/Http/Controllers/OpenAPI/BankTransactionRule.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @OA\Schema(
|
||||||
|
* schema="BankTransactionRule",
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="id", type="string", example="AS3df3A", description="The bank transaction rules hashed id"),
|
||||||
|
* @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"),
|
||||||
|
* @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user hashed id"),
|
||||||
|
* @OA\Property(property="name", type="string", example="Rule 1", description="The name of the transaction"),
|
||||||
|
* @OA\Property(
|
||||||
|
* property="rules",
|
||||||
|
* type="array",
|
||||||
|
* description="A mapped collection of the sub rules for the BankTransactionRule",
|
||||||
|
* @OA\Items(
|
||||||
|
* ref="#/components/schemas/BTRules",
|
||||||
|
* ),
|
||||||
|
* ),
|
||||||
|
* @OA\Property(property="auto_convert", type="boolean", example=true, description="Flags whether the rule converts the transaction automatically"),
|
||||||
|
* @OA\Property(property="matches_on_all", type="boolean", example=true, description="Flags whether all subrules are required for the match"),
|
||||||
|
* @OA\Property(property="applies_to", type="string", example="CREDIT", description="Flags whether the rule applies to a CREDIT or DEBIT"),
|
||||||
|
* @OA\Property(property="client_id", type="string", example="AS3df3A", description="The client hashed id"),
|
||||||
|
* @OA\Property(property="vendor_id", type="string", example="AS3df3A", description="The vendor hashed id"),
|
||||||
|
* @OA\Property(property="category_id", type="string", example="AS3df3A", description="The category hashed id"),
|
||||||
|
* )
|
||||||
|
*/
|
528
app/Http/Livewire/BillingPortalPurchasev2.php
Normal file
528
app/Http/Livewire/BillingPortalPurchasev2.php
Normal file
@ -0,0 +1,528 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Factory\ClientFactory;
|
||||||
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Mail\ContactPasswordlessLogin;
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\ClientContact;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Subscription;
|
||||||
|
use App\Repositories\ClientContactRepository;
|
||||||
|
use App\Repositories\ClientRepository;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use App\DataMapper\ClientSettings;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class BillingPortalPurchasev2 extends Component
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Random hash generated by backend to handle the tracking of state.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Top level text on the left side of billing page.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $heading_text;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* E-mail address model for user input.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password model for user input.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of subscription.
|
||||||
|
*
|
||||||
|
* @var Subscription
|
||||||
|
*/
|
||||||
|
public $subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of client contact.
|
||||||
|
*
|
||||||
|
* @var null|ClientContact
|
||||||
|
*/
|
||||||
|
public $contact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rules for validating the form.
|
||||||
|
*
|
||||||
|
* @var \string[][]
|
||||||
|
*/
|
||||||
|
protected $rules = [
|
||||||
|
'email' => ['required', 'email'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id for CompanyGateway record.
|
||||||
|
*
|
||||||
|
* @var string|integer
|
||||||
|
*/
|
||||||
|
public $company_gateway_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id for GatewayType.
|
||||||
|
*
|
||||||
|
* @var string|integer
|
||||||
|
*/
|
||||||
|
public $payment_method_id;
|
||||||
|
|
||||||
|
private $user_coupon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of steps that frontend form follows.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $steps = [
|
||||||
|
'passed_email' => false,
|
||||||
|
'existing_user' => false,
|
||||||
|
'fetched_payment_methods' => false,
|
||||||
|
'fetched_client' => false,
|
||||||
|
'show_start_trial' => false,
|
||||||
|
'passwordless_login_sent' => false,
|
||||||
|
'started_payment' => false,
|
||||||
|
'discount_applied' => false,
|
||||||
|
'show_loading_bar' => false,
|
||||||
|
'not_eligible' => null,
|
||||||
|
'not_eligible_message' => null,
|
||||||
|
'payment_required' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of payment methods fetched from client.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $methods = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of \App\Models\Invoice
|
||||||
|
*
|
||||||
|
* @var Invoice
|
||||||
|
*/
|
||||||
|
public $invoice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coupon model for user input
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $coupon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quantity for seats
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $quantity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First-hit request data (queries, locales...).
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $request_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disabled state of passwordless login button.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $passwordless_login_btn = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of company.
|
||||||
|
*
|
||||||
|
* @var Company
|
||||||
|
*/
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Campaign reference.
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
public $campaign;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
|
$this->quantity = 1;
|
||||||
|
|
||||||
|
$this->price = $this->subscription->price;
|
||||||
|
|
||||||
|
if (request()->query('coupon')) {
|
||||||
|
$this->coupon = request()->query('coupon');
|
||||||
|
$this->handleCoupon();
|
||||||
|
}
|
||||||
|
elseif(strlen($this->subscription->promo_code) == 0 && $this->subscription->promo_discount > 0){
|
||||||
|
$this->price = $this->subscription->promo_price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle user authentication
|
||||||
|
*
|
||||||
|
* @return $this|bool|void
|
||||||
|
*/
|
||||||
|
public function authenticate()
|
||||||
|
{
|
||||||
|
$this->validate();
|
||||||
|
|
||||||
|
$contact = ClientContact::where('email', $this->email)
|
||||||
|
->where('company_id', $this->subscription->company_id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($contact && $this->steps['existing_user'] === false) {
|
||||||
|
return $this->steps['existing_user'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contact && $this->steps['existing_user']) {
|
||||||
|
$attempt = Auth::guard('contact')->attempt(['email' => $this->email, 'password' => $this->password, 'company_id' => $this->subscription->company_id]);
|
||||||
|
|
||||||
|
return $attempt
|
||||||
|
? $this->getPaymentMethods($contact)
|
||||||
|
: session()->flash('message', 'These credentials do not match our records.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->steps['existing_user'] = false;
|
||||||
|
|
||||||
|
$contact = $this->createBlankClient();
|
||||||
|
|
||||||
|
if ($contact && $contact instanceof ClientContact) {
|
||||||
|
$this->getPaymentMethods($contact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a blank client. Used for new customers purchasing.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Laracasts\Presenter\Exceptions\PresenterException
|
||||||
|
*/
|
||||||
|
protected function createBlankClient()
|
||||||
|
{
|
||||||
|
$company = $this->subscription->company;
|
||||||
|
$user = $this->subscription->user;
|
||||||
|
$user->setCompany($company);
|
||||||
|
|
||||||
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => '',
|
||||||
|
'contacts' => [
|
||||||
|
['email' => $this->email],
|
||||||
|
],
|
||||||
|
'client_hash' => Str::random(40),
|
||||||
|
'settings' => ClientSettings::defaults(),
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($this->request_data as $field => $value) {
|
||||||
|
if (in_array($field, Client::$subscriptions_fillable)) {
|
||||||
|
$data[$field] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($field, ClientContact::$subscription_fillable)) {
|
||||||
|
$data['contacts'][0][$field] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nlog($this->subscription->group_settings->settings);
|
||||||
|
// nlog($this->subscription->group_settings->settings->currency_id);
|
||||||
|
|
||||||
|
if(array_key_exists('currency_id', $this->request_data)) {
|
||||||
|
|
||||||
|
$currency = Cache::get('currencies')->filter(function ($item){
|
||||||
|
return $item->id == $this->request_data['currency_id'];
|
||||||
|
})->first();
|
||||||
|
|
||||||
|
if($currency)
|
||||||
|
$data['settings']->currency_id = $currency->id;
|
||||||
|
|
||||||
|
}
|
||||||
|
elseif($this->subscription->group_settings && property_exists($this->subscription->group_settings->settings, 'currency_id')) {
|
||||||
|
|
||||||
|
$currency = Cache::get('currencies')->filter(function ($item){
|
||||||
|
return $item->id == $this->subscription->group_settings->settings->currency_id;
|
||||||
|
})->first();
|
||||||
|
|
||||||
|
if($currency)
|
||||||
|
$data['settings']->currency_id = $currency->id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('locale', $this->request_data)) {
|
||||||
|
$request = $this->request_data;
|
||||||
|
|
||||||
|
$record = Cache::get('languages')->filter(function ($item) use ($request) {
|
||||||
|
return $item->locale == $request['locale'];
|
||||||
|
})->first();
|
||||||
|
|
||||||
|
if ($record) {
|
||||||
|
$data['settings']['language_id'] = (string)$record->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$client = $client_repo->save($data, ClientFactory::create($company->id, $user->id));
|
||||||
|
|
||||||
|
return $client->fresh()->contacts->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetching payment methods from the client.
|
||||||
|
*
|
||||||
|
* @param ClientContact $contact
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
protected function getPaymentMethods(ClientContact $contact): self
|
||||||
|
{
|
||||||
|
Auth::guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
|
$this->contact = $contact;
|
||||||
|
|
||||||
|
if ($this->subscription->trial_enabled) {
|
||||||
|
$this->heading_text = ctrans('texts.plan_trial');
|
||||||
|
$this->steps['show_start_trial'] = true;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)$this->price == 0)
|
||||||
|
$this->steps['payment_required'] = false;
|
||||||
|
else
|
||||||
|
$this->steps['fetched_payment_methods'] = true;
|
||||||
|
|
||||||
|
$this->methods = $contact->client->service()->getPaymentMethods($this->price);
|
||||||
|
|
||||||
|
$this->heading_text = ctrans('texts.payment_methods');
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middle method between selecting payment method &
|
||||||
|
* submitting the from to the backend.
|
||||||
|
*
|
||||||
|
* @param $company_gateway_id
|
||||||
|
* @param $gateway_type_id
|
||||||
|
*/
|
||||||
|
public function handleMethodSelectingEvent($company_gateway_id, $gateway_type_id)
|
||||||
|
{
|
||||||
|
$this->company_gateway_id = $company_gateway_id;
|
||||||
|
$this->payment_method_id = $gateway_type_id;
|
||||||
|
|
||||||
|
$this->handleBeforePaymentEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to handle events before payments.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handleBeforePaymentEvents()
|
||||||
|
{
|
||||||
|
$this->steps['started_payment'] = true;
|
||||||
|
$this->steps['show_loading_bar'] = true;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'client_id' => $this->contact->client->id,
|
||||||
|
'date' => now()->format('Y-m-d'),
|
||||||
|
'invitations' => [[
|
||||||
|
'key' => '',
|
||||||
|
'client_contact_id' => $this->contact->hashed_id,
|
||||||
|
]],
|
||||||
|
'user_input_promo_code' => $this->coupon,
|
||||||
|
'coupon' => empty($this->subscription->promo_code) ? '' : $this->coupon,
|
||||||
|
'quantity' => $this->quantity,
|
||||||
|
];
|
||||||
|
|
||||||
|
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||||
|
|
||||||
|
if (is_array($is_eligible) && $is_eligible['message'] != 'Success') {
|
||||||
|
$this->steps['not_eligible'] = true;
|
||||||
|
$this->steps['not_eligible_message'] = $is_eligible['message'];
|
||||||
|
$this->steps['show_loading_bar'] = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->invoice = $this->subscription
|
||||||
|
->service()
|
||||||
|
->createInvoice($data, $this->quantity)
|
||||||
|
->service()
|
||||||
|
->markSent()
|
||||||
|
->fillDefaults()
|
||||||
|
->adjustInventory()
|
||||||
|
->save();
|
||||||
|
|
||||||
|
Cache::put($this->hash, [
|
||||||
|
'subscription_id' => $this->subscription->id,
|
||||||
|
'email' => $this->email ?? $this->contact->email,
|
||||||
|
'client_id' => $this->contact->client->id,
|
||||||
|
'invoice_id' => $this->invoice->id,
|
||||||
|
'context' => 'purchase',
|
||||||
|
'campaign' => $this->campaign,
|
||||||
|
], now()->addMinutes(60));
|
||||||
|
|
||||||
|
$this->emit('beforePaymentEventsCompleted');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method for starting the trial.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function handleTrial()
|
||||||
|
{
|
||||||
|
return $this->subscription->service()->startTrial([
|
||||||
|
'email' => $this->email ?? $this->contact->email,
|
||||||
|
'quantity' => $this->quantity,
|
||||||
|
'contact_id' => $this->contact->id,
|
||||||
|
'client_id' => $this->contact->client->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePaymentNotRequired()
|
||||||
|
{
|
||||||
|
|
||||||
|
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||||
|
|
||||||
|
if ($is_eligible['status_code'] != 200) {
|
||||||
|
$this->steps['not_eligible'] = true;
|
||||||
|
$this->steps['not_eligible_message'] = $is_eligible['message'];
|
||||||
|
$this->steps['show_loading_bar'] = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->subscription->service()->handleNoPaymentRequired([
|
||||||
|
'email' => $this->email ?? $this->contact->email,
|
||||||
|
'quantity' => $this->quantity,
|
||||||
|
'contact_id' => $this->contact->id,
|
||||||
|
'client_id' => $this->contact->client->id,
|
||||||
|
'coupon' => $this->coupon,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update quantity property.
|
||||||
|
*
|
||||||
|
* @param string $option
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function updateQuantity(string $option): int
|
||||||
|
{
|
||||||
|
$this->handleCoupon();
|
||||||
|
|
||||||
|
if ($this->quantity == 1 && $option == 'decrement') {
|
||||||
|
$this->price = $this->price * 1;
|
||||||
|
return $this->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->quantity > $this->subscription->max_seats_limit && $option == 'increment') {
|
||||||
|
$this->price = $this->price * $this->subscription->max_seats_limit;
|
||||||
|
return $this->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($option == 'increment') {
|
||||||
|
$this->quantity++;
|
||||||
|
$this->price = $this->price * $this->quantity;
|
||||||
|
return $this->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->quantity--;
|
||||||
|
$this->price = $this->price * $this->quantity;
|
||||||
|
|
||||||
|
return $this->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleCoupon()
|
||||||
|
{
|
||||||
|
|
||||||
|
if($this->steps['discount_applied']){
|
||||||
|
$this->price = $this->subscription->promo_price;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->coupon == $this->subscription->promo_code) {
|
||||||
|
$this->price = $this->subscription->promo_price;
|
||||||
|
$this->quantity = 1;
|
||||||
|
$this->steps['discount_applied'] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$this->price = $this->subscription->price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function passwordlessLogin()
|
||||||
|
{
|
||||||
|
$this->passwordless_login_btn = true;
|
||||||
|
|
||||||
|
$contact = ClientContact::query()
|
||||||
|
->where('email', $this->email)
|
||||||
|
->where('company_id', $this->subscription->company_id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$mailer = new NinjaMailerObject();
|
||||||
|
$mailer->mailable = new ContactPasswordlessLogin($this->email, $this->subscription->company, (string)route('client.subscription.purchase', $this->subscription->hashed_id) . '?coupon=' . $this->coupon);
|
||||||
|
$mailer->company = $this->subscription->company;
|
||||||
|
$mailer->settings = $this->subscription->company->settings;
|
||||||
|
$mailer->to_user = $contact;
|
||||||
|
|
||||||
|
NinjaMailerJob::dispatch($mailer);
|
||||||
|
|
||||||
|
$this->steps['passwordless_login_sent'] = true;
|
||||||
|
$this->passwordless_login_btn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
if (array_key_exists('email', $this->request_data)) {
|
||||||
|
$this->email = $this->request_data['email'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->contact instanceof ClientContact) {
|
||||||
|
$this->getPaymentMethods($this->contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
return render('components.livewire.billing-portal-purchasev2');
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,7 @@ class ContactKeyLogin
|
|||||||
$request->session()->invalidate();
|
$request->session()->invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//magic links survive for 1 hour
|
||||||
if ($request->segment(2) && $request->segment(2) == 'magic_link' && $request->segment(3)) {
|
if ($request->segment(2) && $request->segment(2) == 'magic_link' && $request->segment(3)) {
|
||||||
$payload = Cache::get($request->segment(3));
|
$payload = Cache::get($request->segment(3));
|
||||||
|
|
||||||
@ -66,7 +67,11 @@ class ContactKeyLogin
|
|||||||
}
|
}
|
||||||
} elseif ($request->segment(3) && config('ninja.db.multi_db_enabled')) {
|
} elseif ($request->segment(3) && config('ninja.db.multi_db_enabled')) {
|
||||||
if (MultiDB::findAndSetDbByContactKey($request->segment(3))) {
|
if (MultiDB::findAndSetDbByContactKey($request->segment(3))) {
|
||||||
if ($client_contact = ClientContact::where('contact_key', $request->segment(3))->first()) {
|
if ($client_contact = ClientContact::with('company')->where('contact_key', $request->segment(3))->first()) {
|
||||||
|
|
||||||
|
if($client_contact->company->settings->enable_client_portal_password)
|
||||||
|
return redirect()->route('client.login', ['company_key' => $client_contact->company->company_key]);
|
||||||
|
|
||||||
if (empty($client_contact->email)) {
|
if (empty($client_contact->email)) {
|
||||||
$client_contact->email = Str::random(6).'@example.com';
|
$client_contact->email = Str::random(6).'@example.com';
|
||||||
}
|
}
|
||||||
@ -82,7 +87,11 @@ class ContactKeyLogin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($request->segment(2) && $request->segment(2) == 'key_login' && $request->segment(3)) {
|
} elseif ($request->segment(2) && $request->segment(2) == 'key_login' && $request->segment(3)) {
|
||||||
if ($client_contact = ClientContact::where('contact_key', $request->segment(3))->first()) {
|
if ($client_contact = ClientContact::with('company')->where('contact_key', $request->segment(3))->first()) {
|
||||||
|
|
||||||
|
if($client_contact->company->settings->enable_client_portal_password)
|
||||||
|
return redirect()->route('client.login', ['company_key' => $client_contact->company->company_key]);
|
||||||
|
|
||||||
if (empty($client_contact->email)) {
|
if (empty($client_contact->email)) {
|
||||||
$client_contact->email = Str::random(6).'@example.com';
|
$client_contact->email = Str::random(6).'@example.com';
|
||||||
$client_contact->save();
|
$client_contact->save();
|
||||||
@ -125,7 +134,11 @@ class ContactKeyLogin
|
|||||||
return redirect($this->setRedirectPath());
|
return redirect($this->setRedirectPath());
|
||||||
}
|
}
|
||||||
} elseif ($request->segment(3)) {
|
} elseif ($request->segment(3)) {
|
||||||
if ($client_contact = ClientContact::where('contact_key', $request->segment(3))->first()) {
|
if ($client_contact = ClientContact::with('company')->where('contact_key', $request->segment(3))->first()) {
|
||||||
|
|
||||||
|
if($client_contact->company->settings->enable_client_portal_password)
|
||||||
|
return redirect()->route('client.login', ['company_key' => $client_contact->company->company_key]);
|
||||||
|
|
||||||
if (empty($client_contact->email)) {
|
if (empty($client_contact->email)) {
|
||||||
$client_contact->email = Str::random(6).'@example.com';
|
$client_contact->email = Str::random(6).'@example.com';
|
||||||
$client_contact->save();
|
$client_contact->save();
|
||||||
|
@ -44,7 +44,7 @@ class StoreBankTransactionRequest extends Request
|
|||||||
{
|
{
|
||||||
$input = $this->all();
|
$input = $this->all();
|
||||||
|
|
||||||
if(array_key_exists('bank_integration_id', $input) && strlen($input['bank_integration_id']) > 1)
|
if(array_key_exists('bank_integration_id', $input) && strlen($input['bank_integration_id']) > 1 && !is_numeric($input['bank_integration_id']))
|
||||||
$input['bank_integration_id'] = $this->decodePrimaryKey($input['bank_integration_id']);
|
$input['bank_integration_id'] = $this->decodePrimaryKey($input['bank_integration_id']);
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\BankTransactionRule;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
|
||||||
|
class CreateBankTransactionRuleRequest extends Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() : bool
|
||||||
|
{
|
||||||
|
return auth()->user()->can('create', BankTransactionRule::class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\BankTransactionRule;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
|
||||||
|
class DestroyBankTransactionRuleRequest extends Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() : bool
|
||||||
|
{
|
||||||
|
return auth()->user()->can('edit', $this->bank_transaction_rule);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\BankTransactionRule;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
|
||||||
|
class EditBankTransactionRuleRequest extends Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() : bool
|
||||||
|
{
|
||||||
|
return auth()->user()->can('edit', $this->bank_transaction_rule);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\BankTransactionRule;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
|
||||||
|
class ShowBankTransactionRuleRequest extends Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() : bool
|
||||||
|
{
|
||||||
|
return auth()->user()->can('view', $this->bank_transaction_rule);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\BankTransactionRule;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
|
class StoreBankTransactionRuleRequest extends Request
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() : bool
|
||||||
|
{
|
||||||
|
return auth()->user()->can('create', BankTransactionRule::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
/* Ensure we have a client name, and that all emails are unique*/
|
||||||
|
$rules = [
|
||||||
|
'name' => 'bail|required|string',
|
||||||
|
'rules' => 'bail|array',
|
||||||
|
'rules.*.operator' => 'bail|required|nullable',
|
||||||
|
'rules.*.search_key' => 'bail|required|nullable',
|
||||||
|
'rules.*.value' => 'bail|required|nullable',
|
||||||
|
'auto_convert' => 'bail|sometimes|bool',
|
||||||
|
'matches_on_all' => 'bail|sometimes|bool',
|
||||||
|
'applies_to' => 'bail|sometimes|string',
|
||||||
|
];
|
||||||
|
|
||||||
|
if(isset($this->category_id))
|
||||||
|
$rules['category_id'] = 'bail|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
|
if(isset($this->vendor_id))
|
||||||
|
$rules['vendor_id'] = 'bail|sometimes|exists:vendors,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
|
if(isset($this->client_id))
|
||||||
|
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareForValidation()
|
||||||
|
{
|
||||||
|
$input = $this->all();
|
||||||
|
|
||||||
|
$input = $this->decodePrimaryKeys($input);
|
||||||
|
|
||||||
|
$this->replace($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\BankTransactionRule;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
|
class UpdateBankTransactionRuleRequest extends Request
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() : bool
|
||||||
|
{
|
||||||
|
return auth()->user()->can('edit', $this->bank_transaction_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
/* Ensure we have a client name, and that all emails are unique*/
|
||||||
|
$rules = [
|
||||||
|
'name' => 'bail|required|string',
|
||||||
|
'rules' => 'bail|array',
|
||||||
|
'rules.*.operator' => 'bail|required|nullable',
|
||||||
|
'rules.*.search_key' => 'bail|required|nullable',
|
||||||
|
'rules.*.value' => 'bail|required|nullable',
|
||||||
|
'auto_convert' => 'bail|sometimes|bool',
|
||||||
|
'matches_on_all' => 'bail|sometimes|bool',
|
||||||
|
'applies_to' => 'bail|sometimes|string',
|
||||||
|
];
|
||||||
|
|
||||||
|
if(isset($this->category_id))
|
||||||
|
$rules['category_id'] = 'bail|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
|
if(isset($this->vendor_id))
|
||||||
|
$rules['vendor_id'] = 'bail|sometimes|exists:vendors,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
|
if(isset($this->client_id))
|
||||||
|
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareForValidation()
|
||||||
|
{
|
||||||
|
$input = $this->all();
|
||||||
|
|
||||||
|
$input = $this->decodePrimaryKeys($input);
|
||||||
|
|
||||||
|
$this->replace($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -61,22 +61,15 @@ class StoreCompanyRequest extends Request
|
|||||||
{
|
{
|
||||||
$input = $this->all();
|
$input = $this->all();
|
||||||
|
|
||||||
|
if(!isset($input['name']))
|
||||||
|
$input['name'] = 'Untitled Company';
|
||||||
|
|
||||||
if (array_key_exists('google_analytics_url', $input)) {
|
if (array_key_exists('google_analytics_url', $input)) {
|
||||||
$input['google_analytics_key'] = $input['google_analytics_url'];
|
$input['google_analytics_key'] = $input['google_analytics_url'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// $company_settings = CompanySettings::defaults();
|
|
||||||
|
|
||||||
//@todo this code doesn't make sense as we never return $company_settings anywhere
|
|
||||||
//@deprecated???
|
|
||||||
// if (array_key_exists('settings', $input) && ! empty($input['settings'])) {
|
|
||||||
// foreach ($input['settings'] as $key => $value) {
|
|
||||||
// $company_settings->{$key} = $value;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (array_key_exists('portal_domain', $input)) {
|
if (array_key_exists('portal_domain', $input)) {
|
||||||
$input['portal_domain'] = strtolower($input['portal_domain']);
|
$input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
|
@ -74,9 +74,9 @@ class UpdateCompanyRequest extends Request
|
|||||||
|
|
||||||
$input = $this->all();
|
$input = $this->all();
|
||||||
|
|
||||||
if (Ninja::isHosted() && array_key_exists('portal_domain', $input) && strlen($input['portal_domain']) > 1) {
|
if (array_key_exists('portal_domain', $input) && strlen($input['portal_domain']) > 1) {
|
||||||
$input['portal_domain'] = $this->addScheme($input['portal_domain']);
|
$input['portal_domain'] = $this->addScheme($input['portal_domain']);
|
||||||
$input['portal_domain'] = strtolower($input['portal_domain']);
|
$input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('settings', $input)) {
|
if (array_key_exists('settings', $input)) {
|
||||||
@ -108,6 +108,8 @@ class UpdateCompanyRequest extends Request
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$settings['email_style_custom'] = str_replace(['{{','}}'], ['',''], $settings['email_style_custom']);
|
||||||
|
|
||||||
if (! $account->isFreeHostedClient()) {
|
if (! $account->isFreeHostedClient()) {
|
||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
||||||
@ -124,10 +126,12 @@ class UpdateCompanyRequest extends Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function addScheme($url, $scheme = 'https://')
|
private function addScheme($url, $scheme = 'https://')
|
||||||
|
{
|
||||||
|
if(Ninja::isHosted())
|
||||||
{
|
{
|
||||||
$url = str_replace('http://', '', $url);
|
$url = str_replace('http://', '', $url);
|
||||||
|
|
||||||
$url = parse_url($url, PHP_URL_SCHEME) === null ? $scheme.$url : $url;
|
$url = parse_url($url, PHP_URL_SCHEME) === null ? $scheme.$url : $url;
|
||||||
|
}
|
||||||
|
|
||||||
return rtrim($url, '/');
|
return rtrim($url, '/');
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace App\Http\Requests\Report;
|
namespace App\Http\Requests\Report;
|
||||||
|
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
class GenericReportRequest extends Request
|
class GenericReportRequest extends Request
|
||||||
{
|
{
|
||||||
@ -27,11 +28,14 @@ class GenericReportRequest extends Request
|
|||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
nlog($this->date_range);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'start_date' => 'string|date',
|
'date_range' => 'bail|required|string',
|
||||||
'end_date' => 'string|date',
|
// 'start_date' => [Rule::requiredIf($this->date_range === 'custom')],
|
||||||
'date_key' => 'string',
|
// 'end_date' => [Rule::requiredIf($this->date_range === 'custom')],
|
||||||
'date_range' => 'sometimes|string',
|
'end_date' => 'bail|required_if:date_range,custom|nullable|date',
|
||||||
|
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
|
||||||
'report_keys' => 'present|array',
|
'report_keys' => 'present|array',
|
||||||
'send_email' => 'required|bool',
|
'send_email' => 'required|bool',
|
||||||
];
|
];
|
||||||
|
@ -28,8 +28,8 @@ class ProfitLossRequest extends Request
|
|||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'start_date' => 'string|date',
|
'start_date' => 'required_if:date_range,custom|string|date',
|
||||||
'end_date' => 'string|date',
|
'end_date' => 'required_if:date_range,custom|string|date',
|
||||||
'is_income_billed' => 'required|bail|bool',
|
'is_income_billed' => 'required|bail|bool',
|
||||||
'is_expense_billed' => 'bool',
|
'is_expense_billed' => 'bool',
|
||||||
'include_tax' => 'required|bail|bool',
|
'include_tax' => 'required|bail|bool',
|
||||||
|
@ -125,6 +125,10 @@ class Request extends FormRequest
|
|||||||
$input['company_gateway_id'] = $this->decodePrimaryKey($input['company_gateway_id']);
|
$input['company_gateway_id'] = $this->decodePrimaryKey($input['company_gateway_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
|
||||||
|
$input['category_id'] = $this->decodePrimaryKey($input['category_id']);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($input['client_contacts'])) {
|
if (isset($input['client_contacts'])) {
|
||||||
foreach ($input['client_contacts'] as $key => $contact) {
|
foreach ($input['client_contacts'] as $key => $contact) {
|
||||||
if (! array_key_exists('send_email', $contact) || ! array_key_exists('id', $contact)) {
|
if (! array_key_exists('send_email', $contact) || ! array_key_exists('id', $contact)) {
|
||||||
|
@ -35,26 +35,34 @@ class StoreSubscriptionRequest extends Request
|
|||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'product_ids' => ['sometimes'],
|
|
||||||
'recurring_product_ids' => ['sometimes'],
|
|
||||||
'assigned_user_id' => ['sometimes'],
|
|
||||||
'is_recurring' => ['sometimes'],
|
|
||||||
'frequency_id' => ['required_with:recurring_product_ids'],
|
|
||||||
'auto_bill' => ['sometimes'],
|
|
||||||
'promo_code' => ['sometimes'],
|
|
||||||
'promo_discount' => ['sometimes'],
|
|
||||||
'is_amount_discount' => ['sometimes'],
|
|
||||||
'allow_cancellation' => ['sometimes'],
|
|
||||||
'per_set_enabled' => ['sometimes'],
|
|
||||||
'min_seats_limit' => ['sometimes'],
|
|
||||||
'max_seats_limit' => ['sometimes'],
|
|
||||||
'trial_enabled' => ['sometimes'],
|
|
||||||
'trial_duration' => ['sometimes'],
|
|
||||||
'allow_query_overrides' => ['sometimes'],
|
|
||||||
'allow_plan_changes' => ['sometimes'],
|
|
||||||
'refund_period' => ['sometimes'],
|
|
||||||
'webhook_configuration' => ['array'],
|
|
||||||
'name' => ['required', Rule::unique('subscriptions')->where('company_id', auth()->user()->company()->id)],
|
'name' => ['required', Rule::unique('subscriptions')->where('company_id', auth()->user()->company()->id)],
|
||||||
|
'group_id' => ['bail','sometimes', 'nullable', Rule::exists('group_settings','id')->where('company_id', auth()->user()->company()->id)],
|
||||||
|
'assigned_user_id' => ['bail','sometimes', 'nullable', Rule::exists('users','id')->where('account_id', auth()->user()->account_id)],
|
||||||
|
'product_ids' => 'bail|sometimes|nullable|string',
|
||||||
|
'recurring_product_ids' => 'bail|sometimes|nullable|string',
|
||||||
|
'is_recurring' => 'bail|sometimes|bool',
|
||||||
|
'frequency_id' => 'bail|required_with:recurring_product_ids',
|
||||||
|
'auto_bill' => 'bail|sometimes|nullable|string',
|
||||||
|
'promo_code' => 'bail|sometimes|nullable|string',
|
||||||
|
'promo_discount' => 'bail|sometimes|numeric',
|
||||||
|
'is_amount_discount' => 'bail|sometimes|bool',
|
||||||
|
'allow_cancellation' => 'bail|sometimes|bool',
|
||||||
|
'per_set_enabled' => 'bail|sometimes|bool',
|
||||||
|
'min_seats_limit' => 'bail|sometimes|numeric',
|
||||||
|
'max_seats_limit' => 'bail|sometimes|numeric',
|
||||||
|
'trial_enabled' => 'bail|sometimes|bool',
|
||||||
|
'trial_duration' => 'bail|sometimes|numeric',
|
||||||
|
'allow_query_overrides' => 'bail|sometimes|bool',
|
||||||
|
'allow_plan_changes' => 'bail|sometimes|bool',
|
||||||
|
'refund_period' => 'bail|sometimes|numeric',
|
||||||
|
'webhook_configuration' => 'bail|array',
|
||||||
|
'webhook_configuration.post_purchase_url' => 'bail|sometimes|nullable|string',
|
||||||
|
'webhook_configuration.post_purchase_rest_method' => 'bail|sometimes|nullable|string',
|
||||||
|
'webhook_configuration.post_purchase_headers' => 'bail|sometimes|array',
|
||||||
|
'registration_required' => 'bail|sometimes|bool',
|
||||||
|
'optional_recurring_product_ids' => 'bail|sometimes|nullable|string',
|
||||||
|
'optional_product_ids' => 'bail|sometimes|nullable|string',
|
||||||
|
'use_inventory_management' => 'bail|sometimes|bool'
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -37,26 +37,34 @@ class UpdateSubscriptionRequest extends Request
|
|||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'product_ids' => ['sometimes'],
|
'name' => ['bail','sometimes', Rule::unique('subscriptions')->where('company_id', auth()->user()->company()->id)->ignore($this->subscription->id)],
|
||||||
'recurring_product_ids' => ['sometimes'],
|
'group_id' => ['bail','sometimes', 'nullable', Rule::exists('group_settings','id')->where('company_id', auth()->user()->company()->id)],
|
||||||
'assigned_user_id' => ['sometimes'],
|
'assigned_user_id' => ['bail','sometimes', 'nullable', Rule::exists('users','id')->where('account_id', auth()->user()->account_id)],
|
||||||
'is_recurring' => ['sometimes'],
|
'product_ids' => 'bail|sometimes|nullable|string',
|
||||||
'frequency_id' => ['required_with:recurring_product_ids'],
|
'recurring_product_ids' => 'bail|sometimes|nullable|string',
|
||||||
'auto_bill' => ['sometimes'],
|
'is_recurring' => 'bail|sometimes|bool',
|
||||||
'promo_code' => ['sometimes'],
|
'frequency_id' => 'bail|required_with:recurring_product_ids',
|
||||||
'promo_discount' => ['sometimes'],
|
'auto_bill' => 'bail|sometimes|nullable|string',
|
||||||
'is_amount_discount' => ['sometimes'],
|
'promo_code' => 'bail|sometimes|nullable|string',
|
||||||
'allow_cancellation' => ['sometimes'],
|
'promo_discount' => 'bail|sometimes|numeric',
|
||||||
'per_set_enabled' => ['sometimes'],
|
'is_amount_discount' => 'bail|sometimes|bool',
|
||||||
'min_seats_limit' => ['sometimes'],
|
'allow_cancellation' => 'bail|sometimes|bool',
|
||||||
'max_seats_limit' => ['sometimes'],
|
'per_set_enabled' => 'bail|sometimes|bool',
|
||||||
'trial_enabled' => ['sometimes'],
|
'min_seats_limit' => 'bail|sometimes|numeric',
|
||||||
'trial_duration' => ['sometimes'],
|
'max_seats_limit' => 'bail|sometimes|numeric',
|
||||||
'allow_query_overrides' => ['sometimes'],
|
'trial_enabled' => 'bail|sometimes|bool',
|
||||||
'allow_plan_changes' => ['sometimes'],
|
'trial_duration' => 'bail|sometimes|numeric',
|
||||||
'refund_period' => ['sometimes'],
|
'allow_query_overrides' => 'bail|sometimes|bool',
|
||||||
'webhook_configuration' => ['array'],
|
'allow_plan_changes' => 'bail|sometimes|bool',
|
||||||
'name' => ['sometimes', Rule::unique('subscriptions')->where('company_id', auth()->user()->company()->id)->ignore($this->subscription->id)],
|
'refund_period' => 'bail|sometimes|numeric',
|
||||||
|
'webhook_configuration' => 'bail|array',
|
||||||
|
'webhook_configuration.post_purchase_url' => 'bail|sometimes|nullable|string',
|
||||||
|
'webhook_configuration.post_purchase_rest_method' => 'bail|sometimes|nullable|string',
|
||||||
|
'webhook_configuration.post_purchase_headers' => 'bail|sometimes|array',
|
||||||
|
'registration_required' => 'bail|sometimes|bool',
|
||||||
|
'optional_recurring_product_ids' => 'bail|sometimes|nullable|string',
|
||||||
|
'optional_product_ids' => 'bail|sometimes|nullable|string',
|
||||||
|
'use_inventory_management' => 'bail|sometimes|bool',
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -15,6 +15,7 @@ use App\Http\Requests\Request;
|
|||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Utils\Traits\ChecksEntityStatus;
|
use App\Utils\Traits\ChecksEntityStatus;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
class UpdateTaskRequest extends Request
|
class UpdateTaskRequest extends Request
|
||||||
@ -29,6 +30,10 @@ class UpdateTaskRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
|
//prevent locked tasks from updating
|
||||||
|
if($this->task->invoice_id && $this->task->company->invoice_task_lock)
|
||||||
|
return false;
|
||||||
|
|
||||||
return auth()->user()->can('edit', $this->task);
|
return auth()->user()->can('edit', $this->task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,4 +92,11 @@ class UpdateTaskRequest extends Request
|
|||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function failedAuthorization()
|
||||||
|
{
|
||||||
|
throw new AuthorizationException(ctrans('texts.task_update_authorization_error'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class GenerateSmsRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
return auth()->user()->isAdmin();
|
return auth()->user();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ class ValidCompanyQuantity implements Rule
|
|||||||
*/
|
*/
|
||||||
public function passes($attribute, $value)
|
public function passes($attribute, $value)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Ninja::isSelfHost()) {
|
if (Ninja::isSelfHost()) {
|
||||||
return auth()->user()->company()->account->companies->count() < 10;
|
return auth()->user()->company()->account->companies->count() < 10;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ use App\Repositories\PaymentRepository;
|
|||||||
use App\Repositories\ProductRepository;
|
use App\Repositories\ProductRepository;
|
||||||
use App\Repositories\QuoteRepository;
|
use App\Repositories\QuoteRepository;
|
||||||
use App\Repositories\VendorRepository;
|
use App\Repositories\VendorRepository;
|
||||||
|
use App\Services\Bank\BankMatchingService;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
@ -107,6 +108,8 @@ class Csv extends BaseImport implements ImportInterface
|
|||||||
$bank_transaction_count = $this->ingest($data, $entity_type);
|
$bank_transaction_count = $this->ingest($data, $entity_type);
|
||||||
$this->entity_count['bank_transactions'] = $bank_transaction_count;
|
$this->entity_count['bank_transactions'] = $bank_transaction_count;
|
||||||
|
|
||||||
|
BankMatchingService::dispatchSync($this->company->id, $this->company->db);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function client()
|
public function client()
|
||||||
|
@ -196,13 +196,19 @@ class MatchBankTransactions implements ShouldQueue
|
|||||||
$expense->payment_date = Carbon::parse($this->bt->date);
|
$expense->payment_date = Carbon::parse($this->bt->date);
|
||||||
$expense->transaction_reference = $this->bt->description;
|
$expense->transaction_reference = $this->bt->description;
|
||||||
$expense->transaction_id = $this->bt->id;
|
$expense->transaction_id = $this->bt->id;
|
||||||
$expense->vendor_id = array_key_exists('vendor_id', $input) ? $input['vendor_id'] : null;
|
|
||||||
|
if(array_key_exists('vendor_id', $input))
|
||||||
|
$expense->vendor_id = $input['vendor_id'];
|
||||||
|
|
||||||
$expense->invoice_documents = $this->company->invoice_expense_documents;
|
$expense->invoice_documents = $this->company->invoice_expense_documents;
|
||||||
$expense->should_be_invoiced = $this->company->mark_expenses_invoiceable;
|
$expense->should_be_invoiced = $this->company->mark_expenses_invoiceable;
|
||||||
$expense->save();
|
$expense->save();
|
||||||
|
|
||||||
$this->bt->expense_id = $expense->id;
|
$this->bt->expense_id = $expense->id;
|
||||||
$this->bt->vendor_id = array_key_exists('vendor_id', $input) ? $input['vendor_id'] : null;
|
|
||||||
|
if(array_key_exists('vendor_id', $input))
|
||||||
|
$this->bt->vendor_id = $input['vendor_id'];
|
||||||
|
|
||||||
$this->bt->status_id = BankTransaction::STATUS_CONVERTED;
|
$this->bt->status_id = BankTransaction::STATUS_CONVERTED;
|
||||||
$this->bt->save();
|
$this->bt->save();
|
||||||
|
|
||||||
@ -254,6 +260,9 @@ class MatchBankTransactions implements ShouldQueue
|
|||||||
|
|
||||||
}, 1);
|
}, 1);
|
||||||
|
|
||||||
|
if(!$this->invoice)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Create Payment */
|
/* Create Payment */
|
||||||
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ class CompanyExport implements ShouldQueue
|
|||||||
$this->export_data['payments'] = $this->company->payments()->orderBy('number', 'DESC')->cursor()->map(function ($payment){
|
$this->export_data['payments'] = $this->company->payments()->orderBy('number', 'DESC')->cursor()->map(function ($payment){
|
||||||
|
|
||||||
$payment = $this->transformBasicEntities($payment);
|
$payment = $this->transformBasicEntities($payment);
|
||||||
$payment = $this->transformArrayOfKeys($payment, ['client_id','project_id', 'vendor_id', 'client_contact_id', 'invitation_id', 'company_gateway_id']);
|
$payment = $this->transformArrayOfKeys($payment, ['client_id','project_id', 'vendor_id', 'client_contact_id', 'invitation_id', 'company_gateway_id', 'transaction_id']);
|
||||||
|
|
||||||
$payment->paymentables = $this->transformPaymentable($payment);
|
$payment->paymentables = $this->transformPaymentable($payment);
|
||||||
|
|
||||||
@ -456,7 +456,6 @@ class CompanyExport implements ShouldQueue
|
|||||||
|
|
||||||
})->all();
|
})->all();
|
||||||
|
|
||||||
|
|
||||||
$this->export_data['purchase_order_invitations'] = PurchaseOrderInvitation::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($purchase_order){
|
$this->export_data['purchase_order_invitations'] = PurchaseOrderInvitation::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($purchase_order){
|
||||||
|
|
||||||
$purchase_order = $this->transformArrayOfKeys($purchase_order, ['company_id', 'user_id', 'vendor_contact_id', 'purchase_order_id']);
|
$purchase_order = $this->transformArrayOfKeys($purchase_order, ['company_id', 'user_id', 'vendor_contact_id', 'purchase_order_id']);
|
||||||
@ -466,6 +465,21 @@ class CompanyExport implements ShouldQueue
|
|||||||
})->all();
|
})->all();
|
||||||
|
|
||||||
|
|
||||||
|
$this->export_data['bank_integrations'] = $this->company->bank_integrations()->orderBy('id', 'ASC')->cursor()->map(function ($bank_integration){
|
||||||
|
|
||||||
|
$bank_integration = $this->transformArrayOfKeys($bank_integration, ['account_id','company_id', 'user_id']);
|
||||||
|
|
||||||
|
return $bank_integration->makeVisible(['id','user_id','company_id','account_id']);
|
||||||
|
|
||||||
|
})->all();
|
||||||
|
|
||||||
|
$this->export_data['bank_transactions'] = $this->company->bank_transactions()->orderBy('id', 'ASC')->cursor()->map(function ($bank_transaction){
|
||||||
|
|
||||||
|
$bank_transaction = $this->transformArrayOfKeys($bank_transaction, ['company_id', 'user_id','bank_integration_id','expense_id','category_id','ninja_category_id','vendor_id']);
|
||||||
|
|
||||||
|
return $bank_transaction->makeVisible(['id','user_id','company_id']);
|
||||||
|
|
||||||
|
})->all();
|
||||||
|
|
||||||
//write to tmp and email to owner();
|
//write to tmp and email to owner();
|
||||||
|
|
||||||
@ -517,9 +531,6 @@ class CompanyExport implements ShouldQueue
|
|||||||
|
|
||||||
$path = 'backups';
|
$path = 'backups';
|
||||||
|
|
||||||
// if(!Storage::disk(config('filesystems.default'))->exists($path))
|
|
||||||
// Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775);
|
|
||||||
|
|
||||||
$zip_path = public_path('storage/backups/'.$file_name);
|
$zip_path = public_path('storage/backups/'.$file_name);
|
||||||
$zip = new \ZipArchive();
|
$zip = new \ZipArchive();
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ use App\Mail\Import\CompanyImportFailure;
|
|||||||
use App\Mail\Import\ImportCompleted;
|
use App\Mail\Import\ImportCompleted;
|
||||||
use App\Models\Activity;
|
use App\Models\Activity;
|
||||||
use App\Models\Backup;
|
use App\Models\Backup;
|
||||||
|
use App\Models\BankIntegration;
|
||||||
|
use App\Models\BankTransaction;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\ClientGatewayToken;
|
use App\Models\ClientGatewayToken;
|
||||||
@ -142,15 +144,16 @@ class CompanyImport implements ShouldQueue
|
|||||||
'expenses',
|
'expenses',
|
||||||
'tasks',
|
'tasks',
|
||||||
'payments',
|
'payments',
|
||||||
// 'activities',
|
|
||||||
// 'backups',
|
|
||||||
'company_ledger',
|
'company_ledger',
|
||||||
'designs',
|
'designs',
|
||||||
'documents',
|
'documents',
|
||||||
'webhooks',
|
'webhooks',
|
||||||
'system_logs',
|
'system_logs',
|
||||||
'purchase_orders',
|
'purchase_orders',
|
||||||
'purchase_order_invitations'
|
'purchase_order_invitations',
|
||||||
|
'bank_integrations',
|
||||||
|
'bank_transactions',
|
||||||
|
'payments',
|
||||||
];
|
];
|
||||||
|
|
||||||
private $company_properties = [
|
private $company_properties = [
|
||||||
@ -527,6 +530,37 @@ class CompanyImport implements ShouldQueue
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function import_bank_integrations()
|
||||||
|
{
|
||||||
|
$this->genericImport(BankIntegration::class,
|
||||||
|
['assigned_user_id','account_id', 'company_id', 'id', 'hashed_id'],
|
||||||
|
[
|
||||||
|
['users' => 'user_id'],
|
||||||
|
],
|
||||||
|
'bank_integrations',
|
||||||
|
'description');
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function import_bank_transactions()
|
||||||
|
{
|
||||||
|
$this->genericImport(BankTransaction::class,
|
||||||
|
['assigned_user_id','company_id', 'id', 'hashed_id', 'user_id'],
|
||||||
|
[
|
||||||
|
['users' => 'user_id'],
|
||||||
|
['expenses' => 'expense_id'],
|
||||||
|
['vendors' => 'vendor_id'],
|
||||||
|
['expense_categories' => 'ninja_category_id'],
|
||||||
|
['expense_categories' => 'category_id'],
|
||||||
|
['bank_integrations' => 'bank_integration_id']
|
||||||
|
],
|
||||||
|
'bank_transactions',
|
||||||
|
null);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
private function import_recurring_expenses()
|
private function import_recurring_expenses()
|
||||||
{
|
{
|
||||||
//unset / transforms / object_property / match_key
|
//unset / transforms / object_property / match_key
|
||||||
@ -979,6 +1013,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
['vendors' => 'vendor_id'],
|
['vendors' => 'vendor_id'],
|
||||||
['invoice_invitations' => 'invitation_id'],
|
['invoice_invitations' => 'invitation_id'],
|
||||||
['company_gateways' => 'company_gateway_id'],
|
['company_gateways' => 'company_gateway_id'],
|
||||||
|
['bank_transactions' => 'transaction_id'],
|
||||||
],
|
],
|
||||||
'payments',
|
'payments',
|
||||||
'number');
|
'number');
|
||||||
@ -1569,6 +1604,28 @@ class CompanyImport implements ShouldQueue
|
|||||||
$obj_array,
|
$obj_array,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
elseif($class == 'App\Models\BankIntegration'){
|
||||||
|
$new_obj = new BankIntegration();
|
||||||
|
$new_obj->company_id = $this->company->id;
|
||||||
|
$new_obj->account_id = $this->account->id;
|
||||||
|
$new_obj->fill($obj_array);
|
||||||
|
$new_obj->save(['timestamps' => false]);
|
||||||
|
}
|
||||||
|
elseif($class == 'App\Models\BankTransaction'){
|
||||||
|
|
||||||
|
$new_obj = new BankTransaction();
|
||||||
|
$new_obj->company_id = $this->company->id;
|
||||||
|
|
||||||
|
$obj_array['invoice_ids'] = collect(explode(",",$obj_array['invoice_ids']))->map(function ($id) {
|
||||||
|
return $this->transformId('invoices', $id);
|
||||||
|
})->map(function ($encodeable){
|
||||||
|
return $this->encodePrimaryKey($encodeable);
|
||||||
|
})->implode(",");
|
||||||
|
|
||||||
|
|
||||||
|
$new_obj->fill($obj_array);
|
||||||
|
$new_obj->save(['timestamps' => false]);
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
$new_obj = $class::withTrashed()->firstOrNew(
|
$new_obj = $class::withTrashed()->firstOrNew(
|
||||||
[$match_key => $obj->{$match_key}, 'company_id' => $this->company->id],
|
[$match_key => $obj->{$match_key}, 'company_id' => $this->company->id],
|
||||||
|
@ -129,11 +129,8 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
LightLogs::create(new EmailSuccess($this->nmo->company->company_key))
|
LightLogs::create(new EmailSuccess($this->nmo->company->company_key))
|
||||||
->send();
|
->send();
|
||||||
|
|
||||||
// nlog('Using ' . ((int) (memory_get_usage(true) / (1024 * 1024))) . 'MB ');
|
|
||||||
|
|
||||||
$this->nmo = null;
|
$this->nmo = null;
|
||||||
$this->company = null;
|
$this->company = null;
|
||||||
app('queue.worker')->shouldQuit = 1;
|
|
||||||
|
|
||||||
} catch (\Exception | \RuntimeException | \Google\Service\Exception $e) {
|
} catch (\Exception | \RuntimeException | \Google\Service\Exception $e) {
|
||||||
|
|
||||||
|
@ -50,11 +50,20 @@ class ReminderJob implements ShouldQueue
|
|||||||
$this->processReminders();
|
$this->processReminders();
|
||||||
} else {
|
} else {
|
||||||
//multiDB environment, need to
|
//multiDB environment, need to
|
||||||
|
/*
|
||||||
foreach (MultiDB::$dbs as $db) {
|
foreach (MultiDB::$dbs as $db) {
|
||||||
MultiDB::setDB($db);
|
MultiDB::setDB($db);
|
||||||
nlog("set db {$db}");
|
nlog("set db {$db}");
|
||||||
$this->processReminders();
|
$this->processReminders();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
//24-11-2022 fix for potential memory leak during a long running process, the second reminder may run twice
|
||||||
|
foreach (config('ninja.dbs') as $db) {
|
||||||
|
MultiDB::setDB($db);
|
||||||
|
nlog("set db {$db}");
|
||||||
|
$this->processReminders();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +71,8 @@ class ReminderJob implements ShouldQueue
|
|||||||
{
|
{
|
||||||
nlog('Sending invoice reminders '.now()->format('Y-m-d h:i:s'));
|
nlog('Sending invoice reminders '.now()->format('Y-m-d h:i:s'));
|
||||||
|
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
Invoice::query()
|
Invoice::query()
|
||||||
->where('is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
@ -77,16 +88,21 @@ class ReminderJob implements ShouldQueue
|
|||||||
})
|
})
|
||||||
->with('invitations')->cursor()->each(function ($invoice) {
|
->with('invitations')->cursor()->each(function ($invoice) {
|
||||||
if ($invoice->isPayable()) {
|
if ($invoice->isPayable()) {
|
||||||
|
|
||||||
|
//Attempts to prevent duplicates from sending
|
||||||
|
if($invoice->reminder_last_sent && Carbon::parse($invoice->reminder_last_sent)->startOfDay()->eq(now()->startOfDay())){
|
||||||
|
nlog("caught a duplicate reminder for invoice {$invoice->number}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$reminder_template = $invoice->calculateTemplate('invoice');
|
$reminder_template = $invoice->calculateTemplate('invoice');
|
||||||
nlog("reminder template = {$reminder_template}");
|
nlog("reminder template = {$reminder_template}");
|
||||||
$invoice->service()->touchReminder($reminder_template)->save();
|
|
||||||
$invoice = $this->calcLateFee($invoice, $reminder_template);
|
$invoice = $this->calcLateFee($invoice, $reminder_template);
|
||||||
|
$invoice->service()->touchReminder($reminder_template)->save();
|
||||||
$invoice->service()->touchPdf();
|
$invoice->service()->touchPdf(true);
|
||||||
|
|
||||||
//20-04-2022 fixes for endless reminders - generic template naming was wrong
|
//20-04-2022 fixes for endless reminders - generic template naming was wrong
|
||||||
$enabled_reminder = 'enable_'.$reminder_template;
|
$enabled_reminder = 'enable_'.$reminder_template;
|
||||||
|
|
||||||
if ($reminder_template == 'endless_reminder') {
|
if ($reminder_template == 'endless_reminder') {
|
||||||
$enabled_reminder = 'enable_reminder_endless';
|
$enabled_reminder = 'enable_reminder_endless';
|
||||||
}
|
}
|
||||||
@ -99,7 +115,7 @@ class ReminderJob implements ShouldQueue
|
|||||||
(Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) {
|
(Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) {
|
||||||
|
|
||||||
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
|
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
|
||||||
EmailEntity::dispatchSync($invitation, $invitation->company, $reminder_template);
|
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
|
||||||
nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
|
nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,6 +128,7 @@ class ReminderJob implements ShouldQueue
|
|||||||
$invoice->next_send_date = null;
|
$invoice->next_send_date = null;
|
||||||
$invoice->save();
|
$invoice->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,22 +213,17 @@ class ReminderJob implements ShouldQueue
|
|||||||
$invoice->line_items = $invoice_items;
|
$invoice->line_items = $invoice_items;
|
||||||
|
|
||||||
/**Refresh Invoice values*/
|
/**Refresh Invoice values*/
|
||||||
$invoice->calc()->getInvoice()->save();
|
$invoice = $invoice->calc()->getInvoice();
|
||||||
$invoice->fresh();
|
// $invoice->service()->deletePdf(); 24-11-2022 no need to delete here because we regenerate later anyway
|
||||||
$invoice->service()->deletePdf();
|
|
||||||
|
|
||||||
/* Refresh the client here to ensure the balance is fresh */
|
|
||||||
$client = $invoice->client;
|
|
||||||
$client = $client->fresh();
|
|
||||||
|
|
||||||
nlog('adjusting client balance and invoice balance by #'.$invoice->number.' '.($invoice->balance - $temp_invoice_balance));
|
nlog('adjusting client balance and invoice balance by #'.$invoice->number.' '.($invoice->balance - $temp_invoice_balance));
|
||||||
$client->service()->updateBalance($invoice->balance - $temp_invoice_balance)->save();
|
$invoice->client->service()->updateBalance($invoice->balance - $temp_invoice_balance);
|
||||||
$invoice->ledger()->updateInvoiceBalance($invoice->balance - $temp_invoice_balance, "Late Fee Adjustment for invoice {$invoice->number}");
|
$invoice->ledger()->updateInvoiceBalance($invoice->balance - $temp_invoice_balance, "Late Fee Adjustment for invoice {$invoice->number}");
|
||||||
|
|
||||||
$transaction = [
|
$transaction = [
|
||||||
'invoice' => $invoice->transaction_event(),
|
'invoice' => $invoice->transaction_event(),
|
||||||
'payment' => [],
|
'payment' => [],
|
||||||
'client' => $client->transaction_event(),
|
'client' => $invoice->client->transaction_event(),
|
||||||
'credit' => [],
|
'credit' => [],
|
||||||
'metadata' => ['setLateFee'],
|
'metadata' => ['setLateFee'],
|
||||||
];
|
];
|
||||||
|
@ -19,6 +19,9 @@ use stdClass;
|
|||||||
|
|
||||||
class InvoiceEmailFailedActivity implements ShouldQueue
|
class InvoiceEmailFailedActivity implements ShouldQueue
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// public $delay = 10;
|
||||||
|
|
||||||
protected $activity_repo;
|
protected $activity_repo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,13 +18,18 @@ use App\Libraries\MultiDB;
|
|||||||
use App\Mail\Admin\EntityFailedSendObject;
|
use App\Mail\Admin\EntityFailedSendObject;
|
||||||
use App\Notifications\Admin\EntitySentNotification;
|
use App\Notifications\Admin\EntitySentNotification;
|
||||||
use App\Utils\Traits\Notifications\UserNotifies;
|
use App\Utils\Traits\Notifications\UserNotifies;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
class InvoiceFailedEmailNotification
|
class InvoiceFailedEmailNotification
|
||||||
{
|
{
|
||||||
use UserNotifies;
|
|
||||||
|
|
||||||
public $delay = 5;
|
use UserNotifies, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $delay = 10;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -292,6 +292,14 @@ class Activity extends StaticModel
|
|||||||
return $this->belongsTo(Quote::class)->withTrashed();
|
return $this->belongsTo(Quote::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function subscription()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Subscription::class)->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
use App\Models\Filterable;
|
use App\Models\Filterable;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Services\Bank\BankService;
|
use App\Services\Bank\BankService;
|
||||||
|
171
app/Models/BankTransactionRule.php
Normal file
171
app/Models/BankTransactionRule.php
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Filterable;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class BankTransactionRule extends BaseModel
|
||||||
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
use MakesHash;
|
||||||
|
use Filterable;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'rules',
|
||||||
|
'auto_convert',
|
||||||
|
'matches_on_all',
|
||||||
|
'applies_to',
|
||||||
|
'client_id',
|
||||||
|
'vendor_id',
|
||||||
|
'category_id',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'rules' => 'array',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'deleted_at' => 'timestamp',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $dates = [
|
||||||
|
];
|
||||||
|
|
||||||
|
protected array $search_keys = [
|
||||||
|
'description' => 'string',
|
||||||
|
'amount' => 'number',
|
||||||
|
];
|
||||||
|
|
||||||
|
/* Amount */
|
||||||
|
protected array $number_operators = [
|
||||||
|
'=',
|
||||||
|
'>',
|
||||||
|
'>=',
|
||||||
|
'<',
|
||||||
|
'<='
|
||||||
|
];
|
||||||
|
|
||||||
|
/* Description, Client, Vendor, Reference Number */
|
||||||
|
protected array $string_operators = [
|
||||||
|
'is',
|
||||||
|
'contains',
|
||||||
|
'starts_with',
|
||||||
|
'is_empty',
|
||||||
|
];
|
||||||
|
|
||||||
|
private array $search_results = [];
|
||||||
|
|
||||||
|
// rule object looks like this:
|
||||||
|
//[
|
||||||
|
// {
|
||||||
|
// 'search_key': 'client_id',
|
||||||
|
// 'operator' : 'is',
|
||||||
|
// 'value' : 'Sparky'
|
||||||
|
// }
|
||||||
|
//]
|
||||||
|
|
||||||
|
// public function processRule(BankTransaction $bank_transaction)
|
||||||
|
// {
|
||||||
|
// foreach($this->rules as $key => $rule)
|
||||||
|
// {
|
||||||
|
// $this->search($rule, $key, $bank_transaction);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private function search($rule, $key, $bank_transaction)
|
||||||
|
// {
|
||||||
|
// if($rule->search_key == 'amount')
|
||||||
|
// {
|
||||||
|
// //number search
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// //string search
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private function findAmount($amount, $bank_transaction)
|
||||||
|
// {
|
||||||
|
// if($bank_transaction->base_type == 'CREDIT'){
|
||||||
|
// //search invoices
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// //search expenses
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private function searchClient($rule, $bank_transaction)
|
||||||
|
// {
|
||||||
|
// if($bank_transaction->base_type == 'CREDIT'){
|
||||||
|
// //search invoices
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// //search expenses
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private function searchVendor($rule, $bank_transaction)
|
||||||
|
// {
|
||||||
|
// //search expenses
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private function searchDescription($rule, $bank_transaction)
|
||||||
|
// {
|
||||||
|
// //search expenses public notes
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private function searchReference($rule, $bank_transaction)
|
||||||
|
// {
|
||||||
|
// if($bank_transaction->base_type == 'CREDIT'){
|
||||||
|
// //search invoices
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// //search expenses
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function getEntityType()
|
||||||
|
{
|
||||||
|
return self::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function company()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Company::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function vendor()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Vendor::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function client()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Client::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expense_cateogry()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ExpenseCategory::class)->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,6 +13,7 @@ namespace App\Models;
|
|||||||
|
|
||||||
use App\DataMapper\CompanySettings;
|
use App\DataMapper\CompanySettings;
|
||||||
use App\Models\BankTransaction;
|
use App\Models\BankTransaction;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
use App\Models\Language;
|
use App\Models\Language;
|
||||||
use App\Models\Presenters\CompanyPresenter;
|
use App\Models\Presenters\CompanyPresenter;
|
||||||
use App\Models\PurchaseOrder;
|
use App\Models\PurchaseOrder;
|
||||||
@ -123,6 +124,8 @@ class Company extends BaseModel
|
|||||||
'enabled_expense_tax_rates',
|
'enabled_expense_tax_rates',
|
||||||
'invoice_task_project',
|
'invoice_task_project',
|
||||||
'report_include_deleted',
|
'report_include_deleted',
|
||||||
|
'invoice_task_lock',
|
||||||
|
'use_vendor_currency',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
@ -188,6 +191,11 @@ class Company extends BaseModel
|
|||||||
return $this->hasMany(BankTransaction::class);
|
return $this->hasMany(BankTransaction::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function bank_transaction_rules()
|
||||||
|
{
|
||||||
|
return $this->hasMany(BankTransactionRule::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function getCompanyIdAttribute()
|
public function getCompanyIdAttribute()
|
||||||
{
|
{
|
||||||
return $this->encodePrimaryKey($this->id);
|
return $this->encodePrimaryKey($this->id);
|
||||||
@ -541,6 +549,23 @@ class Company extends BaseModel
|
|||||||
return $this->company_users()->withTrashed()->where('is_owner', true)->first()?->user;
|
return $this->company_users()->withTrashed()->where('is_owner', true)->first()?->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function credit_rules()
|
||||||
|
{
|
||||||
|
return BankTransactionRule::query()
|
||||||
|
->where('company_id', $this->id)
|
||||||
|
->where('applies_to', 'CREDIT')
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function debit_rules()
|
||||||
|
{
|
||||||
|
return BankTransactionRule::query()
|
||||||
|
->where('company_id', $this->id)
|
||||||
|
->where('applies_to', 'DEBIT')
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function resolveRouteBinding($value, $field = null)
|
public function resolveRouteBinding($value, $field = null)
|
||||||
{
|
{
|
||||||
return $this->where('id', $this->decodePrimaryKey($value))->firstOrFail();
|
return $this->where('id', $this->decodePrimaryKey($value))->firstOrFail();
|
||||||
|
@ -79,7 +79,8 @@ class PurchaseOrder extends BaseModel
|
|||||||
'partial',
|
'partial',
|
||||||
'paid_to_date',
|
'paid_to_date',
|
||||||
'vendor_id',
|
'vendor_id',
|
||||||
'last_viewed'
|
'last_viewed',
|
||||||
|
'currency_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
@ -54,6 +54,10 @@ class Subscription extends BaseModel
|
|||||||
'price',
|
'price',
|
||||||
'name',
|
'name',
|
||||||
'currency_id',
|
'currency_id',
|
||||||
|
'registration_required',
|
||||||
|
'optional_product_ids',
|
||||||
|
'optional_recurring_product_ids',
|
||||||
|
'use_inventory_management',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
@ -64,6 +64,7 @@ class VendorContact extends Authenticatable implements HasLocalePreference
|
|||||||
'email',
|
'email',
|
||||||
'is_primary',
|
'is_primary',
|
||||||
'vendor_id',
|
'vendor_id',
|
||||||
|
'send_email',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function avatar()
|
public function avatar()
|
||||||
|
@ -111,7 +111,10 @@ class PayPal
|
|||||||
'paymentMethodNonce' => $gateway_response->nonce,
|
'paymentMethodNonce' => $gateway_response->nonce,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if($payment_method->success)
|
||||||
return $payment_method->paymentMethod->token;
|
return $payment_method->paymentMethod->token;
|
||||||
|
else
|
||||||
|
throw new PaymentFailed(property_exists($payment_method, 'message') ? $payment_method->message : 'Undefined error storing payment token.', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,10 +306,53 @@ class CheckoutComPaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $this->gateway->getCustomersClient()->create($request);
|
$response = $this->gateway->getCustomersClient()->create($request);
|
||||||
} catch (\Exception $e) {
|
|
||||||
// API error
|
|
||||||
throw new PaymentFailed($e->getMessage(), $e->getCode());
|
|
||||||
}
|
}
|
||||||
|
catch (CheckoutApiException $e) {
|
||||||
|
// API error
|
||||||
|
$request_id = $e->request_id;
|
||||||
|
$http_status_code = $e->http_status_code;
|
||||||
|
$error_details = $e->error_details;
|
||||||
|
|
||||||
|
if(is_array($error_details)) {
|
||||||
|
$error_details = end($e->error_details['error_codes']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$human_exception = $error_details ? new \Exception($error_details, 400) : $e;
|
||||||
|
|
||||||
|
|
||||||
|
throw new PaymentFailed($human_exception);
|
||||||
|
} catch (CheckoutArgumentException $e) {
|
||||||
|
// Bad arguments
|
||||||
|
|
||||||
|
$error_details = $e->error_details;
|
||||||
|
|
||||||
|
if(is_array($error_details)) {
|
||||||
|
$error_details = end($e->error_details['error_codes']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$human_exception = $error_details ? new \Exception($error_details, 400) : $e;
|
||||||
|
|
||||||
|
throw new PaymentFailed($human_exception);
|
||||||
|
} catch (CheckoutAuthorizationException $e) {
|
||||||
|
// Bad Invalid authorization
|
||||||
|
|
||||||
|
$error_details = $e->error_details;
|
||||||
|
|
||||||
|
if(is_array($error_details)) {
|
||||||
|
$error_details = end($e->error_details['error_codes']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$human_exception = $error_details ? new \Exception($error_details, 400) : $e;
|
||||||
|
|
||||||
|
throw new PaymentFailed($human_exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// catch (\Exception $e) {
|
||||||
|
// // API error
|
||||||
|
// throw new PaymentFailed($e->getMessage(), $e->getCode());
|
||||||
|
// }
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ class CreditCard
|
|||||||
'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method,
|
'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method,
|
||||||
'payment_type' => PaymentType::parseCardType(strtolower($stripe_method->card->brand)) ?: PaymentType::CREDIT_CARD_OTHER,
|
'payment_type' => PaymentType::parseCardType(strtolower($stripe_method->card->brand)) ?: PaymentType::CREDIT_CARD_OTHER,
|
||||||
'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->server_response->amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->server_response->amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
||||||
'transaction_reference' => optional($this->stripe->payment_hash->data->payment_intent->charges->data[0])->id,
|
'transaction_reference' => isset($this->stripe->payment_hash->data->payment_intent->latest_charge) ? $this->stripe->payment_hash->data->payment_intent->latest_charge : optional($this->stripe->payment_hash->data->payment_intent->charges->data[0])->id,
|
||||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -63,7 +63,11 @@ class ImportCustomers
|
|||||||
$this->addCustomer($customer);
|
$this->addCustomer($customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//handle
|
||||||
|
if(is_array($customers->data) && end($customers->data) && array_key_exists('id', end($customers->data)))
|
||||||
$starting_after = end($customers->data)['id'];
|
$starting_after = end($customers->data)['id'];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
} while ($customers->has_more);
|
} while ($customers->has_more);
|
||||||
}
|
}
|
||||||
|
@ -92,14 +92,38 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
if($this->payment_completed)
|
if($this->payment_completed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||||
|
$stripe_driver = $company_gateway->driver()->init();
|
||||||
|
|
||||||
if(optional($this->stripe_request['object']['charges']['data'][0])['id']){
|
$charge_id = false;
|
||||||
|
|
||||||
|
if(isset($this->stripe_request['object']['charges']) && optional($this->stripe_request['object']['charges']['data'][0])['id'])
|
||||||
|
$charge_id = $this->stripe_request['object']['charges']['data'][0]['id']; // API VERSION 2018
|
||||||
|
elseif (isset($this->stripe_request['object']['latest_charge']))
|
||||||
|
$charge_id = $this->stripe_request['object']['latest_charge']; // API VERSION 2022-11-15
|
||||||
|
|
||||||
|
|
||||||
|
if(!$charge_id){
|
||||||
|
nlog("could not resolve charge");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pi = \Stripe\PaymentIntent::retrieve($this->stripe_request['object']['id'], $stripe_driver->stripe_connect_auth);
|
||||||
|
|
||||||
|
$charge = \Stripe\Charge::retrieve($charge_id, $stripe_driver->stripe_connect_auth);
|
||||||
|
|
||||||
|
if(!$charge)
|
||||||
|
{
|
||||||
|
nlog("no charge found");
|
||||||
|
nlog($this->stripe_request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$company = Company::where('company_key', $this->company_key)->first();
|
$company = Company::where('company_key', $this->company_key)->first();
|
||||||
|
|
||||||
$payment = Payment::query()
|
$payment = Payment::query()
|
||||||
->where('company_id', $company->id)
|
->where('company_id', $company->id)
|
||||||
->where('transaction_reference', $this->stripe_request['object']['charges']['data'][0]['id'])
|
->where('transaction_reference', $charge['id'])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
//return early
|
//return early
|
||||||
@ -112,55 +136,47 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
$payment->save();
|
$payment->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash = isset($charge['metadata']['payment_hash']) ? $charge['metadata']['payment_hash'] : false;
|
||||||
$hash = optional($this->stripe_request['object']['charges']['data'][0]['metadata'])['payment_hash'];
|
|
||||||
|
|
||||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
||||||
|
|
||||||
if(!$payment_hash)
|
if(!$payment_hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nlog("payment intent");
|
$stripe_driver->client = $payment_hash->fee_invoice->client;
|
||||||
nlog($this->stripe_request);
|
|
||||||
|
|
||||||
if(array_key_exists('allowed_source_types', $this->stripe_request['object']) && optional($this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash']) && in_array('card', $this->stripe_request['object']['allowed_source_types']))
|
$meta = [
|
||||||
|
'gateway_type_id' => $pi['metadata']['gateway_type_id'],
|
||||||
|
'transaction_reference' => $charge['id'],
|
||||||
|
'customer' => $charge['customer'],
|
||||||
|
'payment_method' => $charge['payment_method'],
|
||||||
|
'card_details' => isset($charge['payment_method_details']['card']['brand']) ? $charge['payment_method_details']['card']['brand'] : PaymentType::CREDIT_CARD_OTHER
|
||||||
|
];
|
||||||
|
|
||||||
|
if(isset($pi['allowed_source_types']) && in_array('card', $pi['allowed_source_types']))
|
||||||
{
|
{
|
||||||
nlog("hash found");
|
|
||||||
|
|
||||||
$hash = $this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash'];
|
|
||||||
|
|
||||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
|
||||||
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
|
|
||||||
$this->updateCreditCardPayment($payment_hash, $client);
|
$this->updateCreditCardPayment($payment_hash, $client, $meta);
|
||||||
}
|
}
|
||||||
elseif(array_key_exists('payment_method_types', $this->stripe_request['object']) && optional($this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash']) && in_array('card', $this->stripe_request['object']['payment_method_types']))
|
elseif(isset($pi['payment_method_types']) && in_array('card', $pi['payment_method_types']))
|
||||||
{
|
{
|
||||||
nlog("hash found");
|
|
||||||
|
|
||||||
$hash = $this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash'];
|
|
||||||
|
|
||||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
|
||||||
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
|
|
||||||
$this->updateCreditCardPayment($payment_hash, $client);
|
$this->updateCreditCardPayment($payment_hash, $client, $meta);
|
||||||
}
|
}
|
||||||
elseif(array_key_exists('payment_method_types', $this->stripe_request['object']) && optional($this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash']) && in_array('us_bank_account', $this->stripe_request['object']['payment_method_types']))
|
elseif(isset($pi['payment_method_types']) && in_array('us_bank_account', $pi['payment_method_types']))
|
||||||
{
|
{
|
||||||
nlog("hash found");
|
|
||||||
|
|
||||||
$hash = $this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash'];
|
|
||||||
|
|
||||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
|
||||||
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
|
|
||||||
$this->updateAchPayment($payment_hash, $client);
|
$this->updateAchPayment($payment_hash, $client, $meta);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SystemLogger::dispatch(
|
SystemLogger::dispatch(
|
||||||
['response' => $this->stripe_request, 'data' => []],
|
['response' => $this->stripe_request, 'data' => []],
|
||||||
@ -174,10 +190,10 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateAchPayment($payment_hash, $client)
|
private function updateAchPayment($payment_hash, $client, $meta)
|
||||||
{
|
{
|
||||||
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||||
$payment_method_type = optional($this->stripe_request['object']['charges']['data'][0]['metadata'])['gateway_type_id'];
|
$payment_method_type = $meta['gateway_type_id'];
|
||||||
$driver = $company_gateway->driver($client)->init()->setPaymentMethod($payment_method_type);
|
$driver = $company_gateway->driver($client)->init()->setPaymentMethod($payment_method_type);
|
||||||
|
|
||||||
$payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
$payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
||||||
@ -188,7 +204,7 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
'payment_method' => $payment_hash->data->object->payment_method,
|
'payment_method' => $payment_hash->data->object->payment_method,
|
||||||
'payment_type' => PaymentType::ACH,
|
'payment_type' => PaymentType::ACH,
|
||||||
'amount' => $payment_hash->data->amount_with_fee,
|
'amount' => $payment_hash->data->amount_with_fee,
|
||||||
'transaction_reference' => $this->stripe_request['object']['charges']['data'][0]['id'],
|
'transaction_reference' => $meta['transaction_reference'],
|
||||||
'gateway_type_id' => GatewayType::BANK_TRANSFER,
|
'gateway_type_id' => GatewayType::BANK_TRANSFER,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -205,9 +221,9 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$customer = $driver->getCustomer($this->stripe_request['object']['charges']['data'][0]['customer']);
|
$customer = $driver->getCustomer($meta['customer']);
|
||||||
$method = $driver->getStripePaymentMethod($this->stripe_request['object']['charges']['data'][0]['payment_method']);
|
$method = $driver->getStripePaymentMethod($meta['payment_method']);
|
||||||
$payment_method = $this->stripe_request['object']['charges']['data'][0]['payment_method'];
|
$payment_method = $meta['payment_method'];
|
||||||
|
|
||||||
$token_exists = ClientGatewayToken::where([
|
$token_exists = ClientGatewayToken::where([
|
||||||
'gateway_customer_reference' => $customer->id,
|
'gateway_customer_reference' => $customer->id,
|
||||||
@ -249,10 +265,10 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function updateCreditCardPayment($payment_hash, $client)
|
private function updateCreditCardPayment($payment_hash, $client, $meta)
|
||||||
{
|
{
|
||||||
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||||
$payment_method_type = optional($this->stripe_request['object']['charges']['data'][0]['metadata'])['gateway_type_id'];
|
$payment_method_type = $meta['gateway_type_id'];
|
||||||
$driver = $company_gateway->driver($client)->init()->setPaymentMethod($payment_method_type);
|
$driver = $company_gateway->driver($client)->init()->setPaymentMethod($payment_method_type);
|
||||||
|
|
||||||
$payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
$payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
||||||
@ -261,9 +277,9 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'payment_method' => $payment_hash->data->object->payment_method,
|
'payment_method' => $payment_hash->data->object->payment_method,
|
||||||
'payment_type' => PaymentType::parseCardType(strtolower(optional($this->stripe_request['object']['charges']['data'][0]['payment_method_details']['card'])['brand'])) ?: PaymentType::CREDIT_CARD_OTHER,
|
'payment_type' => PaymentType::parseCardType(strtolower($meta['card_details'])) ?: PaymentType::CREDIT_CARD_OTHER,
|
||||||
'amount' => $payment_hash->data->amount_with_fee,
|
'amount' => $payment_hash->data->amount_with_fee,
|
||||||
'transaction_reference' => $this->stripe_request['object']['charges']['data'][0]['id'],
|
'transaction_reference' => $meta['transaction_reference'],
|
||||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -116,11 +116,14 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
throw new StripeConnectFailure('Stripe Connect has not been configured');
|
throw new StripeConnectFailure('Stripe Connect has not been configured');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$this->stripe = new StripeClient(
|
$this->stripe = new StripeClient(
|
||||||
$this->company_gateway->getConfigField('apiKey')
|
$this->company_gateway->getConfigField('apiKey')
|
||||||
);
|
);
|
||||||
|
|
||||||
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
|
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
|
||||||
|
// Stripe::setApiVersion('2022-11-15');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
31
app/Policies/BankTransactionRulePolicy.php
Normal file
31
app/Policies/BankTransactionRulePolicy.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BankTransactionPolicy.
|
||||||
|
*/
|
||||||
|
class BankTransactionRulePolicy extends EntityPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Checks if the user has create permissions.
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function create(User $user) : bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin();
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ use App\Models\Activity;
|
|||||||
use App\Models\Bank;
|
use App\Models\Bank;
|
||||||
use App\Models\BankIntegration;
|
use App\Models\BankIntegration;
|
||||||
use App\Models\BankTransaction;
|
use App\Models\BankTransaction;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\CompanyGateway;
|
use App\Models\CompanyGateway;
|
||||||
@ -45,6 +46,7 @@ use App\Models\Webhook;
|
|||||||
use App\Policies\ActivityPolicy;
|
use App\Policies\ActivityPolicy;
|
||||||
use App\Policies\BankIntegrationPolicy;
|
use App\Policies\BankIntegrationPolicy;
|
||||||
use App\Policies\BankTransactionPolicy;
|
use App\Policies\BankTransactionPolicy;
|
||||||
|
use App\Policies\BankTransactionRulePolicy;
|
||||||
use App\Policies\ClientPolicy;
|
use App\Policies\ClientPolicy;
|
||||||
use App\Policies\CompanyGatewayPolicy;
|
use App\Policies\CompanyGatewayPolicy;
|
||||||
use App\Policies\CompanyPolicy;
|
use App\Policies\CompanyPolicy;
|
||||||
@ -86,6 +88,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
Activity::class => ActivityPolicy::class,
|
Activity::class => ActivityPolicy::class,
|
||||||
BankIntegration::class => BankIntegrationPolicy::class,
|
BankIntegration::class => BankIntegrationPolicy::class,
|
||||||
BankTransaction::class => BankTransactionPolicy::class,
|
BankTransaction::class => BankTransactionPolicy::class,
|
||||||
|
BankTransactionRule::class => BankTransactionRulePolicy::class,
|
||||||
Client::class => ClientPolicy::class,
|
Client::class => ClientPolicy::class,
|
||||||
Company::class => CompanyPolicy::class,
|
Company::class => CompanyPolicy::class,
|
||||||
CompanyToken::class => CompanyTokenPolicy::class,
|
CompanyToken::class => CompanyTokenPolicy::class,
|
||||||
|
@ -451,7 +451,7 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
PaymentEmailedActivity::class,
|
PaymentEmailedActivity::class,
|
||||||
],
|
],
|
||||||
PaymentWasEmailedAndFailed::class => [
|
PaymentWasEmailedAndFailed::class => [
|
||||||
PaymentEmailFailureActivity::class,
|
// PaymentEmailFailureActivity::class,
|
||||||
],
|
],
|
||||||
PurchaseOrderWasArchived::class => [
|
PurchaseOrderWasArchived::class => [
|
||||||
PurchaseOrderArchivedActivity::class,
|
PurchaseOrderArchivedActivity::class,
|
||||||
|
@ -60,7 +60,7 @@ class ActivityRepository extends BaseRepository
|
|||||||
$activity->save();
|
$activity->save();
|
||||||
|
|
||||||
//rate limiter
|
//rate limiter
|
||||||
// $this->createBackup($entity, $activity);
|
$this->createBackup($entity, $activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Jobs\Bank\MatchBankTransactions;
|
||||||
use App\Models\BankTransaction;
|
use App\Models\BankTransaction;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\TaskStatus;
|
use App\Models\TaskStatus;
|
||||||
@ -28,17 +29,25 @@ class BankTransactionRepository extends BaseRepository
|
|||||||
$bank_transaction->bank_integration_id = $data['bank_integration_id'];
|
$bank_transaction->bank_integration_id = $data['bank_integration_id'];
|
||||||
|
|
||||||
$bank_transaction->fill($data);
|
$bank_transaction->fill($data);
|
||||||
|
|
||||||
$bank_transaction->save();
|
$bank_transaction->save();
|
||||||
|
|
||||||
if($bank_transaction->base_type == 'CREDIT' && $invoice = $bank_transaction->service()->matchInvoiceNumber())
|
$bank_transaction->service()->processRules();
|
||||||
|
|
||||||
|
return $bank_transaction->fresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convert_matched($bank_transactions)
|
||||||
{
|
{
|
||||||
$bank_transaction->invoice_ids = $invoice->hashed_id;
|
|
||||||
$bank_transaction->status_id = BankTransaction::STATUS_MATCHED;
|
|
||||||
$bank_transaction->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $bank_transaction;
|
$data['transactions'] = $bank_transactions->map(function ($bt){
|
||||||
}
|
return ['id' => $bt->id, 'invoice_ids' => $bt->invoice_ids];
|
||||||
|
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
|
$bts = (new MatchBankTransactions(auth()->user()->company()->id, auth()->user()->company()->db, $data))->handle();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
35
app/Repositories/BankTransactionRuleRepository.php
Normal file
35
app/Repositories/BankTransactionRuleRepository.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use App\Models\Task;
|
||||||
|
use App\Models\TaskStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for bank transaction rule repository.
|
||||||
|
*/
|
||||||
|
class BankTransactionRuleRepository extends BaseRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
public function save($data, BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
|
||||||
|
$bank_transaction_rule->fill($data);
|
||||||
|
|
||||||
|
$bank_transaction_rule->save();
|
||||||
|
|
||||||
|
return $bank_transaction_rule;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -11,35 +11,35 @@
|
|||||||
|
|
||||||
namespace App\Services\Bank;
|
namespace App\Services\Bank;
|
||||||
|
|
||||||
|
use App\Factory\ExpenseCategoryFactory;
|
||||||
|
use App\Factory\ExpenseFactory;
|
||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\BankTransaction;
|
use App\Models\BankTransaction;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Models\ExpenseCategory;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
use App\Services\Bank\BankService;
|
||||||
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class BankMatchingService implements ShouldQueue
|
class BankMatchingService implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, GeneratesCounter;
|
||||||
|
|
||||||
private $company_id;
|
|
||||||
|
|
||||||
private Company $company;
|
private Company $company;
|
||||||
|
|
||||||
private $db;
|
|
||||||
|
|
||||||
private $invoices;
|
private $invoices;
|
||||||
|
|
||||||
public $deleteWhenMissingModels = true;
|
public $deleteWhenMissingModels = true;
|
||||||
|
|
||||||
public function __construct($company_id, $db)
|
public function __construct(private int $company_id, private string $db){}
|
||||||
{
|
|
||||||
$this->company_id = $company_id;
|
|
||||||
$this->db = $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
@ -48,15 +48,12 @@ class BankMatchingService implements ShouldQueue
|
|||||||
|
|
||||||
$this->company = Company::find($this->company_id);
|
$this->company = Company::find($this->company_id);
|
||||||
|
|
||||||
$this->invoices = Invoice::where('company_id', $this->company->id)
|
$this->matchTransactions();
|
||||||
->whereIn('status_id', [1,2,3])
|
|
||||||
->where('is_deleted', 0)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$this->match();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function match()
|
private function matchTransactions()
|
||||||
{
|
{
|
||||||
|
|
||||||
BankTransaction::where('company_id', $this->company->id)
|
BankTransaction::where('company_id', $this->company->id)
|
||||||
@ -64,21 +61,14 @@ class BankMatchingService implements ShouldQueue
|
|||||||
->cursor()
|
->cursor()
|
||||||
->each(function ($bt){
|
->each(function ($bt){
|
||||||
|
|
||||||
$invoice = $this->invoices->first(function ($value, $key) use ($bt){
|
(new BankService($bt))->processRules();
|
||||||
|
|
||||||
return str_contains($bt->description, $value->number);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if($invoice)
|
}
|
||||||
|
|
||||||
|
public function middleware()
|
||||||
{
|
{
|
||||||
$bt->invoice_ids = $invoice->hashed_id;
|
return [new WithoutOverlapping($this->company_id)];
|
||||||
$bt->status_id = BankTransaction::STATUS_MATCHED;
|
|
||||||
$bt->save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace App\Services\Bank;
|
|||||||
|
|
||||||
use App\Models\BankTransaction;
|
use App\Models\BankTransaction;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Services\Bank\ProcessBankRule;
|
use App\Services\Bank\ProcessBankRules;
|
||||||
|
|
||||||
class BankService
|
class BankService
|
||||||
{
|
{
|
||||||
@ -40,11 +40,9 @@ class BankService
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRule($rule)
|
public function processRules()
|
||||||
{
|
{
|
||||||
(new ProcessBankRule($this->bank_transaction, $rule))->run();
|
(new ProcessBankRules($this->bank_transaction))->run();
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Services\Bank;
|
|
||||||
|
|
||||||
use App\Models\BankTransaction;
|
|
||||||
use App\Services\AbstractService;
|
|
||||||
|
|
||||||
class ProcessBankRule extends AbstractService
|
|
||||||
{
|
|
||||||
|
|
||||||
public function __construct(private BankTransaction $bank_transaction, $rule){}
|
|
||||||
|
|
||||||
public function run() : void
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
206
app/Services/Bank/ProcessBankRules.php
Normal file
206
app/Services/Bank/ProcessBankRules.php
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Services\Bank;
|
||||||
|
|
||||||
|
use App\Factory\ExpenseCategoryFactory;
|
||||||
|
use App\Factory\ExpenseFactory;
|
||||||
|
use App\Models\BankTransaction;
|
||||||
|
use App\Models\ExpenseCategory;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Services\AbstractService;
|
||||||
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
|
class ProcessBankRules extends AbstractService
|
||||||
|
{
|
||||||
|
use GeneratesCounter;
|
||||||
|
|
||||||
|
protected $credit_rules;
|
||||||
|
|
||||||
|
protected $debit_rules;
|
||||||
|
|
||||||
|
protected $categories;
|
||||||
|
|
||||||
|
public function __construct(public BankTransaction $bank_transaction){}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
if($this->bank_transaction->base_type == 'DEBIT')
|
||||||
|
$this->matchDebit();
|
||||||
|
else
|
||||||
|
$this->matchCredit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function matchCredit()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->credit_rules = $this->bank_transaction->company->credit_rules();
|
||||||
|
|
||||||
|
$this->invoices = Invoice::where('company_id', $this->bank_transaction->company_id)
|
||||||
|
->whereIn('status_id', [1,2,3])
|
||||||
|
->where('is_deleted', 0)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$invoice = $this->invoices->first(function ($value, $key){
|
||||||
|
|
||||||
|
return str_contains($this->bank_transaction->description, $value->number);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if($invoice)
|
||||||
|
{
|
||||||
|
$this->bank_transaction->invoice_ids = $invoice->hashed_id;
|
||||||
|
$this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED;
|
||||||
|
$this->bank_transaction->save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//stub for credit rules
|
||||||
|
foreach($this->credit_rules as $rule)
|
||||||
|
{
|
||||||
|
// $this->bank_transaction->bank_transaction_rule_id = $bank_transaction_rule->id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function matchDebit()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->debit_rules = $this->bank_transaction->company->debit_rules();
|
||||||
|
|
||||||
|
$this->categories = collect(Cache::get('bank_categories'));
|
||||||
|
|
||||||
|
foreach($this->debit_rules as $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
|
||||||
|
$matches = 0;
|
||||||
|
|
||||||
|
foreach($bank_transaction_rule['rules'] as $rule)
|
||||||
|
{
|
||||||
|
$rule_count = count($bank_transaction_rule['rules']);
|
||||||
|
|
||||||
|
if($rule['search_key'] == 'description')
|
||||||
|
{
|
||||||
|
|
||||||
|
if($this->matchStringOperator($this->bank_transaction->description, $rule['value'], $rule['operator'])){
|
||||||
|
$matches++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($rule['search_key'] == 'amount')
|
||||||
|
{
|
||||||
|
|
||||||
|
if($this->matchNumberOperator($this->bank_transaction->amount, $rule['value'] , $rule['operator'])){
|
||||||
|
$matches++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($bank_transaction_rule['matches_on_all'] && ($matches == $rule_count)) || (!$bank_transaction_rule['matches_on_all'] && $matches > 0))
|
||||||
|
{
|
||||||
|
|
||||||
|
// $this->bank_transaction->client_id = empty($rule['client_id']) ? null : $rule['client_id'];
|
||||||
|
$this->bank_transaction->vendor_id = $bank_transaction_rule->vendor_id;
|
||||||
|
$this->bank_transaction->ninja_category_id = $bank_transaction_rule->category_id;
|
||||||
|
$this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED;
|
||||||
|
$this->bank_transaction->bank_transaction_rule_id = $bank_transaction_rule->id;
|
||||||
|
$this->bank_transaction->save();
|
||||||
|
|
||||||
|
if($bank_transaction_rule['auto_convert'])
|
||||||
|
{
|
||||||
|
|
||||||
|
$expense = ExpenseFactory::create($this->bank_transaction->company_id, $this->bank_transaction->user_id);
|
||||||
|
$expense->category_id = $bank_transaction_rule->category_id ?: $this->resolveCategory();
|
||||||
|
$expense->amount = $this->bank_transaction->amount;
|
||||||
|
$expense->number = $this->getNextExpenseNumber($expense);
|
||||||
|
$expense->currency_id = $this->bank_transaction->currency_id;
|
||||||
|
$expense->date = Carbon::parse($this->bank_transaction->date);
|
||||||
|
$expense->payment_date = Carbon::parse($this->bank_transaction->date);
|
||||||
|
$expense->transaction_reference = $this->bank_transaction->description;
|
||||||
|
$expense->transaction_id = $this->bank_transaction->id;
|
||||||
|
$expense->vendor_id = $bank_transaction_rule->vendor_id;
|
||||||
|
$expense->invoice_documents = $this->bank_transaction->company->invoice_expense_documents;
|
||||||
|
$expense->should_be_invoiced = $this->bank_transaction->company->mark_expenses_invoiceable;
|
||||||
|
$expense->save();
|
||||||
|
|
||||||
|
$this->bank_transaction->expense_id = $expense->id;
|
||||||
|
$this->bank_transaction->status_id = BankTransaction::STATUS_CONVERTED;
|
||||||
|
$this->bank_transaction->save();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveCategory()
|
||||||
|
{
|
||||||
|
$category = $this->categories->firstWhere('highLevelCategoryId', $this->bank_transaction->category_id);
|
||||||
|
|
||||||
|
$ec = ExpenseCategory::where('company_id', $this->bank_transaction->company_id)->where('bank_category_id', $this->bank_transaction->category_id)->first();
|
||||||
|
|
||||||
|
if($ec)
|
||||||
|
return $ec->id;
|
||||||
|
|
||||||
|
if($category)
|
||||||
|
{
|
||||||
|
$ec = ExpenseCategoryFactory::create($this->bank_transaction->company_id, $this->bank_transaction->user_id);
|
||||||
|
$ec->bank_category_id = $this->bank_transaction->category_id;
|
||||||
|
$ec->name = $category->highLevelCategoryName;
|
||||||
|
$ec->save();
|
||||||
|
|
||||||
|
return $ec->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function matchNumberOperator($bt_value, $rule_value, $operator) :bool
|
||||||
|
{
|
||||||
|
|
||||||
|
return match ($operator) {
|
||||||
|
'>' => floatval($bt_value) > floatval($rule_value),
|
||||||
|
'>=' => floatval($bt_value) >= floatval($rule_value),
|
||||||
|
'=' => floatval($bt_value) == floatval($rule_value),
|
||||||
|
'<' => floatval($bt_value) < floatval($rule_value),
|
||||||
|
'<=' => floatval($bt_value) <= floatval($rule_value),
|
||||||
|
default => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function matchStringOperator($bt_value, $rule_value, $operator) :bool
|
||||||
|
{
|
||||||
|
$bt_value = strtolower(str_replace(" ", "", $bt_value));
|
||||||
|
$rule_value = strtolower(str_replace(" ", "", $rule_value));
|
||||||
|
$rule_length = iconv_strlen($rule_value);
|
||||||
|
|
||||||
|
return match ($operator) {
|
||||||
|
'is' => $bt_value == $rule_value,
|
||||||
|
'contains' => stripos($bt_value, $rule_value) !== false,
|
||||||
|
'starts_with' => substr($bt_value, 0, $rule_length) == $rule_value,
|
||||||
|
'is_empty' => empty($bt_value),
|
||||||
|
default => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -29,24 +29,30 @@ class ClientService
|
|||||||
|
|
||||||
public function updateBalance(float $amount)
|
public function updateBalance(float $amount)
|
||||||
{
|
{
|
||||||
// $this->client->balance += $amount;
|
|
||||||
|
|
||||||
|
try {
|
||||||
\DB::connection(config('database.default'))->transaction(function () use($amount) {
|
\DB::connection(config('database.default'))->transaction(function () use($amount) {
|
||||||
|
|
||||||
|
nlog("inside transaction - updating balance by {$amount}");
|
||||||
|
|
||||||
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
|
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
|
||||||
$this->client->balance += $amount;
|
$this->client->balance += $amount;
|
||||||
$this->client->save();
|
$this->client->save();
|
||||||
|
|
||||||
}, 2);
|
}, 2);
|
||||||
|
}
|
||||||
|
catch (\Throwable $throwable) {
|
||||||
|
nlog("DB ERROR " . $throwable->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateBalanceAndPaidToDate(float $balance, float $paid_to_date)
|
public function updateBalanceAndPaidToDate(float $balance, float $paid_to_date)
|
||||||
{
|
{
|
||||||
// $this->client->balance += $amount;
|
|
||||||
// $this->client->paid_to_date += $amount;
|
|
||||||
|
|
||||||
|
try {
|
||||||
\DB::connection(config('database.default'))->transaction(function () use($balance, $paid_to_date) {
|
\DB::connection(config('database.default'))->transaction(function () use($balance, $paid_to_date) {
|
||||||
|
|
||||||
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
|
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
|
||||||
@ -55,6 +61,12 @@ class ClientService
|
|||||||
$this->client->save();
|
$this->client->save();
|
||||||
|
|
||||||
}, 2);
|
}, 2);
|
||||||
|
}
|
||||||
|
catch (\Throwable $throwable) {
|
||||||
|
nlog("DB ERROR " . $throwable->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ class ApplyPayment
|
|||||||
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
|
||||||
if ((int) $this->invoice->balance == 0) {
|
if ((int) $this->invoice->balance == 0) {
|
||||||
$this->invoice->service()->deletePdf();
|
$this->invoice->service()->touchPdf();
|
||||||
$this->invoice = $this->invoice->fresh();
|
$this->invoice = $this->invoice->fresh();
|
||||||
event(new InvoiceWasPaid($this->invoice, $this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasPaid($this->invoice, $this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ class ApplyPayment extends AbstractService
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->invoice->service()->applyNumber()->workFlow()->save();
|
$this->invoice->service()->applyNumber()->workFlow()->touchPdf()->save();
|
||||||
|
|
||||||
$transaction = [
|
$transaction = [
|
||||||
'invoice' => $this->invoice->transaction_event(),
|
'invoice' => $this->invoice->transaction_event(),
|
||||||
|
@ -83,7 +83,7 @@ class ApplyPaymentAmount extends AbstractService
|
|||||||
->updatePaidToDate($payment->amount)
|
->updatePaidToDate($payment->amount)
|
||||||
->setCalculatedStatus()
|
->setCalculatedStatus()
|
||||||
->applyNumber()
|
->applyNumber()
|
||||||
->deletePdf()
|
->touchPdf()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$this->invoice
|
$this->invoice
|
||||||
|
@ -112,10 +112,12 @@ class InvoiceService
|
|||||||
* @param Payment $payment The Payment
|
* @param Payment $payment The Payment
|
||||||
* @param float $payment_amount The Payment amount
|
* @param float $payment_amount The Payment amount
|
||||||
* @return InvoiceService Parent class object
|
* @return InvoiceService Parent class object
|
||||||
|
* @deprecated 24-11-2022 - cannot find any references to this method anywhere
|
||||||
*/
|
*/
|
||||||
public function applyPayment(Payment $payment, float $payment_amount)
|
public function applyPayment(Payment $payment, float $payment_amount)
|
||||||
{
|
{
|
||||||
$this->deletePdf();
|
// $this->deletePdf();
|
||||||
|
$this->invoice = $this->markSent()->save();
|
||||||
|
|
||||||
$this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run();
|
$this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run();
|
||||||
|
|
||||||
@ -218,7 +220,6 @@ class InvoiceService
|
|||||||
public function markDeleted()
|
public function markDeleted()
|
||||||
{
|
{
|
||||||
$this->removeUnpaidGatewayFees();
|
$this->removeUnpaidGatewayFees();
|
||||||
$this->deletePdf();
|
|
||||||
|
|
||||||
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
||||||
|
|
||||||
@ -378,6 +379,7 @@ class InvoiceService
|
|||||||
})->toArray();
|
})->toArray();
|
||||||
|
|
||||||
$this->invoice = $this->invoice->calc()->getInvoice();
|
$this->invoice = $this->invoice->calc()->getInvoice();
|
||||||
|
$this->invoice->service()->touchPdf();
|
||||||
|
|
||||||
/* 24-03-2022 */
|
/* 24-03-2022 */
|
||||||
$new_balance = $this->invoice->balance;
|
$new_balance = $this->invoice->balance;
|
||||||
|
@ -104,7 +104,6 @@ class DeletePayment
|
|||||||
|
|
||||||
$client = $this->payment
|
$client = $this->payment
|
||||||
->client
|
->client
|
||||||
->fresh()
|
|
||||||
->service()
|
->service()
|
||||||
->updateBalance($net_deletable)
|
->updateBalance($net_deletable)
|
||||||
->save();
|
->save();
|
||||||
@ -136,9 +135,8 @@ class DeletePayment
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$client = $this->payment->client->fresh();
|
$this->payment
|
||||||
|
->client
|
||||||
$client
|
|
||||||
->service()
|
->service()
|
||||||
->updatePaidToDate(($this->payment->amount - $this->payment->refunded) * -1)
|
->updatePaidToDate(($this->payment->amount - $this->payment->refunded) * -1)
|
||||||
->save();
|
->save();
|
||||||
@ -146,7 +144,7 @@ class DeletePayment
|
|||||||
$transaction = [
|
$transaction = [
|
||||||
'invoice' => [],
|
'invoice' => [],
|
||||||
'payment' => [],
|
'payment' => [],
|
||||||
'client' => $client->transaction_event(),
|
'client' => $this->payment->client->transaction_event(),
|
||||||
'credit' => [],
|
'credit' => [],
|
||||||
'metadata' => [],
|
'metadata' => [],
|
||||||
];
|
];
|
||||||
|
@ -62,12 +62,14 @@ class UpdateInvoicePayment
|
|||||||
$paid_amount = $paid_invoice->amount;
|
$paid_amount = $paid_invoice->amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
$client->service()->updateBalanceAndPaidToDate($paid_amount*-1, $paid_amount);
|
$client->service()->updatePaidToDate($paid_amount); //always use the payment->amount
|
||||||
|
|
||||||
/* Need to determine here is we have an OVER payment - if YES only apply the max invoice amount */
|
/* Need to determine here is we have an OVER payment - if YES only apply the max invoice amount */
|
||||||
if($paid_amount > $invoice->partial && $paid_amount > $invoice->balance)
|
if($paid_amount > $invoice->partial && $paid_amount > $invoice->balance)
|
||||||
$paid_amount = $invoice->balance;
|
$paid_amount = $invoice->balance;
|
||||||
|
|
||||||
|
$client->service()->updateBalance($paid_amount*-1); //only ever use the amount applied to the invoice
|
||||||
|
|
||||||
/*Improve performance here - 26-01-2022 - also change the order of events for invoice first*/
|
/*Improve performance here - 26-01-2022 - also change the order of events for invoice first*/
|
||||||
//caution what if we amount paid was less than partial - we wipe it!
|
//caution what if we amount paid was less than partial - we wipe it!
|
||||||
$invoice->balance -= $paid_amount;
|
$invoice->balance -= $paid_amount;
|
||||||
|
@ -40,12 +40,8 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
|
|
||||||
class TaskSchedulerService
|
class TaskSchedulerService
|
||||||
{
|
{
|
||||||
public Scheduler $scheduler;
|
|
||||||
|
|
||||||
public function __construct(Scheduler $scheduler)
|
public function __construct(public Scheduler $scheduler) {}
|
||||||
{
|
|
||||||
$this->scheduler = $scheduler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store(Scheduler $scheduler, CreateScheduledTaskRequest $request)
|
public function store(Scheduler $scheduler, CreateScheduledTaskRequest $request)
|
||||||
{
|
{
|
||||||
|
90
app/Transformers/BankTransactionRuleTransformer.php
Normal file
90
app/Transformers/BankTransactionRuleTransformer.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Transformers;
|
||||||
|
|
||||||
|
use App\Models\Account;
|
||||||
|
use App\Models\BankTransaction;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\Expense;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Transformers\VendorTransformer;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BankTransactionRuleTransformer.
|
||||||
|
*/
|
||||||
|
class BankTransactionRuleTransformer extends EntityTransformer
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $defaultIncludes = [
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $availableIncludes = [
|
||||||
|
'company',
|
||||||
|
'vendor',
|
||||||
|
'client',
|
||||||
|
'expense_category',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BankTransaction $bank_integration
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform(BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => (string) $this->encodePrimaryKey($bank_transaction_rule->id),
|
||||||
|
'name' => (string) $bank_transaction_rule->name,
|
||||||
|
'rules' => $bank_transaction_rule->rules ?: (array) [],
|
||||||
|
'auto_convert' => (bool) $bank_transaction_rule->auto_convert,
|
||||||
|
'matches_on_all' => (bool) $bank_transaction_rule->matches_on_all,
|
||||||
|
'applies_to' => (string) $bank_transaction_rule->applies_to,
|
||||||
|
'client_id' => $this->encodePrimaryKey($bank_transaction_rule->client_id) ?: '',
|
||||||
|
'vendor_id' => $this->encodePrimaryKey($bank_transaction_rule->vendor_id) ?: '',
|
||||||
|
'category_id' => $this->encodePrimaryKey($bank_transaction_rule->category_id) ?: '',
|
||||||
|
'is_deleted' => (bool) $bank_transaction_rule->is_deleted,
|
||||||
|
'created_at' => (int) $bank_transaction_rule->created_at,
|
||||||
|
'updated_at' => (int) $bank_transaction_rule->updated_at,
|
||||||
|
'archived_at' => (int) $bank_transaction_rule->deleted_at,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function includeCompany(BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
$transformer = new CompanyTransformer($this->serializer);
|
||||||
|
|
||||||
|
return $this->includeItem($bank_transaction_rule->company, $transformer, Company::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function includeClient(BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
$transformer = new ClientTransformer($this->serializer);
|
||||||
|
|
||||||
|
return $this->includeItem($bank_transaction_rule->expense, $transformer, Client::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function includeVendor(BankTransactionRule $bank_transaction_rule)
|
||||||
|
{
|
||||||
|
$transformer = new VendorTransformer($this->serializer);
|
||||||
|
|
||||||
|
return $this->includeItem($bank_transaction_rule->vendor, $transformer, Vendor::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -67,6 +67,7 @@ class BankTransactionTransformer extends EntityTransformer
|
|||||||
'invoice_ids' => (string) $bank_transaction->invoice_ids ?: '',
|
'invoice_ids' => (string) $bank_transaction->invoice_ids ?: '',
|
||||||
'expense_id'=> (string) $this->encodePrimaryKey($bank_transaction->expense_id) ?: '',
|
'expense_id'=> (string) $this->encodePrimaryKey($bank_transaction->expense_id) ?: '',
|
||||||
'vendor_id'=> (string) $this->encodePrimaryKey($bank_transaction->vendor_id) ?: '',
|
'vendor_id'=> (string) $this->encodePrimaryKey($bank_transaction->vendor_id) ?: '',
|
||||||
|
'bank_transaction_rule_id' => (string) $this->encodePrimaryKey($bank_transaction->bank_transaction_rule_id) ?: '',
|
||||||
'is_deleted' => (bool) $bank_transaction->is_deleted,
|
'is_deleted' => (bool) $bank_transaction->is_deleted,
|
||||||
'created_at' => (int) $bank_transaction->created_at,
|
'created_at' => (int) $bank_transaction->created_at,
|
||||||
'updated_at' => (int) $bank_transaction->updated_at,
|
'updated_at' => (int) $bank_transaction->updated_at,
|
||||||
|
@ -43,6 +43,7 @@ use App\Models\TaxRate;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Webhook;
|
use App\Models\Webhook;
|
||||||
use App\Transformers\BankIntegrationTransformer;
|
use App\Transformers\BankIntegrationTransformer;
|
||||||
|
use App\Transformers\BankTransactionRuleTransformer;
|
||||||
use App\Transformers\BankTransactionTransformer;
|
use App\Transformers\BankTransactionTransformer;
|
||||||
use App\Transformers\PurchaseOrderTransformer;
|
use App\Transformers\PurchaseOrderTransformer;
|
||||||
use App\Transformers\RecurringExpenseTransformer;
|
use App\Transformers\RecurringExpenseTransformer;
|
||||||
@ -104,6 +105,7 @@ class CompanyTransformer extends EntityTransformer
|
|||||||
'purchase_orders',
|
'purchase_orders',
|
||||||
'bank_integrations',
|
'bank_integrations',
|
||||||
'bank_transactions',
|
'bank_transactions',
|
||||||
|
'bank_transaction_rules',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -186,6 +188,8 @@ class CompanyTransformer extends EntityTransformer
|
|||||||
'enabled_expense_tax_rates' => (int) $company->enabled_expense_tax_rates,
|
'enabled_expense_tax_rates' => (int) $company->enabled_expense_tax_rates,
|
||||||
'invoice_task_project' => (bool) $company->invoice_task_project,
|
'invoice_task_project' => (bool) $company->invoice_task_project,
|
||||||
'report_include_deleted' => (bool) $company->report_include_deleted,
|
'report_include_deleted' => (bool) $company->report_include_deleted,
|
||||||
|
'invoice_task_lock' => (bool) $company->invoice_task_lock,
|
||||||
|
'use_vendor_currency' => (bool) $company->use_vendor_currency,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,6 +235,14 @@ class CompanyTransformer extends EntityTransformer
|
|||||||
return $this->includeCollection($company->bank_transactions, $transformer, BankTransaction::class);
|
return $this->includeCollection($company->bank_transactions, $transformer, BankTransaction::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function includeBankTransactionRules(Company $company)
|
||||||
|
{
|
||||||
|
$transformer = new BankTransactionRuleTransformer($this->serializer);
|
||||||
|
|
||||||
|
return $this->includeCollection($company->bank_transaction_rules, $transformer, BankTransactionRule::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function includeBankIntegrations(Company $company)
|
public function includeBankIntegrations(Company $company)
|
||||||
{
|
{
|
||||||
$transformer = new BankIntegrationTransformer($this->serializer);
|
$transformer = new BankIntegrationTransformer($this->serializer);
|
||||||
|
@ -132,6 +132,7 @@ class PurchaseOrderTransformer extends EntityTransformer
|
|||||||
'paid_to_date' => (float)$purchase_order->paid_to_date,
|
'paid_to_date' => (float)$purchase_order->paid_to_date,
|
||||||
'subscription_id' => $this->encodePrimaryKey($purchase_order->subscription_id),
|
'subscription_id' => $this->encodePrimaryKey($purchase_order->subscription_id),
|
||||||
'expense_id' => $this->encodePrimaryKey($purchase_order->expense_id),
|
'expense_id' => $this->encodePrimaryKey($purchase_order->expense_id),
|
||||||
|
'currency_id' => $purchase_order->currency_id ? (string) $purchase_order->currency_id : '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,10 @@ class SubscriptionTransformer extends EntityTransformer
|
|||||||
'updated_at' => (int) $subscription->updated_at,
|
'updated_at' => (int) $subscription->updated_at,
|
||||||
'archived_at' => (int) $subscription->deleted_at,
|
'archived_at' => (int) $subscription->deleted_at,
|
||||||
'plan_map' => '', //@deprecated 03/04/2021
|
'plan_map' => '', //@deprecated 03/04/2021
|
||||||
|
'use_inventory_management' => (bool) $subscription->use_inventory_management,
|
||||||
|
'optional_recurring_product_ids' =>(string)$subscription->optional_recurring_product_ids,
|
||||||
|
'optional_product_ids' => (string) $subscription->optional_product_ids,
|
||||||
|
'registration_required' => (bool) $subscription->registration_required,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,6 @@ class TaskTransformer extends EntityTransformer
|
|||||||
'user_id' => (string) $this->encodePrimaryKey($task->user_id),
|
'user_id' => (string) $this->encodePrimaryKey($task->user_id),
|
||||||
'assigned_user_id' => (string) $this->encodePrimaryKey($task->assigned_user_id),
|
'assigned_user_id' => (string) $this->encodePrimaryKey($task->assigned_user_id),
|
||||||
'number' => (string) $task->number ?: '',
|
'number' => (string) $task->number ?: '',
|
||||||
// 'start_time' => (int) $task->start_time,
|
|
||||||
'description' => (string) $task->description ?: '',
|
'description' => (string) $task->description ?: '',
|
||||||
'duration' => (int) $task->duration ?: 0,
|
'duration' => (int) $task->duration ?: 0,
|
||||||
'rate' => (float) $task->rate ?: 0,
|
'rate' => (float) $task->rate ?: 0,
|
||||||
|
@ -134,6 +134,30 @@ class Helpers
|
|||||||
|
|
||||||
$replacements = [
|
$replacements = [
|
||||||
'literal' => [
|
'literal' => [
|
||||||
|
':MONTH_BEFORE' => \sprintf(
|
||||||
|
'%s %s %s',
|
||||||
|
Carbon::now()->subMonth(1)->translatedFormat($entity->date_format()),
|
||||||
|
ctrans('texts.to'),
|
||||||
|
Carbon::now()->subDay(1)->translatedFormat($entity->date_format()),
|
||||||
|
),
|
||||||
|
':YEAR_BEFORE' => \sprintf(
|
||||||
|
'%s %s %s',
|
||||||
|
Carbon::now()->subYear(1)->translatedFormat($entity->date_format()),
|
||||||
|
ctrans('texts.to'),
|
||||||
|
Carbon::now()->subDay(1)->translatedFormat($entity->date_format()),
|
||||||
|
),
|
||||||
|
':MONTH_AFTER' => \sprintf(
|
||||||
|
'%s %s %s',
|
||||||
|
Carbon::now()->translatedFormat($entity->date_format()),
|
||||||
|
ctrans('texts.to'),
|
||||||
|
Carbon::now()->addMonth(1)->subDay(1)->translatedFormat($entity->date_format()),
|
||||||
|
),
|
||||||
|
':YEAR_AFTER' => \sprintf(
|
||||||
|
'%s %s %s',
|
||||||
|
Carbon::now()->translatedFormat($entity->date_format()),
|
||||||
|
ctrans('texts.to'),
|
||||||
|
Carbon::now()->addYear(1)->subDay(1)->translatedFormat($entity->date_format()),
|
||||||
|
),
|
||||||
':MONTHYEAR' => \sprintf(
|
':MONTHYEAR' => \sprintf(
|
||||||
'%s %s',
|
'%s %s',
|
||||||
Carbon::createFromDate(now()->month)->translatedFormat('F'),
|
Carbon::createFromDate(now()->month)->translatedFormat('F'),
|
||||||
@ -150,15 +174,15 @@ class Helpers
|
|||||||
),
|
),
|
||||||
':WEEK_AHEAD' => \sprintf(
|
':WEEK_AHEAD' => \sprintf(
|
||||||
'%s %s %s',
|
'%s %s %s',
|
||||||
Carbon::now()->addDays(6)->translatedFormat($entity->date_format()),
|
Carbon::now()->addDays(7)->translatedFormat($entity->date_format()),
|
||||||
ctrans('texts.to'),
|
ctrans('texts.to'),
|
||||||
Carbon::now()->addDays(13)->translatedFormat($entity->date_format())
|
Carbon::now()->addDays(13)->translatedFormat($entity->date_format())
|
||||||
),
|
),
|
||||||
':WEEK' => \sprintf(
|
':WEEK' => \sprintf(
|
||||||
'%s %s %s',
|
'%s %s %s',
|
||||||
Carbon::now()->subDays(7)->translatedFormat($entity->date_format()),
|
Carbon::now()->translatedFormat($entity->date_format()),
|
||||||
ctrans('texts.to'),
|
ctrans('texts.to'),
|
||||||
Carbon::now()->addDays(13)->translatedFormat($entity->date_format())
|
Carbon::now()->addDays(6)->translatedFormat($entity->date_format())
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
'raw' => [
|
'raw' => [
|
||||||
|
@ -95,10 +95,14 @@ class SystemHealth
|
|||||||
|
|
||||||
if(strlen(config('ninja.currency_converter_api_key')) == 0){
|
if(strlen(config('ninja.currency_converter_api_key')) == 0){
|
||||||
|
|
||||||
|
try{
|
||||||
$cs = DB::table('clients')
|
$cs = DB::table('clients')
|
||||||
->select('settings->currency_id as id')
|
->select('settings->currency_id as id')
|
||||||
->get();
|
->get();
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
return true; //fresh installs, there may be no DB connection, nor migrations could have run yet.
|
||||||
|
}
|
||||||
|
|
||||||
$currency_count = $cs->unique('id')->filter(function ($value){
|
$currency_count = $cs->unique('id')->filter(function ($value){
|
||||||
return !is_null($value->id);
|
return !is_null($value->id);
|
||||||
|
@ -68,7 +68,7 @@ trait Inviteable
|
|||||||
);
|
);
|
||||||
$writer = new Writer($renderer);
|
$writer = new Writer($renderer);
|
||||||
|
|
||||||
$qr = $writer->writeString($this->getPaymentLink());
|
$qr = $writer->writeString($this->getPaymentLink(), 'utf-8');
|
||||||
|
|
||||||
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
||||||
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
||||||
@ -80,7 +80,7 @@ trait Inviteable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity_type = Str::snake(class_basename($this->entityType()));
|
$entity_type = Str::snake(class_basename($this->entityType()));
|
||||||
@ -95,7 +95,7 @@ trait Inviteable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->company->portal_mode) {
|
switch ($this->company->portal_mode) {
|
||||||
@ -121,7 +121,7 @@ trait Inviteable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->company->portal_mode) {
|
switch ($this->company->portal_mode) {
|
||||||
|
@ -14,8 +14,8 @@ return [
|
|||||||
'require_https' => env('REQUIRE_HTTPS', true),
|
'require_https' => env('REQUIRE_HTTPS', true),
|
||||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||||
'app_version' => '5.5.41',
|
'app_version' => '5.5.42',
|
||||||
'app_tag' => '5.5.41',
|
'app_tag' => '5.5.42',
|
||||||
'minimum_client_version' => '5.0.16',
|
'minimum_client_version' => '5.0.16',
|
||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', ''),
|
'api_secret' => env('API_SECRET', ''),
|
||||||
@ -211,4 +211,5 @@ return [
|
|||||||
'dev_mode' => env("YODLEE_DEV_MODE", false),
|
'dev_mode' => env("YODLEE_DEV_MODE", false),
|
||||||
'config_name' => env("YODLEE_CONFIG_NAME", false),
|
'config_name' => env("YODLEE_CONFIG_NAME", false),
|
||||||
],
|
],
|
||||||
|
'dbs' => ['db-ninja-01','db-ninja-02']
|
||||||
];
|
];
|
||||||
|
31
database/factories/BankTransactionRuleFactory.php
Normal file
31
database/factories/BankTransactionRuleFactory.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Account;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class BankTransactionRuleFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function definition()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' =>$this->faker->name(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::create('bank_transaction_rules', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedInteger('company_id');
|
||||||
|
$table->unsignedInteger('user_id');
|
||||||
|
|
||||||
|
$table->string('name'); //name of rule
|
||||||
|
$table->mediumText('rules')->nullable(); //array of rule objects
|
||||||
|
$table->boolean('auto_convert')->default(false); //auto convert to match
|
||||||
|
$table->boolean('matches_on_all')->default(false); //match on all rules or just one
|
||||||
|
$table->string('applies_to')->default('CREDIT'); //CREDIT/DEBIT
|
||||||
|
|
||||||
|
$table->unsignedInteger('client_id')->nullable();
|
||||||
|
$table->unsignedInteger('vendor_id')->nullable();
|
||||||
|
$table->unsignedInteger('category_id')->nullable();
|
||||||
|
|
||||||
|
$table->boolean('is_deleted')->default(0);
|
||||||
|
$table->timestamps(6);
|
||||||
|
$table->softDeletes('deleted_at', 6);
|
||||||
|
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
|
||||||
|
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade')->onUpdate('cascade');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Currency;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::table('companies', function (Blueprint $table)
|
||||||
|
{
|
||||||
|
$table->boolean('invoice_task_lock')->default(false);
|
||||||
|
$table->boolean('use_vendor_currency')->default(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('purchase_orders', function (Blueprint $table)
|
||||||
|
{
|
||||||
|
$table->unsignedInteger('currency_id')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('bank_transactions', function (Blueprint $table)
|
||||||
|
{
|
||||||
|
$table->bigInteger('bank_transaction_rule_id')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('subscriptions', function (Blueprint $table)
|
||||||
|
{
|
||||||
|
$table->boolean('registration_required')->default(false);
|
||||||
|
$table->boolean('use_inventory_management')->default(false);
|
||||||
|
$table->text('optional_product_ids')->nullable();
|
||||||
|
$table->text('optional_recurring_product_ids')->nullable();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$currencies = [
|
||||||
|
|
||||||
|
['id' => 113, 'name' => 'Swazi lilangeni', 'code' => 'SZL', 'symbol' => 'E', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($currencies as $currency) {
|
||||||
|
$record = Currency::whereCode($currency['code'])->first();
|
||||||
|
if ($record) {
|
||||||
|
$record->name = $currency['name'];
|
||||||
|
$record->symbol = $currency['symbol'];
|
||||||
|
$record->precision = $currency['precision'];
|
||||||
|
$record->thousand_separator = $currency['thousand_separator'];
|
||||||
|
$record->decimal_separator = $currency['decimal_separator'];
|
||||||
|
if (isset($currency['swap_currency_symbol'])) {
|
||||||
|
$record->swap_currency_symbol = $currency['swap_currency_symbol'];
|
||||||
|
}
|
||||||
|
$record->save();
|
||||||
|
} else {
|
||||||
|
Currency::create($currency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\Illuminate\Support\Facades\Artisan::call('ninja:design-update');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -127,6 +127,15 @@ class CurrenciesSeeder extends Seeder
|
|||||||
['id' => 102, 'name' => 'Moldovan Leu', 'code' => 'MDL', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['id' => 102, 'name' => 'Moldovan Leu', 'code' => 'MDL', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['id' => 103, 'name' => 'Kazakhstani Tenge', 'code' => 'KZT', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['id' => 103, 'name' => 'Kazakhstani Tenge', 'code' => 'KZT', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['id' => 104, 'name' => 'Ethiopian Birr', 'code' => 'ETB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['id' => 104, 'name' => 'Ethiopian Birr', 'code' => 'ETB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 105, 'name' => 'Gambia Dalasi', 'code' => 'GMD', 'symbol' => 'D', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 106, 'name' => 'Paraguayan Guarani', 'code' => 'PYG', 'symbol' => '₲', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 107, 'name' => 'Malawi Kwacha', 'code' => 'MWK', 'symbol' => 'MK', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 108, 'name' => 'Zimbabwean Dollar', 'code' => 'ZWL', 'symbol' => 'Z$', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 109, 'name' => 'Cambodian Riel', 'code' => 'KHR', 'symbol' => '៛', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 110, 'name' => 'Vanuatu Vatu', 'code' => 'VUV', 'symbol' => 'VT', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 111, 'name' => 'Cuban Peso', 'code' => 'CUP', 'symbol' => '₱', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 112, 'name' => 'Cayman Island Dollar', 'code' => 'KYD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 113, 'name' => 'Swazi lilangeni', 'code' => 'SZL', 'symbol' => 'E', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($currencies as $currency) {
|
foreach ($currencies as $currency) {
|
||||||
|
@ -4843,6 +4843,11 @@ $LANG = array(
|
|||||||
'refresh_accounts' => 'Refresh Accounts',
|
'refresh_accounts' => 'Refresh Accounts',
|
||||||
'upgrade_to_connect_bank_account' => 'Upgrade to Enterprise to connect your bank account',
|
'upgrade_to_connect_bank_account' => 'Upgrade to Enterprise to connect your bank account',
|
||||||
'click_here_to_connect_bank_account' => 'Click here to connect your bank account',
|
'click_here_to_connect_bank_account' => 'Click here to connect your bank account',
|
||||||
|
'task_update_authorization_error' => 'Insufficient permissions, or task may be locked',
|
||||||
|
'cash_vs_accrual' => 'Accrual accounting',
|
||||||
|
'cash_vs_accrual_help' => 'Turn on for accrual reporting, turn off for cash basis reporting.',
|
||||||
|
'expense_paid_report' => 'Expensed reporting',
|
||||||
|
'expense_paid_report_help' => 'Turn on for reporting all expenses, turn off for reporting only paid expenses',
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
65
package-lock.json
generated
65
package-lock.json
generated
@ -5,6 +5,8 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tailwindcss/forms": "^0.3.4",
|
||||||
|
"@tailwindcss/line-clamp": "^0.3.1",
|
||||||
"autoprefixer": "^10.3.7",
|
"autoprefixer": "^10.3.7",
|
||||||
"axios": "^0.25",
|
"axios": "^0.25",
|
||||||
"card-js": "^1.0.13",
|
"card-js": "^1.0.13",
|
||||||
@ -25,6 +27,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/compat-data": "7.15.0",
|
"@babel/compat-data": "7.15.0",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||||
|
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||||
"laravel-mix-purgecss": "^6.0.0",
|
"laravel-mix-purgecss": "^6.0.0",
|
||||||
"vue-template-compiler": "^2.6.14"
|
"vue-template-compiler": "^2.6.14"
|
||||||
}
|
}
|
||||||
@ -1682,6 +1685,34 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/aspect-ratio": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==",
|
||||||
|
"dev": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/forms": {
|
||||||
|
"version": "0.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.3.4.tgz",
|
||||||
|
"integrity": "sha512-vlAoBifNJUkagB+PAdW4aHMe4pKmSLroH398UPgIogBFc91D2VlHUxe4pjxQhiJl0Nfw53sHSJSQBSTQBZP3vA==",
|
||||||
|
"dependencies": {
|
||||||
|
"mini-svg-data-uri": "^1.2.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/line-clamp": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@trysound/sax": {
|
"node_modules/@trysound/sax": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||||
@ -5742,6 +5773,14 @@
|
|||||||
"url": "https://opencollective.com/webpack"
|
"url": "https://opencollective.com/webpack"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mini-svg-data-uri": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
|
||||||
|
"bin": {
|
||||||
|
"mini-svg-data-uri": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimalistic-assert": {
|
"node_modules/minimalistic-assert": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||||
@ -10285,6 +10324,27 @@
|
|||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tailwindcss/aspect-ratio": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"@tailwindcss/forms": {
|
||||||
|
"version": "0.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.3.4.tgz",
|
||||||
|
"integrity": "sha512-vlAoBifNJUkagB+PAdW4aHMe4pKmSLroH398UPgIogBFc91D2VlHUxe4pjxQhiJl0Nfw53sHSJSQBSTQBZP3vA==",
|
||||||
|
"requires": {
|
||||||
|
"mini-svg-data-uri": "^1.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tailwindcss/line-clamp": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"@trysound/sax": {
|
"@trysound/sax": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||||
@ -13399,6 +13459,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mini-svg-data-uri": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="
|
||||||
|
},
|
||||||
"minimalistic-assert": {
|
"minimalistic-assert": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||||
|
@ -11,10 +11,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/compat-data": "7.15.0",
|
"@babel/compat-data": "7.15.0",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||||
|
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||||
"laravel-mix-purgecss": "^6.0.0",
|
"laravel-mix-purgecss": "^6.0.0",
|
||||||
"vue-template-compiler": "^2.6.14"
|
"vue-template-compiler": "^2.6.14"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tailwindcss/line-clamp": "^0.3.1",
|
||||||
|
"@tailwindcss/forms": "^0.3.4",
|
||||||
"autoprefixer": "^10.3.7",
|
"autoprefixer": "^10.3.7",
|
||||||
"axios": "^0.25",
|
"axios": "^0.25",
|
||||||
"card-js": "^1.0.13",
|
"card-js": "^1.0.13",
|
||||||
|
2
public/css/app.css
vendored
2
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
556
public/flutter_service_worker.js
vendored
556
public/flutter_service_worker.js
vendored
@ -3,305 +3,305 @@ const MANIFEST = 'flutter-app-manifest';
|
|||||||
const TEMP = 'flutter-temp-cache';
|
const TEMP = 'flutter-temp-cache';
|
||||||
const CACHE_NAME = 'flutter-app-cache';
|
const CACHE_NAME = 'flutter-app-cache';
|
||||||
const RESOURCES = {
|
const RESOURCES = {
|
||||||
"version.json": "eaa34b1fc12792d815c0443fbfbc076b",
|
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "b62641afc9ab487008e996a5c5865e56",
|
||||||
"canvaskit/canvaskit.wasm": "bf50631470eb967688cca13ee181af62",
|
|
||||||
"canvaskit/canvaskit.js": "2bc454a691c631b07a9307ac4ca47797",
|
|
||||||
"canvaskit/profiling/canvaskit.wasm": "95a45378b69e77af5ed2bc72b2209b94",
|
|
||||||
"canvaskit/profiling/canvaskit.js": "38164e5a72bdad0faa4ce740c9b8e564",
|
|
||||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
|
||||||
"flutter.js": "f85e6fb278b0fd20c349186fb46ae36d",
|
|
||||||
"/": "112f22769207bffb3936c08dec3ffa4d",
|
|
||||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
|
||||||
"main.dart.js": "bddfba2a7d482fece1e7a9ff84429256",
|
|
||||||
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
|
|
||||||
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
|
|
||||||
"assets/NOTICES": "1a34e70168d56fad075adfb4bdbb20eb",
|
|
||||||
"assets/fonts/MaterialIcons-Regular.otf": "95db9098c58fd6db106f1116bae85a0b",
|
|
||||||
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
|
||||||
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
|
|
||||||
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
|
|
||||||
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
|
|
||||||
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
|
|
||||||
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
|
|
||||||
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
|
|
||||||
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
|
|
||||||
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
|
|
||||||
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
|
||||||
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
|
||||||
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
|
|
||||||
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
|
|
||||||
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
|
|
||||||
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
|
||||||
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
|
|
||||||
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
|
|
||||||
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
|
|
||||||
"assets/assets/images/logo_dark.png": "a233ed1d4d0f7414bf97a9a10f11fb0a",
|
|
||||||
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sj.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/hn.png": "9ecf68aed83c4a9b3f1e6275d96bfb04",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/zw.png": "078a3267ea8eabf88b2d43fe4aed5ce5",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mq.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cy.png": "7b36f4af86257a3f15f5a5a16f4a2fcd",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cm.png": "42d52fa71e8b4dbb182ff431749e8d0d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/kg.png": "c4aa6d221d9a9d332155518d6b82dbc7",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gh.png": "b35464dca793fa33e51bf890b5f3d92b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gw.png": "05606b9a6393971bd87718b809e054f9",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/vu.png": "3f201fdfb6d669a64c35c20a801016d1",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/aw.png": "a93ddf8e32d246dc47f6631f38e0ed92",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/qa.png": "eb9b3388e554cf85aea1e739247548df",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/br.png": "5093e0cd8fd3c094664cd17ea8a36fd1",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pg.png": "0f7e03465a93e0b4e3e1c9d3dd5814a4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sb.png": "296ecedbd8d1c2a6422c3ba8e5cd54bd",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sn.png": "68eaa89bbc83b3f356e1ba2096b09b3c",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/uz.png": "3adad3bac322220cac8abc1c7cbaacac",
|
"assets/packages/intl_phone_field/assets/flags/uz.png": "3adad3bac322220cac8abc1c7cbaacac",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ps.png": "52a25a48658ca9274830ffa124a8c1db",
|
"assets/packages/intl_phone_field/assets/flags/vu.png": "3f201fdfb6d669a64c35c20a801016d1",
|
||||||
"assets/packages/intl_phone_field/assets/flags/bn.png": "ed650de06fff61ff27ec92a872197948",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/si.png": "24237e53b34752554915e71e346bb405",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ml.png": "0c50dfd539e87bb4313da0d4556e2d13",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lt.png": "7df2cd6566725685f7feb2051f916a3e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gb-nir.png": "98773db151c150cabe845183241bfe6b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gm.png": "7148d3715527544c2e7d8d6f4a445bb6",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gt.png": "706a0c3b5e0b589c843e2539e813839e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/vc.png": "da3ca14a978717467abbcdece05d3544",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ae.png": "792efc5eb6c31d780bd34bf4bad69f3f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bm.png": "b366ba84cbc8286c830f392bb9086be5",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pk.png": "7a6a621f7062589677b3296ca16c6718",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mm.png": "32e5293d6029d8294c7dfc3c3835c222",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ar.png": "3bd245f8c28f70c9ef9626dae27adc65",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/kw.png": "3ca448e219d0df506fb2efd5b91be092",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cf.png": "263583ffdf7a888ce4fba8487d1da0b2",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/at.png": "570c070177a5ea0fe03e20107ebf5283",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pt.png": "eba93d33545c78cc67915d9be8323661",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ng.png": "aedbe364bd1543832e88e64b5817e877",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/va.png": "c010bf145f695d5c8fb551bafc081f77",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cl.png": "6735e0e2d88c119e9ed1533be5249ef1",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sr.png": "9f912879f2829a625436ccd15e643e39",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mo.png": "849848a26bbfc87024017418ad7a6233",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/eu.png": "c58ece3931acb87faadc5b940d4f7755",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gs.png": "419dd57836797a3f1bf6258ea6589f9a",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tz.png": "56ec99c7e0f68b88a2210620d873683a",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gb.png": "98773db151c150cabe845183241bfe6b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/nc.png": "cb36e0c945b79d56def11b23c6a9c7e9",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ro.png": "85af99741fe20664d9a7112cfd8d9722",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/xk.png": "079259fbcb1f3c78dafa944464295c16",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gb-eng.png": "0d9f2a6775fd52b79e1d78eb1dda10cf",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/se.png": "25dd5434891ac1ca2ad1af59cda70f80",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/uy.png": "da4247b21fcbd9e30dc2b3f7c5dccb64",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ck.png": "39f343868a8dc8ca95d27b27a5caf480",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sy.png": "24186a0f4ce804a16c91592db5a16a3a",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bz.png": "fd2d7d27a5ddabe4eb9a10b1d3a433e4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/nz.png": "65c811e96eb6c9da65538f899c110895",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mh.png": "18dda388ef5c1cf37cae5e7d5fef39bc",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/um.png": "8fe7c4fed0a065fdfb9bd3125c6ecaa1",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ss.png": "b0120cb000b31bb1a5c801c3592139bc",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lu.png": "6274fd1cae3c7a425d25e4ccb0941bb8",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bb.png": "a8473747387e4e7a8450c499529f1c93",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mu.png": "c5228d1e94501d846b5bf203f038ae49",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/is.png": "907840430252c431518005b562707831",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ir.png": "37f67c3141e9843196cb94815be7bd37",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/np.png": "6e099fb1e063930bdd00e8df5cef73d4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/kz.png": "cb3b0095281c9d7e7fb5ce1716ef8ee5",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/do.png": "ed35983a9263bb5713be37d9a52caddc",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/my.png": "f7f962e8a074387fd568c9d4024e0959",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/za.png": "b28280c6c3eb4624c18b5455d4a1b1ff",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ci.png": "7f5ca3779d5ff6ce0c803a6efa0d2da7",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/an.png": "4e4b90fbca1275d1839ca5b44fc51071",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ec.png": "c1ae60d080be91f3be31e92e0a2d9555",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ai.png": "ce5e91ed1725f0499b9231b69a7fd448",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tc.png": "d728d6763c17c520ad6bcf3c24282a29",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/az.png": "6ffa766f6883d2d3d350cdc22a062ca3",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/wf.png": "6f1644b8f907d197c0ff7ed2f366ad64",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/as.png": "d9c1da515c6f945c2e2554592a9dfaae",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/kp.png": "e1c8bb52f31fca22d3368d8f492d8f27",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ma.png": "057ea2e08587f1361b3547556adae0c2",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/hk.png": "4b5ec424348c98ec71a46ad3dce3931d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ly.png": "8d65057351859065d64b4c118ff9e30e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sa.png": "7c95c1a877148e2aa21a213d720ff4fd",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/kh.png": "d48d51e8769a26930da6edfc15de97fe",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ad.png": "384e9845debe9aca8f8586d9bedcb7e6",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sz.png": "d1829842e45c2b2b29222c1b7e201591",
|
"assets/packages/intl_phone_field/assets/flags/sz.png": "d1829842e45c2b2b29222c1b7e201591",
|
||||||
"assets/packages/intl_phone_field/assets/flags/pw.png": "2e697cc6907a7b94c7f94f5d9b3bdccc",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bi.png": "adda8121501f0543f1075244a1acc275",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/th.png": "11ce0c9f8c738fd217ea52b9bc29014b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lv.png": "53105fea0cc9cc554e0ceaabc53a2d5d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mg.png": "0ef6271ad284ebc0069ff0aeb5a3ad1e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bg.png": "1d24bc616e3389684ed2c9f18bcb0209",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tk.png": "60428ff1cdbae680e5a0b8cde4677dd5",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/hu.png": "281582a753e643b46bdd894047db08bb",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cx.png": "8efa3231c8a3900a78f2b51d829f8c52",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cr.png": "bfd8b41e63fc3cc829c72c4b2e170532",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/am.png": "aaa39141fbc80205bebaa0200b55a13a",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/vg.png": "fc095e11f5b58604d6f4d3c2b43d167f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ua.png": "b4b10d893611470661b079cb30473871",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/de.png": "5d9561246523cf6183928756fd605e25",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ms.png": "9c955a926cf7d57fccb450a97192afa7",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/nl.png": "3649c177693bfee9c2fcc63c191a51f1",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/dm.png": "8886b222ed9ccd00f67e8bcf86dadcc2",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sl.png": "61b9d992c8a6a83abc4d432069617811",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/rw.png": "d1aae0647a5b1ab977ae43ab894ce2c3",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gy.png": "159a260bf0217128ea7475ba5b272b6a",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/dk.png": "abcd01bdbcc02b4a29cbac237f29cd1d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/il.png": "1e06ad7783f24332405d36561024cc4c",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/om.png": "cebd9ab4b9ab071b2142e21ae2129efc",
|
"assets/packages/intl_phone_field/assets/flags/om.png": "cebd9ab4b9ab071b2142e21ae2129efc",
|
||||||
"assets/packages/intl_phone_field/assets/flags/bv.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
"assets/packages/intl_phone_field/assets/flags/so.png": "1ce20d052f9d057250be96f42647513b",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ke.png": "cf5aae3699d3cacb39db9803edae172b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ax.png": "ec2062c36f09ed8fb90ac8992d010024",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/io.png": "83d45bbbff087d47b2b39f1c20598f52",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mv.png": "d9245f74e34d5c054413ace4b86b4f16",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gg.png": "eed435d25bd755aa7f9cd7004b9ed49d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ca.png": "76f2fac1d3b2cc52ba6695c2e2941632",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cv.png": "9b1f31f9fc0795d728328dedd33eb1c0",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gb-wls.png": "d7d7c77c72cd425d993bdc50720f4d04",
|
"assets/packages/intl_phone_field/assets/flags/gb-wls.png": "d7d7c77c72cd425d993bdc50720f4d04",
|
||||||
"assets/packages/intl_phone_field/assets/flags/bq.png": "3649c177693bfee9c2fcc63c191a51f1",
|
"assets/packages/intl_phone_field/assets/flags/de.png": "5d9561246523cf6183928756fd605e25",
|
||||||
"assets/packages/intl_phone_field/assets/flags/es.png": "654965f9722f6706586476fb2f5d30dd",
|
"assets/packages/intl_phone_field/assets/flags/er.png": "8ca78e10878a2e97c1371b38c5d258a7",
|
||||||
"assets/packages/intl_phone_field/assets/flags/mr.png": "f2a62602d43a1ee14625af165b96ce2f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ug.png": "9a0f358b1eb19863e21ae2063fab51c0",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/be.png": "7e5e1831cdd91935b38415479a7110eb",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/fm.png": "d571b8bc4b80980a81a5edbde788b6d2",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gd.png": "7a4864ccfa2a0564041c2d1f8a13a8c9",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/et.png": "57edff61c7fddf2761a19948acef1498",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/hr.png": "69711b2ea009a3e7c40045b538768d4e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lk.png": "5a3a063cfff4a92fb0ba6158e610e025",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bs.png": "2b9540c4fa514f71911a48de0bd77e71",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ws.png": "f206322f3e22f175869869dbfadb6ce8",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/kn.png": "f318e2fd87e5fd2cabefe9ff252bba46",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pa.png": "78e3e4fd56f0064837098fe3f22fb41b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/zm.png": "81cec35b715f227328cad8f314acd797",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lc.png": "8c1a03a592aa0a99fcaf2b81508a87eb",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mx.png": "84b12a569b209e213daccfcbdd1fc799",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gu.png": "2acb614b442e55864411b6e418df6eab",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/au.png": "72be14316f0af3903cdca7a726c0c589",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tl.png": "c80876dc80cda5ab6bb8ef078bc6b05d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/eg.png": "311d780e8e3dd43f87e6070f6feb74c7",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/vn.png": "32ff65ccbf31a707a195be2a5141a89b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tf.png": "b2c044b86509e7960b5ba66b094ea285",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bo.png": "3ccf6fa7f9cbc27949b8418925e4e89c",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/jp.png": "25ac778acd990bedcfdc02a9b4570045",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/je.png": "288f8dca26098e83ff0455b08cceca1b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ls.png": "2bca756f9313957347404557acb532b0",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sg.png": "bc772e50b8c79f08f3c2189f5d8ce491",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pe.png": "4d9249aab70a26fadabb14380b3b55d2",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bh.png": "a1acd86ef0e19ea5f0297bbe1de6cfd4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bd.png": "86a0e4bd8787dc8542137a407e0f987f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cw.png": "6c598eb0d331d6b238da57055ec00d33",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/fk.png": "da8b0fe48829aae2c8feb4839895de63",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/nf.png": "1c2069b299ce3660a2a95ec574dfde25",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tg.png": "7f91f02b26b74899ff882868bd611714",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pl.png": "f20e9ef473a9ed24176f5ad74dd0d50a",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mz.png": "1ab1ac750fbbb453d33e9f25850ac2a0",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/fo.png": "2c7d9233582e83a86927e634897a2a90",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sh.png": "98773db151c150cabe845183241bfe6b",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/py.png": "154d4add03b4878caf00bd3249e14f40",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tj.png": "c73b793f2acd262e71b9236e64c77636",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ph.png": "e4025d1395a8455f1ba038597a95228c",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/li.png": "ecdf7b3fe932378b110851674335d9ab",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tr.png": "27feab1a5ca390610d07e0c6bd4720d5",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gl.png": "b79e24ee1889b7446ba3d65564b86810",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mp.png": "87351c30a529071ee9a4bb67765fea4f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ao.png": "5f0a372aa3aa7150a3dafea97acfc10d",
|
"assets/packages/intl_phone_field/assets/flags/ao.png": "5f0a372aa3aa7150a3dafea97acfc10d",
|
||||||
"assets/packages/intl_phone_field/assets/flags/jo.png": "c01cb41f74f9db0cf07ba20f0af83011",
|
"assets/packages/intl_phone_field/assets/flags/ml.png": "0c50dfd539e87bb4313da0d4556e2d13",
|
||||||
"assets/packages/intl_phone_field/assets/flags/aq.png": "0c586e7b91aa192758fdd0f03adb84d8",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gr.png": "ec11281d7decbf07b81a23a72a609b59",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sd.png": "65ce270762dfc87475ea99bd18f79025",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/fr.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cg.png": "eca97338cc1cb5b5e91bec72af57b3d4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ht.png": "630f7f8567d87409a32955107ad11a86",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bt.png": "3cfe1440e952bc7266d71f7f1454fa23",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ba.png": "d415bad33b35de3f095177e8e86cbc82",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ye.png": "4cf73209d90e9f02ead1565c8fdf59e5",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ky.png": "38e39eba673e82c48a1f25bd103a7e97",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/me.png": "590284bc85810635ace30a173e615ca4",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bf.png": "63f1c67fca7ce8b52b3418a90af6ad37",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bw.png": "fac8b90d7404728c08686dc39bab4fb3",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mk.png": "835f2263974de523fa779d29c90595bf",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gb-sct.png": "75106a5e49e3e16da76cb33bdac102ab",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ne.png": "a20724c177e86d6a27143aa9c9664a6f",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tn.png": "6612e9fec4bef022cbd45cbb7c02b2b6",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/tm.png": "0980fb40ec450f70896f2c588510f933",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gq.png": "4286e56f388a37f64b21eb56550c06d9",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/md.png": "8911d3d821b95b00abbba8771e997eb3",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cc.png": "31a475216e12fef447382c97b42876ce",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lb.png": "f80cde345f0d9bd0086531808ce5166a",
|
"assets/packages/intl_phone_field/assets/flags/lb.png": "f80cde345f0d9bd0086531808ce5166a",
|
||||||
"assets/packages/intl_phone_field/assets/flags/it.png": "5c8e910e6a33ec63dfcda6e8960dd19c",
|
"assets/packages/intl_phone_field/assets/flags/um.png": "8fe7c4fed0a065fdfb9bd3125c6ecaa1",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ru.png": "6974dcb42ad7eb3add1009ea0c6003e3",
|
"assets/packages/intl_phone_field/assets/flags/je.png": "288f8dca26098e83ff0455b08cceca1b",
|
||||||
"assets/packages/intl_phone_field/assets/flags/dj.png": "078bd37d41f746c3cb2d84c1e9611c55",
|
"assets/packages/intl_phone_field/assets/flags/th.png": "11ce0c9f8c738fd217ea52b9bc29014b",
|
||||||
"assets/packages/intl_phone_field/assets/flags/mt.png": "f3119401ae0c3a9d6e2dc23803928c06",
|
"assets/packages/intl_phone_field/assets/flags/gb-sct.png": "75106a5e49e3e16da76cb33bdac102ab",
|
||||||
"assets/packages/intl_phone_field/assets/flags/id.png": "80bb82d11d5bc144a21042e77972bca9",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/in.png": "1dec13ba525529cffd4c7f8a35d51121",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gp.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ch.png": "a251702f7760b0aac141428ed60b7b66",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sk.png": "2a1ee716d4b41c017ff1dbf3fd3ffc64",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sc.png": "e969fd5afb1eb5902675b6bcf49a8c2e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/cd.png": "5b5f832ed6cd9f9240cb31229d8763dc",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mc.png": "90c2ad7f144d73d4650cbea9dd621275",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ve.png": "893391d65cbd10ca787a73578c77d3a7",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/bj.png": "6fdc6449f73d23ad3f07060f92db4423",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/hm.png": "72be14316f0af3903cdca7a726c0c589",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/vi.png": "3f317c56f31971b3179abd4e03847036",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/nu.png": "f4169998548e312584c67873e0d9352d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/pm.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/ie.png": "1d91912afc591dd120b47b56ea78cdbf",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/mw.png": "ffc1f18eeedc1dfbb1080aa985ce7d05",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/sv.png": "217b691efbef7a0f48cdd53e91997f0e",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/gi.png": "446aa44aaa063d240adab88243b460d3",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/fj.png": "1c6a86752578eb132390febf12789cd6",
|
"assets/packages/intl_phone_field/assets/flags/fj.png": "1c6a86752578eb132390febf12789cd6",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ga.png": "b0e5b2fa1b7106c7652a955db24c11c4",
|
"assets/packages/intl_phone_field/assets/flags/sh.png": "98773db151c150cabe845183241bfe6b",
|
||||||
"assets/packages/intl_phone_field/assets/flags/mn.png": "16086e8d89c9067d29fd0f2ea7021a45",
|
"assets/packages/intl_phone_field/assets/flags/bf.png": "63f1c67fca7ce8b52b3418a90af6ad37",
|
||||||
"assets/packages/intl_phone_field/assets/flags/cz.png": "73ecd64c6144786c4d03729b1dd9b1f3",
|
"assets/packages/intl_phone_field/assets/flags/pg.png": "0f7e03465a93e0b4e3e1c9d3dd5814a4",
|
||||||
"assets/packages/intl_phone_field/assets/flags/eh.png": "515a9cf2620c802e305b5412ac81aed2",
|
"assets/packages/intl_phone_field/assets/flags/ir.png": "37f67c3141e9843196cb94815be7bd37",
|
||||||
"assets/packages/intl_phone_field/assets/flags/al.png": "722cf9e5c7a1d9c9e4608fb44dbb427d",
|
"assets/packages/intl_phone_field/assets/flags/gl.png": "b79e24ee1889b7446ba3d65564b86810",
|
||||||
"assets/packages/intl_phone_field/assets/flags/tv.png": "c57025ed7ae482210f29b9da86b0d211",
|
"assets/packages/intl_phone_field/assets/flags/pt.png": "eba93d33545c78cc67915d9be8323661",
|
||||||
"assets/packages/intl_phone_field/assets/flags/tt.png": "a8e1fc5c65dc8bc362a9453fadf9c4b3",
|
"assets/packages/intl_phone_field/assets/flags/ki.png": "14db0fc29398730064503907bd696176",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cl.png": "6735e0e2d88c119e9ed1533be5249ef1",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/vi.png": "3f317c56f31971b3179abd4e03847036",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/si.png": "24237e53b34752554915e71e346bb405",
|
||||||
"assets/packages/intl_phone_field/assets/flags/km.png": "5554c8746c16d4f482986fb78ffd9b36",
|
"assets/packages/intl_phone_field/assets/flags/km.png": "5554c8746c16d4f482986fb78ffd9b36",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/np.png": "6e099fb1e063930bdd00e8df5cef73d4",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pe.png": "4d9249aab70a26fadabb14380b3b55d2",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cg.png": "eca97338cc1cb5b5e91bec72af57b3d4",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ug.png": "9a0f358b1eb19863e21ae2063fab51c0",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/my.png": "f7f962e8a074387fd568c9d4024e0959",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cv.png": "9b1f31f9fc0795d728328dedd33eb1c0",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cw.png": "6c598eb0d331d6b238da57055ec00d33",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/vg.png": "fc095e11f5b58604d6f4d3c2b43d167f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sg.png": "bc772e50b8c79f08f3c2189f5d8ce491",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sv.png": "217b691efbef7a0f48cdd53e91997f0e",
|
||||||
"assets/packages/intl_phone_field/assets/flags/cu.png": "f41715bd51f63a9aebf543788543b4c4",
|
"assets/packages/intl_phone_field/assets/flags/cu.png": "f41715bd51f63a9aebf543788543b4c4",
|
||||||
"assets/packages/intl_phone_field/assets/flags/us.png": "83b065848d14d33c0d10a13e01862f34",
|
"assets/packages/intl_phone_field/assets/flags/gy.png": "159a260bf0217128ea7475ba5b272b6a",
|
||||||
"assets/packages/intl_phone_field/assets/flags/cn.png": "040539c2cdb60ebd9dc8957cdc6a8ad0",
|
"assets/packages/intl_phone_field/assets/flags/im.png": "7c9ccb825f0fca557d795c4330cf4f50",
|
||||||
"assets/packages/intl_phone_field/assets/flags/sx.png": "9c19254973d8acf81581ad95b408c7e6",
|
"assets/packages/intl_phone_field/assets/flags/za.png": "b28280c6c3eb4624c18b5455d4a1b1ff",
|
||||||
"assets/packages/intl_phone_field/assets/flags/na.png": "cdc00e9267a873609b0abea944939ff7",
|
"assets/packages/intl_phone_field/assets/flags/ky.png": "38e39eba673e82c48a1f25bd103a7e97",
|
||||||
"assets/packages/intl_phone_field/assets/flags/iq.png": "bc3e6f68c5188dbf99b473e2bea066f2",
|
"assets/packages/intl_phone_field/assets/flags/by.png": "beabf61e94fb3a4f7c7a7890488b213d",
|
||||||
"assets/packages/intl_phone_field/assets/flags/pr.png": "b97b2f4432c430bc340d893f36527e31",
|
"assets/packages/intl_phone_field/assets/flags/no.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
||||||
"assets/packages/intl_phone_field/assets/flags/la.png": "e8cd9c3ee6e134adcbe3e986e1974e4a",
|
"assets/packages/intl_phone_field/assets/flags/cz.png": "73ecd64c6144786c4d03729b1dd9b1f3",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mv.png": "d9245f74e34d5c054413ace4b86b4f16",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tk.png": "60428ff1cdbae680e5a0b8cde4677dd5",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/al.png": "722cf9e5c7a1d9c9e4608fb44dbb427d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/va.png": "c010bf145f695d5c8fb551bafc081f77",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/py.png": "154d4add03b4878caf00bd3249e14f40",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/as.png": "d9c1da515c6f945c2e2554592a9dfaae",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/hu.png": "281582a753e643b46bdd894047db08bb",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sc.png": "e969fd5afb1eb5902675b6bcf49a8c2e",
|
||||||
"assets/packages/intl_phone_field/assets/flags/pn.png": "0b0641b356af4c3e3489192ff4b0be77",
|
"assets/packages/intl_phone_field/assets/flags/pn.png": "0b0641b356af4c3e3489192ff4b0be77",
|
||||||
"assets/packages/intl_phone_field/assets/flags/st.png": "fef62c31713ff1063da2564df3f43eea",
|
"assets/packages/intl_phone_field/assets/flags/st.png": "fef62c31713ff1063da2564df3f43eea",
|
||||||
"assets/packages/intl_phone_field/assets/flags/im.png": "7c9ccb825f0fca557d795c4330cf4f50",
|
"assets/packages/intl_phone_field/assets/flags/ye.png": "4cf73209d90e9f02ead1565c8fdf59e5",
|
||||||
"assets/packages/intl_phone_field/assets/flags/tw.png": "b1101fd5f871a9ffe7c9ad191a7d3304",
|
"assets/packages/intl_phone_field/assets/flags/hr.png": "69711b2ea009a3e7c40045b538768d4e",
|
||||||
"assets/packages/intl_phone_field/assets/flags/nr.png": "1316f3a8a419d8be1975912c712535ea",
|
"assets/packages/intl_phone_field/assets/flags/az.png": "6ffa766f6883d2d3d350cdc22a062ca3",
|
||||||
"assets/packages/intl_phone_field/assets/flags/pf.png": "1ae72c24380d087cbe2d0cd6c3b58821",
|
"assets/packages/intl_phone_field/assets/flags/gd.png": "7a4864ccfa2a0564041c2d1f8a13a8c9",
|
||||||
"assets/packages/intl_phone_field/assets/flags/er.png": "8ca78e10878a2e97c1371b38c5d258a7",
|
"assets/packages/intl_phone_field/assets/flags/tt.png": "a8e1fc5c65dc8bc362a9453fadf9c4b3",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ki.png": "14db0fc29398730064503907bd696176",
|
"assets/packages/intl_phone_field/assets/flags/ss.png": "b0120cb000b31bb1a5c801c3592139bc",
|
||||||
"assets/packages/intl_phone_field/assets/flags/re.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
"assets/packages/intl_phone_field/assets/flags/mw.png": "ffc1f18eeedc1dfbb1080aa985ce7d05",
|
||||||
"assets/packages/intl_phone_field/assets/flags/jm.png": "074400103847c56c37425a73f9d23665",
|
"assets/packages/intl_phone_field/assets/flags/sy.png": "24186a0f4ce804a16c91592db5a16a3a",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ag.png": "41c11d5668c93ba6e452f811defdbb24",
|
"assets/packages/intl_phone_field/assets/flags/tr.png": "27feab1a5ca390610d07e0c6bd4720d5",
|
||||||
"assets/packages/intl_phone_field/assets/flags/fi.png": "3ccd69a842e55183415b7ea2c04b15c8",
|
"assets/packages/intl_phone_field/assets/flags/mn.png": "16086e8d89c9067d29fd0f2ea7021a45",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cm.png": "42d52fa71e8b4dbb182ff431749e8d0d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/li.png": "ecdf7b3fe932378b110851674335d9ab",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gt.png": "706a0c3b5e0b589c843e2539e813839e",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gg.png": "eed435d25bd755aa7f9cd7004b9ed49d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bo.png": "3ccf6fa7f9cbc27949b8418925e4e89c",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ca.png": "76f2fac1d3b2cc52ba6695c2e2941632",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ch.png": "a251702f7760b0aac141428ed60b7b66",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bb.png": "a8473747387e4e7a8450c499529f1c93",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/dj.png": "078bd37d41f746c3cb2d84c1e9611c55",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/me.png": "590284bc85810635ace30a173e615ca4",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sl.png": "61b9d992c8a6a83abc4d432069617811",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mq.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gp.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sa.png": "7c95c1a877148e2aa21a213d720ff4fd",
|
||||||
"assets/packages/intl_phone_field/assets/flags/td.png": "009303b6188ca0e30bd50074b16f0b16",
|
"assets/packages/intl_phone_field/assets/flags/td.png": "009303b6188ca0e30bd50074b16f0b16",
|
||||||
"assets/packages/intl_phone_field/assets/flags/so.png": "1ce20d052f9d057250be96f42647513b",
|
"assets/packages/intl_phone_field/assets/flags/kg.png": "c4aa6d221d9a9d332155518d6b82dbc7",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ge.png": "6fbd41f07921fa415347ebf6dff5b0f7",
|
"assets/packages/intl_phone_field/assets/flags/do.png": "ed35983a9263bb5713be37d9a52caddc",
|
||||||
"assets/packages/intl_phone_field/assets/flags/bl.png": "dae94f5465d3390fdc5929e4f74d3f5f",
|
"assets/packages/intl_phone_field/assets/flags/dk.png": "abcd01bdbcc02b4a29cbac237f29cd1d",
|
||||||
"assets/packages/intl_phone_field/assets/flags/co.png": "e3b1be16dcdae6cb72e9c238fdddce3c",
|
"assets/packages/intl_phone_field/assets/flags/bn.png": "ed650de06fff61ff27ec92a872197948",
|
||||||
"assets/packages/intl_phone_field/assets/flags/yt.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
"assets/packages/intl_phone_field/assets/flags/aq.png": "0c586e7b91aa192758fdd0f03adb84d8",
|
||||||
"assets/packages/intl_phone_field/assets/flags/af.png": "ba710b50a060b5351381b55366396c30",
|
"assets/packages/intl_phone_field/assets/flags/mx.png": "84b12a569b209e213daccfcbdd1fc799",
|
||||||
"assets/packages/intl_phone_field/assets/flags/gn.png": "b2287c03c88a72d968aa796a076ba056",
|
"assets/packages/intl_phone_field/assets/flags/gn.png": "b2287c03c88a72d968aa796a076ba056",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ni.png": "e398dc23e79d9ccd702546cc25f126bf",
|
"assets/packages/intl_phone_field/assets/flags/ma.png": "057ea2e08587f1361b3547556adae0c2",
|
||||||
"assets/packages/intl_phone_field/assets/flags/no.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
"assets/packages/intl_phone_field/assets/flags/mm.png": "32e5293d6029d8294c7dfc3c3835c222",
|
||||||
"assets/packages/intl_phone_field/assets/flags/sm.png": "a8d6801cb7c5360e18f0a2ed146b396d",
|
"assets/packages/intl_phone_field/assets/flags/kh.png": "d48d51e8769a26930da6edfc15de97fe",
|
||||||
"assets/packages/intl_phone_field/assets/flags/ee.png": "e242645cae28bd5291116ea211f9a566",
|
"assets/packages/intl_phone_field/assets/flags/ly.png": "8d65057351859065d64b4c118ff9e30e",
|
||||||
"assets/packages/intl_phone_field/assets/flags/rs.png": "9dff535d2d08c504be63062f39eff0b7",
|
"assets/packages/intl_phone_field/assets/flags/pk.png": "7a6a621f7062589677b3296ca16c6718",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sj.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cr.png": "bfd8b41e63fc3cc829c72c4b2e170532",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ke.png": "cf5aae3699d3cacb39db9803edae172b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/na.png": "cdc00e9267a873609b0abea944939ff7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/lv.png": "53105fea0cc9cc554e0ceaabc53a2d5d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/zw.png": "078a3267ea8eabf88b2d43fe4aed5ce5",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bv.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/vn.png": "32ff65ccbf31a707a195be2a5141a89b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/hn.png": "9ecf68aed83c4a9b3f1e6275d96bfb04",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/uy.png": "da4247b21fcbd9e30dc2b3f7c5dccb64",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ie.png": "1d91912afc591dd120b47b56ea78cdbf",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/in.png": "1dec13ba525529cffd4c7f8a35d51121",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tm.png": "0980fb40ec450f70896f2c588510f933",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/qa.png": "eb9b3388e554cf85aea1e739247548df",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ag.png": "41c11d5668c93ba6e452f811defdbb24",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/se.png": "25dd5434891ac1ca2ad1af59cda70f80",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/io.png": "83d45bbbff087d47b2b39f1c20598f52",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gi.png": "446aa44aaa063d240adab88243b460d3",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pl.png": "f20e9ef473a9ed24176f5ad74dd0d50a",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cy.png": "7b36f4af86257a3f15f5a5a16f4a2fcd",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/lc.png": "8c1a03a592aa0a99fcaf2b81508a87eb",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pr.png": "b97b2f4432c430bc340d893f36527e31",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gr.png": "ec11281d7decbf07b81a23a72a609b59",
|
||||||
"assets/packages/intl_phone_field/assets/flags/dz.png": "132ceca353a95c8214676b2e94ecd40f",
|
"assets/packages/intl_phone_field/assets/flags/dz.png": "132ceca353a95c8214676b2e94ecd40f",
|
||||||
"assets/packages/intl_phone_field/assets/flags/by.png": "beabf61e94fb3a4f7c7a7890488b213d",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/lr.png": "b92c75e18dd97349c75d6a43bd17ee94",
|
|
||||||
"assets/packages/intl_phone_field/assets/flags/to.png": "1cdd716b5b5502f85d6161dac6ee6c5b",
|
"assets/packages/intl_phone_field/assets/flags/to.png": "1cdd716b5b5502f85d6161dac6ee6c5b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ve.png": "893391d65cbd10ca787a73578c77d3a7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tj.png": "c73b793f2acd262e71b9236e64c77636",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/la.png": "e8cd9c3ee6e134adcbe3e986e1974e4a",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/am.png": "aaa39141fbc80205bebaa0200b55a13a",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tg.png": "7f91f02b26b74899ff882868bd611714",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/aw.png": "a93ddf8e32d246dc47f6631f38e0ed92",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/md.png": "8911d3d821b95b00abbba8771e997eb3",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/et.png": "57edff61c7fddf2761a19948acef1498",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bt.png": "3cfe1440e952bc7266d71f7f1454fa23",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tv.png": "c57025ed7ae482210f29b9da86b0d211",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ax.png": "ec2062c36f09ed8fb90ac8992d010024",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tn.png": "6612e9fec4bef022cbd45cbb7c02b2b6",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sx.png": "9c19254973d8acf81581ad95b408c7e6",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gb-eng.png": "0d9f2a6775fd52b79e1d78eb1dda10cf",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ee.png": "e242645cae28bd5291116ea211f9a566",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ls.png": "2bca756f9313957347404557acb532b0",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/is.png": "907840430252c431518005b562707831",
|
||||||
"assets/packages/intl_phone_field/assets/flags/kr.png": "a3b7da3b76b20a70e9cd63cc2315b51b",
|
"assets/packages/intl_phone_field/assets/flags/kr.png": "a3b7da3b76b20a70e9cd63cc2315b51b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/yt.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ba.png": "d415bad33b35de3f095177e8e86cbc82",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tc.png": "d728d6763c17c520ad6bcf3c24282a29",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sr.png": "9f912879f2829a625436ccd15e643e39",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ae.png": "792efc5eb6c31d780bd34bf4bad69f3f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mz.png": "1ab1ac750fbbb453d33e9f25850ac2a0",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bh.png": "a1acd86ef0e19ea5f0297bbe1de6cfd4",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mo.png": "849848a26bbfc87024017418ad7a6233",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ni.png": "e398dc23e79d9ccd702546cc25f126bf",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/au.png": "72be14316f0af3903cdca7a726c0c589",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gs.png": "419dd57836797a3f1bf6258ea6589f9a",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/lr.png": "b92c75e18dd97349c75d6a43bd17ee94",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ps.png": "52a25a48658ca9274830ffa124a8c1db",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bg.png": "1d24bc616e3389684ed2c9f18bcb0209",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gw.png": "05606b9a6393971bd87718b809e054f9",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/jm.png": "074400103847c56c37425a73f9d23665",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bw.png": "fac8b90d7404728c08686dc39bab4fb3",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pa.png": "78e3e4fd56f0064837098fe3f22fb41b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/id.png": "80bb82d11d5bc144a21042e77972bca9",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/re.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/vc.png": "da3ca14a978717467abbcdece05d3544",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/xk.png": "079259fbcb1f3c78dafa944464295c16",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tz.png": "56ec99c7e0f68b88a2210620d873683a",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/lu.png": "6274fd1cae3c7a425d25e4ccb0941bb8",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tf.png": "b2c044b86509e7960b5ba66b094ea285",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ws.png": "f206322f3e22f175869869dbfadb6ce8",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/nu.png": "f4169998548e312584c67873e0d9352d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ms.png": "9c955a926cf7d57fccb450a97192afa7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mu.png": "c5228d1e94501d846b5bf203f038ae49",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ga.png": "b0e5b2fa1b7106c7652a955db24c11c4",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mc.png": "90c2ad7f144d73d4650cbea9dd621275",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/il.png": "1e06ad7783f24332405d36561024cc4c",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/fo.png": "2c7d9233582e83a86927e634897a2a90",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/jo.png": "c01cb41f74f9db0cf07ba20f0af83011",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/fr.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/nl.png": "3649c177693bfee9c2fcc63c191a51f1",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sk.png": "2a1ee716d4b41c017ff1dbf3fd3ffc64",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/jp.png": "25ac778acd990bedcfdc02a9b4570045",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/be.png": "7e5e1831cdd91935b38415479a7110eb",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tl.png": "c80876dc80cda5ab6bb8ef078bc6b05d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/es.png": "654965f9722f6706586476fb2f5d30dd",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/nc.png": "cb36e0c945b79d56def11b23c6a9c7e9",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/dm.png": "8886b222ed9ccd00f67e8bcf86dadcc2",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/rw.png": "d1aae0647a5b1ab977ae43ab894ce2c3",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gb-nir.png": "98773db151c150cabe845183241bfe6b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/lk.png": "5a3a063cfff4a92fb0ba6158e610e025",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mt.png": "f3119401ae0c3a9d6e2dc23803928c06",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mr.png": "f2a62602d43a1ee14625af165b96ce2f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sd.png": "65ce270762dfc87475ea99bd18f79025",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/kp.png": "e1c8bb52f31fca22d3368d8f492d8f27",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bs.png": "2b9540c4fa514f71911a48de0bd77e71",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cn.png": "040539c2cdb60ebd9dc8957cdc6a8ad0",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/wf.png": "6f1644b8f907d197c0ff7ed2f366ad64",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sm.png": "a8d6801cb7c5360e18f0a2ed146b396d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/co.png": "e3b1be16dcdae6cb72e9c238fdddce3c",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/br.png": "5093e0cd8fd3c094664cd17ea8a36fd1",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/iq.png": "bc3e6f68c5188dbf99b473e2bea066f2",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/rs.png": "9dff535d2d08c504be63062f39eff0b7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/nr.png": "1316f3a8a419d8be1975912c712535ea",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sb.png": "296ecedbd8d1c2a6422c3ba8e5cd54bd",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gq.png": "4286e56f388a37f64b21eb56550c06d9",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bi.png": "adda8121501f0543f1075244a1acc275",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bl.png": "dae94f5465d3390fdc5929e4f74d3f5f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/an.png": "4e4b90fbca1275d1839ca5b44fc51071",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mh.png": "18dda388ef5c1cf37cae5e7d5fef39bc",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ci.png": "7f5ca3779d5ff6ce0c803a6efa0d2da7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ar.png": "3bd245f8c28f70c9ef9626dae27adc65",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/us.png": "83b065848d14d33c0d10a13e01862f34",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ro.png": "85af99741fe20664d9a7112cfd8d9722",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/nz.png": "65c811e96eb6c9da65538f899c110895",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ph.png": "e4025d1395a8455f1ba038597a95228c",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/at.png": "570c070177a5ea0fe03e20107ebf5283",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bq.png": "3649c177693bfee9c2fcc63c191a51f1",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/fi.png": "3ccd69a842e55183415b7ea2c04b15c8",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/nf.png": "1c2069b299ce3660a2a95ec574dfde25",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pf.png": "1ae72c24380d087cbe2d0cd6c3b58821",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bz.png": "fd2d7d27a5ddabe4eb9a10b1d3a433e4",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ad.png": "384e9845debe9aca8f8586d9bedcb7e6",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ua.png": "b4b10d893611470661b079cb30473871",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mg.png": "0ef6271ad284ebc0069ff0aeb5a3ad1e",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pm.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ht.png": "630f7f8567d87409a32955107ad11a86",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/kn.png": "f318e2fd87e5fd2cabefe9ff252bba46",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ng.png": "aedbe364bd1543832e88e64b5817e877",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ne.png": "a20724c177e86d6a27143aa9c9664a6f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/zm.png": "81cec35b715f227328cad8f314acd797",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cx.png": "8efa3231c8a3900a78f2b51d829f8c52",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/hk.png": "4b5ec424348c98ec71a46ad3dce3931d",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/fm.png": "d571b8bc4b80980a81a5edbde788b6d2",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bj.png": "6fdc6449f73d23ad3f07060f92db4423",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/hm.png": "72be14316f0af3903cdca7a726c0c589",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/pw.png": "2e697cc6907a7b94c7f94f5d9b3bdccc",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mk.png": "835f2263974de523fa779d29c90595bf",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cd.png": "5b5f832ed6cd9f9240cb31229d8763dc",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cc.png": "31a475216e12fef447382c97b42876ce",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/eu.png": "c58ece3931acb87faadc5b940d4f7755",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ru.png": "6974dcb42ad7eb3add1009ea0c6003e3",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/eh.png": "515a9cf2620c802e305b5412ac81aed2",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/it.png": "5c8e910e6a33ec63dfcda6e8960dd19c",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/sn.png": "68eaa89bbc83b3f356e1ba2096b09b3c",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ck.png": "39f343868a8dc8ca95d27b27a5caf480",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bm.png": "b366ba84cbc8286c830f392bb9086be5",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ge.png": "6fbd41f07921fa415347ebf6dff5b0f7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/kw.png": "3ca448e219d0df506fb2efd5b91be092",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/bd.png": "86a0e4bd8787dc8542137a407e0f987f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ec.png": "c1ae60d080be91f3be31e92e0a2d9555",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gm.png": "7148d3715527544c2e7d8d6f4a445bb6",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gb.png": "98773db151c150cabe845183241bfe6b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/eg.png": "311d780e8e3dd43f87e6070f6feb74c7",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gu.png": "2acb614b442e55864411b6e418df6eab",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/kz.png": "cb3b0095281c9d7e7fb5ce1716ef8ee5",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/gh.png": "b35464dca793fa33e51bf890b5f3d92b",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/mp.png": "87351c30a529071ee9a4bb67765fea4f",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/fk.png": "da8b0fe48829aae2c8feb4839895de63",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/ai.png": "ce5e91ed1725f0499b9231b69a7fd448",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/lt.png": "7df2cd6566725685f7feb2051f916a3e",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/tw.png": "b1101fd5f871a9ffe7c9ad191a7d3304",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/cf.png": "263583ffdf7a888ce4fba8487d1da0b2",
|
||||||
|
"assets/packages/intl_phone_field/assets/flags/af.png": "ba710b50a060b5351381b55366396c30",
|
||||||
|
"assets/packages/window_manager/images/ic_chrome_minimize.png": "4282cd84cb36edf2efb950ad9269ca62",
|
||||||
"assets/packages/window_manager/images/ic_chrome_maximize.png": "af7499d7657c8b69d23b85156b60298c",
|
"assets/packages/window_manager/images/ic_chrome_maximize.png": "af7499d7657c8b69d23b85156b60298c",
|
||||||
"assets/packages/window_manager/images/ic_chrome_unmaximize.png": "4a90c1909cb74e8f0d35794e2f61d8bf",
|
"assets/packages/window_manager/images/ic_chrome_unmaximize.png": "4a90c1909cb74e8f0d35794e2f61d8bf",
|
||||||
"assets/packages/window_manager/images/ic_chrome_minimize.png": "4282cd84cb36edf2efb950ad9269ca62",
|
|
||||||
"assets/packages/window_manager/images/ic_chrome_close.png": "75f4b8ab3608a05461a31fc18d6b47c2",
|
"assets/packages/window_manager/images/ic_chrome_close.png": "75f4b8ab3608a05461a31fc18d6b47c2",
|
||||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "b62641afc9ab487008e996a5c5865e56",
|
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
|
||||||
|
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
|
||||||
|
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
|
||||||
|
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
|
||||||
|
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
|
||||||
|
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
|
||||||
|
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
|
||||||
|
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
|
||||||
|
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
||||||
|
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
|
||||||
|
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
||||||
|
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
||||||
|
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
|
||||||
|
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
|
||||||
|
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
|
||||||
|
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
|
||||||
|
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
|
||||||
|
"assets/assets/images/logo_dark.png": "a233ed1d4d0f7414bf97a9a10f11fb0a",
|
||||||
|
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
|
||||||
|
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
||||||
|
"assets/NOTICES": "1a34e70168d56fad075adfb4bdbb20eb",
|
||||||
|
"assets/fonts/MaterialIcons-Regular.otf": "95db9098c58fd6db106f1116bae85a0b",
|
||||||
|
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
|
||||||
|
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
|
||||||
"assets/shaders/ink_sparkle.frag": "face5c2f106eecf1dda786745c50b01f",
|
"assets/shaders/ink_sparkle.frag": "face5c2f106eecf1dda786745c50b01f",
|
||||||
|
"flutter.js": "f85e6fb278b0fd20c349186fb46ae36d",
|
||||||
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
|
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||||
|
"canvaskit/profiling/canvaskit.js": "38164e5a72bdad0faa4ce740c9b8e564",
|
||||||
|
"canvaskit/profiling/canvaskit.wasm": "95a45378b69e77af5ed2bc72b2209b94",
|
||||||
|
"canvaskit/canvaskit.js": "2bc454a691c631b07a9307ac4ca47797",
|
||||||
|
"canvaskit/canvaskit.wasm": "bf50631470eb967688cca13ee181af62",
|
||||||
|
"/": "686443a10b66af2e91462a76c539a39a",
|
||||||
|
"version.json": "eaa34b1fc12792d815c0443fbfbc076b",
|
||||||
|
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||||
|
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35"
|
"main.dart.js": "301d099d604c2a0ce586552202f8d3ed"
|
||||||
};
|
};
|
||||||
|
|
||||||
// The application shell files that are downloaded before a service worker can
|
// The application shell files that are downloaded before a service worker can
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user