Merge branch 'v5-stable' into yodlee
@ -1 +1 @@
|
||||
5.5.2
|
||||
5.5.7
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -47,6 +47,6 @@ class RecurringCommand extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
RecurringInvoicesCron::dispatchSync();
|
||||
(new RecurringInvoicesCron())->handle();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -19,6 +19,8 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
*/
|
||||
class ProductFilters extends QueryFilters
|
||||
{
|
||||
protected $with_property = 'product_key';
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -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, []);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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'];
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -613,7 +613,6 @@ class PaymentController extends BaseController
|
||||
// code...
|
||||
break;
|
||||
case 'email':
|
||||
//dispatch email to queue
|
||||
$payment->service()->sendEmail();
|
||||
|
||||
if (! $bulk) {
|
||||
|
@ -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);
|
||||
|
@ -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('/');
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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')]);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
155
app/Http/Middleware/VendorContactKeyLogin.php
Normal 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';
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -23,7 +23,8 @@ class BlackListRule implements Rule
|
||||
'candassociates.com',
|
||||
'vusra.com',
|
||||
'fourthgenet.com',
|
||||
'arxxwalls.com'
|
||||
'arxxwalls.com',
|
||||
'superhostforumla.com'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -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'])
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
70
app/Jobs/Cron/CompanyRecurringCron.php
Normal 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);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
91
app/Jobs/Cron/SendCompanyRecurring.php
Normal 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());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -31,6 +31,8 @@ class ClientLedgerBalanceUpdate implements ShouldQueue
|
||||
|
||||
public $client;
|
||||
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public function __construct(Company $company, Client $client)
|
||||
{
|
||||
$this->company = $company;
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
*/
|
@ -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}"));
|
||||
|
||||
|
@ -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();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,6 @@ class ReachWorkflowSettings
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
QuoteWorkflowSettings::dispatchSync($event->quote);
|
||||
(new QuoteWorkflowSettings($event->quote))->handle();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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'];
|
||||
}
|
||||
|
@ -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 = [
|
||||
|
92
app/PaymentDrivers/Stripe/Jobs/UpdateCustomer.php
Normal 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);
|
||||
|
||||
}
|
||||
}
|
@ -271,9 +271,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
],
|
||||
MessageSending::class => [
|
||||
],
|
||||
MessageSent::class => [
|
||||
MailSentListener::class,
|
||||
],
|
||||
// MessageSent::class => [
|
||||
// MailSentListener::class,
|
||||
// ],
|
||||
UserWasCreated::class => [
|
||||
CreatedUserActivity::class,
|
||||
SendVerificationNotification::class,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ class Helpers
|
||||
break;
|
||||
|
||||
default:
|
||||
return is_null($value) ? '' : $value;
|
||||
return is_null($value) ? '' : $this->processReservedKeywords($value, $entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -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'),
|
||||
|
@ -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)
|
||||
|
@ -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
@ -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"
|
||||
}
|
||||
|
@ -124,7 +124,6 @@ return [
|
||||
'emergency' => [
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
],
|
||||
],
|
||||
|
||||
'gelf' => [
|
||||
'driver' => 'custom',
|
||||
@ -188,5 +187,6 @@ return [
|
||||
'extra_prefix' => null,
|
||||
],
|
||||
|
||||
]
|
||||
|
||||
];
|
||||
|
@ -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', ''),
|
||||
|
@ -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'),
|
||||
],
|
||||
|
||||
];
|
||||
|
@ -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();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
@ -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()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -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"}]}]
|
@ -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
|
||||
|
||||
|
BIN
public/assets/assets/google_fonts/Roboto-Regular.ttf
Normal file
BIN
public/assets/packages/intl_phone_field/assets/flags/ad.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/ae.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
public/assets/packages/intl_phone_field/assets/flags/af.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/ag.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/ai.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/al.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/am.png
Normal file
After Width: | Height: | Size: 122 B |
BIN
public/assets/packages/intl_phone_field/assets/flags/an.png
Normal file
After Width: | Height: | Size: 610 B |
BIN
public/assets/packages/intl_phone_field/assets/flags/ao.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/aq.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
public/assets/packages/intl_phone_field/assets/flags/ar.png
Normal file
After Width: | Height: | Size: 991 B |