mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge pull request #9865 from turbo124/v5-develop
Fixes for recurring invoice queries
This commit is contained in:
commit
a2dc354e2c
@ -1 +1 @@
|
|||||||
5.10.17
|
5.10.18
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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');
|
||||||
|
@ -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();
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
22
composer.lock
generated
@ -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",
|
||||||
|
@ -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),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user