Merge branch 'v5-stable' into yodlee

This commit is contained in:
David Bomba 2022-08-05 11:27:52 +10:00
commit effd1678a5
367 changed files with 333699 additions and 324590 deletions

View File

@ -1 +1 @@
5.5.2
5.5.7

View File

@ -131,9 +131,9 @@ class CreateAccount extends Command
'settings' => null,
]);
CreateCompanyPaymentTerms::dispatchSync($company, $user);
CreateCompanyTaskStatuses::dispatchSync($company, $user);
VersionCheck::dispatchSync();
(new CreateCompanyPaymentTerms($company, $user))->handle();
(new CreateCompanyTaskStatuses($company, $user))->handle();
(new VersionCheck())->handle();
}
private function warmCache()

View File

@ -112,9 +112,9 @@ class DemoMode extends Command
$this->info('Seeding Random Data');
$this->createSmallAccount();
VersionCheck::dispatchSync();
(new VersionCheck())->handle();
CompanySizeCheck::dispatchSync();
(new CompanySizeCheck())->handle();
}
private function createSmallAccount()
@ -164,8 +164,8 @@ class DemoMode extends Command
]);
}
CreateCompanyPaymentTerms::dispatchSync($company, $user);
CreateCompanyTaskStatuses::dispatchSync($company, $user);
(new CreateCompanyPaymentTerms($company, $user))->handle();
(new CreateCompanyTaskStatuses($company, $user))->handle();
$company_token = new CompanyToken;
$company_token->user_id = $user->id;

View File

@ -43,13 +43,13 @@ class HostedUsers extends Command
{
Company::on('db-ninja-01')->each(function ($company) {
if (Ninja::isHosted()) {
\Modules\Admin\Jobs\Account\NinjaUser::dispatchSync([], $company);
(new \Modules\Admin\Jobs\Account\NinjaUser([], $company))->handle();
}
});
Company::on('db-ninja-02')->each(function ($company) {
if (Ninja::isHosted()) {
\Modules\Admin\Jobs\Account\NinjaUser::dispatchSync([], $company);
(new \Modules\Admin\Jobs\Account\NinjaUser([], $company))->handle();
}
});
}

View File

@ -47,6 +47,6 @@ class RecurringCommand extends Command
*/
public function handle()
{
RecurringInvoicesCron::dispatchSync();
(new RecurringInvoicesCron())->handle();
}
}

View File

@ -96,6 +96,6 @@ class SendTestEmails extends Command
$nmo->settings = $user->account->companies()->first()->settings;
$nmo->to_user = $user;
NinjaMailerJob::dispatchSync($nmo);
(new NinjaMailerJob($nmo))->handle();
}
}

View File

@ -12,6 +12,7 @@
namespace App\Factory;
use App\Models\VendorContact;
use Illuminate\Support\Str;
class VendorContactFactory
{
@ -21,6 +22,7 @@ class VendorContactFactory
$vendor_contact->first_name = '';
$vendor_contact->user_id = $user_id;
$vendor_contact->company_id = $company_id;
$vendor_contact->contact_key = Str::random(40);
$vendor_contact->id = 0;
return $vendor_contact;

View File

@ -19,6 +19,8 @@ use Illuminate\Database\Eloquent\Builder;
*/
class ProductFilters extends QueryFilters
{
protected $with_property = 'product_key';
/**
* Filter based on search text.
*

View File

@ -52,6 +52,13 @@ abstract class QueryFilters
*/
protected $builder;
/**
* The "with" filter property column.
*
* var string
*/
protected $with_property = 'id';
/**
* Create a new QueryFilters instance.
*
@ -218,4 +225,11 @@ abstract class QueryFilters
return $this->builder;
}
public function with(string $value): Builder
{
return $this->builder
->orWhere($this->with_property, $value)
->orderByRaw("{$this->with_property} = ? DESC", [$value]);
}
}

View File

@ -31,11 +31,11 @@ class GmailTransport extends AbstractTransport
protected function doSend(SentMessage $message): void
{
nlog("in Do Send");
nlog("In Do Send");
$message = MessageConverter::toEmail($message->getOriginalMessage());
$token = $message->getHeaders()->get('GmailToken')->getValue();
$message->getHeaders()->remove('GmailToken');
$token = $message->getHeaders()->get('gmailtoken')->getValue();
$message->getHeaders()->remove('gmailtoken');
$client = new Client();
$client->setClientId(config('ninja.auth.google.client_id'));
@ -45,7 +45,25 @@ class GmailTransport extends AbstractTransport
$service = new Gmail($client);
$body = new Message();
$body->setRaw($this->base64_encode($message->toString()));
$bccs = $message->getHeaders()->get('Bcc');
$bcc_list = '';
if($bccs)
{
$bcc_list = 'Bcc: ';
foreach($bccs->getAddresses() as $address){
$bcc_list .= $address->getAddress() .',';
}
$bcc_list = rtrim($bcc_list, ",") . "\r\n";
}
$body->setRaw($this->base64_encode($bcc_list.$message->toString()));
$service->users_messages->send('me', $body, []);

View File

@ -16,7 +16,6 @@ use Microsoft\Graph\Graph;
use Microsoft\Graph\Model\UploadSession;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\MessageConverter;
class Office365MailTransport extends AbstractTransport
@ -33,25 +32,40 @@ class Office365MailTransport extends AbstractTransport
$symfony_message = MessageConverter::toEmail($message->getOriginalMessage());
$graph = new Graph();
$token = $symfony_message->getHeaders()->get('GmailToken')->getValue();
$symfony_message->getHeaders()->remove('GmailToken');
$token = $symfony_message->getHeaders()->get('gmailtoken')->getValue();
$symfony_message->getHeaders()->remove('gmailtoken');
$graph->setAccessToken($token);
try {
$graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail')
->attachBody(base64_encode($message->toString()))
->addHeaders(['Content-Type' => 'text/plain'])
->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute();
} catch (\Exception $e) {
sleep(5);
$graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail')
->attachBody(base64_encode($message->toString()))
->addHeaders(['Content-Type' => 'text/plain'])
->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute();
$bccs = $symfony_message->getHeaders()->get('Bcc');
$bcc_list = '';
if($bccs)
{
foreach($bccs->getAddresses() as $address){
$bcc_list .= 'Bcc: "'.$address->getAddress().'" <'.$address->getAddress().'>\r\n';
}
}
try {
$graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail')
->attachBody(base64_encode($bcc_list.$message->toString()))
->addHeaders(['Content-Type' => 'text/plain'])
->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute();
} catch (\Exception $e) {
sleep(5);
$graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail')
->attachBody(base64_encode($bcc_list.$message->toString()))
->addHeaders(['Content-Type' => 'text/plain'])
->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute();
}
}

View File

@ -37,7 +37,7 @@ class ContactLoginController extends Controller
$this->middleware('guest:contact', ['except' => ['logout']]);
}
public function showLoginForm(Request $request)
public function showLoginForm(Request $request, $company_key = false)
{
$company = false;
$account = false;
@ -46,6 +46,13 @@ class ContactLoginController extends Controller
MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
$company = Company::where('company_key', $request->input('company_key'))->first();
}
elseif($request->has('company_key')){
MultiDB::findAndSetDbByCompanyKey($request->input('company_key'));
$company = Company::where('company_key', $request->input('company_key'))->first();
}elseif($company_key){
MultiDB::findAndSetDbByCompanyKey($company_key);
$company = Company::where('company_key', $company_key)->first();
}
if ($company) {
$account = $company->account;

View File

@ -294,7 +294,7 @@ class LoginController extends BaseController
$cu->first()->account->companies->each(function ($company) use ($cu, $request) {
if ($company->tokens()->where('is_system', true)->count() == 0) {
CreateCompanyToken::dispatchSync($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
(new CreateCompanyToken($company, $cu->first()->user, $request->server('HTTP_USER_AGENT')))->handle();
}
});
@ -474,7 +474,7 @@ class LoginController extends BaseController
if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) {
auth()->user()->companies->each(function ($company) {
if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()) {
CreateCompanyToken::dispatchSync($company, auth()->user(), 'Google_O_Auth');
(new CreateCompanyToken($company, auth()->user(), 'Google_O_Auth'))->handle();
}
});
}

View File

@ -84,7 +84,7 @@ class InvitationController extends Controller
->with($entity)
->where('key', $invitation_key)
->with('contact.client')
->first();
->firstOrFail();
if($invitation->{$entity}->is_deleted)
return $this->render('generic.not_available', ['account' => $invitation->company->account, 'company' => $invitation->company]);
@ -119,7 +119,6 @@ class InvitationController extends Controller
return redirect()->route('client.login');
} else {
nlog("else - default - login contact");
request()->session()->invalidate();
auth()->guard('contact')->loginUsingId($client_contact->id, true);
}
@ -195,7 +194,7 @@ class InvitationController extends Controller
$file_name = $invitation->{$entity}->numberFormatter().'.pdf';
$file = CreateRawPdf::dispatchNow($invitation, $invitation->company->db);
$file = (new CreateRawPdf($invitation, $invitation->company->db))->handle();
$headers = ['Content-Type' => 'application/pdf'];

View File

@ -212,8 +212,8 @@ class CompanyController extends BaseController
$this->forced_includes = ['company_user'];
$company = (new CreateCompany($request->all(), auth()->user()->company()->account))->handle();
CreateCompanyPaymentTerms::dispatchSync($company, auth()->user());
CreateCompanyTaskStatuses::dispatchSync($company, auth()->user());
(new CreateCompanyPaymentTerms($company, auth()->user()))->handle();
(new CreateCompanyTaskStatuses($company, auth()->user()))->handle();
$company = $this->company_repo->save($request->all(), $company);

View File

@ -567,6 +567,9 @@ class DesignController extends BaseController
case 'purchase_order':
$company->purchase_orders()->update(['design_id' => $design_id]);
break;
case 'recurring_invoice':
$company->recurring_invoices()->update(['design_id' => $design_id]);
break;
default:
// code...
break;

View File

@ -113,7 +113,6 @@ class ImportController extends Controller
/** @var UploadedFile $file */
foreach ($request->files->get('files') as $entityType => $file) {
$contents = file_get_contents($file->getPathname());
// Store the csv in cache with an expiry of 10 minutes
Cache::put($hash.'-'.$entityType, base64_encode($contents), 600);
}

View File

@ -613,7 +613,6 @@ class PaymentController extends BaseController
// code...
break;
case 'email':
//dispatch email to queue
$payment->service()->sendEmail();
if (! $bulk) {

View File

@ -136,15 +136,6 @@ class SelfUpdateController extends BaseController
//clean up old snappdf installations
$this->cleanOldSnapChromeBinaries();
// try{
// $s = new Snappdf;
// $s->getChromiumPath();
// chmod($this->generatePlatformExecutable($s->getChromiumPath()), 0755);
// }
// catch(\Exception $e){
// nlog("I could not set the file permissions for chrome");
// }
$zipFile = new \PhpZip\ZipFile();
$zipFile->openFile($file);
@ -153,14 +144,6 @@ class SelfUpdateController extends BaseController
$zipFile->close();
// $zip = new \ZipArchive;
// $res = $zip->open($file);
// if ($res === TRUE) {
// $zip->extractTo(base_path());
// $zip->close();
// }
nlog('Finished extracting files');
unlink($file);

View File

@ -145,10 +145,10 @@ class SetupController extends Controller
/* Create the first account. */
if (Account::count() == 0) {
CreateAccount::dispatchSync($request->all(), $request->getClientIp());
(new CreateAccount($request->all(), $request->getClientIp()))->handle();
}
VersionCheck::dispatchSync();
(new VersionCheck())->handle();
$this->buildCache(true);
@ -316,7 +316,7 @@ class SetupController extends Controller
$this->buildCache(true);
SchedulerCheck::dispatchSync();
(new SchedulerCheck())->handle();
return redirect('/');
}

View File

@ -73,7 +73,6 @@ class InvitationController extends Controller
auth()->guard('vendor')->loginUsingId($vendor_contact->id, true);
} else {
nlog("else - default - login contact");
request()->session()->invalidate();
auth()->guard('vendor')->loginUsingId($vendor_contact->id, true);
}

View File

@ -0,0 +1,42 @@
<?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\VendorPortal;
use App\Http\Controllers\Controller;
use App\Http\ViewComposers\PortalComposer;
use App\Models\RecurringInvoice;
use Auth;
class VendorContactHashLoginController extends Controller
{
/**
* Logs a user into the client portal using their contact_key
* @param string $contact_key The contact key
* @return Auth|Redirect
*/
public function login(string $contact_key)
{
return redirect('/vendors/purchase_orders');
}
public function magicLink(string $magic_link)
{
return redirect($this->setRedirectPath());
}
public function errorPage()
{
return render('generic.error', ['title' => session()->get('title'), 'notification' => session()->get('notification')]);
}
}

View File

@ -42,6 +42,7 @@ use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustProxies;
use App\Http\Middleware\UrlSetDb;
use App\Http\Middleware\UserVerified;
use App\Http\Middleware\VendorContactKeyLogin;
use App\Http\Middleware\VendorLocale;
use App\Http\Middleware\VerifyCsrfToken;
use App\Http\Middleware\VerifyHash;
@ -166,6 +167,7 @@ class Kernel extends HttpKernel
'shop_token_auth' => ShopTokenAuth::class,
'phantom_secret' => PhantomSecret::class,
'contact_key_login' => ContactKeyLogin::class,
'vendor_contact_key_login' => VendorContactKeyLogin::class,
'check_client_existence' => CheckClientExistence::class,
'user_verified' => UserVerified::class,
'document_db' => SetDocumentDb::class,

View File

@ -263,6 +263,17 @@ class BillingPortalPurchase extends Component
}
}
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;
}
if (array_key_exists('locale', $this->request_data)) {
$request = $this->request_data;

View File

@ -50,7 +50,6 @@ class SetDomainNameDb
];
if ($company = MultiDB::findAndSetDbByDomain($query)) {
//$request->merge(['company_key' => $company->company_key]);
session()->put('company_key', $company->company_key);
} else {
if ($request->json) {
@ -68,7 +67,6 @@ class SetDomainNameDb
];
if ($company = MultiDB::findAndSetDbByDomain($query)) {
//$request->merge(['company_key' => $company->company_key]);
session()->put('company_key', $company->company_key);
} else {
if ($request->json) {

View File

@ -0,0 +1,155 @@
<?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\Middleware;
use App\Http\ViewComposers\PortalComposer;
use App\Libraries\MultiDB;
use App\Models\Vendor;
use App\Models\VendorContact;
use Auth;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class VendorContactKeyLogin
{
/**
* Handle an incoming request.
*
* Sets a contact LOGGED IN if an appropriate vendor_hash is provided as a query parameter
* OR
* If the contact_key is provided in the route
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::guard('vendor')->check()) {
Auth::guard('vendor')->logout();
$request->session()->invalidate();
}
if ($request->segment(2) && $request->segment(2) == 'magic_link' && $request->segment(3)) {
$payload = Cache::get($request->segment(3));
if (! $payload) {
abort(403, 'Link expired.');
}
$contact_email = $payload['email'];
if ($vendor_contact = VendorContact::where('email', $contact_email)->where('company_id', $payload['company_id'])->first()) {
if (empty($vendor_contact->email)) {
$vendor_contact->email = Str::random(15).'@example.com';
}
$vendor_contact->save();
auth()->guard('vendor')->loginUsingId($vendor_contact->id, true);
if ($request->query('redirect') && ! empty($request->query('redirect'))) {
return redirect()->to($request->query('redirect'));
}
return redirect($this->setRedirectPath());
}
} elseif ($request->segment(3) && config('ninja.db.multi_db_enabled')) {
if (MultiDB::findAndSetDbByContactKey($request->segment(3))) {
if ($vendor_contact = VendorContact::where('contact_key', $request->segment(3))->first()) {
if (empty($vendor_contact->email)) {
$vendor_contact->email = Str::random(6).'@example.com';
}
$vendor_contact->save();
auth()->guard('vendor')->loginUsingId($vendor_contact->id, true);
if ($request->query('next')) {
return redirect()->to($request->query('next'));
}
return redirect($this->setRedirectPath());
}
}
} elseif ($request->segment(2) && $request->segment(2) == 'key_login' && $request->segment(3)) {
if ($vendor_contact = VendorContact::where('contact_key', $request->segment(3))->first()) {
if (empty($vendor_contact->email)) {
$vendor_contact->email = Str::random(6).'@example.com';
$vendor_contact->save();
}
auth()->guard('vendor')->loginUsingId($vendor_contact->id, true);
if ($request->query('next')) {
return redirect($request->query('next'));
}
return redirect($this->setRedirectPath());
}
} elseif ($request->has('vendor_hash') && config('ninja.db.multi_db_enabled')) {
if (MultiDB::findAndSetDbByClientHash($request->input('vendor_hash'))) {
if ($client = Vendor::where('vendor_hash', $request->input('vendor_hash'))->first()) {
$primary_contact = $client->primary_contact()->first();
if (empty($primary_contact->email)) {
$primary_contact->email = Str::random(6).'@example.com';
}
$primary_contact->save();
auth()->guard('vendor')->loginUsingId($primary_contact->id, true);
return redirect($this->setRedirectPath());
}
}
} elseif ($request->has('vendor_hash')) {
if ($client = Vendor::where('vendor_hash', $request->input('vendor_hash'))->first()) {
$primary_contact = $client->primary_contact()->first();
if (empty($primary_contact->email)) {
$primary_contact->email = Str::random(6).'@example.com';
}
$primary_contact->save();
auth()->guard('vendor')->loginUsingId($primary_contact->id, true);
return redirect($this->setRedirectPath());
}
} elseif ($request->segment(3)) {
if ($vendor_contact = VendorContact::where('contact_key', $request->segment(3))->first()) {
if (empty($vendor_contact->email)) {
$vendor_contact->email = Str::random(6).'@example.com';
$vendor_contact->save();
}
auth()->guard('vendor')->loginUsingId($vendor_contact->id, true);
if ($request->query('next')) {
return redirect($request->query('next'));
}
return redirect($this->setRedirectPath());
}
}
//28-02-2022 middleware should not allow this to progress as we should have redirected by this stage.
abort(404, 'Unable to authenticate.');
return $next($request);
}
private function setRedirectPath()
{
return 'vendor/purchase_orders';
}
}

View File

@ -97,10 +97,6 @@ class UpdateClientRequest extends Request
{
$input = $this->all();
if (isset($input['group_settings_id'])) {
$input['group_settings_id'] = $this->decodePrimaryKey($input['group_settings_id']);
}
/* If the user removes the currency we must always set the default */
if (array_key_exists('settings', $input) && ! array_key_exists('currency_id', $input['settings'])) {
$input['settings']['currency_id'] = (string) auth()->user()->company()->settings->currency_id;

View File

@ -23,7 +23,8 @@ class BlackListRule implements Rule
'candassociates.com',
'vusra.com',
'fourthgenet.com',
'arxxwalls.com'
'arxxwalls.com',
'superhostforumla.com'
];
/**

View File

@ -42,7 +42,7 @@ class ExpenseTransformer extends BaseTransformer
'client_id' => isset($data['expense.client'])
? $this->getClientId($data['expense.client'])
: null,
'date' => $clientId,
'date' => strlen($this->getString($data, 'expense.date') > 1) ? date('Y-m-d', strtotime($this->getString($data, 'expense.date'))) : now()->format('Y-m-d'),
'public_notes' => $this->getString($data, 'expense.public_notes'),
'private_notes' => $this->getString($data, 'expense.private_notes'),
'category_id' => isset($data['expense.category'])

View File

@ -84,6 +84,7 @@ class CreateAccount
if (Ninja::isHosted()) {
$sp794f3f->hosted_client_count = config('ninja.quotas.free.clients');
$sp794f3f->hosted_company_count = config('ninja.quotas.free.max_companies');
$sp794f3f->account_sms_verified = true;
// $sp794f3f->trial_started = now();
// $sp794f3f->trial_plan = 'pro';
}
@ -97,8 +98,8 @@ class CreateAccount
$spaa9f78 = (new CreateUser($this->request, $sp794f3f, $sp035a66, true))->handle();
CreateCompanyPaymentTerms::dispatchSync($sp035a66, $spaa9f78);
CreateCompanyTaskStatuses::dispatchSync($sp035a66, $spaa9f78);
(new CreateCompanyPaymentTerms($sp035a66, $spaa9f78))->handle();
(new CreateCompanyTaskStatuses($sp035a66, $spaa9f78))->handle();
if ($spaa9f78) {
auth()->login($spaa9f78, false);

View File

@ -80,7 +80,7 @@ class ZipCredits implements ShouldQueue
$path = $this->credits->first()->client->quote_filepath($invitation);
$this->credits->each(function ($credit) {
CreateEntityPdf::dispatchSync($credit->invitations()->first());
(new CreateEntityPdf($credit->invitations()->first()))->handle();
});
try {

View File

@ -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\Jobs\Cron;
use App\Jobs\RecurringInvoice\SendRecurring;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\RecurringInvoice;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Carbon;
/*@not used*/
class CompanyRecurringCron
{
use Dispatchable;
public $tries = 1;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
public function handle() : void
{
//multiDB environment, need to
foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db);
Company::where('is_disabled', 0)
->whereHas('recurring_invoices', function ($query){
$query->where('next_send_date', '<=', now()->toDateTimeString())
->whereNotNull('next_send_date')
->whereNull('deleted_at')
->where('is_deleted', false)
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('remaining_cycles', '!=', '0')
->whereHas('client', function ($query) {
$query->where('is_deleted', 0)
->where('deleted_at', null);
});
})
->cursor()->each(function ($company){
SendCompanyRecurring::dispatch($company->id, $company->db);
});
}
}
}

View File

@ -62,8 +62,7 @@ class RecurringInvoicesCron
nlog(now()->format('Y-m-d').' Sending Recurring Invoices. Count = '.$recurring_invoices->count());
$recurring_invoices->each(function ($recurring_invoice, $key) {
nlog('Current date = '.now()->format('Y-m-d').' Recurring date = '.$recurring_invoice->next_send_date);
// nlog('Current date = '.now()->format('Y-m-d').' Recurring date = '.$recurring_invoice->next_send_date);
nlog("Trying to send {$recurring_invoice->number}");
/* Special check if we should generate another invoice is the previous one is yet to be paid */
@ -74,7 +73,7 @@ class RecurringInvoicesCron
}
try {
SendRecurring::dispatchSync($recurring_invoice, $recurring_invoice->company->db);
(new SendRecurring($recurring_invoice, $recurring_invoice->company->db))->handle();
} catch (\Exception $e) {
nlog("Unable to sending recurring invoice {$recurring_invoice->id} ".$e->getMessage());
}
@ -103,7 +102,6 @@ class RecurringInvoicesCron
nlog(now()->format('Y-m-d').' Sending Recurring Invoices. Count = '.$recurring_invoices->count());
$recurring_invoices->each(function ($recurring_invoice, $key) {
nlog('Current date = '.now()->format('Y-m-d').' Recurring date = '.$recurring_invoice->next_send_date.' Recurring #id = '.$recurring_invoice->id);
nlog("Trying to send {$recurring_invoice->number}");
@ -114,7 +112,7 @@ class RecurringInvoicesCron
}
try {
SendRecurring::dispatchSync($recurring_invoice, $recurring_invoice->company->db);
(new SendRecurring($recurring_invoice, $recurring_invoice->company->db))->handle();
} catch (\Exception $e) {
nlog("Unable to sending recurring invoice {$recurring_invoice->id} ".$e->getMessage());
}

View File

@ -0,0 +1,91 @@
<?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\Jobs\Cron;
use App\Jobs\RecurringInvoice\SendRecurring;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\RecurringInvoice;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Carbon;
/*@not used*/
class SendCompanyRecurring
{
use Dispatchable;
public $tries = 1;
/**
* Create a new job instance.
*
* @return void
*/
public $company;
public $db;
public function __construct($company_id, $db)
{
$this->company_id = $company_id;
$this->db = $db;
}
/**
* Execute the job.
*
* @return void
*/
public function handle() : void
{
MultiDB::setDB($this->db);
$recurring_invoices = Company::where('id', $this->company_id)
->where('is_disabled', 0)
->whereHas('recurring_invoices', function ($query){
$query->where('next_send_date', '<=', now()->toDateTimeString())
->whereNotNull('next_send_date')
->whereNull('deleted_at')
->where('is_deleted', false)
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('remaining_cycles', '!=', '0')
->whereHas('client', function ($query) {
$query->where('is_deleted', 0)
->where('deleted_at', null);
});
})
->cursor()->each(function ($recurring_invoice){
nlog("Trying to send {$recurring_invoice->number}");
if ($recurring_invoice->company->stop_on_unpaid_recurring) {
if ($recurring_invoice->invoices()->whereIn('status_id', [2, 3])->where('is_deleted', 0)->where('balance', '>', 0)->exists()) {
return;
}
}
try {
(new SendRecurring($recurring_invoice, $recurring_invoice->company->db))->handle();
} catch (\Exception $e) {
nlog("Unable to sending recurring invoice {$recurring_invoice->id} ".$e->getMessage());
}
});
}
}

View File

@ -126,7 +126,7 @@ class EmailEntity implements ShouldQueue
$nmo->reminder_template = $this->reminder_template;
$nmo->entity = $this->entity;
NinjaMailerJob::dispatchSync($nmo);
(new NinjaMailerJob($nmo))->handle();
}
private function resolveEntityString() :string

View File

@ -72,7 +72,7 @@ class CSVIngest implements ShouldQueue
set_time_limit(0);
$engine = $this->bootEngine($this->import_type);
$engine = $this->bootEngine();
foreach (['client', 'product', 'invoice', 'payment', 'vendor', 'expense'] as $entity) {
$engine->import($entity);
@ -106,29 +106,23 @@ class CSVIngest implements ShouldQueue
}
}
private function bootEngine(string $import_type)
private function bootEngine()
{
switch ($import_type) {
switch ($this->import_type) {
case 'csv':
return new Csv($this->request, $this->company);
break;
case 'waveaccounting':
return new Wave($this->request, $this->company);
break;
case 'invoicely':
return new Invoicely($this->request, $this->company);
break;
case 'invoice2go':
return new Invoice2Go($this->request, $this->company);
break;
case 'zoho':
return new Zoho($this->request, $this->company);
break;
case 'freshbooks':
return new Freshbooks($this->request, $this->company);
break;
default:
// code...
nlog("could not return provider");
break;
}
}

View File

@ -80,7 +80,7 @@ class ZipInvoices implements ShouldQueue
$path = $this->invoices->first()->client->invoice_filepath($invitation);
$this->invoices->each(function ($invoice) {
CreateEntityPdf::dispatchSync($invoice->invitations()->first());
(new CreateEntityPdf($invoice->invitations()->first()))->handle();
});
try {

View File

@ -31,6 +31,8 @@ class ClientLedgerBalanceUpdate implements ShouldQueue
public $client;
public $deleteWhenMissingModels = true;
public function __construct(Company $company, Client $client)
{
$this->company = $company;

View File

@ -100,6 +100,8 @@ class NinjaMailerJob implements ShouldQueue
$this->nmo->mailable->replyTo($this->company->owner()->email, $this->company->owner()->present()->name());
}
$this->nmo->mailable->tag($this->company->company_key);
//send email
try {
nlog("trying to send to {$this->nmo->to_user->email} ". now()->toDateTimeString());
@ -115,7 +117,7 @@ class NinjaMailerJob implements ShouldQueue
/* Count the amount of emails sent across all the users accounts */
Cache::increment($this->company->account->key);
} catch (\Exception $e) {
} catch (\Exception | \RuntimeException $e) {
nlog("error failed with {$e->getMessage()}");
@ -228,8 +230,8 @@ class NinjaMailerJob implements ShouldQueue
$this->nmo
->mailable
->from($user->email, $user->name())
->withSwiftMessage(function ($message) use($token) {
$message->getHeaders()->addTextHeader('GmailToken', $token);
->withSymfonyMessage(function ($message) use($token) {
$message->getHeaders()->addTextHeader('gmailtoken', $token);
});
sleep(rand(1,3));
@ -298,8 +300,8 @@ class NinjaMailerJob implements ShouldQueue
$this->nmo
->mailable
->from($user->email, $user->name())
->withSwiftMessage(function ($message) use($token) {
$message->getHeaders()->addTextHeader('GmailToken', $token);
->withSymfonyMessage(function ($message) use($token) {
$message->getHeaders()->addTextHeader('gmailtoken', $token);
});
}

View File

@ -39,7 +39,7 @@ class CheckDbStatus implements ShouldQueue
*/
public function handle()
{
DbStatus::dispatchSync('db-ninja-01', 'db.status.db-ninja-01');
DbStatus::dispatchSync('db-ninja-02', 'db.status.db-ninja-02');
(new DbStatus('db-ninja-01', 'db.status.db-ninja-01'))->handle();
(new DbStatus('db-ninja-02', 'db.status.db-ninja-02'))->handle();
}
}

View File

@ -214,7 +214,7 @@ class SendReminders implements ShouldQueue
if ($this->checkSendSetting($invoice, $template) && $invoice->company->account->hasFeature(Account::FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
nlog('firing email');
EmailEntity::dispatchSync($invitation, $invitation->company, $template);
EmailEntity::dispatch($invitation, $invitation->company, $template)->delay(10);
}
});

View File

@ -89,7 +89,7 @@ class PurchaseOrderEmail implements ShouldQueue
$nmo->reminder_template = 'purchase_order';
$nmo->entity = $invitation->purchase_order;
NinjaMailerJob::dispatchSync($nmo);
NinjaMailerJob::dispatch($nmo)->delay(5);
});
if ($this->purchase_order->invitations->count() >= 1) {

View File

@ -82,7 +82,7 @@ class ZipPurchaseOrders implements ShouldQueue
$path = $this->purchase_orders->first()->vendor->purchase_order_filepath($invitation);
$this->purchase_orders->each(function ($purchase_order) {
CreatePurchaseOrderPdf::dispatchSync($purchase_order->invitations()->first());
(new CreatePurchaseOrderPdf($purchase_order->invitations()->first()))->handle();
});
try {

View File

@ -80,7 +80,7 @@ class ZipQuotes implements ShouldQueue
$path = $this->quotes->first()->client->quote_filepath($invitation);
$this->quotes->each(function ($quote) {
CreateEntityPdf::dispatchSync($quote->invitations()->first());
(new CreateEntityPdf($quote->invitations()->first()))->handle();
});
try {

View File

@ -15,6 +15,7 @@ use App\DataMapper\Analytics\SendRecurringFailure;
use App\Events\Invoice\InvoiceWasEmailed;
use App\Factory\InvoiceInvitationFactory;
use App\Factory\RecurringInvoiceToInvoiceFactory;
use App\Jobs\Cron\AutoBill;
use App\Jobs\Entity\EmailEntity;
use App\Models\Invoice;
use App\Models\RecurringInvoice;
@ -107,21 +108,12 @@ class SendRecurring implements ShouldQueue
$this->recurring_invoice->setCompleted();
}
nlog('next send date = '.$this->recurring_invoice->next_send_date);
nlog('remaining cycles = '.$this->recurring_invoice->remaining_cycles);
nlog('last send date = '.$this->recurring_invoice->last_sent_date);
// nlog('next send date = '.$this->recurring_invoice->next_send_date);
// nlog('remaining cycles = '.$this->recurring_invoice->remaining_cycles);
// nlog('last send date = '.$this->recurring_invoice->last_sent_date);
$this->recurring_invoice->save();
/*
if ($this->recurring_invoice->company->pause_recurring_until_paid){
$this->recurring_invoice->service()
->stop();
}
*/
event('eloquent.created: App\Models\Invoice', $invoice);
if ($invoice->client->getSetting('auto_email_invoice')) {
@ -135,7 +127,7 @@ class SendRecurring implements ShouldQueue
$invoice->invitations->each(function ($invitation) use ($invoice) {
if ($invitation->contact && ! $invitation->contact->trashed() && strlen($invitation->contact->email) >= 1 && $invoice->client->getSetting('auto_email_invoice')) {
try {
EmailEntity::dispatch($invitation, $invoice->company);
EmailEntity::dispatch($invitation, $invoice->company)->delay(10);
} catch (\Exception $e) {
nlog($e->getMessage());
}
@ -147,11 +139,14 @@ class SendRecurring implements ShouldQueue
if ($invoice->client->getSetting('auto_bill_date') == 'on_send_date' && $invoice->auto_bill_enabled) {
nlog("attempting to autobill {$invoice->number}");
$invoice->service()->autoBill();
// $invoice->service()->autoBill();
AutoBill::dispatch($invoice, $this->db)->delay(20);
} elseif ($invoice->client->getSetting('auto_bill_date') == 'on_due_date' && $invoice->auto_bill_enabled) {
if ($invoice->due_date && Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) {
nlog("attempting to autobill {$invoice->number}");
$invoice->service()->autoBill();
// $invoice->service()->autoBill();
AutoBill::dispatch($invoice, $this->db)->delay(20);
}
}
}
@ -188,3 +183,17 @@ class SendRecurring implements ShouldQueue
nlog(print_r($exception->getMessage(), 1));
}
}
/**
*
* 1/8/2022
*
* Improvements here include moving the emailentity and autobilling into the queue.
*
* Further improvements could using the CompanyRecurringCron.php stub which divides
* the recurring invoices into companies and spins them off into their own queue to
* improve parallel processing.
*
* Need to be careful we do not overload redis and OOM.
*/

View File

@ -116,7 +116,7 @@ class StartMigration implements ShouldQueue
throw new NonExistingMigrationFile('Migration file does not exist, or it is corrupted.');
}
Import::dispatchSync($file, $this->company, $this->user);
(new Import($file, $this->company, $this->user))->handle();
Storage::deleteDirectory(public_path("storage/migrations/{$filename}"));

View File

@ -35,17 +35,19 @@ class MailSentListener implements ShouldQueue
*/
public function handle(MessageSent $event)
{
if (property_exists($event->message, 'invitation') && $event->message->invitation) {
MultiDB::setDb($event->message->invitation->company->db);
nlog("mail listener");
nlog($event);
// if (property_exists($event->message, 'invitation') && $event->message->invitation) {
// MultiDB::setDb($event->sent->invitation->company->db);
if ($event->message->getHeaders()->get('x-pm-message-id')) {
$postmark_id = $event->message->getHeaders()->get('x-pm-message-id')->getValue();
// if ($event->message->getHeaders()->get('x-pm-message-id')) {
// $postmark_id = $event->sent->getHeaders()->get('x-pm-message-id')->getValue();
// nlog($postmark_id);
$invitation = $event->message->invitation;
$invitation->message_id = $postmark_id;
$invitation->save();
}
}
// // nlog($postmark_id);
// $invitation = $event->sent->invitation;
// $invitation->message_id = $postmark_id;
// $invitation->save();
// }
// }
}
}

View File

@ -27,6 +27,6 @@ class ReachWorkflowSettings
{
MultiDB::setDb($event->company->db);
QuoteWorkflowSettings::dispatchSync($event->quote);
(new QuoteWorkflowSettings($event->quote))->handle();
}
}

View File

@ -119,11 +119,12 @@ class TemplateEmail extends Mailable
->withSymfonyMessage(function ($message) use ($company) {
$message->getHeaders()->addTextHeader('Tag', $company->company_key);
$message->invitation = $this->invitation;
});
})
->tag($company->company_key);
/*In the hosted platform we need to slow things down a little for Storage to catch up.*/
if(Ninja::isHosted()){
if(Ninja::isHosted() && $this->invitation){
$path = false;
@ -134,12 +135,14 @@ class TemplateEmail extends Mailable
elseif($this->invitation->credit)
$path = $this->client->credit_filepath($this->invitation).$this->invitation->credit->numberFormatter().'.pdf';
sleep(1);
if($path && !Storage::disk(config('filesystems.default'))->exists($path)){
sleep(2);
if(!Storage::disk(config('filesystems.default'))->exists($path)) {
CreateEntityPdf::dispatchSync($this->invitation);
(new CreateEntityPdf($this->invitation))->handle();
sleep(2);
}

View File

@ -113,26 +113,24 @@ class VendorTemplateEmail extends Mailable
->withSymfonyMessage(function ($message) {
$message->getHeaders()->addTextHeader('Tag', $this->company->company_key);
$message->invitation = $this->invitation;
});
})
->tag($this->company->company_key);
/*In the hosted platform we need to slow things down a little for Storage to catch up.*/
// if (Ninja::isHosted()) {
// sleep(1);
// }
if(Ninja::isHosted()){
if(Ninja::isHosted() && $this->invitation){
$path = false;
if($this->invitation->purchase_order)
$path = $this->vendor->purchase_order_filepath($this->invitation).$this->invitation->purchase_order->numberFormatter().'.pdf';
sleep(1);
if($path && !Storage::disk(config('filesystems.default'))->exists($path)){
sleep(2);
if(!Storage::disk(config('filesystems.default'))->exists($path)) {
CreatePurchaseOrderPdf::dispatchSync($this->invitation);
(new CreatePurchaseOrderPdf($this->invitation))->handle();
sleep(2);
}

View File

@ -51,6 +51,9 @@ class Backup extends BaseModel
{
nlog('deleting => '.$this->filename);
if(!$this->filename)
return;
try {
Storage::disk(config('filesystems.default'))->delete($this->filename);
} catch (\Exception $e) {

View File

@ -119,6 +119,7 @@ class Company extends BaseModel
'track_inventory',
'inventory_notification_threshold',
'stock_notification',
'enabled_expense_tax_rates',
];
protected $hidden = [
@ -518,7 +519,7 @@ class Company extends BaseModel
public function owner()
{
return $this->company_users()->withTrashed()->where('is_owner', true)->first()->user;
return $this->company_users()->withTrashed()->where('is_owner', true)->first()?->user;
}
public function resolveRouteBinding($value, $field = null)

View File

@ -129,8 +129,8 @@ class CreditInvitation extends BaseModel
$storage_path = Storage::url($this->credit->client->quote_filepath($this).$this->credit->numberFormatter().'.pdf');
if (! Storage::exists($this->credit->client->credit_filepath($this).$this->credit->numberFormatter().'.pdf')) {
event(new CreditWasUpdated($this, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
CreateEntityPdf::dispatchSync($this);
event(new CreditWasUpdated($this->credit, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
(new CreateEntityPdf($this))->handle();
}
return $storage_path;

View File

@ -112,7 +112,7 @@ class InvoiceInvitation extends BaseModel
if (! Storage::exists($this->invoice->client->invoice_filepath($this).$this->invoice->numberFormatter().'.pdf')) {
event(new InvoiceWasUpdated($this->invoice, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
CreateEntityPdf::dispatchSync($this);
(new CreateEntityPdf($this))->handle();
}
return $storage_path;

View File

@ -134,7 +134,7 @@ class QuoteInvitation extends BaseModel
if (! Storage::exists($this->quote->client->quote_filepath($this).$this->quote->numberFormatter().'.pdf')) {
event(new QuoteWasUpdated($this->quote, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
CreateEntityPdf::dispatchSync($this);
(new CreateEntityPdf($this))->handle();
}
return $storage_path;

View File

@ -172,6 +172,11 @@ class Vendor extends BaseModel
return $this->company->company_key.'/'.$this->vendor_hash.'/'.$contact_key.'/purchase_orders/';
}
public function locale()
{
return $this->company->locale();
}
public function country()
{
return $this->belongsTo(Country::class);

View File

@ -154,4 +154,13 @@ class VendorContact extends Authenticatable implements HasLocalePreference
{
return $this->hasMany(PurchaseOrderInvitation::class);
}
public function getLoginLink()
{
$domain = isset($this->company->portal_domain) ? $this->company->portal_domain : $this->company->domain();
return $domain.'/vendor/key_login/'.$this->contact_key;
}
}

View File

@ -29,7 +29,7 @@ class SpamNotification extends Notification
* @return void
*/
protected array $spam_list;
public array $spam_list;
public function __construct($spam_list)
{
@ -74,43 +74,45 @@ class SpamNotification extends Notification
{
$content = '';
foreach($this->spam_list as $spam_list)
{
// foreach($this->spam_lists as $spam_list)
// {
if(array_key_exists('companies', $spam_list))
if(array_key_exists('companies', $this->spam_list))
{
$content .= " Companies \n";
foreach($spam_list['companies'] as $company)
foreach($this->spam_list['companies'] as $company)
{
$content .= "{$company['name']} - c_key={$company['company_key']} - a_key={$company['account_key']} - {$company['owner']} \n";
}
}
if(array_key_exists('templates', $spam_list))
if(array_key_exists('templates', $this->spam_list))
{
$content .= " Templates \n";
foreach($spam_list['templates'] as $company)
foreach($this->spam_list['templates'] as $company)
{
$content .= "{$company['name']} - c_key={$company['company_key']} - a_key={$company['account_key']} - {$company['owner']} \n";
}
}
if(array_key_exists('users', $spam_list))
if(array_key_exists('users', $this->spam_list))
{
$content .= ' Users \n';
foreach($spam_list['users'] as $user)
foreach($this->spam_list['users'] as $user)
{
$content .= "{$user['email']} - a_key={$user['account_key']} - created={$user['created']} \n";
}
}
}
// }
return (new SlackMessage)
->success()

View File

@ -148,13 +148,15 @@ class CreditCard
private function buildBillingAddress()
{
return [
$data = [
'name' => $this->paytrace->client->present()->name(),
'street_address' => $this->paytrace->client->address1,
'city' => $this->paytrace->client->city,
'state' => $this->paytrace->client->state,
'zip' => $this->paytrace->client->postal_code,
];
nlog($data);
}
public function paymentView($data)

View File

@ -191,21 +191,23 @@ class PaytracePaymentDriver extends BaseDriver
$fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required'];
}
if ($this->company_gateway->require_billing_address) {
$fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required'];
if ($this->company_gateway->require_billing_address) {
$fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_postal_code) {
// if ($this->company_gateway->require_postal_code) {
$fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required'];
}
$fields[] = ['name' => 'client_shipping_city', 'label' => ctrans('texts.shipping_city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_state', 'label' => ctrans('texts.shipping_state'), 'type' => 'text', 'validation' => 'required'];
// }
if ($this->company_gateway->require_shipping_address) {
$fields[] = ['name' => 'client_shipping_address_line_1', 'label' => ctrans('texts.shipping_address1'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_city', 'label' => ctrans('texts.shipping_city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_state', 'label' => ctrans('texts.shipping_state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_postal_code', 'label' => ctrans('texts.shipping_postal_code'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_country_id', 'label' => ctrans('texts.shipping_country'), 'type' => 'text', 'validation' => 'required'];
}

View File

@ -20,6 +20,7 @@ use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\StripePaymentDriver;
use App\PaymentDrivers\Stripe\Jobs\UpdateCustomer;
use Stripe\PaymentIntent;
use Stripe\PaymentMethod;
@ -129,6 +130,8 @@ class CreditCard
public function processSuccessfulPayment()
{
UpdateCustomer::dispatch($this->stripe->company_gateway->company->company_key, $this->stripe->company_gateway->id, $this->stripe->client->id);
$stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method);
$data = [

View File

@ -0,0 +1,92 @@
<?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\PaymentDrivers\Stripe\Jobs;
use App\Jobs\Mail\PaymentFailedMailer;
use App\Jobs\Util\SystemLogger;
use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Stripe\Utilities;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class UpdateCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Utilities;
public $tries = 1;
public $deleteWhenMissingModels = true;
public int $company_gateway_id;
public string $company_key;
private int $client_id;
public function __construct(string $company_key, int $company_gateway_id, int $client_id)
{
$this->company_key = $company_key;
$this->company_gateway_id = $company_gateway_id;
$this->client_id = $client_id;
}
public function handle()
{
MultiDB::findAndSetDbByCompanyKey($this->company_key);
$company = Company::where('company_key', $this->company_key)->first();
if($company->id !== config('ninja.ninja_default_company_id'))
return;
$company_gateway = CompanyGateway::find($this->company_gateway_id);
$client = Client::withTrashed()->find($this->client_id);
$stripe = $company_gateway->driver($client)->init();
$customer = $stripe->findOrCreateCustomer();
//Else create a new record
$data['name'] = $client->present()->name();
$data['phone'] = substr($client->present()->phone(), 0, 20);
$data['address']['line1'] = $client->address1;
$data['address']['line2'] = $client->address2;
$data['address']['city'] = $client->city;
$data['address']['postal_code'] = $client->postal_code;
$data['address']['state'] = $client->state;
$data['address']['country'] = $client->country ? $client->country->iso_3166_2 : '';
$data['shipping']['name'] = $client->present()->name();
$data['shipping']['address']['line1'] = $client->shipping_address1;
$data['shipping']['address']['line2'] = $client->shipping_address2;
$data['shipping']['address']['city'] = $client->shipping_city;
$data['shipping']['address']['postal_code'] = $client->shipping_postal_code;
$data['shipping']['address']['state'] = $client->shipping_state;
$data['shipping']['address']['country'] = $client->shipping_country ? $client->shipping_country->iso_3166_2 : '';
\Stripe\Customer::update($customer->id, $data, $stripe->stripe_connect_auth);
}
}

View File

@ -271,9 +271,9 @@ class EventServiceProvider extends ServiceProvider
],
MessageSending::class => [
],
MessageSent::class => [
MailSentListener::class,
],
// MessageSent::class => [
// MailSentListener::class,
// ],
UserWasCreated::class => [
CreatedUserActivity::class,
SendVerificationNotification::class,

View File

@ -196,7 +196,7 @@ class CreditService
try {
if ($force) {
$this->credit->invitations->each(function ($invitation) {
CreateEntityPdf::dispatchSync($invitation);
(new CreateEntityPdf($invitation))->handle();
});
return $this;
@ -243,7 +243,7 @@ class CreditService
public function deletePdf()
{
$this->credit->invitations->each(function ($invitation) {
UnlinkFile::dispatchSync(config('filesystems.default'), $this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf');
(new UnlinkFile(config('filesystems.default'), $this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf'))->handle();
});
return $this;

View File

@ -45,10 +45,7 @@ class SendEmail
$this->credit->invitations->each(function ($invitation) {
if (! $invitation->contact->trashed() && $invitation->contact->email) {
// $email_builder = (new CreditEmail())->build($invitation, $this->reminder_template);
// EmailCredit::dispatchNow($email_builder, $invitation, $invitation->company);
EmailEntity::dispatchSync($invitation, $invitation->company, $this->reminder_template);
EmailEntity::dispatch($invitation, $invitation->company, $this->reminder_template);
}
});

View File

@ -421,7 +421,7 @@ class InvoiceService
try {
if ($force) {
$this->invoice->invitations->each(function ($invitation) {
CreateEntityPdf::dispatchSync($invitation);
(new CreateEntityPdf($invitation))->handle();
});
return $this;
@ -560,7 +560,7 @@ class InvoiceService
public function adjustInventory($old_invoice = [])
{
if ($this->invoice->company->track_inventory) {
AdjustProductInventory::dispatchSync($this->invoice->company, $this->invoice, $old_invoice);
(new AdjustProductInventory($this->invoice->company, $this->invoice, $old_invoice))->handle();
}
return $this;

View File

@ -55,7 +55,6 @@ class MarkPaid extends AbstractService
$payment->amount = $this->invoice->balance;
$payment->applied = $this->invoice->balance;
$payment->number = $this->getNextPaymentNumber($this->invoice->client, $payment);
$payment->status_id = Payment::STATUS_COMPLETED;
$payment->client_id = $this->invoice->client_id;
$payment->transaction_reference = ctrans('texts.manual_entry');
@ -74,6 +73,8 @@ class MarkPaid extends AbstractService
$payment->saveQuietly();
$payment->service()->applyNumber()->save();
$this->setExchangeRate($payment);
/* Create a payment relationship to the invoice entity */

View File

@ -45,7 +45,7 @@ class SendEmail extends AbstractService
$this->invoice->invitations->each(function ($invitation) {
if (! $invitation->contact->trashed() && $invitation->contact->email) {
EmailEntity::dispatchSync($invitation, $invitation->company, $this->reminder_template);
EmailEntity::dispatch($invitation, $invitation->company, $this->reminder_template)->delay(10);
}
});
}

View File

@ -70,7 +70,6 @@ class NotificationService extends AbstractService
public function ninja()
{
Notification::route('slack', config('ninja.notification.slack'))
->route('mail', config('ninja.notification.mail'))
->notify($this->notification);
}
}

View File

@ -34,13 +34,10 @@ class SendEmail
{
$this->payment->load('company', 'client.contacts');
$this->payment->client->contacts->each(function ($contact) {
if ($contact->email) {
// dispatchSync always returns 0, in this case we can handle it without returning false;
return EmailPayment::dispatchSync($this->payment, $this->payment->company, $contact);
// return false;
//11-01-2021 only send payment receipt to the first contact
}
});
$contact = $this->payment->client->contacts()->first();
if ($contact?->email)
EmailPayment::dispatch($this->payment, $this->payment->company, $contact);
}
}

View File

@ -136,7 +136,7 @@ class QuoteService
try {
if ($force) {
$this->quote->invitations->each(function ($invitation) {
CreateEntityPdf::dispatchSync($invitation);
(new CreateEntityPdf($invitation))->handle();
});
return $this;
@ -225,7 +225,7 @@ class QuoteService
public function deletePdf()
{
$this->quote->invitations->each(function ($invitation) {
UnlinkFile::dispatchSync(config('filesystems.default'), $this->quote->client->quote_filepath($invitation).$this->quote->numberFormatter().'.pdf');
(new UnlinkFile(config('filesystems.default'), $this->quote->client->quote_filepath($invitation).$this->quote->numberFormatter().'.pdf'))->handle();
});
return $this;

View File

@ -63,6 +63,19 @@ class CreateRecurringInvitations extends AbstractService
info($e->getMessage());
}
if ($this->entity->invitations()->count() == 0) {
$invitation = $this->invitation_class::where('company_id', $this->entity->company_id)
->where($this->entity_id_name, $this->entity->id)
->withTrashed()
->first();
if ($invitation)
$invitation->restore();
}
return $this->entity;
}
}

View File

@ -177,6 +177,7 @@ class CompanyTransformer extends EntityTransformer
'inventory_notification_threshold' => (int) $company->inventory_notification_threshold,
'track_inventory' => (bool) $company->track_inventory,
'enable_applying_payments' => (bool) $company->enable_applying_payments,
'enabled_expense_tax_rates' => (int) $company->enabled_expense_tax_rates,
];
}

View File

@ -42,6 +42,7 @@ class VendorContactTransformer extends EntityTransformer
'custom_value2' => $vendor->custom_value2 ?: '',
'custom_value3' => $vendor->custom_value3 ?: '',
'custom_value4' => $vendor->custom_value4 ?: '',
'link' => $vendor->getLoginLink(),
];
}
}

View File

@ -76,7 +76,7 @@ class Helpers
break;
default:
return is_null($value) ? '' : $value;
return is_null($value) ? '' : $this->processReservedKeywords($value, $entity);
break;
}
}

View File

@ -67,9 +67,9 @@ class SystemHealth
'current_php_version' => phpversion(),
'current_php_cli_version' => (string) self::checkPhpCli(),
'is_okay' => version_compare(phpversion(), self::$php_version, '>='),
'memory_limit' => ini_get('memory_limit'),
],
'env_writable' => self::checkEnvWritable(),
//'mail' => self::testMailServer(),
'simple_db_check' => self::simpleDbCheck(),
'cache_enabled' => self::checkConfigCache(),
'phantom_enabled' => (bool) config('ninja.phantomjs_pdf_generation'),

View File

@ -22,9 +22,9 @@ trait Uploadable
{
public function removeLogo($company)
{
if (Storage::exists($company->settings->company_logo)) {
UnlinkFile::dispatchSync(config('filesystems.default'), $company->settings->company_logo);
}
//if (Storage::disk(config('filesystems.default'))->exists($company->settings->company_logo)) {
(new UnlinkFile(config('filesystems.default'), $company->settings->company_logo))->handle();
//}
}
public function uploadLogo($file, $company, $entity)

View File

@ -36,7 +36,7 @@
"ext-json": "*",
"ext-libxml": "*",
"afosto/yaac": "^1.4",
"asm/php-ansible": "^4",
"asm/php-ansible": "^4.0",
"authorizenet/authorizenet": "^2.0",
"awobaz/compoships": "^2.1",
"bacon/bacon-qr-code": "^2.0",
@ -162,4 +162,4 @@
},
"minimum-stability": "dev",
"prefer-stable": true
}
}

40
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bbd6f8107bd70628ea7527c968ca3c8d",
"content-hash": "dd251d0b8181fc819aded8d8d5c6bb07",
"packages": [
{
"name": "afosto/yaac",
@ -378,16 +378,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.231.15",
"version": "3.231.16",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "ba379285d24b609a997bd8b40933d3e0a3826dfb"
"reference": "c50adea1de4ad3d6dda41310a8af5ce13ee876d5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ba379285d24b609a997bd8b40933d3e0a3826dfb",
"reference": "ba379285d24b609a997bd8b40933d3e0a3826dfb",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c50adea1de4ad3d6dda41310a8af5ce13ee876d5",
"reference": "c50adea1de4ad3d6dda41310a8af5ce13ee876d5",
"shasum": ""
},
"require": {
@ -464,9 +464,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.231.15"
"source": "https://github.com/aws/aws-sdk-php/tree/3.231.16"
},
"time": "2022-07-27T18:59:36+00:00"
"time": "2022-07-28T18:17:24+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -7438,16 +7438,16 @@
},
{
"name": "psy/psysh",
"version": "v0.11.7",
"version": "v0.11.8",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
"reference": "77fc7270031fbc28f9a7bea31385da5c4855cb7a"
"reference": "f455acf3645262ae389b10e9beba0c358aa6994e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/77fc7270031fbc28f9a7bea31385da5c4855cb7a",
"reference": "77fc7270031fbc28f9a7bea31385da5c4855cb7a",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/f455acf3645262ae389b10e9beba0c358aa6994e",
"reference": "f455acf3645262ae389b10e9beba0c358aa6994e",
"shasum": ""
},
"require": {
@ -7508,9 +7508,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
"source": "https://github.com/bobthecow/psysh/tree/v0.11.7"
"source": "https://github.com/bobthecow/psysh/tree/v0.11.8"
},
"time": "2022-07-07T13:49:11+00:00"
"time": "2022-07-28T14:25:11+00:00"
},
{
"name": "ralouphie/getallheaders",
@ -16461,16 +16461,16 @@
},
{
"name": "vimeo/psalm",
"version": "4.24.0",
"version": "v4.25.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
"reference": "06dd975cb55d36af80f242561738f16c5f58264f"
"reference": "d7cd84c4ebca74ba3419b9601f81d177bcbe2aac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/06dd975cb55d36af80f242561738f16c5f58264f",
"reference": "06dd975cb55d36af80f242561738f16c5f58264f",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/d7cd84c4ebca74ba3419b9601f81d177bcbe2aac",
"reference": "d7cd84c4ebca74ba3419b9601f81d177bcbe2aac",
"shasum": ""
},
"require": {
@ -16562,9 +16562,9 @@
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
"source": "https://github.com/vimeo/psalm/tree/4.24.0"
"source": "https://github.com/vimeo/psalm/tree/v4.25.0"
},
"time": "2022-06-26T11:47:54+00:00"
"time": "2022-07-25T17:04:37+00:00"
},
{
"name": "webmozart/path-util",
@ -16707,5 +16707,5 @@
"platform-dev": {
"php": "^7.4|^8.0"
},
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.3.0"
}

View File

@ -124,7 +124,6 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
],
'gelf' => [
'driver' => 'custom',
@ -188,5 +187,6 @@ return [
'extra_prefix' => null,
],
]
];

View File

@ -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.2',
'app_tag' => '5.5.2',
'app_version' => '5.5.7',
'app_tag' => '5.5.7',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -44,57 +44,56 @@ return [
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('SES_REGION', 'us-east-1'),
],
'sparkpost' => [
'secret' => env('SPARKPOST_SECRET'),
],
'sparkpost' => [
'secret' => env('SPARKPOST_SECRET'),
],
'gmail' => [
'token' => '',
],
'gmail' => [
'token' => '',
],
'stripe' => [
'model' => App\Models\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
'stripe' => [
'model' => App\Models\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
'github' => [
'client_id' => env('GITHUB_CLIENT_ID'),
'client_secret' => env('GITHUB_CLIENT_SECRET'),
'redirect' => env('GITHUB_OAUTH_REDIRECT'),
],
'github' => [
'client_id' => env('GITHUB_CLIENT_ID'),
'client_secret' => env('GITHUB_CLIENT_SECRET'),
'redirect' => env('GITHUB_OAUTH_REDIRECT'),
],
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_OAUTH_REDIRECT'),
],
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_OAUTH_REDIRECT'),
],
'facebook' => [
'client_id' => env('FACEBOOK_CLIENT_ID'),
'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
'redirect' => env('FACEBOOK_OAUTH_REDIRECT'),
],
'facebook' => [
'client_id' => env('FACEBOOK_CLIENT_ID'),
'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
'redirect' => env('FACEBOOK_OAUTH_REDIRECT'),
],
'linkedin' => [
'client_id' => env('LINKEDIN_CLIENT_ID'),
'client_secret' => env('LINKEDIN_CLIENT_SECRET'),
'redirect' => env('LINKEDIN_OAUTH_REDIRECT'),
],
'linkedin' => [
'client_id' => env('LINKEDIN_CLIENT_ID'),
'client_secret' => env('LINKEDIN_CLIENT_SECRET'),
'redirect' => env('LINKEDIN_OAUTH_REDIRECT'),
],
'twitter' => [
'client_id' => env('TWITTER_CLIENT_ID'),
'client_secret' => env('TWITTER_CLIENT_SECRET'),
'redirect' => env('TWITTER_OAUTH_REDIRECT'),
],
'twitter' => [
'client_id' => env('TWITTER_CLIENT_ID'),
'client_secret' => env('TWITTER_CLIENT_SECRET'),
'redirect' => env('TWITTER_OAUTH_REDIRECT'),
],
'bitbucket' => [
'client_id' => env('BITBUCKET_CLIENT_ID'),
'client_secret' => env('BITBUCKET_CLIENT_SECRET'),
'redirect' => env('BITBUCKET_OAUTH_REDIRECT'),
],
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'bitbucket' => [
'client_id' => env('BITBUCKET_CLIENT_ID'),
'client_secret' => env('BITBUCKET_CLIENT_SECRET'),
'redirect' => env('BITBUCKET_OAUTH_REDIRECT'),
],
];

View File

@ -19,7 +19,12 @@ class AddSmsVerificationToHostedAccount extends Migration
$table->boolean('account_sms_verified')->default(0);
});
App\Models\Account::query()->update(['account_sms_verified' => true]);
App\Models\Account::query()->cursor()->each(function ($account){
$account->account_sms_verified = true;
$account->save();
});
}
/**

View File

@ -0,0 +1,38 @@
<?php
use App\Models\Company;
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('enabled_expense_tax_rates')->default(0);
});
Company::query()->where('enabled_item_tax_rates', true)->cursor()->each(function ($company){
$company->enabled_expense_tax_rates = true;
$company->save();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
};

View File

@ -0,0 +1,38 @@
<?php
use App\Models\Company;
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->unsignedInteger('enabled_expense_tax_rates')->default(0)->change();
});
Company::query()->where('enabled_item_tax_rates', true)->cursor()->each(function ($company){
$company->enabled_expense_tax_rates = $company->enabled_item_tax_rates;
$company->save();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/material_design_icons_flutter/Material Design Icons","fonts":[{"asset":"packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf"}]}]
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"Roboto","fonts":[{"asset":"assets/google_fonts/Roboto-Regular.ttf"}]},{"family":"packages/material_design_icons_flutter/Material Design Icons","fonts":[{"asset":"packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf"}]}]

View File

@ -2347,6 +2347,35 @@ printing
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
--------------------------------------------------------------------------------
bitsdojo_window
bitsdojo_window_linux
bitsdojo_window_macos
bitsdojo_window_platform_interface
bitsdojo_window_windows
MIT License
Copyright (c) 2020-2021 Bogdan Hobeanu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
boardview
@ -6619,7 +6648,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
dart_console
win32
Copyright 2019, the Dart project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -13130,6 +13158,31 @@ 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.
--------------------------------------------------------------------------------
intl_phone_field
MIT License
Copyright (c) 2021 Vansh Goel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
js
@ -15540,6 +15593,8 @@ SOFTWARE.
--------------------------------------------------------------------------------
permission_handler
permission_handler_android
permission_handler_apple
permission_handler_platform_interface
MIT License
@ -15564,6 +15619,31 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
permission_handler_windows
MIT License
Copyright (c) 2018 Baseflow
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
petitparser
xml
@ -15602,6 +15682,31 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
pinput
smart_auth
The MIT License (MIT)
Copyright (c) 2022 Tornike Kurdadze
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
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
USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
platform_detect
@ -16681,6 +16786,31 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing permissions
and limitations under the License.
--------------------------------------------------------------------------------
screen_retriever
window_manager
MIT License
Copyright (c) 2022 LiJianying <lijy91@foxmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
sentry
// Copyright 2014 The Chromium Authors. All rights reserved.
@ -19286,6 +19416,35 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
win32
Copyright 2019, the Dart project 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.
--------------------------------------------------------------------------------
xxhash

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

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