Merge pull request #9865 from turbo124/v5-develop

Fixes for recurring invoice queries
This commit is contained in:
David Bomba 2024-08-05 08:40:06 +10:00 committed by GitHub
commit a2dc354e2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 73 additions and 71 deletions

View File

@ -1 +1 @@
5.10.17 5.10.18

View File

@ -59,9 +59,9 @@ class ExportController extends BaseController
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = auth()->user(); $user = auth()->user();
$hash = Str::uuid(); $hash = Str::uuid()->toString();
$url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]); $url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]);
Cache::put($hash, $url, now()->addHour()); Cache::put($hash, $url, 3600);
CompanyExport::dispatch($user->getCompany(), $user, $hash); CompanyExport::dispatch($user->getCompany(), $user, $hash);

View File

@ -4,15 +4,15 @@ namespace App\Http\Middleware;
use Closure; use Closure;
use Illuminate\Cache\RateLimiter; use Illuminate\Cache\RateLimiter;
use Illuminate\Contracts\Redis\Factory as Redis;
use Illuminate\Redis\Limiters\DurationLimiter; use Illuminate\Redis\Limiters\DurationLimiter;
use Illuminate\Routing\Middleware\ThrottleRequests;
class ThrottleRequestsWithPredis extends ThrottleRequests class ThrottleRequestsWithPredis extends \Illuminate\Routing\Middleware\ThrottleRequests
{ {
/** /**
* The Redis factory implementation. * The Redis factory implementation.
* *
* @var \Illuminate\Redis\Connections\Connection * @var \Illuminate\Contracts\Redis\Factory
*/ */
protected $redis; protected $redis;
@ -34,13 +34,17 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
* Create a new request throttler. * Create a new request throttler.
* *
* @param \Illuminate\Cache\RateLimiter $limiter * @param \Illuminate\Cache\RateLimiter $limiter
* @param \Illuminate\Contracts\Redis\Factory $redis
* @return void * @return void
*/ */
public function __construct(RateLimiter $limiter) public function __construct(RateLimiter $limiter, Redis $redis)
{ {
parent::__construct($limiter); parent::__construct($limiter);
$this->redis = \Illuminate\Support\Facades\Redis::connection('sentinel-cache'); $this->redis = \Illuminate\Support\Facades\Redis::connection('sentinel-cache');
// $this->redis = $redis;
} }
/** /**
@ -56,7 +60,7 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
protected function handleRequest($request, Closure $next, array $limits) protected function handleRequest($request, Closure $next, array $limits)
{ {
foreach ($limits as $limit) { foreach ($limits as $limit) {
if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decayMinutes)) { if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decaySeconds)) {
throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback); throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback);
} }
} }
@ -79,16 +83,13 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
* *
* @param string $key * @param string $key
* @param int $maxAttempts * @param int $maxAttempts
* @param int $decayMinutes * @param int $decaySeconds
* @return mixed * @return mixed
*/ */
protected function tooManyAttempts($key, $maxAttempts, $decayMinutes) protected function tooManyAttempts($key, $maxAttempts, $decaySeconds)
{ {
$limiter = new DurationLimiter( $limiter = new DurationLimiter(
$this->redis, $this->getRedisConnection(), $key, $maxAttempts, $decaySeconds
$key,
$maxAttempts,
$decayMinutes * 60
); );
return tap(! $limiter->acquire(), function () use ($key, $limiter) { return tap(! $limiter->acquire(), function () use ($key, $limiter) {
@ -121,4 +122,14 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
{ {
return $this->decaysAt[$key] - $this->currentTime(); return $this->decaysAt[$key] - $this->currentTime();
} }
/**
* Get the Redis connection that should be used for throttling.
*
* @return \Illuminate\Redis\Connections\Connection
*/
protected function getRedisConnection()
{
return $this->redis;
}
} }

View File

@ -695,7 +695,7 @@ class CompanyExport implements ShouldQueue
$url = Cache::get($this->hash); $url = Cache::get($this->hash);
Cache::put($this->hash, $storage_path, now()->addHour()); Cache::put($this->hash, $storage_path, 3600);
App::forgetInstance('translator'); App::forgetInstance('translator');
$t = app('translator'); $t = app('translator');

View File

@ -48,12 +48,12 @@ class RecurringInvoicesCron
Auth::logout(); Auth::logout();
if (! config('ninja.db.multi_db_enabled')) { if (! config('ninja.db.multi_db_enabled')) {
$recurring_invoices = RecurringInvoice::query()->where('recurring_invoices.status_id', RecurringInvoice::STATUS_ACTIVE) $recurring_invoices = RecurringInvoice::query()->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('recurring_invoices.is_deleted', false) ->where('is_deleted', false)
->where('recurring_invoices.remaining_cycles', '!=', '0') ->where('remaining_cycles', '!=', '0')
->whereNotNull('recurring_invoices.next_send_date') ->whereNotNull('next_send_date')
->whereNull('recurring_invoices.deleted_at') ->whereNull('deleted_at')
->where('recurring_invoices.next_send_date', '<=', now()->toDateTimeString()) ->where('next_send_date', '<=', now()->toDateTimeString())
->whereHas('client', function ($query) { ->whereHas('client', function ($query) {
$query->where('is_deleted', 0) $query->where('is_deleted', 0)
->where('deleted_at', null); ->where('deleted_at', null);
@ -87,27 +87,18 @@ class RecurringInvoicesCron
foreach (MultiDB::$dbs as $db) { foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db); MultiDB::setDB($db);
$recurring_invoices = RecurringInvoice::query()->where('recurring_invoices.status_id', RecurringInvoice::STATUS_ACTIVE) $recurring_invoices = RecurringInvoice::query()->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('recurring_invoices.is_deleted', false) ->where('is_deleted', false)
->where('recurring_invoices.remaining_cycles', '!=', '0') ->where('remaining_cycles', '!=', '0')
->whereNull('recurring_invoices.deleted_at') ->whereNull('deleted_at')
->whereNotNull('recurring_invoices.next_send_date') ->whereNotNull('next_send_date')
->where('recurring_invoices.next_send_date', '<=', now()->toDateTimeString()) ->where('next_send_date', '<=', now()->toDateTimeString())
// ->whereHas('client', function ($query) { ->whereHas('client', function ($query) {
// $query->where('is_deleted', 0) $query->where('is_deleted', 0)
// ->where('deleted_at', null); ->where('deleted_at', null);
// })
// ->whereHas('company', function ($query) {
// $query->where('is_disabled', 0);
// })
->leftJoin('clients', function ($join) {
$join->on('recurring_invoices.client_id', '=', 'clients.id')
->where('clients.is_deleted', 0)
->whereNull('clients.deleted_at');
}) })
->leftJoin('companies', function ($join) { ->whereHas('company', function ($query) {
$join->on('recurring_invoices.company_id', '=', 'companies.id') $query->where('is_disabled', 0);
->where('companies.is_disabled', 0);
}) })
->with('company') ->with('company')
->cursor(); ->cursor();

View File

@ -176,8 +176,8 @@ class SendRecurring implements ShouldQueue
private function createRecurringInvitations($invoice): Invoice private function createRecurringInvitations($invoice): Invoice
{ {
if ($this->recurring_invoice->invitations->count() == 0) { if ($this->recurring_invoice->invitations->count() == 0) {
$this->recurring_invoice->service()->createInvitations()->save(); $this->recurring_invoice = $this->recurring_invoice->service()->createInvitations()->save();
$this->recurring_invoice = $this->recurring_invoice->fresh(); // $this->recurring_invoice = $this->recurring_invoice->fresh();
} }
$this->recurring_invoice->invitations->each(function ($recurring_invitation) use ($invoice) { $this->recurring_invoice->invitations->each(function ($recurring_invitation) use ($invoice) {

View File

@ -61,10 +61,10 @@ class QuoteReminderJob implements ShouldQueue
nrlog("Sending quote reminders on ".now()->format('Y-m-d h:i:s')); nrlog("Sending quote reminders on ".now()->format('Y-m-d h:i:s'));
Quote::query() Quote::query()
->where('quotes.is_deleted', 0) ->where('is_deleted', 0)
->whereIn('quotes.status_id', [Invoice::STATUS_SENT]) ->whereIn('status_id', [Invoice::STATUS_SENT])
->whereNull('quotes.deleted_at') ->whereNull('deleted_at')
->where('quotes.next_send_date', '<=', now()->toDateTimeString()) ->where('next_send_date', '<=', now()->toDateTimeString())
->whereHas('client', function ($query) { ->whereHas('client', function ($query) {
$query->where('is_deleted', 0) $query->where('is_deleted', 0)
->where('deleted_at', null); ->where('deleted_at', null);
@ -88,10 +88,10 @@ class QuoteReminderJob implements ShouldQueue
nrlog("Sending quote reminders on db {$db} ".now()->format('Y-m-d h:i:s')); nrlog("Sending quote reminders on db {$db} ".now()->format('Y-m-d h:i:s'));
Quote::query() Quote::query()
->where('quotes.is_deleted', 0) ->where('is_deleted', 0)
->whereIn('quotes.status_id', [Invoice::STATUS_SENT]) ->whereIn('status_id', [Invoice::STATUS_SENT])
->whereNull('quotes.deleted_at') ->whereNull('deleted_at')
->where('quotes.next_send_date', '<=', now()->toDateTimeString()) ->where('next_send_date', '<=', now()->toDateTimeString())
->whereHas('client', function ($query) { ->whereHas('client', function ($query) {
$query->where('is_deleted', 0) $query->where('is_deleted', 0)
->where('deleted_at', null); ->where('deleted_at', null);

View File

@ -11,17 +11,17 @@
namespace App\Providers; namespace App\Providers;
use App\Http\Middleware\ThrottleRequestsWithPredis;
use App\Models\Scheduler;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Models\Scheduler;
use Illuminate\Http\Request;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Route;
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
use App\Http\Middleware\ThrottleRequestsWithPredis;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider class RouteServiceProvider extends ServiceProvider
{ {

View File

@ -482,7 +482,7 @@ class TemplateService
default => $processed = [], default => $processed = [],
}; };
nlog(json_encode($processed)); // nlog(json_encode($processed));
return $processed; return $processed;

22
composer.lock generated
View File

@ -16665,23 +16665,23 @@
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
"version": "v8.3.0", "version": "v8.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nunomaduro/collision.git", "url": "https://github.com/nunomaduro/collision.git",
"reference": "b49f5b2891ce52726adfd162841c69d4e4c84229" "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/b49f5b2891ce52726adfd162841c69d4e4c84229", "url": "https://api.github.com/repos/nunomaduro/collision/zipball/e7d1aa8ed753f63fa816932bbc89678238843b4a",
"reference": "b49f5b2891ce52726adfd162841c69d4e4c84229", "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"filp/whoops": "^2.15.4", "filp/whoops": "^2.15.4",
"nunomaduro/termwind": "^2.0.1", "nunomaduro/termwind": "^2.0.1",
"php": "^8.2.0", "php": "^8.2.0",
"symfony/console": "^7.1.2" "symfony/console": "^7.1.3"
}, },
"conflict": { "conflict": {
"laravel/framework": "<11.0.0 || >=12.0.0", "laravel/framework": "<11.0.0 || >=12.0.0",
@ -16689,13 +16689,13 @@
}, },
"require-dev": { "require-dev": {
"larastan/larastan": "^2.9.8", "larastan/larastan": "^2.9.8",
"laravel/framework": "^11.16.0", "laravel/framework": "^11.19.0",
"laravel/pint": "^1.16.2", "laravel/pint": "^1.17.1",
"laravel/sail": "^1.30.2", "laravel/sail": "^1.31.0",
"laravel/sanctum": "^4.0.2", "laravel/sanctum": "^4.0.2",
"laravel/tinker": "^2.9.0", "laravel/tinker": "^2.9.0",
"orchestra/testbench-core": "^9.2.1", "orchestra/testbench-core": "^9.2.3",
"pestphp/pest": "^2.34.9 || ^3.0.0", "pestphp/pest": "^2.35.0 || ^3.0.0",
"sebastian/environment": "^6.1.0 || ^7.0.0" "sebastian/environment": "^6.1.0 || ^7.0.0"
}, },
"type": "library", "type": "library",
@ -16758,7 +16758,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2024-07-16T22:41:01+00:00" "time": "2024-08-03T15:32:23+00:00"
}, },
{ {
"name": "phar-io/manifest", "name": "phar-io/manifest",

View File

@ -17,8 +17,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION', '5.10.17'), 'app_version' => env('APP_VERSION', '5.10.18'),
'app_tag' => env('APP_TAG', '5.10.17'), 'app_tag' => env('APP_TAG', '5.10.18'),
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false), 'api_secret' => env('API_SECRET', false),