diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 85eacbfbe6e9..1db8664c900d 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -100,7 +100,7 @@ class InvoiceController extends BaseController if ($clone) { $invoice->id = $invoice->public_id = null; $invoice->is_public = false; - $invoice->invoice_number = $account->getNextInvoiceNumber($invoice); + $invoice->invoice_number = $account->getNextNumber($invoice); $invoice->balance = $invoice->amount; $invoice->invoice_status_id = 0; $invoice->invoice_date = Utils::today(); diff --git a/app/Models/Account.php b/app/Models/Account.php index fe341944fb8f..73ffcef47654 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -864,7 +864,7 @@ class Account extends Eloquent if ($this->hasClientNumberPattern($invoice) && !$clientId) { // do nothing, we don't yet know the value } elseif ( ! $invoice->invoice_number) { - $invoice->invoice_number = $this->getNextInvoiceNumber($invoice); + $invoice->invoice_number = $this->getNextNumber($invoice); } } diff --git a/app/Models/Client.php b/app/Models/Client.php index 2ec39f8f4b48..d88f5986c0b8 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -535,7 +535,7 @@ class Client extends EntityModel Client::creating(function ($client) { $client->setNullValues(); - $client->account->incrementClientCounter(); + $client->account->incrementCounter($client); }); Client::updating(function ($client) { diff --git a/app/Models/Traits/GeneratesNumbers.php b/app/Models/Traits/GeneratesNumbers.php index 2c7c5dc2fba9..d7b4a410df61 100644 --- a/app/Models/Traits/GeneratesNumbers.php +++ b/app/Models/Traits/GeneratesNumbers.php @@ -11,43 +11,48 @@ use App\Models\Client; trait GeneratesNumbers { /** - * @param $invoice - * @param bool $validateUnique + * @param $entity * @return mixed|string */ - public function getNextInvoiceNumber($invoice, $validateUnique = true) + public function getNextNumber($entity = false) { - if ($this->hasNumberPattern($invoice->invoice_type_id)) { - $number = $this->getNumberPattern($invoice); - } else { - $counter = $this->getCounter($invoice->invoice_type_id); - $prefix = $this->getNumberPrefix($invoice->invoice_type_id); - $counterOffset = 0; - $check = false; + $entity = $entity ?: new Client(); + $entityType = $entity->getEntityType(); - // confirm the invoice number isn't already taken - do { + $counter = $this->getCounter($entityType); + $prefix = $this->getNumberPrefix($entityType); + $counterOffset = 0; + $check = false; + + // confirm the invoice number isn't already taken + do { + if ($this->hasNumberPattern($entityType)) { + $number = $this->applyNumberPattern($entity, $counter); + } else { $number = $prefix . str_pad($counter, $this->invoice_number_padding, '0', STR_PAD_LEFT); - if ($validateUnique) { - $check = Invoice::scope(false, $this->id)->whereInvoiceNumber($number)->withTrashed()->first(); - $counter++; - $counterOffset++; - } - } while ($check); - - // update the invoice counter to be caught up - if ($counterOffset > 1) { - if ($invoice->isType(INVOICE_TYPE_QUOTE) && !$this->share_counter) { - $this->quote_number_counter += $counterOffset - 1; - } else { - $this->invoice_number_counter += $counterOffset - 1; - } - - $this->save(); } + + if ($entity->isEntityType(ENTITY_CLIENT)) { + $check = Client::scope(false, $this->id)->whereIdNumber($number)->withTrashed()->first(); + } else { + $check = Invoice::scope(false, $this->id)->whereInvoiceNumber($number)->withTrashed()->first(); + } + $counter++; + $counterOffset++; + } while ($check); + + // update the counter to be caught up + if ($counterOffset > 1) { + if ($entity->isType(INVOICE_TYPE_QUOTE) && !$this->share_counter) { + $this->quote_number_counter += $counterOffset - 1; + } else { + $this->{$entityType.'_number_counter'} += $counterOffset - 1; + } + + $this->save(); } - if ($invoice->recurring_invoice_id) { + if ($entity->recurring_invoice_id) { $number = $this->recurring_invoice_number_prefix . $number; } @@ -55,33 +60,44 @@ trait GeneratesNumbers } /** - * @param $invoice_type_id + * @param $entityType * @return string */ - public function getNumberPrefix($invoice_type_id) + public function getNumberPrefix($entityType) { if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) { return ''; } - return ($invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_prefix : $this->invoice_number_prefix) ?: ''; + $field = "{$entityType}_number_prefix"; + return $this->$field ?: ''; } /** - * @param $invoice_type_id + * @param $entityType * @return bool */ - public function hasNumberPattern($invoice_type_id) + public function getNumberPattern($entityType) { if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) { return false; } - return $invoice_type_id == INVOICE_TYPE_QUOTE ? ($this->quote_number_pattern ? true : false) : ($this->invoice_number_pattern ? true : false); + $field = "{$entityType}_number_pattern"; + return $this->$field; } /** - * @param $invoice + * @param $entityType + * @return bool + */ + public function hasNumberPattern($entityType) + { + return $this->getNumberPattern($entityType) ? true : false; + } + + /** + * @param $entityType * @return string */ public function hasClientNumberPattern($invoice) @@ -92,12 +108,14 @@ trait GeneratesNumbers } /** - * @param $invoice + * @param $entity * @return bool|mixed */ - public function getNumberPattern($invoice) + public function applyNumberPattern($entity, $counter = 0) { - $pattern = $invoice->invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_pattern : $this->invoice_number_pattern; + $entityType = $entity->getEntityType(); + $counter = $counter ?: $this->getCounter($entityType); + $pattern = $this->getNumberPattern($entityType); if (!$pattern) { return false; @@ -107,11 +125,11 @@ trait GeneratesNumbers $replace = [date('Y')]; $search[] = '{$counter}'; - $replace[] = str_pad($this->getCounter($invoice->invoice_type_id), $this->invoice_number_padding, '0', STR_PAD_LEFT); + $replace[] = str_pad($counter, $this->invoice_number_padding, '0', STR_PAD_LEFT); if (strstr($pattern, '{$userId}')) { $search[] = '{$userId}'; - $replace[] = str_pad(($invoice->user->public_id + 1), 2, '0', STR_PAD_LEFT); + $replace[] = str_pad(($entity->user->public_id + 1), 2, '0', STR_PAD_LEFT); } $matches = false; @@ -125,8 +143,8 @@ trait GeneratesNumbers $pattern = str_replace($search, $replace, $pattern); - if ($invoice->client_id) { - $pattern = $this->getClientInvoiceNumber($pattern, $invoice); + if ($entity->client_id) { + $pattern = $this->getClientInvoiceNumber($pattern, $entity); } return $pattern; @@ -157,12 +175,18 @@ trait GeneratesNumbers } /** - * @param $invoice_type_id + * @param $entityType * @return mixed */ - public function getCounter($invoice_type_id) + public function getCounter($entityType) { - return $invoice_type_id == INVOICE_TYPE_QUOTE && !$this->share_counter ? $this->quote_number_counter : $this->invoice_number_counter; + if ($entityType == ENTITY_CLIENT) { + return $this->client_number_counter; + } elseif ($entityType == ENTITY_QUOTE && ! $this->share_counter) { + return $this->quote_number_counter; + } else { + return $this->invoice_number_counter; + } } /** @@ -172,20 +196,17 @@ trait GeneratesNumbers public function previewNextInvoiceNumber($entityType = ENTITY_INVOICE) { $invoice = $this->createInvoice($entityType); - return $this->getNextInvoiceNumber($invoice); + return $this->getNextNumber($invoice); } /** - * @param $invoice + * @param $entity */ - public function incrementCounter($invoice) + public function incrementCounter($entity) { - // if they didn't use the counter don't increment it - if ($invoice->invoice_number != $this->getNextInvoiceNumber($invoice, false)) { - return; - } - - if ($invoice->isType(INVOICE_TYPE_QUOTE) && !$this->share_counter) { + if ($entity->isEntityType(ENTITY_CLIENT)) { + $this->client_number_counter += 1; + } elseif ($entity->isType(INVOICE_TYPE_QUOTE) && ! $this->share_counter) { $this->quote_number_counter += 1; } else { $this->invoice_number_counter += 1; @@ -194,79 +215,7 @@ trait GeneratesNumbers $this->save(); } - public function getNextClientNumber() - { - if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) { - return ''; - } - - $counter = $this->client_number_counter; - $prefix = $this->client_number_prefix; - $counterOffset = 0; - $check = false; - - // confirm the invoice number isn't already taken - do { - if ($this->client_number_pattern) { - $number = $this->getClientNumberPattern($counter); - } else { - $number = $prefix . str_pad($counter, $this->invoice_number_padding, '0', STR_PAD_LEFT); - } - - $check = Client::scope(false, $this->id)->whereIdNumber($number)->withTrashed()->first(); - $counter++; - $counterOffset++; - } while ($check); - - // update the invoice counter to be caught up - if ($counterOffset > 1) { - $this->client_number_counter += $counterOffset - 1; - $this->save(); - } - - return $number; - } - - private function getClientNumberPattern($counter) - { - $pattern = $this->client_number_pattern; - - if ( ! $pattern) { - return false; - } - - $search = ['{$year}']; - $replace = [date('Y')]; - - $search[] = '{$counter}'; - $replace[] = str_pad($counter, $this->invoice_number_padding, '0', STR_PAD_LEFT); - - if (strstr($pattern, '{$userId}') && Auth::check()) { - $search[] = '{$userId}'; - $replace[] = str_pad((Auth::user()->public_id + 1), 2, '0', STR_PAD_LEFT); - } - - $matches = false; - preg_match('/{\$date:(.*?)}/', $pattern, $matches); - if (count($matches) > 1) { - $format = $matches[1]; - $search[] = $matches[0]; - $date = Carbon::now(session(SESSION_TIMEZONE, DEFAULT_TIMEZONE))->format($format); - $replace[] = str_replace($format, $date, $matches[1]); - } - - return str_replace($search, $replace, $pattern); - } - - public function incrementClientCounter() - { - if ($this->client_number_counter) { - $this->client_number_counter += 1; - $this->save(); - } - } - - public function useClientNumbers() + public function clientNumbersEnabled() { return $this->hasFeature(FEATURE_INVOICE_SETTINGS) && $this->client_number_counter; } diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php index 66a230317377..27be4232e4fb 100644 --- a/app/Ninja/Repositories/AccountRepository.php +++ b/app/Ninja/Repositories/AccountRepository.php @@ -278,7 +278,7 @@ class AccountRepository $invoice->user_id = $account->users()->first()->id; $invoice->public_id = $publicId; $invoice->client_id = $client->id; - $invoice->invoice_number = $account->getNextInvoiceNumber($invoice); + $invoice->invoice_number = $account->getNextNumber($invoice); $invoice->invoice_date = $renewalDate->format('Y-m-d'); $invoice->amount = $invoice->balance = $plan_cost - $credit; $invoice->invoice_type_id = INVOICE_TYPE_STANDARD; diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php index ee0440877bde..5156298e453b 100644 --- a/app/Ninja/Repositories/ClientRepository.php +++ b/app/Ninja/Repositories/ClientRepository.php @@ -79,7 +79,7 @@ class ClientRepository extends BaseRepository } elseif (!$publicId || $publicId == '-1') { $client = Client::createNew(); if (Auth::check() && Auth::user()->account->client_number_counter && empty($data['id_number'])) { - $data['id_number'] = Auth::user()->account->getNextClientNumber(); + $data['id_number'] = Auth::user()->account->getNextNumber(); } } else { $client = Client::scope($publicId)->with('contacts')->firstOrFail(); diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index 3a616fdfb5ca..d40e3fd7e9af 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -659,7 +659,7 @@ class InvoiceRepository extends BaseRepository $invoiceNumber = false; } } - $clone->invoice_number = $invoiceNumber ?: $account->getNextInvoiceNumber($clone); + $clone->invoice_number = $invoiceNumber ?: $account->getNextNumber($clone); $clone->invoice_date = Utils::today(); foreach ([ @@ -859,7 +859,7 @@ class InvoiceRepository extends BaseRepository $invoice->invoice_type_id = INVOICE_TYPE_STANDARD; $invoice->client_id = $recurInvoice->client_id; $invoice->recurring_invoice_id = $recurInvoice->id; - $invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber($invoice); + $invoice->invoice_number = $recurInvoice->account->getNextNumber($invoice); $invoice->amount = $recurInvoice->amount; $invoice->balance = $recurInvoice->amount; $invoice->invoice_date = Utils::today(); diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php index f35bb14b077e..ea675f6c74b1 100644 --- a/app/Services/ImportService.php +++ b/app/Services/ImportService.php @@ -318,7 +318,7 @@ class ImportService if ($entityType == ENTITY_INVOICE && !$data['invoice_number']) { $account = Auth::user()->account; $invoice = Invoice::createNew(); - $data['invoice_number'] = $account->getNextInvoiceNumber($invoice); + $data['invoice_number'] = $account->getNextNumber($invoice); } if (EntityModel::validate($data, $entityType) !== true) { diff --git a/resources/views/accounts/invoice_settings.blade.php b/resources/views/accounts/invoice_settings.blade.php index ed9d8e629874..3c7edac2518b 100644 --- a/resources/views/accounts/invoice_settings.blade.php +++ b/resources/views/accounts/invoice_settings.blade.php @@ -135,7 +135,7 @@ ->label(trans('texts.counter')) ->addGroupClass('pad-checkbox') ->help(trans('texts.client_number_help') . ' ' . - trans('texts.next_client_number', ['number' => $account->getNextClientNumber()])) !!} + trans('texts.next_client_number', ['number' => $account->getNextNumber()])) !!} @if ( ! $account->client_number_counter) diff --git a/resources/views/clients/edit.blade.php b/resources/views/clients/edit.blade.php index d9098f0333bf..a63f7160ebc9 100644 --- a/resources/views/clients/edit.blade.php +++ b/resources/views/clients/edit.blade.php @@ -25,7 +25,7 @@ {!! Former::populate($client) !!} {!! Former::hidden('public_id') !!} @elseif ($account->client_number_counter) - {!! Former::populateField('id_number', $account->getNextClientNumber()) !!} + {!! Former::populateField('id_number', $account->getNextNumber()) !!} @endif