Merge pull request #4752 from turbo124/v5-stable

5.0.53
This commit is contained in:
David Bomba 2021-01-24 16:08:35 +11:00 committed by GitHub
commit a274fdc353
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 123082 additions and 119738 deletions

View File

@ -12,7 +12,7 @@ services:
group: deprecated-2017Q4 group: deprecated-2017Q4
php: php:
- 7.3 # - 7.3
- 7.4 - 7.4
# - nightly # - nightly
@ -38,7 +38,7 @@ env:
before_install: before_install:
# set GitHub token and update composer # set GitHub token and update composer
- if [ -n "$GH_TOKEN" ]; then composer config github-oauth.github.com ${GH_TOKEN}; fi; - if [ -n "$GH_TOKEN" ]; then composer config github-oauth.github.com ${GH_TOKEN}; fi;
- composer self-update && composer -V - composer self-update 1.10.19 && composer -V
# - export USE_ZEND_ALLOC=0 # - export USE_ZEND_ALLOC=0
- rvm use 1.9.3 --install --fuzzy - rvm use 1.9.3 --install --fuzzy
- cp .env.travis .env - cp .env.travis .env
@ -77,7 +77,7 @@ before_script:
script: script:
- php ./vendor/bin/phpunit --debug --verbose --coverage-clover=coverage.xml - php ./vendor/bin/phpunit --debug --verbose --coverage-clover=coverage.xml
- php artisan dusk #- php artisan dusk
#- npm test #- npm test
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)

View File

@ -1 +1 @@
5.0.52 5.0.53

View File

@ -298,7 +298,7 @@ class CheckData extends Command
$invoice_balance = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance'); $invoice_balance = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance');
$credit_balance = $client->credits->where('is_deleted', false)->sum('balance'); $credit_balance = $client->credits->where('is_deleted', false)->sum('balance');
$invoice_balance -= $credit_balance; // $invoice_balance -= $credit_balance;//doesn't make sense to remove the credit amount
$ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first(); $ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first();
@ -388,9 +388,9 @@ class CheckData extends Command
foreach (Client::cursor()->where('is_deleted', 0) as $client) { foreach (Client::cursor()->where('is_deleted', 0) as $client) {
//$invoice_balance = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance'); //$invoice_balance = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance');
$invoice_balance = Invoice::where('client_id', $client->id)->where('is_deleted', false)->where('status_id', '>', 1)->withTrashed()->sum('balance'); $invoice_balance = Invoice::where('client_id', $client->id)->where('is_deleted', false)->where('status_id', '>', 1)->withTrashed()->sum('balance');
$client_balance = Credit::where('client_id', $client->id)->where('is_deleted', false)->withTrashed()->sum('balance'); $credit_balance = Credit::where('client_id', $client->id)->where('is_deleted', false)->withTrashed()->sum('balance');
$invoice_balance -= $client_balance; // $invoice_balance -= $credit_balance;
$ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first(); $ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first();

View File

@ -331,7 +331,7 @@ class CreateTestData extends Command
$this->info('Creating '.$this->count.' clients'); $this->info('Creating '.$this->count.' clients');
for ($x = 0; $x < $this->count * 500; $x++) { for ($x = 0; $x < $this->count * 200; $x++) {
$z = $x + 1; $z = $x + 1;
$this->info('Creating client # '.$z); $this->info('Creating client # '.$z);

View File

@ -15,6 +15,7 @@ use App\Jobs\Cron\RecurringInvoicesCron;
use App\Jobs\Ninja\AdjustEmailQuota; use App\Jobs\Ninja\AdjustEmailQuota;
use App\Jobs\Ninja\CompanySizeCheck; use App\Jobs\Ninja\CompanySizeCheck;
use App\Jobs\Util\ReminderJob; use App\Jobs\Util\ReminderJob;
use App\Jobs\Util\SchedulerCheck;
use App\Jobs\Util\SendFailedEmails; use App\Jobs\Util\SendFailedEmails;
use App\Jobs\Util\UpdateExchangeRates; use App\Jobs\Util\UpdateExchangeRates;
use App\Jobs\Util\VersionCheck; use App\Jobs\Util\VersionCheck;
@ -42,7 +43,6 @@ class Kernel extends ConsoleKernel
protected function schedule(Schedule $schedule) protected function schedule(Schedule $schedule)
{ {
//$schedule->job(new RecurringInvoicesCron)->hourly();
$schedule->job(new VersionCheck)->daily()->withoutOverlapping(); $schedule->job(new VersionCheck)->daily()->withoutOverlapping();
$schedule->command('ninja:check-data')->daily()->withoutOverlapping(); $schedule->command('ninja:check-data')->daily()->withoutOverlapping();
@ -57,13 +57,20 @@ class Kernel extends ConsoleKernel
/* Run hosted specific jobs */ /* Run hosted specific jobs */
if (Ninja::isHosted()) { if (Ninja::isHosted()) {
$schedule->job(new AdjustEmailQuota())->daily()->withoutOverlapping(); $schedule->job(new AdjustEmailQuota())->daily()->withoutOverlapping();
$schedule->job(new SendFailedEmails())->daily()->withoutOverlapping(); $schedule->job(new SendFailedEmails())->daily()->withoutOverlapping();
} }
/* Run queue's in shared hosting with this*/ /* Run queue's with this*/
if (Ninja::isSelfHost()) { if (Ninja::isSelfHost()) {
$schedule->command('queue:work')->everyMinute()->withoutOverlapping(); $schedule->command('queue:work')->everyMinute()->withoutOverlapping();
$schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping(); //we need to add this as we are seeing cached queues mess up the system on first load.
//we need to add this as we are seeing cached queues mess up the system on first load.
$schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping();
$schedule->job(new SchedulerCheck)->everyFiveMinutes()->withoutOverlapping();
} }
} }

View File

@ -11,6 +11,7 @@
namespace App\Factory; namespace App\Factory;
use App\DataMapper\FeesAndLimits;
use App\Models\CompanyGateway; use App\Models\CompanyGateway;
class CompanyGatewayFactory class CompanyGatewayFactory
@ -20,7 +21,8 @@ class CompanyGatewayFactory
$company_gateway = new CompanyGateway; $company_gateway = new CompanyGateway;
$company_gateway->company_id = $company_id; $company_gateway->company_id = $company_id;
$company_gateway->user_id = $user_id; $company_gateway->user_id = $user_id;
// $company_gateway->fees_and_limits = new FeesAndLimits;
return $company_gateway; return $company_gateway;
} }
} }

View File

@ -11,6 +11,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\DataMapper\FeesAndLimits;
use App\Factory\CompanyGatewayFactory; use App\Factory\CompanyGatewayFactory;
use App\Http\Requests\CompanyGateway\CreateCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\CreateCompanyGatewayRequest;
use App\Http\Requests\CompanyGateway\DestroyCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\DestroyCompanyGatewayRequest;
@ -18,6 +19,7 @@ use App\Http\Requests\CompanyGateway\EditCompanyGatewayRequest;
use App\Http\Requests\CompanyGateway\ShowCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\ShowCompanyGatewayRequest;
use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest;
use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
use App\Models\Client;
use App\Models\CompanyGateway; use App\Models\CompanyGateway;
use App\Repositories\CompanyRepository; use App\Repositories\CompanyRepository;
use App\Transformers\CompanyGatewayTransformer; use App\Transformers\CompanyGatewayTransformer;
@ -191,6 +193,18 @@ class CompanyGatewayController extends BaseController
$company_gateway->fill($request->all()); $company_gateway->fill($request->all());
$company_gateway->save(); $company_gateway->save();
/*Always ensure at least one fees and limits object is set per gateway*/
if(!isset($company_gateway->fees_and_limits)) {
$gateway_types = $company_gateway->driver(new Client)->gatewayTypes();
$fees_and_limits = new \stdClass;
$fees_and_limits->{$gateway_types[0]} = new FeesAndLimits;
$company_gateway->fees_and_limits = $fees_and_limits;
$company_gateway->save();
}
return $this->itemResponse($company_gateway); return $this->itemResponse($company_gateway);
} }

View File

@ -687,8 +687,8 @@ class InvoiceController extends BaseController
break; break;
case 'delete': case 'delete':
//need to make sure the invoice is cancelled first!! //need to make sure the invoice is cancelled first!!
//$invoice->service()->handleCancellation()->save(); //$invoice->service()->handleCancellation()s->save();
nlog("inside delete");
$this->invoice_repo->delete($invoice); $this->invoice_repo->delete($invoice);
if (! $bulk) { if (! $bulk) {

View File

@ -122,6 +122,7 @@ class SetupController extends Controller
]; ];
try { try {
foreach ($env_values as $property => $value) { foreach ($env_values as $property => $value) {
$this->updateEnvironmentProperty($property, $value); $this->updateEnvironmentProperty($property, $value);
} }

View File

@ -25,6 +25,7 @@ class StoreCompanyGatewayRequest extends Request
* *
* @return bool * @return bool
*/ */
public function authorize() : bool public function authorize() : bool
{ {
return auth()->user()->isAdmin(); return auth()->user()->isAdmin();
@ -43,27 +44,32 @@ class StoreCompanyGatewayRequest extends Request
protected function prepareForValidation() protected function prepareForValidation()
{ {
$input = $this->all(); $input = $this->all();
$gateway = Gateway::where('key', $input['gateway_key'])->first(); $gateway = Gateway::where('key', $input['gateway_key'])->first();
$default_gateway_fields = json_decode($gateway->fields); $default_gateway_fields = json_decode($gateway->fields);
/*Force gateway properties */ /*Force gateway properties */
if (isset($input['config']) && is_object(json_decode($input['config']))) { if (isset($input['config']) && is_object(json_decode($input['config']))) {
foreach (json_decode($input['config']) as $key => $value) { foreach (json_decode($input['config']) as $key => $value) {
$default_gateway_fields->{$key} = $value; $default_gateway_fields->{$key} = $value;
} }
$input['config'] = json_encode($default_gateway_fields); $input['config'] = json_encode($default_gateway_fields);
} }
if (isset($input['config'])) { if (isset($input['config']))
$input['config'] = encrypt($input['config']); $input['config'] = encrypt($input['config']);
}
if (isset($input['fees_and_limits']))
if (isset($input['fees_and_limits'])) {
$input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']); $input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']);
}
$this->replace($input); $this->replace($input);
} }
} }

View File

@ -53,21 +53,40 @@ class ValidInvoicesRules implements Rule
//todo optimize this into a single query //todo optimize this into a single query
foreach ($this->input['invoices'] as $invoice) { foreach ($this->input['invoices'] as $invoice) {
$unique_array[] = $invoice['invoice_id']; $unique_array[] = $invoice['invoice_id'];
$inv = Invoice::whereId($invoice['invoice_id'])->first(); $inv = Invoice::whereId($invoice['invoice_id'])->first();
if (! $inv) { if (! $inv) {
$this->error_msg = 'Invoice not found '; $this->error_msg = 'Invoice not found ';
return false; return false;
} }
if ($inv->client_id != $this->input['client_id']) { if ($inv->client_id != $this->input['client_id']) {
$this->error_msg = 'Selected invoices are not from a single client'; $this->error_msg = 'Selected invoices are not from a single client';
return false; return false;
} }
if($inv->status_id == Invoice::STATUS_DRAFT && $invoice['amount'] <= $inv->amount){
//catch here nothing to do - we need this to prevent the last elseif triggering
}
else if($inv->status_id == Invoice::STATUS_DRAFT && $invoice['amount'] > $inv->amount){
$this->error_msg = 'Amount cannot be greater than invoice balance';
return false;
}
else if($invoice['amount'] > $inv->balance) {
$this->error_msg = 'Amount cannot be greater than invoice balance';
return false;
}
} }
if (! (array_unique($unique_array) == $unique_array)) { if (! (array_unique($unique_array) == $unique_array)) {

View File

@ -96,7 +96,7 @@ class ZipInvoices extends BaseMailerJob implements ShouldQueue
Mail::to($this->email) Mail::to($this->email)
->send(new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path.$file_name), $this->company)); ->send(new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path.$file_name), $this->company));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); // //$this->failed($e);
} }
UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1)); UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1));

View File

@ -96,7 +96,7 @@ class EntityFailedSendMailer extends BaseMailerJob implements ShouldQueue
->send(new EntityNotificationMailer($mail_obj)); ->send(new EntityNotificationMailer($mail_obj));
} catch (\Exception $e) { } catch (\Exception $e) {
nlog("failing in EntityFailedSendMailer"); nlog("failing in EntityFailedSendMailer");
$this->failed($e); //$this->failed($e);
$this->logMailError($e->getMessage(), $this->entity->client); $this->logMailError($e->getMessage(), $this->entity->client);
} }
} }

View File

@ -83,7 +83,7 @@ class EntityPaidMailer extends BaseMailerJob implements ShouldQueue
Mail::to($this->user->email) Mail::to($this->user->email)
->send(new EntityNotificationMailer($mail_obj)); ->send(new EntityNotificationMailer($mail_obj));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); // //$this->failed($e);
$this->logMailError($e->getMessage(), $this->payment->client); $this->logMailError($e->getMessage(), $this->payment->client);
} }
} }

View File

@ -90,7 +90,7 @@ class EntitySentMailer extends BaseMailerJob implements ShouldQueue
Mail::to($this->user->email) Mail::to($this->user->email)
->send(new EntityNotificationMailer($mail_obj)); ->send(new EntityNotificationMailer($mail_obj));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); // //$this->failed($e);
$this->logMailError($e->getMessage(), $this->entity->client); $this->logMailError($e->getMessage(), $this->entity->client);
} }
} }

View File

@ -88,7 +88,7 @@ class EntityViewedMailer extends BaseMailerJob implements ShouldQueue
Mail::to($this->user->email) Mail::to($this->user->email)
->send(new EntityNotificationMailer($mail_obj)); ->send(new EntityNotificationMailer($mail_obj));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); //$this->failed($e);
$this->logMailError($e->getMessage(), $this->entity->client); $this->logMailError($e->getMessage(), $this->entity->client);
} }
} }

View File

@ -73,7 +73,7 @@ class MailRouter extends BaseMailerJob implements ShouldQueue
Mail::to($this->to_user->email) Mail::to($this->to_user->email)
->send($this->mailable); ->send($this->mailable);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); //$this->failed($e);
if ($this->to_user instanceof ClientContact) { if ($this->to_user instanceof ClientContact) {
$this->logMailError($e->getMessage(), $this->to_user->client); $this->logMailError($e->getMessage(), $this->to_user->client);

View File

@ -98,7 +98,7 @@ class PaymentFailureMailer extends BaseMailerJob implements ShouldQueue
Mail::to($company_user->user->email) Mail::to($company_user->user->email)
->send(new EntityNotificationMailer($mail_obj)); ->send(new EntityNotificationMailer($mail_obj));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); //$this->failed($e);
$this->logMailError($e->getMessage(), $this->client); $this->logMailError($e->getMessage(), $this->client);
} }
} }

View File

@ -308,7 +308,7 @@ class SendReminders implements ShouldQueue
$invoice = $invoice->calc()->getInvoice(); $invoice = $invoice->calc()->getInvoice();
$this->invoice->client->service()->updateBalance($this->invoice->balance - $temp_invoice_balance)->save(); $this->invoice->client->service()->updateBalance($this->invoice->balance - $temp_invoice_balance)->save();
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance - $temp_invoice_balance); $this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance - $temp_invoice_balance, "Late Fee Adjustment for invoice {$this->invoice->number}");
return $invoice; return $invoice;
} }

View File

@ -84,7 +84,7 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
} catch (\Exception $e) { } catch (\Exception $e) {
nlog("mailing failed with message " . $e->getMessage()); nlog("mailing failed with message " . $e->getMessage());
event(new PaymentWasEmailedAndFailed($this->payment, $this->company, Mail::failures(), Ninja::eventVars())); event(new PaymentWasEmailedAndFailed($this->payment, $this->company, Mail::failures(), Ninja::eventVars()));
$this->failed($e); //$this->failed($e);
return $this->logMailError($e->getMessage(), $this->payment->client); return $this->logMailError($e->getMessage(), $this->payment->client);
} }

View File

@ -54,7 +54,18 @@ class UpdateOrCreateProduct implements ShouldQueue
public function handle() public function handle()
{ {
MultiDB::setDB($this->company->db); MultiDB::setDB($this->company->db);
/*
* If the invoice was generated from a Task or Expense then
* we do NOT update the product details this short block we
* check for the presence of a task_id and/or expense_id
*/
$expense_count = count(array_column((array)$this->products, 'expense_id'));
$task_count = count(array_column((array)$this->products, 'task_id'));
if($task_count >= 1 || $expense_count >= 1)
return;
//only update / create products - not tasks or gateway fees //only update / create products - not tasks or gateway fees
$updateable_products = collect($this->products)->filter(function ($item) { $updateable_products = collect($this->products)->filter(function ($item) {
return $item->type_id == 1; return $item->type_id == 1;

View File

@ -79,7 +79,7 @@ class UserEmailChanged extends BaseMailerJob implements ShouldQueue
Mail::to($this->new_email) Mail::to($this->new_email)
->send(new UserNotificationMailer($mail_obj)); ->send(new UserNotificationMailer($mail_obj));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->failed($e); //$this->failed($e);
$this->logMailError($e->getMessage(), $this->company->owner()); $this->logMailError($e->getMessage(), $this->company->owner());
} }
} }

View File

@ -0,0 +1,70 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Jobs\Util;
use App\Models\Account;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Artisan;
class SchedulerCheck implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
set_time_limit(0);
Account::whereNotNull('id')->update(['is_scheduler_running' => true]);
if(config('ninja.app_version') != base_path('VERSION.txt'))
{
try {
Artisan::call('migrate', ['--force' => true]);
} catch (\Exception $e) {
nlog("I wasn't able to migrate the data.");
}
try {
Artisan::call('optimize');
} catch (\Exception $e) {
nlog("I wasn't able to optimize.");
}
try {
Artisan::call('view:clear');
} catch (\Exception $e) {
nlog("I wasn't able to clear the views.");
}
VersionCheck::dispatch();
}
}
}

View File

@ -49,10 +49,7 @@ class ClientContact extends Authenticatable implements HasLocalePreference
'hashed_id', 'hashed_id',
]; ];
protected $with = [ protected $with = [];
// 'client',
// 'company'
];
protected $casts = [ protected $casts = [
'updated_at' => 'timestamp', 'updated_at' => 'timestamp',
@ -87,12 +84,6 @@ class ClientContact extends Authenticatable implements HasLocalePreference
'client_id', 'client_id',
]; ];
/* Changing the username to id allows us to login() a contact that doesn't have an email address set*/
public function username()
{
return 'id';
}
public function getEntityType() public function getEntityType()
{ {
return self::class; return self::class;

View File

@ -108,7 +108,6 @@ class CompanyGateway extends BaseModel
private function driver_class() private function driver_class()
{ {
$class = 'App\\PaymentDrivers\\'.$this->gateway->provider.'PaymentDriver'; $class = 'App\\PaymentDrivers\\'.$this->gateway->provider.'PaymentDriver';
//$class = str_replace('\\', '', $class);
$class = str_replace('_', '', $class); $class = str_replace('_', '', $class);
if (class_exists($class)) { if (class_exists($class)) {

View File

@ -90,4 +90,14 @@ class CompanyPresenter extends EntityPresenter
return false; return false;
} }
} }
public function getSpcQrCode($client_custom, $invoice_number, $balance)
{
$settings = $this->entity->settings;
return
"SPC\n0200\n1\nCH860021421411198240K\nK\n{$this->name}\n{$settings->address1}\n{$settings->postal_code} {$settings->city}\n\n\nCH\n\n\n\n\n\n\n\n{$balance}\n{$client_custom}\n\n\n\n\n\n\n\nNON\n\n{$invoice_number}\nEPD\n";
}
} }

View File

@ -264,7 +264,7 @@ class BaseDriver extends AbstractPaymentDriver
if (collect($invoice->line_items)->contains('type_id', '3')) { if (collect($invoice->line_items)->contains('type_id', '3')) {
$invoice->service()->toggleFeesPaid()->save(); $invoice->service()->toggleFeesPaid()->save();
$invoice->client->service()->updateBalance($fee_total)->save(); $invoice->client->service()->updateBalance($fee_total)->save();
$invoice->ledger()->updateInvoiceBalance($fee_total, $notes = 'Gateway fee adjustment'); $invoice->ledger()->updateInvoiceBalance($fee_total, "Gateway fee adjustment for invoice {$invoice->number}");
} }
}); });
} }

View File

@ -306,7 +306,7 @@ class BasePaymentDriver
if (collect($invoice->line_items)->contains('type_id', '3')) { if (collect($invoice->line_items)->contains('type_id', '3')) {
$invoice->service()->toggleFeesPaid()->save(); $invoice->service()->toggleFeesPaid()->save();
$invoice->client->service()->updateBalance($fee_total)->save(); $invoice->client->service()->updateBalance($fee_total)->save();
$invoice->ledger()->updateInvoiceBalance($fee_total, $notes = 'Gateway fee adjustment'); $invoice->ledger()->updateInvoiceBalance($fee_total, "Gateway fee adjustment for Invoice {$invoice->number}");
} }
}); });
} }

View File

@ -293,7 +293,7 @@ class BaseRepository
if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) { if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
$model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount'])); $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']), "Update adjustment for invoice {$model->number}");
$model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save(); $model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save();
} }

View File

@ -58,6 +58,10 @@ class ClientContactRepository extends BaseRepository
$update_contact->client_id = $client->id; $update_contact->client_id = $client->id;
} }
/* We need to set NULL email addresses to blank strings to pass authentication*/
if(array_key_exists('email', $contact) && is_null($contact['email']))
$contact['email'] = '';
$update_contact->fill($contact); $update_contact->fill($contact);
if (array_key_exists('password', $contact) && strlen($contact['password']) > 1) { if (array_key_exists('password', $contact) && strlen($contact['password']) > 1) {
@ -77,6 +81,7 @@ class ClientContactRepository extends BaseRepository
$new_contact->contact_key = Str::random(40); $new_contact->contact_key = Str::random(40);
$new_contact->is_primary = true; $new_contact->is_primary = true;
$new_contact->confirmed = true; $new_contact->confirmed = true;
$new_contact->email = ' ';
$new_contact->save(); $new_contact->save();
} }
} }

View File

@ -64,6 +64,7 @@ class PaymentRepository extends BaseRepository
*/ */
private function applyPayment(array $data, Payment $payment): ?Payment private function applyPayment(array $data, Payment $payment): ?Payment
{ {
$is_existing_payment = true; $is_existing_payment = true;
//check currencies here and fill the exchange rate data if necessary //check currencies here and fill the exchange rate data if necessary
@ -117,6 +118,8 @@ class PaymentRepository extends BaseRepository
if (array_key_exists('invoices', $data) && is_array($data['invoices']) && count($data['invoices']) > 0) { if (array_key_exists('invoices', $data) && is_array($data['invoices']) && count($data['invoices']) > 0) {
$invoice_totals = array_sum(array_column($data['invoices'], 'amount')); $invoice_totals = array_sum(array_column($data['invoices'], 'amount'));
nlog("invoice totals = {$invoice_totals}");
$invoices = Invoice::whereIn('id', array_column($data['invoices'], 'invoice_id'))->get(); $invoices = Invoice::whereIn('id', array_column($data['invoices'], 'invoice_id'))->get();
$payment->invoices()->saveMany($invoices); $payment->invoices()->saveMany($invoices);
@ -155,6 +158,11 @@ class PaymentRepository extends BaseRepository
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
} }
nlog("payment amount = {$payment->amount}");
nlog("payment applied = {$payment->applied}");
nlog("invoice totals = {$invoice_totals}");
nlog("credit totals = {$credit_totals}");
$payment->applied += ($invoice_totals - $credit_totals); //wont work because - check tests $payment->applied += ($invoice_totals - $credit_totals); //wont work because - check tests
// $payment->applied += $invoice_totals; //wont work because - check tests // $payment->applied += $invoice_totals; //wont work because - check tests

View File

@ -136,11 +136,13 @@ class PaymentMethod
foreach ($this->gateways as $gateway) { foreach ($this->gateways as $gateway) {
foreach ($gateway->driver($this->client)->gatewayTypes() as $type) { foreach ($gateway->driver($this->client)->gatewayTypes() as $type) {
if (isset($gateway->fees_and_limits) && property_exists($gateway->fees_and_limits, $type)) { if (isset($gateway->fees_and_limits) && property_exists($gateway->fees_and_limits, $type)) {
if ($this->validGatewayForAmount($gateway->fees_and_limits->{$type}, $this->amount)) {
if ($this->validGatewayForAmount($gateway->fees_and_limits->{$type}, $this->amount) && $gateway->fees_and_limits->{$type}->is_enabled) {
$this->payment_methods[] = [$gateway->id => $type]; $this->payment_methods[] = [$gateway->id => $type];
} }
} else { } else {
$this->payment_methods[] = [$gateway->id => $type]; //$this->payment_methods[] = [$gateway->id => $type];
} }
} }
} }

View File

@ -93,10 +93,6 @@ class AddGatewayFee extends AbstractService
/**Refresh Invoice values*/ /**Refresh Invoice values*/
$this->invoice = $this->invoice->calc()->getInvoice(); $this->invoice = $this->invoice->calc()->getInvoice();
/*Update client balance*/ // don't increment until we have process the payment!
//$this->invoice->client->service()->updateBalance($gateway_fee)->save();
//$this->invoice->ledger()->updateInvoiceBalance($gateway_fee, $notes = 'Gateway fee adjustment');
return $this->invoice; return $this->invoice;
} }
@ -122,10 +118,6 @@ class AddGatewayFee extends AbstractService
$this->invoice = $this->invoice->calc()->getInvoice(); $this->invoice = $this->invoice->calc()->getInvoice();
// $this->invoice->client->service()->updateBalance($gateway_fee)->save();
// $this->invoice->ledger()->updateInvoiceBalance($gateway_fee, $notes = 'Discount fee adjustment');
return $this->invoice; return $this->invoice;
} }
} }

View File

@ -30,52 +30,92 @@ class ApplyPayment extends AbstractService
$this->payment_amount = $payment_amount; $this->payment_amount = $payment_amount;
} }
/* Apply payment to a single invoice */
public function run() public function run()
{ {
$this->invoice->fresh('client');
$amount_paid = 0;
if ($this->invoice->hasPartial()) {
if ($this->invoice->partial == $this->payment_amount)
{
//is partial and amount is exactly the partial amount
$amount_paid = $this->payment_amount * -1;
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid);
}
elseif ($this->invoice->partial > 0 && $this->invoice->partial > $this->payment_amount)
{
//partial amount exists, but the amount is less than the partial amount
$amount_paid = $this->payment_amount * -1;
$this->invoice->service()->updatePartial($amount_paid)->updateBalance($amount_paid);
}
elseif ($this->invoice->partial > 0 && $this->invoice->partial < $this->payment_amount)
{
//partial exists and the amount paid is GREATER than the partial amount
$amount_paid = $this->payment_amount * -1;
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid);
}
}
else
{
if ($this->payment_amount == $this->invoice->balance)
{
$amount_paid = $this->payment_amount * -1;
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid);
}
elseif ($this->payment_amount < $this->invoice->balance)
{
//partial invoice payment made
$amount_paid = $this->payment_amount * -1;
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid);
}
elseif ($this->payment_amount > $this->invoice->balance)
{
//partial invoice payment made
$amount_paid = $this->invoice->balance * -1;
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid);
}
}
$this->payment $this->payment
->ledger() ->ledger()
->updatePaymentBalance($this->payment_amount * -1); ->updatePaymentBalance($amount_paid);
// info("apply payment method - current client balance = {$this->payment->client->balance}"); $this->invoice->client->service()->updateBalance($amount_paid)->save();
// info("reducing client balance by payment amount {$this->payment_amount}");
$this->invoice->client->service()->updateBalance($this->payment_amount * -1)->save();
// info("post client balance = {$this->invoice->client->balance}");
/* Update Pivot Record amount */ /* Update Pivot Record amount */
$this->payment->invoices->each(function ($inv) { $this->payment->invoices->each(function ($inv) use($amount_paid){
if ($inv->id == $this->invoice->id) { if ($inv->id == $this->invoice->id) {
$inv->pivot->amount = $this->payment_amount; $inv->pivot->amount = ($amount_paid*-1);
$inv->pivot->save(); $inv->pivot->save();
} }
}); });
$this->invoice->fresh('client');
// info("1 end of apply payment method the client balance = {$this->invoice->client->balance}");
if ($this->invoice->hasPartial()) {
//is partial and amount is exactly the partial amount
if ($this->invoice->partial == $this->payment_amount) {
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount * -1);
} elseif ($this->invoice->partial > 0 && $this->invoice->partial > $this->payment_amount) { //partial amount exists, but the amount is less than the partial amount
$this->invoice->service()->updatePartial($this->payment_amount * -1)->updateBalance($this->payment_amount * -1);
} elseif ($this->invoice->partial > 0 && $this->invoice->partial < $this->payment_amount) { //partial exists and the amount paid is GREATER than the partial amount
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount * -1);
}
} elseif ($this->payment_amount == $this->invoice->balance) { //total invoice paid.
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($this->payment_amount * -1);
} elseif ($this->payment_amount < $this->invoice->balance) { //partial invoice payment made
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount * -1);
}
// info("2 end of apply payment method the client balnace = {$this->invoice->client->balance}");
$this->invoice->service()->applyNumber()->save(); $this->invoice->service()->applyNumber()->save();
// info("3 end of apply payment method the client balnace = {$this->invoice->client->balance}");
return $this->invoice; return $this->invoice;
} }
} }

View File

@ -147,8 +147,8 @@ class AutoBillInvoice extends AbstractService
->save(); ->save();
$this->invoice->ledger() $this->invoice->ledger()
->updateInvoiceBalance($amount * -1, 'Invoice payment using Credit') ->updateInvoiceBalance($amount * -1, "Invoice {$this->invoice->number} payment using Credit {$current_credit->number}")
->updateCreditBalance($amount * -1, 'Credits used to pay down Invoice ' . $this->invoice->number) ->updateCreditBalance($amount * -1, "Credit {$current_credit->number} used to pay down Invoice {$this->invoice->number}")
->save(); ->save();
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
@ -325,7 +325,7 @@ class AutoBillInvoice extends AbstractService
if ($starting_amount != $this->invoice->amount && $this->invoice->status_id != Invoice::STATUS_DRAFT) { if ($starting_amount != $this->invoice->amount && $this->invoice->status_id != Invoice::STATUS_DRAFT) {
$this->invoice->client->service()->updateBalance($this->invoice->amount - $starting_amount)->save(); $this->invoice->client->service()->updateBalance($this->invoice->amount - $starting_amount)->save();
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->amount - $starting_amount, 'Invoice balance updated after stale gateway fee removed')->save(); $this->invoice->ledger()->updateInvoiceBalance($this->invoice->amount - $starting_amount, "Invoice {$this->invoice->number} balance updated after stale gateway fee removed")->save();
} }
return $this; return $this;

View File

@ -42,7 +42,7 @@ class HandleCancellation extends AbstractService
$this->backupCancellation($adjustment); $this->backupCancellation($adjustment);
//set invoice balance to 0 //set invoice balance to 0
$this->invoice->ledger()->updateInvoiceBalance($adjustment, 'Invoice cancellation'); $this->invoice->ledger()->updateInvoiceBalance($adjustment, "Invoice {$this->invoice->number} cancellation");
$this->invoice->balance = 0; $this->invoice->balance = 0;
$this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save(); $this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save();
@ -57,11 +57,13 @@ class HandleCancellation extends AbstractService
public function reverse() public function reverse()
{ {
/* The stored cancelled object - contains the adjustment and status*/
$cancellation = $this->invoice->backup->cancellation; $cancellation = $this->invoice->backup->cancellation;
/* Will turn the negative cancellation amount to a positive adjustment*/
$adjustment = $cancellation->adjustment * -1; $adjustment = $cancellation->adjustment * -1;
$this->invoice->ledger()->updateInvoiceBalance($adjustment, 'Invoice cancellation REVERSAL'); $this->invoice->ledger()->updateInvoiceBalance($adjustment, "Invoice {$this->invoice->number} reversal");
/* Reverse the invoice status and balance */ /* Reverse the invoice status and balance */
$this->invoice->balance += $adjustment; $this->invoice->balance += $adjustment;

View File

@ -71,14 +71,15 @@ class HandleRestore extends AbstractService
} }
//adjust ledger balance //adjust ledger balance
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance, 'Restored invoice {$this->invoice->number}')->save(); $this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance, "Restored invoice {$this->invoice->number}")->save();
//adjust paid to dates //adjust paid to dates
$this->invoice->client->service()->updatePaidToDate($this->payment_total)->save(); $this->invoice->client->service()->updatePaidToDate($this->payment_total)->save();
$this->invoice->client->service()->updateBalance($this->invoice->balance)->save(); $this->invoice->client->service()->updateBalance($this->invoice->balance)->save();
$this->invoice->ledger()->updatePaymentBalance($this->payment_total, 'Restored payment for invoice {$this->invoice->number}')->save(); // you only need to touch the ledger ONCE per transaction.
// $this->invoice->ledger()->updatePaymentBalance($this->payment_total*-1, "Restored payment for invoice {$this->invoice->number}")->save();
$this->windBackInvoiceNumber(); $this->windBackInvoiceNumber();

View File

@ -36,9 +36,6 @@ class MarkInvoiceDeleted extends AbstractService
if ($this->invoice->is_deleted) { if ($this->invoice->is_deleted) {
return $this->invoice; return $this->invoice;
} }
// if(in_array($this->invoice->status_id, ['currencies', 'industries', 'languages', 'countries', 'banks']))
// return $this->
$this->cleanup() $this->cleanup()
->setAdjustmentAmount() ->setAdjustmentAmount()
@ -53,25 +50,26 @@ class MarkInvoiceDeleted extends AbstractService
private function adjustLedger() private function adjustLedger()
{ {
$this->invoice->ledger()->updatePaymentBalance($this->adjustment_amount * -1); $this->invoice->ledger()->updatePaymentBalance($this->adjustment_amount * -1, 'Invoice Deleted - reducing ledger balance'); //reduces the payment balance by payment totals
return $this; return $this;
} }
private function adjustPaidToDate() private function adjustPaidToDate()
{ {
$this->invoice->client->service()->updatePaidToDate($this->adjustment_amount * -1)->save(); $this->invoice->client->service()->updatePaidToDate($this->adjustment_amount * -1)->save(); //reduces the paid to date by the payment totals
return $this; return $this;
} }
private function adjustBalance() private function adjustBalance()
{ {
$this->invoice->client->service()->updateBalance($this->invoice->balance * -1)->save(); $this->invoice->client->service()->updateBalance($this->invoice->balance * -1)->save(); //reduces the client balance by the invoice amount.
return $this; return $this;
} }
/* Adjust the payment amounts */
private function adjustPayments() private function adjustPayments()
{ {
//if total payments = adjustment amount - that means we need to delete the payments as well. //if total payments = adjustment amount - that means we need to delete the payments as well.
@ -79,6 +77,7 @@ class MarkInvoiceDeleted extends AbstractService
if ($this->adjustment_amount == $this->total_payments) { if ($this->adjustment_amount == $this->total_payments) {
$this->invoice->payments()->update(['payments.deleted_at' => now(), 'payments.is_deleted' => true]); $this->invoice->payments()->update(['payments.deleted_at' => now(), 'payments.is_deleted' => true]);
} else { } else {
//adjust payments down by the amount applied to the invoice payment. //adjust payments down by the amount applied to the invoice payment.
$this->invoice->payments->each(function ($payment) { $this->invoice->payments->each(function ($payment) {
@ -96,6 +95,12 @@ class MarkInvoiceDeleted extends AbstractService
return $this; return $this;
} }
/**
* Set the values of two variables
*
* $this->adjustment_amount - sum of the invoice paymentables
* $this->total_payments - sum of the invoice payments
*/
private function setAdjustmentAmount() private function setAdjustmentAmount()
{ {
foreach ($this->invoice->payments as $payment) { foreach ($this->invoice->payments as $payment) {
@ -111,6 +116,12 @@ class MarkInvoiceDeleted extends AbstractService
return $this; return $this;
} }
/*
*
* This sets the invoice number to _deleted
* and also removes the links to existing entities
*
*/
private function cleanup() private function cleanup()
{ {
$check = false; $check = false;
@ -143,7 +154,7 @@ class MarkInvoiceDeleted extends AbstractService
return $number; return $number;
} }
/* Touches all paymentables as deleted */
private function deletePaymentables() private function deletePaymentables()
{ {
$this->invoice->payments->each(function ($payment) { $this->invoice->payments->each(function ($payment) {

View File

@ -51,7 +51,7 @@ class MarkSent extends AbstractService
$this->client->service()->updateBalance($this->invoice->balance)->save(); $this->client->service()->updateBalance($this->invoice->balance)->save();
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance); $this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance, "Invoice {$this->invoice->number} marked as sent.");
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars())); event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars()));

View File

@ -47,7 +47,7 @@ class LedgerService
return $this; return $this;
} }
public function updatePaymentBalance($adjustment) public function updatePaymentBalance($adjustment, $notes = '')
{ {
$balance = 0; $balance = 0;
@ -63,6 +63,7 @@ class LedgerService
$company_ledger->adjustment = $adjustment; $company_ledger->adjustment = $adjustment;
$company_ledger->balance = $balance + $adjustment; $company_ledger->balance = $balance + $adjustment;
$company_ledger->activity_id = Activity::UPDATE_PAYMENT; $company_ledger->activity_id = Activity::UPDATE_PAYMENT;
$company_ledger->notes = $notes;
$company_ledger->save(); $company_ledger->save();
$this->entity->company_ledger()->save($company_ledger); $this->entity->company_ledger()->save($company_ledger);

View File

@ -80,7 +80,7 @@ class DeletePayment
if ($this->payment->invoices()->exists()) { if ($this->payment->invoices()->exists()) {
$this->payment->invoices()->each(function ($paymentable_invoice) { $this->payment->invoices()->each(function ($paymentable_invoice) {
$paymentable_invoice->service()->updateBalance($paymentable_invoice->pivot->amount)->save(); $paymentable_invoice->service()->updateBalance($paymentable_invoice->pivot->amount)->save();
$paymentable_invoice->ledger()->updateInvoiceBalance($paymentable_invoice->pivot->amount)->save(); $paymentable_invoice->ledger()->updateInvoiceBalance($paymentable_invoice->pivot->amount, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")->save();
$paymentable_invoice->client->service()->updateBalance($paymentable_invoice->pivot->amount)->save(); $paymentable_invoice->client->service()->updateBalance($paymentable_invoice->pivot->amount)->save();
if ($paymentable_invoice->balance == $paymentable_invoice->amount) { if ($paymentable_invoice->balance == $paymentable_invoice->amount) {

View File

@ -76,6 +76,7 @@ class AccountTransformer extends EntityTransformer
'report_errors' => (bool) $account->report_errors, 'report_errors' => (bool) $account->report_errors,
'debug_enabled' => (bool) config('ninja.debug_enabled'), 'debug_enabled' => (bool) config('ninja.debug_enabled'),
'is_docker' => (bool) config('ninja.is_docker'), 'is_docker' => (bool) config('ninja.is_docker'),
'is_scheduler_running' => (bool) $account->is_scheduler_running,
]; ];
} }

View File

@ -29,7 +29,7 @@ class TaskStatusTransformer extends EntityTransformer
'created_at' => (int) $task_status->created_at, 'created_at' => (int) $task_status->created_at,
'updated_at' => (int) $task_status->updated_at, 'updated_at' => (int) $task_status->updated_at,
'archived_at' => (int) $task_status->deleted_at, 'archived_at' => (int) $task_status->deleted_at,
'status_order' => $task_status->status_order, 'status_order' => is_null($task_status->status_order) ? null : (int)$task_status->status_order,
]; ];
} }
} }

View File

@ -67,7 +67,7 @@ class TaskTransformer extends EntityTransformer
'status_id' => $this->encodePrimaryKey($task->status_id) ?: '', 'status_id' => $this->encodePrimaryKey($task->status_id) ?: '',
'status_sort_order' => (int) $task->status_sort_order, //deprecated 5.0.34 'status_sort_order' => (int) $task->status_sort_order, //deprecated 5.0.34
'is_date_based' => (bool) $task->is_date_based, 'is_date_based' => (bool) $task->is_date_based,
'status_order' => $task->status_order 'status_order' => is_null($task->status_order) ? null : (int)$task->status_order,
]; ];
} }
} }

View File

@ -274,6 +274,8 @@ class HtmlEngine
$data['$company.website'] = ['value' => $this->settings->website ?: '&nbsp;', 'label' => ctrans('texts.website')]; $data['$company.website'] = ['value' => $this->settings->website ?: '&nbsp;', 'label' => ctrans('texts.website')];
$data['$company.address'] = ['value' => $this->company->present()->address($this->settings) ?: '&nbsp;', 'label' => ctrans('texts.address')]; $data['$company.address'] = ['value' => $this->company->present()->address($this->settings) ?: '&nbsp;', 'label' => ctrans('texts.address')];
$data['$spc_qr_code'] = ['value' => $this->company->present()->getSpcQrCode($this->client->custom1, $this->entity->number, $this->entity->balance), 'label' => ''];
$logo = $this->company->present()->logo($this->settings); $logo = $this->company->present()->logo($this->settings);
$data['$company.logo'] = ['value' => $logo ?: '&nbsp;', 'label' => ctrans('texts.logo')]; $data['$company.logo'] = ['value' => $logo ?: '&nbsp;', 'label' => ctrans('texts.logo')];

View File

@ -197,7 +197,7 @@ class TemplateEngine
} }
} else { } else {
$wrapper = view($this->getTemplatePath($email_style), $data)->render(); $wrapper = view($this->getTemplatePath($email_style), $data)->render();
$injection = '<head><link rel="stylesheet" type="text/css" property="stylesheet" href="'.config('ninja.app_url').'/css/tailwind-1.2.0.css">'; $injection = '';
$wrapper = str_replace('<head>', $injection, $wrapper); $wrapper = str_replace('<head>', $injection, $wrapper);
} }
@ -208,7 +208,7 @@ class TemplateEngine
'raw_body' => $this->raw_body, 'raw_body' => $this->raw_body,
'raw_subject' => $this->raw_subject 'raw_subject' => $this->raw_subject
]; ];
$this->tearDown(); $this->tearDown();
return $data; return $data;

View File

@ -78,24 +78,6 @@ trait CompanyGatewayFeesAndLimitsSaver
} }
} }
// public function cleanFeesAndLimits($fees_and_limits)
// {
// $new_arr = [];
// foreach ($fees_and_limits as $key => $value) {
// $fal = new FeesAndLimits;
// foreach ($value as $k => $v) {
// $fal->{$k} = $v;
// $fal->{$k} = BaseSettings::castAttribute(FeesAndLimits::$casts[$k], $v);
// }
// $new_arr[$key] = (array)$fal;
// }
// return $new_arr;
// }
//
public function cleanFeesAndLimits($fees_and_limits) public function cleanFeesAndLimits($fees_and_limits)
{ {
$new_arr = []; $new_arr = [];

View File

@ -1,20 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Css Files
|--------------------------------------------------------------------------
|
| Css file of your style for your emails
| The content of these files will be added directly into the inliner
| Use absolute paths, ie. public_path('css/main.css')
|
*/
'css-files' => [
public_path('css/app.css'),
],
];

View File

@ -13,7 +13,7 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', ''), 'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.0.52', 'app_version' => '5.0.53',
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false), 'api_secret' => env('API_SECRET', false),

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class SchedulerIsRunningCheck extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accounts', function (Blueprint $table) {
$table->boolean('is_scheduler_running')->default(false);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -758,96 +758,6 @@ distribution.
contributors may be used to endorse or promote products derived from contributors may be used to endorse or promote products derived from
this software without specific prior written permission. this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
accessibility
Copyright (c) 2017 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
accessibility
Copyright (c) 2018 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
accessibility
Copyright (c) 2019 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -1022,6 +932,38 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
accessibility accessibility
engine
gpu
tonic
txt
Copyright 2013 The Flutter Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
accessibility
fuchsia_sdk fuchsia_sdk
skia skia
zlib zlib
@ -6124,6 +6066,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
dart dart
Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
for details. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
dart
Copyright 2009 The Go Authors. All rights reserved. Copyright 2009 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file license that can be found in the LICENSE file
@ -6338,37 +6309,6 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
engine
gpu
tonic
txt
Copyright 2013 The Flutter Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
extended_image extended_image
@ -16758,6 +16698,102 @@ skia
Copyright 2020 Google, LLC Copyright 2020 Google, LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
skia
Copyright 2021 Google Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
skia
Copyright 2021 Google LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
skia
Copyright 2021 Google LLC.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
met: met:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3,36 +3,36 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache'; const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache'; const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = { const RESOURCES = {
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1", "icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf", "icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc", "favicon.ico": "51636d3a390451561744c42188ccd628",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978", "manifest.json": "77215c1737c7639764e64a192be2f7b8",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024", "assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "3e722fd57a6db80ee119f0e2c230ccff",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6", "assets/NOTICES": "c3e1cbfaeb1a4f54fadae1bd6558d91b",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541", "assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3", "assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "c1242726c7eac4eb5e843d826f78fb1b", "assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f", "assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac", "assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
"assets/NOTICES": "1965e076d9705b3500fedcfad4bebcdf",
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
"version.json": "6b7a4ad416a3730ae32b64e007cef7f3",
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
"main.dart.js": "970638cb2278a4390edc11bc44e7adf8",
"manifest.json": "77215c1737c7639764e64a192be2f7b8",
"/": "23224b5e03519aaa87594403d54412cf", "/": "23224b5e03519aaa87594403d54412cf",
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35", "version.json": "7e4c19c87f9676a83714d8b531ea766f",
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed", "main.dart.js": "02890c9cc903cb49fedeb25707c8416f",
"favicon.ico": "51636d3a390451561744c42188ccd628" "favicon.png": "dca91c54388f52eded692718d5a98b8b"
}; };
// The application shell files that are downloaded before a service worker can // The application shell files that are downloaded before a service worker can
@ -173,7 +173,7 @@ async function downloadOffline() {
} }
currentContent[key] = true; currentContent[key] = true;
} }
for (var resourceKey in Object.keys(RESOURCES)) { for (var resourceKey of Object.keys(RESOURCES)) {
if (!currentContent[resourceKey]) { if (!currentContent[resourceKey]) {
resources.push(resourceKey); resources.push(resourceKey);
} }

241907
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"app_name":"invoiceninja_flutter","version":"5.0.38","build_number":"38"} {"app_name":"invoiceninja_flutter","version":"5.0.39","build_number":"39"}

View File

@ -1,26 +1,27 @@
@component('email.template.master', ['design' => 'light', 'settings' =>$settings]) @component('email.template.master', ['design' => 'light', 'settings' => $settings])
@slot('header')
@component('email.components.header', ['p' => $title, 'logo' => $logo]) @slot('header')
@include('email.components.header', ['logo' => $logo])
@endslot
<p>{{ $title }}</p>
@slot('greeting')
@lang($message)
@endslot
@component('email.components.button', ['url' => $url])
@lang($button)
@endcomponent @endcomponent
@endslot
<p> @slot('signature')
{!! $message !!} {{ $signature }}
</p> @endslot
@component('email.components.button', ['url' => $url]) @slot('footer')
@lang($button) @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '&copy; InvoiceNinja'])
For any info, please visit InvoiceNinja.
@endcomponent
@endslot
@endcomponent @endcomponent
@slot('signature')
{{ $signature }}
@endslot
@slot('footer')
@component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '&copy; InvoiceNinja'])
For any info, please visit InvoiceNinja.
@endcomponent
@endslot
@endcomponent

View File

@ -1,3 +1,3 @@
<div class="px-10 py-6 flex flex-col items-center"> <a href="{{ $url }}" target="_blank" class="button">
<a href="{{ $url }}" class="bg-green-500 px-4 py-3 text-white leading-tight hover:bg-green-600" style="color: white !important;">{{ $slot }}</a> {{ $slot }}
</div> </a>

View File

@ -1,13 +1,11 @@
<div class="mt-8 text-center break-words"> <p>{{ $slot }}</p>
<p class="block text-center text-sm break-words">{{ $slot }}</p>
@isset($url) @isset($url)
<a href="{{ $url }}" class="text-blue-500 hover:text-blue-600 mt-4 text-sm break-words"> <a href="{{ $url }}" target="_blank">
@isset($url_text) @isset($url_text)
{!! $url_text !!} {!! $url_text !!}
@else @else
{{ $url }} {{ $url }}
@endisset @endisset
</a> </a>
@endisset @endisset
</div>

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light', 'settings' => $settings]) @component('email.template.master', ['design' => 'light'])
@slot('header') @slot('header')
@include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png']) @include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
@endslot @endslot

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light', 'settings' => $settings]) @component('email.template.master', ['design' => 'light'])
@slot('header') @slot('header')
@include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png']) @include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
@endslot @endslot

View File

@ -64,7 +64,12 @@
<table cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;"> <table cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
<tr> <tr>
<td align="center" id="email-content"> <td align="center" id="email-content">
@yield('greeting')
{{ $slot }} {{ $slot }}
@yield('signature')
@yield('footer')
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -50,7 +50,7 @@
</th> </th>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary"> <th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
<span role="button" wire:click="sortBy('balance')" class="cursor-pointer"> <span role="button" wire:click="sortBy('balance')" class="cursor-pointer">
{{ ctrans('texts.balance') }} {{ ctrans('texts.amount') }}
</span> </span>
</th> </th>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary"> <th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">

View File

@ -72,8 +72,10 @@
{{-- Feel free to push anything to header using @push('header') --}} {{-- Feel free to push anything to header using @push('header') --}}
@stack('head') @stack('head')
@if((bool) \App\Utils\Ninja::isSelfHost()) @if((bool) \App\Utils\Ninja::isSelfHost() && !empty($client->getSetting('portal_custom_head')))
{!! $client->getSetting('portal_custom_head') !!} <div class="py-1 text-sm text-center text-white bg-primary">
{!! $client->getSetting('portal_custom_head') !!}
</div>
@endif @endif
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" /> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" />
@ -125,7 +127,9 @@
@stack('footer') @stack('footer')
@if((bool) \App\Utils\Ninja::isSelfHost()) @if((bool) \App\Utils\Ninja::isSelfHost())
{!! $client->getSetting('portal_custom_footer') !!} <div class="py-1 text-sm text-center text-white bg-primary">
{!! $client->getSetting('portal_custom_footer') !!}
</div>
@endif @endif
</footer> </footer>

View File

@ -67,7 +67,7 @@
</div> </div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"> <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500"> <dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.balance') }} {{ ctrans('texts.amount') }}
</dt> </dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ App\Utils\Number::formatMoney($quote->balance, $quote->client) }} {{ App\Utils\Number::formatMoney($quote->balance, $quote->client) }}

View File

@ -68,8 +68,8 @@
</dt> </dt>
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> <dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<select name="encryption" class="input w-full form-select"> <select name="encryption" class="input w-full form-select">
<option value="tls">TLS</option> <option value="tls">STARTTLS</option>
<option value="ssl">SSL</option> <option value="ssl">SSL/TLS</option>
</select> </select>
</dd> </dd>
</div> </div>