commit
aa72fe15a8
129 changed files with 362226 additions and 348954 deletions
|
|
@ -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\Util\VersionCheck;
|
||||
use App\Models\Account;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
|
|
@ -223,6 +225,18 @@ class DemoMode extends Command
|
|||
'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');
|
||||
|
||||
for ($x = 0; $x < $this->count; $x++) {
|
||||
|
|
|
|||
|
|
@ -48,46 +48,46 @@ class Kernel extends ConsoleKernel
|
|||
$schedule->job(new VersionCheck)->daily();
|
||||
|
||||
/* Checks and cleans redundant files */
|
||||
$schedule->job(new DiskCleanup)->daily()->withoutOverlapping();
|
||||
$schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping()->name('disk-cleanup-job')->onOneServer();
|
||||
|
||||
/* Send reminders */
|
||||
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping();
|
||||
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping()->name('reminder-job')->onOneServer();
|
||||
|
||||
/* Returns the number of jobs in the queue */
|
||||
$schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping();
|
||||
|
||||
/* Checks for large companies and marked them as is_large */
|
||||
$schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping();
|
||||
$schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
|
||||
|
||||
/* Pulls in the latest exchange rates */
|
||||
$schedule->job(new UpdateExchangeRates)->dailyAt('23:30')->withoutOverlapping();
|
||||
|
||||
/* Runs cleanup code for subscriptions */
|
||||
$schedule->job(new SubscriptionCron)->daily()->withoutOverlapping();
|
||||
$schedule->job(new SubscriptionCron)->dailyAt('00:01')->withoutOverlapping()->name('subscription-job')->onOneServer();
|
||||
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping();
|
||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer();
|
||||
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping();
|
||||
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping()->name('recurring-expense-job')->onOneServer();
|
||||
|
||||
/* Fires notifications for expired Quotes */
|
||||
$schedule->job(new QuoteCheckExpired)->dailyAt('05:00')->withoutOverlapping();
|
||||
$schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping()->name('quote-expired-job')->onOneServer();
|
||||
|
||||
/* Performs auto billing */
|
||||
$schedule->job(new AutoBillCron)->dailyAt('06:00')->withoutOverlapping();
|
||||
$schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping()->name('auto-bill-job')->onOneServer();
|
||||
|
||||
/* Checks the status of the scheduler */
|
||||
$schedule->job(new SchedulerCheck)->daily()->withoutOverlapping();
|
||||
$schedule->job(new SchedulerCheck)->dailyAt('01:10')->withoutOverlapping();
|
||||
|
||||
/* Checks for scheduled tasks */
|
||||
$schedule->job(new TaskScheduler())->daily()->withoutOverlapping();
|
||||
$schedule->job(new TaskScheduler())->dailyAt('06:50')->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
|
||||
|
||||
/* Performs system maintenance such as pruning the backup table */
|
||||
$schedule->job(new SystemMaintenance)->weekly()->withoutOverlapping();
|
||||
$schedule->job(new SystemMaintenance)->sundays()->at('02:30')->withoutOverlapping()->name('system-maintenance-job')->onOneServer();
|
||||
|
||||
/* Pulls in bank transactions from third party services */
|
||||
$schedule->job(new BankTransactionSync)->dailyAt('04:00')->withoutOverlapping();
|
||||
$schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer();
|
||||
|
||||
if (Ninja::isSelfHost()) {
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ class Handler extends ExceptionHandler
|
|||
} elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
|
||||
return response()->json(['message'=>'Fatal error'], 500);
|
||||
} 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) {
|
||||
return redirect()
|
||||
->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;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
|
|
@ -19,6 +20,8 @@ use Illuminate\Database\Eloquent\Builder;
|
|||
*/
|
||||
class TaskFilters extends QueryFilters
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ class AccountTransformer implements AccountTransformerInterface
|
|||
return [
|
||||
'id' => $account->id,
|
||||
'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_number' => property_exists($account, 'accountNumber') ? '**** ' . substr($account?->accountNumber, -7) : '',
|
||||
'provider_account_id' => $account->providerAccountId,
|
||||
|
|
|
|||
|
|
@ -48,8 +48,15 @@ class EpcQrGenerator
|
|||
|
||||
$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'>
|
||||
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
||||
|
||||
|
|
@ -69,7 +76,7 @@ class EpcQrGenerator
|
|||
$this->formatMoney($this->amount),
|
||||
$this->sepa['purpose'],
|
||||
substr($this->invoice->number,0,34),
|
||||
substr($this->invoice->public_notes,0,139),
|
||||
'',
|
||||
''
|
||||
)), "\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -87,10 +87,10 @@ class SwissQrGenerator
|
|||
$qrBill->setUltimateDebtor(
|
||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
||||
substr($this->client->present()->name(), 0 , 70),
|
||||
$this->client->address1 ? substr($this->client->address1, 0 , 70) : '',
|
||||
$this->client->address2 ? substr($this->client->address2, 0 , 16) : '',
|
||||
$this->client->postal_code ? substr($this->client->postal_code, 0, 16) : '',
|
||||
$this->client->city ? substr($this->client->city, 0, 35) : '',
|
||||
$this->client->address1 ? substr($this->client->address1, 0 , 70) : '_',
|
||||
$this->client->address2 ? substr($this->client->address2, 0 , 16) : '_',
|
||||
$this->client->postal_code ? substr($this->client->postal_code, 0, 16) : '_',
|
||||
$this->client->city ? substr($this->client->city, 0, 35) : '_',
|
||||
'CH'
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ class ActivityController extends BaseController
|
|||
'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||
'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());
|
||||
|
|
|
|||
|
|
@ -481,19 +481,32 @@ class BankTransactionController extends BaseController
|
|||
{
|
||||
$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);
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$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) {
|
||||
if (auth()->user()->can('edit', $bank_transaction)) {
|
||||
$this->bank_transaction_repo->{$action}($bank_transaction);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* 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());
|
||||
|
|
|
|||
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.bank_integrations',
|
||||
'company.bank_transactions',
|
||||
'company.bank_transaction_rules',
|
||||
];
|
||||
|
||||
private $mini_load = [
|
||||
|
|
@ -126,6 +127,7 @@ class BaseController extends Controller
|
|||
'company.expense_categories',
|
||||
'company.subscriptions',
|
||||
'company.bank_integrations',
|
||||
'company.bank_transaction_rules',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
|
|
@ -456,6 +458,13 @@ class BaseController extends Controller
|
|||
$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);
|
||||
}
|
||||
},
|
||||
'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.
|
||||
*
|
||||
|
|
@ -56,4 +75,7 @@ class SubscriptionPurchaseController extends Controller
|
|||
App::setLocale($record->locale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ class CompanyController extends BaseController
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
|||
use App\Http\Requests\Invoice\UpdateInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\UpdateReminderRequest;
|
||||
use App\Http\Requests\Invoice\UploadInvoiceRequest;
|
||||
use App\Jobs\Cron\AutoBill;
|
||||
use App\Jobs\Entity\EmailEntity;
|
||||
use App\Jobs\Invoice\BulkInvoiceJob;
|
||||
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 */
|
||||
switch ($action) {
|
||||
case 'auto_bill':
|
||||
AutoBill::dispatch($invoice->id, $invoice->company->db);
|
||||
return $this->itemResponse($invoice);
|
||||
|
||||
case 'clone_to_invoice':
|
||||
$invoice = CloneInvoiceFactory::create($invoice, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
break;
|
||||
|
||||
case 'clone_to_quote':
|
||||
$quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id);
|
||||
|
||||
|
|
@ -767,7 +771,7 @@ class InvoiceController extends BaseController
|
|||
}
|
||||
break;
|
||||
case 'cancel':
|
||||
$invoice = $invoice->service()->handleCancellation()->deletePdf()->touchPdf()->save();
|
||||
$invoice = $invoice->service()->handleCancellation()->touchPdf()->save();
|
||||
|
||||
if (! $bulk) {
|
||||
$this->itemResponse($invoice);
|
||||
|
|
@ -777,7 +781,7 @@ class InvoiceController extends BaseController
|
|||
case 'email':
|
||||
//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'));
|
||||
} else {
|
||||
$this->reminder_template = $invoice->calculateTemplate('invoice');
|
||||
|
|
|
|||
|
|
@ -181,7 +181,10 @@ class MigrationController extends BaseController
|
|||
$company->tasks()->forceDelete();
|
||||
$company->vendors()->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();
|
||||
|
||||
$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="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="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="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"),
|
||||
|
|
|
|||
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();
|
||||
}
|
||||
|
||||
//magic links survive for 1 hour
|
||||
if ($request->segment(2) && $request->segment(2) == 'magic_link' && $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')) {
|
||||
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)) {
|
||||
$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)) {
|
||||
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)) {
|
||||
$client_contact->email = Str::random(6).'@example.com';
|
||||
$client_contact->save();
|
||||
|
|
@ -125,7 +134,11 @@ class ContactKeyLogin
|
|||
return redirect($this->setRedirectPath());
|
||||
}
|
||||
} 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)) {
|
||||
$client_contact->email = Str::random(6).'@example.com';
|
||||
$client_contact->save();
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class StoreBankTransactionRequest extends Request
|
|||
{
|
||||
$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']);
|
||||
|
||||
$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();
|
||||
|
||||
if(!isset($input['name']))
|
||||
$input['name'] = 'Untitled Company';
|
||||
|
||||
if (array_key_exists('google_analytics_url', $input)) {
|
||||
$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)) {
|
||||
$input['portal_domain'] = strtolower($input['portal_domain']);
|
||||
$input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/");
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
|
|
|
|||
|
|
@ -74,9 +74,9 @@ class UpdateCompanyRequest extends Request
|
|||
|
||||
$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'] = strtolower($input['portal_domain']);
|
||||
$input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/");
|
||||
}
|
||||
|
||||
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()) {
|
||||
return $settings;
|
||||
}
|
||||
|
|
@ -124,10 +126,12 @@ class UpdateCompanyRequest extends Request
|
|||
}
|
||||
|
||||
private function addScheme($url, $scheme = 'https://')
|
||||
{
|
||||
if(Ninja::isHosted())
|
||||
{
|
||||
$url = str_replace('http://', '', $url);
|
||||
|
||||
$url = parse_url($url, PHP_URL_SCHEME) === null ? $scheme.$url : $url;
|
||||
}
|
||||
|
||||
return rtrim($url, '/');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
namespace App\Http\Requests\Report;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class GenericReportRequest extends Request
|
||||
{
|
||||
|
|
@ -27,11 +28,12 @@ class GenericReportRequest extends Request
|
|||
|
||||
public function rules()
|
||||
{
|
||||
nlog($this->date_range);
|
||||
|
||||
return [
|
||||
'start_date' => 'string|date',
|
||||
'end_date' => 'string|date',
|
||||
'date_key' => 'string',
|
||||
'date_range' => 'sometimes|string',
|
||||
'date_range' => 'bail|required|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',
|
||||
'send_email' => 'required|bool',
|
||||
];
|
||||
|
|
@ -53,6 +55,12 @@ class GenericReportRequest extends Request
|
|||
$input['send_email'] = true;
|
||||
}
|
||||
|
||||
if (array_key_exists('date_range', $input) && $input['date_range'] != 'custom') {
|
||||
$input['start_date'] = null;
|
||||
$input['end_date'] = null;
|
||||
}
|
||||
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ class ProfitLossRequest extends Request
|
|||
public function rules()
|
||||
{
|
||||
return [
|
||||
'start_date' => 'string|date',
|
||||
'end_date' => 'string|date',
|
||||
'start_date' => 'required_if:date_range,custom|string|date',
|
||||
'end_date' => 'required_if:date_range,custom|string|date',
|
||||
'is_income_billed' => 'required|bail|bool',
|
||||
'is_expense_billed' => 'bool',
|
||||
'include_tax' => 'required|bail|bool',
|
||||
|
|
|
|||
|
|
@ -125,6 +125,10 @@ class Request extends FormRequest
|
|||
$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'])) {
|
||||
foreach ($input['client_contacts'] as $key => $contact) {
|
||||
if (! array_key_exists('send_email', $contact) || ! array_key_exists('id', $contact)) {
|
||||
|
|
|
|||
|
|
@ -35,26 +35,34 @@ class StoreSubscriptionRequest extends Request
|
|||
public function 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)],
|
||||
'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);
|
||||
|
|
|
|||
|
|
@ -37,26 +37,34 @@ class UpdateSubscriptionRequest extends Request
|
|||
public function 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' => ['sometimes', Rule::unique('subscriptions')->where('company_id', auth()->user()->company()->id)->ignore($this->subscription->id)],
|
||||
'name' => ['bail','sometimes', Rule::unique('subscriptions')->where('company_id', auth()->user()->company()->id)->ignore($this->subscription->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);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use App\Http\Requests\Request;
|
|||
use App\Models\Project;
|
||||
use App\Utils\Traits\ChecksEntityStatus;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateTaskRequest extends Request
|
||||
|
|
@ -29,6 +30,10 @@ class UpdateTaskRequest extends Request
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -87,4 +92,11 @@ class UpdateTaskRequest extends Request
|
|||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
|
||||
protected function failedAuthorization()
|
||||
{
|
||||
throw new AuthorizationException(ctrans('texts.task_update_authorization_error'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class ConfirmSmsRequest extends Request
|
|||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class GenerateSmsRequest extends Request
|
|||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class ValidCompanyQuantity implements Rule
|
|||
*/
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
|
||||
if (Ninja::isSelfHost()) {
|
||||
return auth()->user()->company()->account->companies->count() < 10;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ use App\Repositories\PaymentRepository;
|
|||
use App\Repositories\ProductRepository;
|
||||
use App\Repositories\QuoteRepository;
|
||||
use App\Repositories\VendorRepository;
|
||||
use App\Services\Bank\BankMatchingService;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
|
@ -107,6 +108,8 @@ class Csv extends BaseImport implements ImportInterface
|
|||
$bank_transaction_count = $this->ingest($data, $entity_type);
|
||||
$this->entity_count['bank_transactions'] = $bank_transaction_count;
|
||||
|
||||
BankMatchingService::dispatchSync($this->company->id, $this->company->db);
|
||||
|
||||
}
|
||||
|
||||
public function client()
|
||||
|
|
|
|||
|
|
@ -196,13 +196,19 @@ class MatchBankTransactions implements ShouldQueue
|
|||
$expense->payment_date = Carbon::parse($this->bt->date);
|
||||
$expense->transaction_reference = $this->bt->description;
|
||||
$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->should_be_invoiced = $this->company->mark_expenses_invoiceable;
|
||||
$expense->save();
|
||||
|
||||
$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->save();
|
||||
|
||||
|
|
@ -254,6 +260,9 @@ class MatchBankTransactions implements ShouldQueue
|
|||
|
||||
}, 1);
|
||||
|
||||
if(!$this->invoice)
|
||||
return;
|
||||
|
||||
/* Create Payment */
|
||||
$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){
|
||||
|
||||
$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);
|
||||
|
||||
|
|
@ -456,7 +456,6 @@ class CompanyExport implements ShouldQueue
|
|||
|
||||
})->all();
|
||||
|
||||
|
||||
$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']);
|
||||
|
|
@ -466,6 +465,21 @@ class CompanyExport implements ShouldQueue
|
|||
})->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();
|
||||
|
||||
|
|
@ -517,9 +531,6 @@ class CompanyExport implements ShouldQueue
|
|||
|
||||
$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 = new \ZipArchive();
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ use App\Mail\Import\CompanyImportFailure;
|
|||
use App\Mail\Import\ImportCompleted;
|
||||
use App\Models\Activity;
|
||||
use App\Models\Backup;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\ClientGatewayToken;
|
||||
|
|
@ -142,15 +144,16 @@ class CompanyImport implements ShouldQueue
|
|||
'expenses',
|
||||
'tasks',
|
||||
'payments',
|
||||
// 'activities',
|
||||
// 'backups',
|
||||
'company_ledger',
|
||||
'designs',
|
||||
'documents',
|
||||
'webhooks',
|
||||
'system_logs',
|
||||
'purchase_orders',
|
||||
'purchase_order_invitations'
|
||||
'purchase_order_invitations',
|
||||
'bank_integrations',
|
||||
'bank_transactions',
|
||||
'payments',
|
||||
];
|
||||
|
||||
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()
|
||||
{
|
||||
//unset / transforms / object_property / match_key
|
||||
|
|
@ -979,6 +1013,7 @@ class CompanyImport implements ShouldQueue
|
|||
['vendors' => 'vendor_id'],
|
||||
['invoice_invitations' => 'invitation_id'],
|
||||
['company_gateways' => 'company_gateway_id'],
|
||||
['bank_transactions' => 'transaction_id'],
|
||||
],
|
||||
'payments',
|
||||
'number');
|
||||
|
|
@ -1569,6 +1604,28 @@ class CompanyImport implements ShouldQueue
|
|||
$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{
|
||||
$new_obj = $class::withTrashed()->firstOrNew(
|
||||
[$match_key => $obj->{$match_key}, 'company_id' => $this->company->id],
|
||||
|
|
|
|||
|
|
@ -49,10 +49,6 @@ class SystemMaintenance implements ShouldQueue
|
|||
|
||||
nlog('Starting System Maintenance');
|
||||
|
||||
if (Ninja::isHosted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$delete_pdf_days = config('ninja.maintenance.delete_pdfs');
|
||||
|
||||
nlog("Number of days to keep PDFs {$delete_pdf_days}");
|
||||
|
|
|
|||
|
|
@ -50,11 +50,20 @@ class ReminderJob implements ShouldQueue
|
|||
$this->processReminders();
|
||||
} else {
|
||||
//multiDB environment, need to
|
||||
/*
|
||||
foreach (MultiDB::$dbs as $db) {
|
||||
MultiDB::setDB($db);
|
||||
nlog("set db {$db}");
|
||||
$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'));
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
Invoice::query()
|
||||
->where('is_deleted', 0)
|
||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||
|
|
@ -76,17 +87,22 @@ class ReminderJob implements ShouldQueue
|
|||
$query->where('is_disabled', 0);
|
||||
})
|
||||
->with('invitations')->cursor()->each(function ($invoice) {
|
||||
// if ($invoice->refresh() && $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');
|
||||
nlog("reminder template = {$reminder_template}");
|
||||
$invoice->service()->touchReminder($reminder_template)->save();
|
||||
$invoice = $this->calcLateFee($invoice, $reminder_template);
|
||||
|
||||
$invoice->service()->touchPdf();
|
||||
|
||||
//20-04-2022 fixes for endless reminders - generic template naming was wrong
|
||||
$enabled_reminder = 'enable_'.$reminder_template;
|
||||
|
||||
if ($reminder_template == 'endless_reminder') {
|
||||
$enabled_reminder = 'enable_reminder_endless';
|
||||
}
|
||||
|
|
@ -99,7 +115,7 @@ class ReminderJob implements ShouldQueue
|
|||
(Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) {
|
||||
|
||||
$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}");
|
||||
});
|
||||
|
||||
|
|
@ -112,6 +128,7 @@ class ReminderJob implements ShouldQueue
|
|||
$invoice->next_send_date = null;
|
||||
$invoice->save();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -196,28 +213,25 @@ class ReminderJob implements ShouldQueue
|
|||
$invoice->line_items = $invoice_items;
|
||||
|
||||
/**Refresh Invoice values*/
|
||||
$invoice->calc()->getInvoice()->save();
|
||||
$invoice->fresh();
|
||||
$invoice->service()->deletePdf();
|
||||
|
||||
/* Refresh the client here to ensure the balance is fresh */
|
||||
$client = $invoice->client;
|
||||
$client = $client->fresh();
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
// $invoice->service()->deletePdf(); 24-11-2022 no need to delete here because we regenerate later anyway
|
||||
|
||||
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}");
|
||||
|
||||
$transaction = [
|
||||
'invoice' => $invoice->transaction_event(),
|
||||
'payment' => [],
|
||||
'client' => $client->transaction_event(),
|
||||
'credit' => [],
|
||||
'metadata' => ['setLateFee'],
|
||||
];
|
||||
// $transaction = [
|
||||
// 'invoice' => $invoice->transaction_event(),
|
||||
// 'payment' => [],
|
||||
// 'client' => $invoice->client->transaction_event(),
|
||||
// 'credit' => [],
|
||||
// 'metadata' => ['setLateFee'],
|
||||
// ];
|
||||
|
||||
// TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $invoice->company->db);
|
||||
|
||||
$invoice->service()->touchPdf(true);
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,13 +37,14 @@ class VersionCheck implements ShouldQueue
|
|||
{
|
||||
$version_file = trim(@file_get_contents(config('ninja.version_url')));
|
||||
|
||||
nlog("latest version = {$version_file}");
|
||||
|
||||
if (Ninja::isSelfHost() && $version_file) {
|
||||
Account::whereNotNull('id')->update(['latest_version' => $version_file]);
|
||||
}
|
||||
|
||||
if (Ninja::isSelfHost()) {
|
||||
|
||||
nlog("latest version = {$version_file}");
|
||||
|
||||
$account = Account::first();
|
||||
|
||||
if (! $account) {
|
||||
|
|
|
|||
|
|
@ -14,18 +14,13 @@ namespace App\Listeners\Invoice;
|
|||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use stdClass;
|
||||
|
||||
class InvoiceEmailFailedActivity implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $delay = 10;
|
||||
// public $delay = 10;
|
||||
|
||||
protected $activity_repo;
|
||||
|
||||
|
|
|
|||
|
|
@ -292,6 +292,14 @@ class Activity extends StaticModel
|
|||
return $this->belongsTo(Quote::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function subscription()
|
||||
{
|
||||
return $this->belongsTo(Subscription::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Models\Filterable;
|
||||
use App\Models\Invoice;
|
||||
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\Models\BankTransaction;
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Models\Language;
|
||||
use App\Models\Presenters\CompanyPresenter;
|
||||
use App\Models\PurchaseOrder;
|
||||
|
|
@ -123,6 +124,8 @@ class Company extends BaseModel
|
|||
'enabled_expense_tax_rates',
|
||||
'invoice_task_project',
|
||||
'report_include_deleted',
|
||||
'invoice_task_lock',
|
||||
'use_vendor_currency',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
|
|
@ -188,6 +191,11 @@ class Company extends BaseModel
|
|||
return $this->hasMany(BankTransaction::class);
|
||||
}
|
||||
|
||||
public function bank_transaction_rules()
|
||||
{
|
||||
return $this->hasMany(BankTransactionRule::class);
|
||||
}
|
||||
|
||||
public function getCompanyIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
|
|
@ -541,6 +549,23 @@ class Company extends BaseModel
|
|||
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)
|
||||
{
|
||||
return $this->where('id', $this->decodePrimaryKey($value))->firstOrFail();
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ class PurchaseOrder extends BaseModel
|
|||
'partial',
|
||||
'paid_to_date',
|
||||
'vendor_id',
|
||||
'last_viewed'
|
||||
'last_viewed',
|
||||
'currency_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ class Subscription extends BaseModel
|
|||
'price',
|
||||
'name',
|
||||
'currency_id',
|
||||
'registration_required',
|
||||
'optional_product_ids',
|
||||
'optional_recurring_product_ids',
|
||||
'use_inventory_management',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class VendorContact extends Authenticatable implements HasLocalePreference
|
|||
'email',
|
||||
'is_primary',
|
||||
'vendor_id',
|
||||
'send_email',
|
||||
];
|
||||
|
||||
public function avatar()
|
||||
|
|
|
|||
|
|
@ -111,7 +111,10 @@ class PayPal
|
|||
'paymentMethodNonce' => $gateway_response->nonce,
|
||||
]);
|
||||
|
||||
if($payment_method->success)
|
||||
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 {
|
||||
$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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class CreditCard
|
|||
'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method,
|
||||
'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()),
|
||||
'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,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,11 @@ class ImportCustomers
|
|||
$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'];
|
||||
else
|
||||
break;
|
||||
|
||||
} while ($customers->has_more);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,14 +92,38 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||
if($this->payment_completed)
|
||||
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();
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $this->stripe_request['object']['charges']['data'][0]['id'])
|
||||
->where('transaction_reference', $charge['id'])
|
||||
->first();
|
||||
|
||||
//return early
|
||||
|
|
@ -112,55 +136,47 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||
$payment->save();
|
||||
}
|
||||
|
||||
|
||||
$hash = optional($this->stripe_request['object']['charges']['data'][0]['metadata'])['payment_hash'];
|
||||
$hash = isset($charge['metadata']['payment_hash']) ? $charge['metadata']['payment_hash'] : false;
|
||||
|
||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
||||
|
||||
if(!$payment_hash)
|
||||
return;
|
||||
|
||||
nlog("payment intent");
|
||||
nlog($this->stripe_request);
|
||||
$stripe_driver->client = $payment_hash->fee_invoice->client;
|
||||
|
||||
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);
|
||||
$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);
|
||||
$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);
|
||||
$client = $invoice->client;
|
||||
|
||||
$this->updateAchPayment($payment_hash, $client);
|
||||
$this->updateAchPayment($payment_hash, $client, $meta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['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);
|
||||
$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);
|
||||
|
||||
$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_type' => PaymentType::ACH,
|
||||
'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,
|
||||
];
|
||||
|
||||
|
|
@ -205,9 +221,9 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||
|
||||
try {
|
||||
|
||||
$customer = $driver->getCustomer($this->stripe_request['object']['charges']['data'][0]['customer']);
|
||||
$method = $driver->getStripePaymentMethod($this->stripe_request['object']['charges']['data'][0]['payment_method']);
|
||||
$payment_method = $this->stripe_request['object']['charges']['data'][0]['payment_method'];
|
||||
$customer = $driver->getCustomer($meta['customer']);
|
||||
$method = $driver->getStripePaymentMethod($meta['payment_method']);
|
||||
$payment_method = $meta['payment_method'];
|
||||
|
||||
$token_exists = ClientGatewayToken::where([
|
||||
'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);
|
||||
$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);
|
||||
|
||||
$payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
||||
|
|
@ -261,9 +277,9 @@ class PaymentIntentWebhook implements ShouldQueue
|
|||
|
||||
$data = [
|
||||
'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,
|
||||
'transaction_reference' => $this->stripe_request['object']['charges']['data'][0]['id'],
|
||||
'transaction_reference' => $meta['transaction_reference'],
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -116,11 +116,14 @@ class StripePaymentDriver extends BaseDriver
|
|||
throw new StripeConnectFailure('Stripe Connect has not been configured');
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->stripe = new StripeClient(
|
||||
$this->company_gateway->getConfigField('apiKey')
|
||||
);
|
||||
|
||||
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
|
||||
// Stripe::setApiVersion('2022-11-15');
|
||||
|
||||
}
|
||||
|
||||
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\BankIntegration;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
|
|
@ -45,6 +46,7 @@ use App\Models\Webhook;
|
|||
use App\Policies\ActivityPolicy;
|
||||
use App\Policies\BankIntegrationPolicy;
|
||||
use App\Policies\BankTransactionPolicy;
|
||||
use App\Policies\BankTransactionRulePolicy;
|
||||
use App\Policies\ClientPolicy;
|
||||
use App\Policies\CompanyGatewayPolicy;
|
||||
use App\Policies\CompanyPolicy;
|
||||
|
|
@ -86,6 +88,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
Activity::class => ActivityPolicy::class,
|
||||
BankIntegration::class => BankIntegrationPolicy::class,
|
||||
BankTransaction::class => BankTransactionPolicy::class,
|
||||
BankTransactionRule::class => BankTransactionRulePolicy::class,
|
||||
Client::class => ClientPolicy::class,
|
||||
Company::class => CompanyPolicy::class,
|
||||
CompanyToken::class => CompanyTokenPolicy::class,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Jobs\Bank\MatchBankTransactions;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskStatus;
|
||||
|
|
@ -28,17 +29,25 @@ class BankTransactionRepository extends BaseRepository
|
|||
$bank_transaction->bank_integration_id = $data['bank_integration_id'];
|
||||
|
||||
$bank_transaction->fill($data);
|
||||
|
||||
$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;
|
||||
|
||||
use App\Factory\ExpenseCategoryFactory;
|
||||
use App\Factory\ExpenseFactory;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Company;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Models\Invoice;
|
||||
use App\Services\Bank\BankService;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class BankMatchingService implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
private $company_id;
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, GeneratesCounter;
|
||||
|
||||
private Company $company;
|
||||
|
||||
private $db;
|
||||
|
||||
private $invoices;
|
||||
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public function __construct($company_id, $db)
|
||||
{
|
||||
$this->company_id = $company_id;
|
||||
$this->db = $db;
|
||||
}
|
||||
public function __construct(private int $company_id, private string $db){}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
|
@ -48,15 +48,12 @@ class BankMatchingService implements ShouldQueue
|
|||
|
||||
$this->company = Company::find($this->company_id);
|
||||
|
||||
$this->invoices = Invoice::where('company_id', $this->company->id)
|
||||
->whereIn('status_id', [1,2,3])
|
||||
->where('is_deleted', 0)
|
||||
->get();
|
||||
$this->matchTransactions();
|
||||
|
||||
|
||||
$this->match();
|
||||
}
|
||||
|
||||
private function match()
|
||||
private function matchTransactions()
|
||||
{
|
||||
|
||||
BankTransaction::where('company_id', $this->company->id)
|
||||
|
|
@ -64,21 +61,14 @@ class BankMatchingService implements ShouldQueue
|
|||
->cursor()
|
||||
->each(function ($bt){
|
||||
|
||||
$invoice = $this->invoices->first(function ($value, $key) use ($bt){
|
||||
|
||||
return str_contains($bt->description, $value->number);
|
||||
(new BankService($bt))->processRules();
|
||||
|
||||
});
|
||||
|
||||
if($invoice)
|
||||
}
|
||||
|
||||
public function middleware()
|
||||
{
|
||||
$bt->invoice_ids = $invoice->hashed_id;
|
||||
$bt->status_id = BankTransaction::STATUS_MATCHED;
|
||||
$bt->save();
|
||||
return [new WithoutOverlapping($this->company_id)];
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace App\Services\Bank;
|
|||
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Invoice;
|
||||
use App\Services\Bank\ProcessBankRule;
|
||||
use App\Services\Bank\ProcessBankRules;
|
||||
|
||||
class BankService
|
||||
{
|
||||
|
|
@ -40,11 +40,9 @@ class BankService
|
|||
|
||||
}
|
||||
|
||||
public function processRule($rule)
|
||||
public function processRules()
|
||||
{
|
||||
(new ProcessBankRule($this->bank_transaction, $rule))->run();
|
||||
|
||||
return $this;
|
||||
(new ProcessBankRules($this->bank_transaction))->run();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
// $this->client->balance += $amount;
|
||||
|
||||
try {
|
||||
\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->balance += $amount;
|
||||
$this->client->save();
|
||||
|
||||
}, 2);
|
||||
}
|
||||
catch (\Throwable $throwable) {
|
||||
nlog("DB ERROR " . $throwable->getMessage());
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
|
||||
|
|
@ -55,6 +61,12 @@ class ClientService
|
|||
$this->client->save();
|
||||
|
||||
}, 2);
|
||||
}
|
||||
catch (\Throwable $throwable) {
|
||||
nlog("DB ERROR " . $throwable->getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class ApplyPayment
|
|||
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
if ((int) $this->invoice->balance == 0) {
|
||||
$this->invoice->service()->deletePdf();
|
||||
$this->invoice->service()->touchPdf();
|
||||
$this->invoice = $this->invoice->fresh();
|
||||
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 = [
|
||||
'invoice' => $this->invoice->transaction_event(),
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class ApplyPaymentAmount extends AbstractService
|
|||
->updatePaidToDate($payment->amount)
|
||||
->setCalculatedStatus()
|
||||
->applyNumber()
|
||||
->deletePdf()
|
||||
->touchPdf()
|
||||
->save();
|
||||
|
||||
$this->invoice
|
||||
|
|
|
|||
|
|
@ -112,10 +112,12 @@ class InvoiceService
|
|||
* @param Payment $payment The Payment
|
||||
* @param float $payment_amount The Payment amount
|
||||
* @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)
|
||||
{
|
||||
$this->deletePdf();
|
||||
// $this->deletePdf();
|
||||
$this->invoice = $this->markSent()->save();
|
||||
|
||||
$this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run();
|
||||
|
||||
|
|
@ -218,7 +220,6 @@ class InvoiceService
|
|||
public function markDeleted()
|
||||
{
|
||||
$this->removeUnpaidGatewayFees();
|
||||
$this->deletePdf();
|
||||
|
||||
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
||||
|
||||
|
|
@ -378,6 +379,7 @@ class InvoiceService
|
|||
})->toArray();
|
||||
|
||||
$this->invoice = $this->invoice->calc()->getInvoice();
|
||||
$this->invoice->service()->touchPdf();
|
||||
|
||||
/* 24-03-2022 */
|
||||
$new_balance = $this->invoice->balance;
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ class DeletePayment
|
|||
|
||||
$client = $this->payment
|
||||
->client
|
||||
->fresh()
|
||||
->service()
|
||||
->updateBalance($net_deletable)
|
||||
->save();
|
||||
|
|
@ -136,9 +135,8 @@ class DeletePayment
|
|||
});
|
||||
}
|
||||
|
||||
$client = $this->payment->client->fresh();
|
||||
|
||||
$client
|
||||
$this->payment
|
||||
->client
|
||||
->service()
|
||||
->updatePaidToDate(($this->payment->amount - $this->payment->refunded) * -1)
|
||||
->save();
|
||||
|
|
@ -146,7 +144,7 @@ class DeletePayment
|
|||
$transaction = [
|
||||
'invoice' => [],
|
||||
'payment' => [],
|
||||
'client' => $client->transaction_event(),
|
||||
'client' => $this->payment->client->transaction_event(),
|
||||
'credit' => [],
|
||||
'metadata' => [],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -62,12 +62,14 @@ class UpdateInvoicePayment
|
|||
$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 */
|
||||
if($paid_amount > $invoice->partial && $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*/
|
||||
//caution what if we amount paid was less than partial - we wipe it!
|
||||
$invoice->balance -= $paid_amount;
|
||||
|
|
|
|||
|
|
@ -40,12 +40,8 @@ use Symfony\Component\HttpFoundation\Request;
|
|||
|
||||
class TaskSchedulerService
|
||||
{
|
||||
public Scheduler $scheduler;
|
||||
|
||||
public function __construct(Scheduler $scheduler)
|
||||
{
|
||||
$this->scheduler = $scheduler;
|
||||
}
|
||||
public function __construct(public Scheduler $scheduler) {}
|
||||
|
||||
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 ?: '',
|
||||
'expense_id'=> (string) $this->encodePrimaryKey($bank_transaction->expense_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,
|
||||
'created_at' => (int) $bank_transaction->created_at,
|
||||
'updated_at' => (int) $bank_transaction->updated_at,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ use App\Models\TaxRate;
|
|||
use App\Models\User;
|
||||
use App\Models\Webhook;
|
||||
use App\Transformers\BankIntegrationTransformer;
|
||||
use App\Transformers\BankTransactionRuleTransformer;
|
||||
use App\Transformers\BankTransactionTransformer;
|
||||
use App\Transformers\PurchaseOrderTransformer;
|
||||
use App\Transformers\RecurringExpenseTransformer;
|
||||
|
|
@ -104,6 +105,7 @@ class CompanyTransformer extends EntityTransformer
|
|||
'purchase_orders',
|
||||
'bank_integrations',
|
||||
'bank_transactions',
|
||||
'bank_transaction_rules',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -186,6 +188,8 @@ class CompanyTransformer extends EntityTransformer
|
|||
'enabled_expense_tax_rates' => (int) $company->enabled_expense_tax_rates,
|
||||
'invoice_task_project' => (bool) $company->invoice_task_project,
|
||||
'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);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
$transformer = new BankIntegrationTransformer($this->serializer);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ class PurchaseOrderTransformer extends EntityTransformer
|
|||
'paid_to_date' => (float)$purchase_order->paid_to_date,
|
||||
'subscription_id' => $this->encodePrimaryKey($purchase_order->subscription_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,
|
||||
'archived_at' => (int) $subscription->deleted_at,
|
||||
'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),
|
||||
'assigned_user_id' => (string) $this->encodePrimaryKey($task->assigned_user_id),
|
||||
'number' => (string) $task->number ?: '',
|
||||
// 'start_time' => (int) $task->start_time,
|
||||
'description' => (string) $task->description ?: '',
|
||||
'duration' => (int) $task->duration ?: 0,
|
||||
'rate' => (float) $task->rate ?: 0,
|
||||
|
|
|
|||
|
|
@ -134,6 +134,30 @@ class Helpers
|
|||
|
||||
$replacements = [
|
||||
'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(
|
||||
'%s %s',
|
||||
Carbon::createFromDate(now()->month)->translatedFormat('F'),
|
||||
|
|
@ -150,15 +174,15 @@ class Helpers
|
|||
),
|
||||
':WEEK_AHEAD' => \sprintf(
|
||||
'%s %s %s',
|
||||
Carbon::now()->addDays(6)->translatedFormat($entity->date_format()),
|
||||
Carbon::now()->addDays(7)->translatedFormat($entity->date_format()),
|
||||
ctrans('texts.to'),
|
||||
Carbon::now()->addDays(13)->translatedFormat($entity->date_format())
|
||||
),
|
||||
':WEEK' => \sprintf(
|
||||
'%s %s %s',
|
||||
Carbon::now()->subDays(7)->translatedFormat($entity->date_format()),
|
||||
Carbon::now()->translatedFormat($entity->date_format()),
|
||||
ctrans('texts.to'),
|
||||
Carbon::now()->addDays(13)->translatedFormat($entity->date_format())
|
||||
Carbon::now()->addDays(6)->translatedFormat($entity->date_format())
|
||||
),
|
||||
],
|
||||
'raw' => [
|
||||
|
|
|
|||
|
|
@ -95,10 +95,14 @@ class SystemHealth
|
|||
|
||||
if(strlen(config('ninja.currency_converter_api_key')) == 0){
|
||||
|
||||
try{
|
||||
$cs = DB::table('clients')
|
||||
->select('settings->currency_id as id')
|
||||
->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){
|
||||
return !is_null($value->id);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ trait Inviteable
|
|||
);
|
||||
$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'>
|
||||
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
||||
|
|
@ -80,7 +80,7 @@ trait Inviteable
|
|||
if (Ninja::isHosted()) {
|
||||
$domain = $this->company->domain();
|
||||
} 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()));
|
||||
|
|
@ -95,7 +95,7 @@ trait Inviteable
|
|||
if (Ninja::isHosted()) {
|
||||
$domain = $this->company->domain();
|
||||
} 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) {
|
||||
|
|
@ -121,7 +121,7 @@ trait Inviteable
|
|||
if (Ninja::isHosted()) {
|
||||
$domain = $this->company->domain();
|
||||
} 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) {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ return [
|
|||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => '5.5.41',
|
||||
'app_tag' => '5.5.41',
|
||||
'app_version' => '5.5.42',
|
||||
'app_tag' => '5.5.42',
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', ''),
|
||||
|
|
@ -211,4 +211,5 @@ return [
|
|||
'dev_mode' => env("YODLEE_DEV_MODE", 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' => 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' => 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) {
|
||||
|
|
|
|||
|
|
@ -4843,6 +4843,11 @@ $LANG = array(
|
|||
'refresh_accounts' => 'Refresh Accounts',
|
||||
'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',
|
||||
'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;
|
||||
|
|
|
|||
65
package-lock.json
generated
65
package-lock.json
generated
|
|
@ -5,6 +5,8 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@tailwindcss/forms": "^0.3.4",
|
||||
"@tailwindcss/line-clamp": "^0.3.1",
|
||||
"autoprefixer": "^10.3.7",
|
||||
"axios": "^0.25",
|
||||
"card-js": "^1.0.13",
|
||||
|
|
@ -25,6 +27,7 @@
|
|||
"devDependencies": {
|
||||
"@babel/compat-data": "7.15.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"laravel-mix-purgecss": "^6.0.0",
|
||||
"vue-template-compiler": "^2.6.14"
|
||||
}
|
||||
|
|
@ -1682,6 +1685,34 @@
|
|||
"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": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
|
|
@ -5742,6 +5773,14 @@
|
|||
"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": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
|
|
@ -10285,6 +10324,27 @@
|
|||
"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": {
|
||||
"version": "0.2.0",
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@
|
|||
"devDependencies": {
|
||||
"@babel/compat-data": "7.15.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"laravel-mix-purgecss": "^6.0.0",
|
||||
"vue-template-compiler": "^2.6.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/line-clamp": "^0.3.1",
|
||||
"@tailwindcss/forms": "^0.3.4",
|
||||
"autoprefixer": "^10.3.7",
|
||||
"axios": "^0.25",
|
||||
"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 CACHE_NAME = 'flutter-app-cache';
|
||||
const RESOURCES = {
|
||||
"version.json": "eaa34b1fc12792d815c0443fbfbc076b",
|
||||
"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/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "b62641afc9ab487008e996a5c5865e56",
|
||||
"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/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/vu.png": "3f201fdfb6d669a64c35c20a801016d1",
|
||||
"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/bv.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
||||
"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/so.png": "1ce20d052f9d057250be96f42647513b",
|
||||
"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/es.png": "654965f9722f6706586476fb2f5d30dd",
|
||||
"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/de.png": "5d9561246523cf6183928756fd605e25",
|
||||
"assets/packages/intl_phone_field/assets/flags/er.png": "8ca78e10878a2e97c1371b38c5d258a7",
|
||||
"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/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/ml.png": "0c50dfd539e87bb4313da0d4556e2d13",
|
||||
"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/ru.png": "6974dcb42ad7eb3add1009ea0c6003e3",
|
||||
"assets/packages/intl_phone_field/assets/flags/dj.png": "078bd37d41f746c3cb2d84c1e9611c55",
|
||||
"assets/packages/intl_phone_field/assets/flags/mt.png": "f3119401ae0c3a9d6e2dc23803928c06",
|
||||
"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/um.png": "8fe7c4fed0a065fdfb9bd3125c6ecaa1",
|
||||
"assets/packages/intl_phone_field/assets/flags/je.png": "288f8dca26098e83ff0455b08cceca1b",
|
||||
"assets/packages/intl_phone_field/assets/flags/th.png": "11ce0c9f8c738fd217ea52b9bc29014b",
|
||||
"assets/packages/intl_phone_field/assets/flags/gb-sct.png": "75106a5e49e3e16da76cb33bdac102ab",
|
||||
"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/mn.png": "16086e8d89c9067d29fd0f2ea7021a45",
|
||||
"assets/packages/intl_phone_field/assets/flags/cz.png": "73ecd64c6144786c4d03729b1dd9b1f3",
|
||||
"assets/packages/intl_phone_field/assets/flags/eh.png": "515a9cf2620c802e305b5412ac81aed2",
|
||||
"assets/packages/intl_phone_field/assets/flags/al.png": "722cf9e5c7a1d9c9e4608fb44dbb427d",
|
||||
"assets/packages/intl_phone_field/assets/flags/tv.png": "c57025ed7ae482210f29b9da86b0d211",
|
||||
"assets/packages/intl_phone_field/assets/flags/tt.png": "a8e1fc5c65dc8bc362a9453fadf9c4b3",
|
||||
"assets/packages/intl_phone_field/assets/flags/sh.png": "98773db151c150cabe845183241bfe6b",
|
||||
"assets/packages/intl_phone_field/assets/flags/bf.png": "63f1c67fca7ce8b52b3418a90af6ad37",
|
||||
"assets/packages/intl_phone_field/assets/flags/pg.png": "0f7e03465a93e0b4e3e1c9d3dd5814a4",
|
||||
"assets/packages/intl_phone_field/assets/flags/ir.png": "37f67c3141e9843196cb94815be7bd37",
|
||||
"assets/packages/intl_phone_field/assets/flags/gl.png": "b79e24ee1889b7446ba3d65564b86810",
|
||||
"assets/packages/intl_phone_field/assets/flags/pt.png": "eba93d33545c78cc67915d9be8323661",
|
||||
"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/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/us.png": "83b065848d14d33c0d10a13e01862f34",
|
||||
"assets/packages/intl_phone_field/assets/flags/cn.png": "040539c2cdb60ebd9dc8957cdc6a8ad0",
|
||||
"assets/packages/intl_phone_field/assets/flags/sx.png": "9c19254973d8acf81581ad95b408c7e6",
|
||||
"assets/packages/intl_phone_field/assets/flags/na.png": "cdc00e9267a873609b0abea944939ff7",
|
||||
"assets/packages/intl_phone_field/assets/flags/iq.png": "bc3e6f68c5188dbf99b473e2bea066f2",
|
||||
"assets/packages/intl_phone_field/assets/flags/pr.png": "b97b2f4432c430bc340d893f36527e31",
|
||||
"assets/packages/intl_phone_field/assets/flags/la.png": "e8cd9c3ee6e134adcbe3e986e1974e4a",
|
||||
"assets/packages/intl_phone_field/assets/flags/gy.png": "159a260bf0217128ea7475ba5b272b6a",
|
||||
"assets/packages/intl_phone_field/assets/flags/im.png": "7c9ccb825f0fca557d795c4330cf4f50",
|
||||
"assets/packages/intl_phone_field/assets/flags/za.png": "b28280c6c3eb4624c18b5455d4a1b1ff",
|
||||
"assets/packages/intl_phone_field/assets/flags/ky.png": "38e39eba673e82c48a1f25bd103a7e97",
|
||||
"assets/packages/intl_phone_field/assets/flags/by.png": "beabf61e94fb3a4f7c7a7890488b213d",
|
||||
"assets/packages/intl_phone_field/assets/flags/no.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
||||
"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/st.png": "fef62c31713ff1063da2564df3f43eea",
|
||||
"assets/packages/intl_phone_field/assets/flags/im.png": "7c9ccb825f0fca557d795c4330cf4f50",
|
||||
"assets/packages/intl_phone_field/assets/flags/tw.png": "b1101fd5f871a9ffe7c9ad191a7d3304",
|
||||
"assets/packages/intl_phone_field/assets/flags/nr.png": "1316f3a8a419d8be1975912c712535ea",
|
||||
"assets/packages/intl_phone_field/assets/flags/pf.png": "1ae72c24380d087cbe2d0cd6c3b58821",
|
||||
"assets/packages/intl_phone_field/assets/flags/er.png": "8ca78e10878a2e97c1371b38c5d258a7",
|
||||
"assets/packages/intl_phone_field/assets/flags/ki.png": "14db0fc29398730064503907bd696176",
|
||||
"assets/packages/intl_phone_field/assets/flags/re.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||
"assets/packages/intl_phone_field/assets/flags/jm.png": "074400103847c56c37425a73f9d23665",
|
||||
"assets/packages/intl_phone_field/assets/flags/ag.png": "41c11d5668c93ba6e452f811defdbb24",
|
||||
"assets/packages/intl_phone_field/assets/flags/fi.png": "3ccd69a842e55183415b7ea2c04b15c8",
|
||||
"assets/packages/intl_phone_field/assets/flags/ye.png": "4cf73209d90e9f02ead1565c8fdf59e5",
|
||||
"assets/packages/intl_phone_field/assets/flags/hr.png": "69711b2ea009a3e7c40045b538768d4e",
|
||||
"assets/packages/intl_phone_field/assets/flags/az.png": "6ffa766f6883d2d3d350cdc22a062ca3",
|
||||
"assets/packages/intl_phone_field/assets/flags/gd.png": "7a4864ccfa2a0564041c2d1f8a13a8c9",
|
||||
"assets/packages/intl_phone_field/assets/flags/tt.png": "a8e1fc5c65dc8bc362a9453fadf9c4b3",
|
||||
"assets/packages/intl_phone_field/assets/flags/ss.png": "b0120cb000b31bb1a5c801c3592139bc",
|
||||
"assets/packages/intl_phone_field/assets/flags/mw.png": "ffc1f18eeedc1dfbb1080aa985ce7d05",
|
||||
"assets/packages/intl_phone_field/assets/flags/sy.png": "24186a0f4ce804a16c91592db5a16a3a",
|
||||
"assets/packages/intl_phone_field/assets/flags/tr.png": "27feab1a5ca390610d07e0c6bd4720d5",
|
||||
"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/so.png": "1ce20d052f9d057250be96f42647513b",
|
||||
"assets/packages/intl_phone_field/assets/flags/ge.png": "6fbd41f07921fa415347ebf6dff5b0f7",
|
||||
"assets/packages/intl_phone_field/assets/flags/bl.png": "dae94f5465d3390fdc5929e4f74d3f5f",
|
||||
"assets/packages/intl_phone_field/assets/flags/co.png": "e3b1be16dcdae6cb72e9c238fdddce3c",
|
||||
"assets/packages/intl_phone_field/assets/flags/yt.png": "134bee9f9d794dc5c0922d1b9bdbb710",
|
||||
"assets/packages/intl_phone_field/assets/flags/af.png": "ba710b50a060b5351381b55366396c30",
|
||||
"assets/packages/intl_phone_field/assets/flags/kg.png": "c4aa6d221d9a9d332155518d6b82dbc7",
|
||||
"assets/packages/intl_phone_field/assets/flags/do.png": "ed35983a9263bb5713be37d9a52caddc",
|
||||
"assets/packages/intl_phone_field/assets/flags/dk.png": "abcd01bdbcc02b4a29cbac237f29cd1d",
|
||||
"assets/packages/intl_phone_field/assets/flags/bn.png": "ed650de06fff61ff27ec92a872197948",
|
||||
"assets/packages/intl_phone_field/assets/flags/aq.png": "0c586e7b91aa192758fdd0f03adb84d8",
|
||||
"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/ni.png": "e398dc23e79d9ccd702546cc25f126bf",
|
||||
"assets/packages/intl_phone_field/assets/flags/no.png": "33bc70259c4908b7b9adeef9436f7a9f",
|
||||
"assets/packages/intl_phone_field/assets/flags/sm.png": "a8d6801cb7c5360e18f0a2ed146b396d",
|
||||
"assets/packages/intl_phone_field/assets/flags/ee.png": "e242645cae28bd5291116ea211f9a566",
|
||||
"assets/packages/intl_phone_field/assets/flags/rs.png": "9dff535d2d08c504be63062f39eff0b7",
|
||||
"assets/packages/intl_phone_field/assets/flags/ma.png": "057ea2e08587f1361b3547556adae0c2",
|
||||
"assets/packages/intl_phone_field/assets/flags/mm.png": "32e5293d6029d8294c7dfc3c3835c222",
|
||||
"assets/packages/intl_phone_field/assets/flags/kh.png": "d48d51e8769a26930da6edfc15de97fe",
|
||||
"assets/packages/intl_phone_field/assets/flags/ly.png": "8d65057351859065d64b4c118ff9e30e",
|
||||
"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/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/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/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_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/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",
|
||||
"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-512.png": "0f9aff01367f0a0c69773d25ca16ef35"
|
||||
"main.dart.js": "301d099d604c2a0ce586552202f8d3ed"
|
||||
};
|
||||
|
||||
// The application shell files that are downloaded before a service worker can
|
||||
|
|
|
|||
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue