mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Improve invoice number generation when race conditions encountered
This commit is contained in:
parent
ee6f2012f6
commit
4f10dcd913
@ -1,85 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Quote Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2021. Quote Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Jobs\Quote;
|
|
||||||
|
|
||||||
use App\Libraries\MultiDB;
|
|
||||||
use App\Models\Company;
|
|
||||||
use App\Models\Quote;
|
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
|
||||||
use App\Utils\Traits\NumberFormatter;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
class ApplyQuoteNumber implements ShouldQueue
|
|
||||||
{
|
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, GeneratesCounter;
|
|
||||||
|
|
||||||
private $quote;
|
|
||||||
|
|
||||||
private $settings;
|
|
||||||
|
|
||||||
private $company;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new job instance.
|
|
||||||
*
|
|
||||||
* @param Quote $quote
|
|
||||||
* @param $settings
|
|
||||||
* @param Company $company
|
|
||||||
*/
|
|
||||||
public function __construct(Quote $quote, $settings, Company $company)
|
|
||||||
{
|
|
||||||
$this->quote = $quote;
|
|
||||||
|
|
||||||
$this->settings = $settings;
|
|
||||||
|
|
||||||
$this->company = $company;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the job.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return Quote
|
|
||||||
*/
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
MultiDB::setDB($this->company->db);
|
|
||||||
|
|
||||||
//return early
|
|
||||||
if ($this->quote->number != '') {
|
|
||||||
return $this->quote;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->settings->quote_number_applied) {
|
|
||||||
case 'when_saved':
|
|
||||||
$this->quote->number = $this->getNextQuoteNumber($this->quote->client, $this->quote);
|
|
||||||
break;
|
|
||||||
case 'when_sent':
|
|
||||||
if ($this->quote->status_id == Quote::STATUS_SENT) {
|
|
||||||
$this->quote->number = $this->getNextQuoteNumber($this->quote->client, $this->quote);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// code...
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->quote->save();
|
|
||||||
|
|
||||||
return $this->quote;
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,6 +15,7 @@ use App\Models\Client;
|
|||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Services\AbstractService;
|
use App\Services\AbstractService;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
|
||||||
class ApplyNumber extends AbstractService
|
class ApplyNumber extends AbstractService
|
||||||
{
|
{
|
||||||
@ -24,6 +25,8 @@ class ApplyNumber extends AbstractService
|
|||||||
|
|
||||||
private $credit;
|
private $credit;
|
||||||
|
|
||||||
|
private bool $completed = true;
|
||||||
|
|
||||||
public function __construct(Client $client, Credit $credit)
|
public function __construct(Client $client, Credit $credit)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
@ -37,8 +40,40 @@ class ApplyNumber extends AbstractService
|
|||||||
return $this->credit;
|
return $this->credit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->credit->number = $this->getNextCreditNumber($this->client, $this->credit);
|
$this->trySaving();
|
||||||
|
// $this->credit->number = $this->getNextCreditNumber($this->client, $this->credit);
|
||||||
|
|
||||||
return $this->credit;
|
return $this->credit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function trySaving()
|
||||||
|
{
|
||||||
|
|
||||||
|
$x=1;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
$this->credit->number = $this->getNextCreditNumber($this->client, $this->credit);
|
||||||
|
$this->credit->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(QueryException $e){
|
||||||
|
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if($x>10)
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while($this->completed);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ use App\Models\Client;
|
|||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Services\AbstractService;
|
use App\Services\AbstractService;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
|
||||||
class ApplyNumber extends AbstractService
|
class ApplyNumber extends AbstractService
|
||||||
{
|
{
|
||||||
@ -24,6 +25,8 @@ class ApplyNumber extends AbstractService
|
|||||||
|
|
||||||
private $invoice;
|
private $invoice;
|
||||||
|
|
||||||
|
private $completed = true;
|
||||||
|
|
||||||
public function __construct(Client $client, Invoice $invoice)
|
public function __construct(Client $client, Invoice $invoice)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
@ -39,11 +42,13 @@ class ApplyNumber extends AbstractService
|
|||||||
|
|
||||||
switch ($this->client->getSetting('counter_number_applied')) {
|
switch ($this->client->getSetting('counter_number_applied')) {
|
||||||
case 'when_saved':
|
case 'when_saved':
|
||||||
$this->invoice->number = $this->getNextInvoiceNumber($this->client, $this->invoice, $this->invoice->recurring_id);
|
$this->trySaving();
|
||||||
|
// $this->invoice->number = $this->getNextInvoiceNumber($this->client, $this->invoice, $this->invoice->recurring_id);
|
||||||
break;
|
break;
|
||||||
case 'when_sent':
|
case 'when_sent':
|
||||||
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
||||||
$this->invoice->number = $this->getNextInvoiceNumber($this->client, $this->invoice, $this->invoice->recurring_id);
|
$this->trySaving();
|
||||||
|
// $this->invoice->number = $this->getNextInvoiceNumber($this->client, $this->invoice, $this->invoice->recurring_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -53,4 +58,33 @@ class ApplyNumber extends AbstractService
|
|||||||
|
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function trySaving()
|
||||||
|
{
|
||||||
|
|
||||||
|
$x=1;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
$this->invoice->number = $this->getNextInvoiceNumber($this->client, $this->invoice, $this->invoice->recurring_id);
|
||||||
|
$this->invoice->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(QueryException $e){
|
||||||
|
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if($x>10)
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while($this->completed);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ use App\Models\Client;
|
|||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Services\AbstractService;
|
use App\Services\AbstractService;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
|
||||||
class ApplyRecurringNumber extends AbstractService
|
class ApplyRecurringNumber extends AbstractService
|
||||||
{
|
{
|
||||||
@ -24,6 +25,8 @@ class ApplyRecurringNumber extends AbstractService
|
|||||||
|
|
||||||
private $invoice;
|
private $invoice;
|
||||||
|
|
||||||
|
private bool $completed = true;
|
||||||
|
|
||||||
public function __construct(Client $client, Invoice $invoice)
|
public function __construct(Client $client, Invoice $invoice)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
@ -39,11 +42,13 @@ class ApplyRecurringNumber extends AbstractService
|
|||||||
|
|
||||||
switch ($this->client->getSetting('counter_number_applied')) {
|
switch ($this->client->getSetting('counter_number_applied')) {
|
||||||
case 'when_saved':
|
case 'when_saved':
|
||||||
$this->invoice->number = $this->getNextRecurringInvoiceNumber($this->client, $this->invoice);
|
$this->trySaving();
|
||||||
|
//$this->invoice->number = $this->getNextRecurringInvoiceNumber($this->client, $this->invoice);
|
||||||
break;
|
break;
|
||||||
case 'when_sent':
|
case 'when_sent':
|
||||||
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
||||||
$this->invoice->number = $this->getNextRecurringInvoiceNumber($this->client, $this->invoice);
|
$this->trySaving();
|
||||||
|
// $this->invoice->number = $this->getNextRecurringInvoiceNumber($this->client, $this->invoice);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -54,4 +59,33 @@ class ApplyRecurringNumber extends AbstractService
|
|||||||
|
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function trySaving()
|
||||||
|
{
|
||||||
|
|
||||||
|
$x=1;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
$this->invoice->number = $this->getNextRecurringInvoiceNumber($this->client, $this->invoice);
|
||||||
|
$this->invoice->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(QueryException $e){
|
||||||
|
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if($x>10)
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while($this->completed);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -14,6 +14,7 @@ namespace App\Services\Payment;
|
|||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Services\AbstractService;
|
use App\Services\AbstractService;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
|
||||||
class ApplyNumber extends AbstractService
|
class ApplyNumber extends AbstractService
|
||||||
{
|
{
|
||||||
@ -21,6 +22,8 @@ class ApplyNumber extends AbstractService
|
|||||||
|
|
||||||
private $payment;
|
private $payment;
|
||||||
|
|
||||||
|
private bool $completed = true;
|
||||||
|
|
||||||
public function __construct(Payment $payment)
|
public function __construct(Payment $payment)
|
||||||
{
|
{
|
||||||
$this->client = $payment->client;
|
$this->client = $payment->client;
|
||||||
@ -34,8 +37,38 @@ class ApplyNumber extends AbstractService
|
|||||||
return $this->payment;
|
return $this->payment;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->payment->number = $this->getNextPaymentNumber($this->client, $this->payment);
|
$this->trySaving();
|
||||||
|
// $this->payment->number = $this->getNextPaymentNumber($this->client, $this->payment);
|
||||||
|
|
||||||
return $this->payment;
|
return $this->payment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function trySaving()
|
||||||
|
{
|
||||||
|
|
||||||
|
$x=1;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
$this->payment->number = $this->getNextPaymentNumber($this->client, $this->payment);
|
||||||
|
$this->payment->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(QueryException $e){
|
||||||
|
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if($x>10)
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while($this->completed);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace App\Services\Quote;
|
|||||||
|
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
|
||||||
class ApplyNumber
|
class ApplyNumber
|
||||||
{
|
{
|
||||||
@ -20,6 +21,8 @@ class ApplyNumber
|
|||||||
|
|
||||||
private $client;
|
private $client;
|
||||||
|
|
||||||
|
private bool $completed = true;
|
||||||
|
|
||||||
public function __construct($client)
|
public function __construct($client)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
@ -33,11 +36,13 @@ class ApplyNumber
|
|||||||
|
|
||||||
switch ($this->client->getSetting('counter_number_applied')) {
|
switch ($this->client->getSetting('counter_number_applied')) {
|
||||||
case 'when_saved':
|
case 'when_saved':
|
||||||
$quote->number = $this->getNextQuoteNumber($this->client, $quote);
|
$quote = $this->trySaving($quote);
|
||||||
|
// $quote->number = $this->getNextQuoteNumber($this->client, $quote);
|
||||||
break;
|
break;
|
||||||
case 'when_sent':
|
case 'when_sent':
|
||||||
if ($quote->status_id == Quote::STATUS_SENT) {
|
if ($quote->status_id == Quote::STATUS_SENT) {
|
||||||
$quote->number = $this->getNextQuoteNumber($this->client, $quote);
|
$quote = $this->trySaving($quote);
|
||||||
|
// $quote->number = $this->getNextQuoteNumber($this->client, $quote);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -48,4 +53,34 @@ class ApplyNumber
|
|||||||
|
|
||||||
return $quote;
|
return $quote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function trySaving($quote)
|
||||||
|
{
|
||||||
|
|
||||||
|
$x=1;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
$quote->number = $this->getNextQuoteNumber($this->client, $quote);
|
||||||
|
$quote->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(QueryException $e){
|
||||||
|
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if($x>10)
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while($this->completed);
|
||||||
|
|
||||||
|
return $quote;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace App\Services\Recurring;
|
|||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Services\AbstractService;
|
use App\Services\AbstractService;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
|
||||||
class ApplyNumber extends AbstractService
|
class ApplyNumber extends AbstractService
|
||||||
{
|
{
|
||||||
@ -23,6 +24,8 @@ class ApplyNumber extends AbstractService
|
|||||||
|
|
||||||
private $recurring_entity;
|
private $recurring_entity;
|
||||||
|
|
||||||
|
private bool $completed = true;
|
||||||
|
|
||||||
public function __construct(Client $client, $recurring_entity)
|
public function __construct(Client $client, $recurring_entity)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
@ -36,8 +39,38 @@ class ApplyNumber extends AbstractService
|
|||||||
if ($this->recurring_entity->number != '')
|
if ($this->recurring_entity->number != '')
|
||||||
return $this->recurring_entity;
|
return $this->recurring_entity;
|
||||||
|
|
||||||
$this->recurring_entity->number = $this->getNextRecurringInvoiceNumber($this->client, $this->recurring_entity);
|
$this->trySaving();
|
||||||
|
//$this->recurring_entity->number = $this->getNextRecurringInvoiceNumber($this->client, $this->recurring_entity);
|
||||||
|
|
||||||
return $this->recurring_entity;
|
return $this->recurring_entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function trySaving()
|
||||||
|
{
|
||||||
|
|
||||||
|
$x=1;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
$this->recurring_entity->number = $this->getNextRecurringInvoiceNumber($this->client, $this->recurring_entity);
|
||||||
|
$this->recurring_entity->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(QueryException $e){
|
||||||
|
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if($x>10)
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while($this->completed);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user