From 3ada7f9997a8360b3296d046c542ae226110ccb5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 25 Mar 2022 17:12:49 +1100 Subject: [PATCH] Convert shared quote/invoice counters --- app/Services/Invoice/ApplyNumber.php | 1 + app/Services/Quote/ConvertQuote.php | 15 + .../Traits/GeneratesConvertedQuoteCounter.php | 758 ++++++++++++++++++ app/Utils/Traits/GeneratesCounter.php | 17 - .../GeneratesConvertedQuoteCounterTest.php | 178 ++++ 5 files changed, 952 insertions(+), 17 deletions(-) create mode 100644 app/Utils/Traits/GeneratesConvertedQuoteCounter.php create mode 100644 tests/Unit/GeneratesConvertedQuoteCounterTest.php diff --git a/app/Services/Invoice/ApplyNumber.php b/app/Services/Invoice/ApplyNumber.php index 786051fb18..2abdf75299 100644 --- a/app/Services/Invoice/ApplyNumber.php +++ b/app/Services/Invoice/ApplyNumber.php @@ -37,6 +37,7 @@ class ApplyNumber extends AbstractService return $this->invoice; } +nlog($this->invoice->toArray()); switch ($this->client->getSetting('counter_number_applied')) { case 'when_saved': $this->invoice->number = $this->getNextInvoiceNumber($this->client, $this->invoice, $this->invoice->recurring_id); diff --git a/app/Services/Quote/ConvertQuote.php b/app/Services/Quote/ConvertQuote.php index 77137f5c24..ae6875e10e 100644 --- a/app/Services/Quote/ConvertQuote.php +++ b/app/Services/Quote/ConvertQuote.php @@ -17,11 +17,13 @@ use App\Factory\InvoiceInvitationFactory; use App\Models\Invoice; use App\Models\Quote; use App\Repositories\InvoiceRepository; +use App\Utils\Traits\GeneratesConvertedQuoteCounter; use App\Utils\Traits\MakesHash; class ConvertQuote { use MakesHash; + use GeneratesConvertedQuoteCounter; private $client; @@ -49,6 +51,19 @@ class ConvertQuote $invoice_array = $invoice->toArray(); $invoice_array['invitations'] = $invites; + //try and convert the invoice number to a quote number here. + if($this->client->getSetting('shared_invoice_quote_counter')) + { + + $converted_number = $this->harvestQuoteCounter($quote, $invoice, $this->client); + + if($converted_number) + { + $invoice_array['number'] = $converted_number; + } + + } + $invoice = $this->invoice_repo->save($invoice_array, $invoice); $invoice->fresh(); diff --git a/app/Utils/Traits/GeneratesConvertedQuoteCounter.php b/app/Utils/Traits/GeneratesConvertedQuoteCounter.php new file mode 100644 index 0000000000..705709aa81 --- /dev/null +++ b/app/Utils/Traits/GeneratesConvertedQuoteCounter.php @@ -0,0 +1,758 @@ +getMergedSettings(); + + $pattern = $settings->quote_number_pattern; + + if(strlen($pattern) > 1 && (stripos($pattern, 'counter') === false)) + $pattern = $pattern.'{$counter}'; + + $number = $this->applyNumberPattern($quote, '_stubling_', $pattern); + + $prefix_counter = str_replace('_stubling_', "", $number); + $counter = str_replace($prefix_counter, "", $quote->number); + + return $this->getNextEntityNumber($invoice, $client, intval($counter)); + } + + private function getNextEntityNumber($invoice, Client $client, $counter) + { + + $settings = $client->getMergedSettings(); + + $pattern = $settings->invoice_number_pattern; + + if(strlen($pattern) > 1 && (stripos($pattern, 'counter') === false)){ + $pattern = $pattern.'{$counter}'; + } + + $padding = $client->getSetting('counter_padding'); + + $number = $this->padCounter($counter, $padding); + + $number = $this->applyNumberPattern($invoice, $number, $pattern); + + $check = Invoice::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->exists(); + + if($check){ + return false; + } + + return $number; + + } + + private function getNumberPattern($entity, Client $client) + { + $pattern_string = ''; + + switch ($entity) { + case Invoice::class: + $pattern_string = 'invoice_number_pattern'; + break; + case Quote::class: + $pattern_string = 'quote_number_pattern'; + break; + case RecurringInvoice::class: + $pattern_string = 'recurring_invoice_number_pattern'; + break; + case Payment::class: + $pattern_string = 'payment_number_pattern'; + break; + case Credit::class: + $pattern_string = 'credit_number_pattern'; + break; + case Project::class: + $pattern_string = 'project_number_pattern'; + break; + } + + return $client->getSetting($pattern_string); + } + + private function getEntityCounter($entity, $client) + { + switch ($entity) { + case Invoice::class: + return 'invoice_number_counter'; + break; + case Quote::class: + + if ($this->hasSharedCounter($client, 'quote')) + return 'invoice_number_counter'; + + return 'quote_number_counter'; + break; + case RecurringInvoice::class: + return 'recurring_invoice_number_counter'; + break; + case RecurringQuote::class: + return 'recurring_quote_number_counter'; + break; + case RecurringExpense::class: + return 'recurring_expense_number_counter'; + break; + case Payment::class: + return 'payment_number_counter'; + break; + case Credit::class: + if ($this->hasSharedCounter($client, 'credit')) + return 'invoice_number_counter'; + + return 'credit_number_counter'; + break; + case Project::class: + return 'project_number_counter'; + break; + + default: + return 'default_number_counter'; + break; + } + } + + /** + * Gets the next invoice number. + * + * @param Client $client The client + * + * @param Invoice|null $invoice + * @return string The next invoice number. + */ + public function getNextInvoiceNumber(Client $client, ?Invoice $invoice, $is_recurring = false) :string + { + $entity_number = $this->getNextEntityNumber(Invoice::class, $client, $is_recurring); + + return $this->replaceUserVars($invoice, $entity_number); + } + + /** + * Gets the next credit number. + * + * @param Client $client The client + * + * @return string The next credit number. + */ + public function getNextCreditNumber(Client $client, ?Credit $credit) :string + { + $entity_number = $this->getNextEntityNumber(Credit::class, $client); + + return $this->replaceUserVars($credit, $entity_number); + + } + + /** + * Gets the next quote number. + * + * @param Client $client The client + * + * @return string The next credit number. + */ + public function getNextQuoteNumber(Client $client, ?Quote $quote) + { + $entity_number = $this->getNextEntityNumber(Quote::class, $client); + + return $this->replaceUserVars($quote, $entity_number); + + } + + public function getNextRecurringInvoiceNumber(Client $client, $recurring_invoice) + { + $entity_number = $this->getNextEntityNumber(RecurringInvoice::class, $client); + + return $this->replaceUserVars($recurring_invoice, $entity_number); + + } + + public function getNextRecurringQuoteNumber(Client $client, $recurring_quote) + { + $entity_number = $this->getNextEntityNumber(RecurringQuote::class, $client); + + return $this->replaceUserVars($recurring_quote, $entity_number); + + } + + /** + * Gets the next Payment number. + * + * @param Client $client The client + * + * @return string The next payment number. + */ + public function getNextPaymentNumber(Client $client, ?Payment $payment) :string + { + $entity_number = $this->getNextEntityNumber(Payment::class, $client); + + return $this->replaceUserVars($payment, $entity_number); + + } + + /** + * Gets the next client number. + * + * @param Client $client The client + * + * @return string The next client number. + * @throws \Exception + */ + public function getNextClientNumber(Client $client) :string + { + //Reset counters if enabled + $this->resetCounters($client); + + $counter = $client->getSetting('client_number_counter'); + $setting_entity = $client->getSettingEntity('client_number_counter'); + + $client_number = $this->checkEntityNumber(Client::class, $client, $counter, $client->getSetting('counter_padding'), $client->getSetting('client_number_pattern')); + + $this->incrementCounter($setting_entity, 'client_number_counter'); + + $entity_number = $client_number; + + return $this->replaceUserVars($client, $entity_number); + + } + + + /** + * Gets the next client number. + * + * @param Vendor $vendor The vendor + * @return string The next vendor number. + */ + public function getNextVendorNumber(Vendor $vendor) :string + { + $this->resetCompanyCounters($vendor->company); + + $counter = $vendor->company->settings->vendor_number_counter; + $setting_entity = $vendor->company->settings->vendor_number_counter; + + $vendor_number = $this->checkEntityNumber(Vendor::class, $vendor, $counter, $vendor->company->settings->counter_padding, $vendor->company->settings->vendor_number_pattern); + + $this->incrementCounter($vendor->company, 'vendor_number_counter'); + + $entity_number = $vendor_number; + + return $this->replaceUserVars($vendor, $entity_number); + + } + + /** + * Project Number Generator. + * @param Project $project + * @return string The project number + */ + public function getNextProjectNumber(Project $project) :string + { + $entity_number = $this->getNextEntityNumber(Project::class, $project->client, false); + + return $this->replaceUserVars($project, $entity_number); + } + + + /** + * Gets the next task number. + * + * @param Task $task The task + * @return string The next task number. + */ + public function getNextTaskNumber(Task $task) :string + { + $this->resetCompanyCounters($task->company); + + $counter = $task->company->settings->task_number_counter; + $setting_entity = $task->company->settings->task_number_counter; + + $task_number = $this->checkEntityNumber(Task::class, $task, $counter, $task->company->settings->counter_padding, $task->company->settings->task_number_pattern); + + $this->incrementCounter($task->company, 'task_number_counter'); + + $entity_number = $task_number; + + return $this->replaceUserVars($task, $entity_number); + + } + + /** + * Gets the next expense number. + * + * @param Expense $expense The expense + * @return string The next expense number. + */ + public function getNextExpenseNumber(Expense $expense) :string + { + $this->resetCompanyCounters($expense->company); + + $counter = $expense->company->settings->expense_number_counter; + $setting_entity = $expense->company->settings->expense_number_counter; + + $expense_number = $this->checkEntityNumber(Expense::class, $expense, $counter, $expense->company->settings->counter_padding, $expense->company->settings->expense_number_pattern); + + $this->incrementCounter($expense->company, 'expense_number_counter'); + + $entity_number = $expense_number; + + return $this->replaceUserVars($expense, $entity_number); + + } + + /** + * Gets the next expense number. + * + * @param RecurringExpense $expense The expense + * @return string The next expense number. + */ + public function getNextRecurringExpenseNumber(RecurringExpense $expense) :string + { + $this->resetCompanyCounters($expense->company); + + // - 18/09/21 need to set this property if it doesn't exist. //todo refactor this for other properties + if(!property_exists($expense->company->settings, 'recurring_expense_number_counter')){ + $settings = $expense->company->settings; + $settings->recurring_expense_number_counter = 1; + $settings->recurring_expense_number_pattern = ''; + $expense->company->settings = $settings; + $expense->company->save(); + } + + $counter = $expense->company->settings->recurring_expense_number_counter; + $setting_entity = $expense->company->settings->recurring_expense_number_counter; + + $expense_number = $this->checkEntityNumber(RecurringExpense::class, $expense, $counter, $expense->company->settings->counter_padding, $expense->company->settings->recurring_expense_number_pattern); + + $this->incrementCounter($expense->company, 'recurring_expense_number_counter'); + + $entity_number = $expense_number; + + return $this->replaceUserVars($expense, $entity_number); + + } + + + /** + * Determines if it has shared counter. + * + * @param Client $client The client + * + * @return bool True if has shared counter, False otherwise. + */ + public function hasSharedCounter(Client $client, string $type = 'quote') : bool + { + if($type == 'quote') + return (bool) $client->getSetting('shared_invoice_quote_counter'); + + if($type == 'credit') + return (bool) $client->getSetting('shared_invoice_credit_counter'); + } + + /** + * Checks that the number has not already been used. + * + * @param $class + * @param Collection $entity The entity ie App\Models\Client, Invoice, Quote etc + * @param int $counter The counter + * @param int $padding The padding + * + * @param string $pattern + * @param string $prefix + * @return string The padded and prefixed entity number + */ + private function checkEntityNumber($class, $entity, $counter, $padding, $pattern, $prefix = '') + { + + $check = false; + $check_counter = 1; + + do { + + $number = $this->padCounter($counter, $padding); + + $number = $this->applyNumberPattern($entity, $number, $pattern); + + $number = $this->prefixCounter($number, $prefix); + + $check = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->exists(); + + $counter++; + $check_counter++; + + if($check_counter > 100) + return $number . "_" . Str::random(5); + + } while ($check); + + return $number; + } + + + /*Check if a number is available for use. */ + public function checkNumberAvailable($class, $entity, $number) :bool + { + + if ($entity = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->exists()) + return false; + + return true; + + } + + /** + * Saves counters at both the company and client level. + * + * @param $entity + * @param string $counter_name The counter name + */ + private function incrementCounter($entity, string $counter_name) :void + { + $settings = $entity->settings; + + if ($counter_name == 'invoice_number_counter' && ! property_exists($entity->settings, 'invoice_number_counter')) { + $settings->invoice_number_counter = 0; + } + + if(!property_exists($settings, $counter_name)) + $settings->{$counter_name} = 1; + + $settings->{$counter_name} = $settings->{$counter_name} + 1; + + $entity->settings = $settings; + + $entity->save(); + } + + private function prefixCounter($counter, $prefix) : string + { + if (strlen($prefix) == 0) { + return $counter; + } + + return $prefix.$counter; + } + + /** + * Pads a number with leading 000000's. + * + * @param int $counter The counter + * @param int $padding The padding + * + * @return string the padded counter + */ + private function padCounter($counter, $padding) :string + { + return str_pad($counter, $padding, '0', STR_PAD_LEFT); + } + + /** + * If we are using counter reset, + * check if we need to reset here. + * + * @param Client $client client entity + * @return void + */ + private function resetCounters(Client $client) + { + $reset_counter_frequency = (int)$client->getSetting('reset_counter_frequency_id'); + + if($reset_counter_frequency == 0) + return; + + $timezone = Timezone::find($client->getSetting('timezone_id')); + + $reset_date = Carbon::parse($client->getSetting('reset_counter_date'), $timezone->name); + + if (! $reset_date->lte(now()) || ! $client->getSetting('reset_counter_date')) { + return false; + } + + switch ($reset_counter_frequency) { + case RecurringInvoice::FREQUENCY_DAILY: + $new_reset_date = $reset_date->addDay(); + break; + case RecurringInvoice::FREQUENCY_WEEKLY: + $new_reset_date = $reset_date->addWeek(); + break; + case RecurringInvoice::FREQUENCY_TWO_WEEKS: + $new_reset_date = $reset_date->addWeeks(2); + break; + case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + $new_reset_date = $reset_date->addWeeks(4); + break; + case RecurringInvoice::FREQUENCY_MONTHLY: + $new_reset_date = $reset_date->addMonth(); + break; + case RecurringInvoice::FREQUENCY_TWO_MONTHS: + $new_reset_date = $reset_date->addMonths(2); + break; + case RecurringInvoice::FREQUENCY_THREE_MONTHS: + $new_reset_date = $reset_date->addMonths(3); + break; + case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + $new_reset_date = $reset_date->addMonths(4); + break; + case RecurringInvoice::FREQUENCY_SIX_MONTHS: + $new_reset_date = $reset_date->addMonths(6); + break; + case RecurringInvoice::FREQUENCY_ANNUALLY: + $new_reset_date = $reset_date->addYear(); + break; + case RecurringInvoice::FREQUENCY_TWO_YEARS: + $new_reset_date = $reset_date->addYears(2); + break; + + default: + $new_reset_date = $reset_date->addYear(); + break; + } + + $settings = $client->company->settings; + $settings->reset_counter_date = $new_reset_date->format('Y-m-d'); + $settings->invoice_number_counter = 1; + $settings->quote_number_counter = 1; + $settings->credit_number_counter = 1; + + $client->company->settings = $settings; + $client->company->save(); + + } + + private function resetCompanyCounters($company) + { + $timezone = Timezone::find($company->settings->timezone_id); + + $reset_date = Carbon::parse($company->settings->reset_counter_date, $timezone->name); + + if (! $reset_date->lte(now()) || ! $company->settings->reset_counter_date) { + return false; + } + + switch ($company->reset_counter_frequency_id) { + case RecurringInvoice::FREQUENCY_DAILY: + $reset_date->addDay(); + break; + case RecurringInvoice::FREQUENCY_WEEKLY: + $reset_date->addWeek(); + break; + case RecurringInvoice::FREQUENCY_TWO_WEEKS: + $reset_date->addWeeks(2); + break; + case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + $reset_date->addWeeks(4); + break; + case RecurringInvoice::FREQUENCY_MONTHLY: + $reset_date->addMonth(); + break; + case RecurringInvoice::FREQUENCY_TWO_MONTHS: + $reset_date->addMonths(2); + break; + case RecurringInvoice::FREQUENCY_THREE_MONTHS: + $reset_date->addMonths(3); + break; + case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + $reset_date->addMonths(4); + break; + case RecurringInvoice::FREQUENCY_SIX_MONTHS: + $reset_date->addMonths(6); + break; + case RecurringInvoice::FREQUENCY_ANNUALLY: + $reset_date->addYear(); + break; + case RecurringInvoice::FREQUENCY_TWO_YEARS: + $reset_date->addYears(2); + break; + } + + $settings = $company->settings; + $settings->reset_counter_date = $reset_date->format('Y-m-d'); + $settings->invoice_number_counter = 1; + $settings->quote_number_counter = 1; + $settings->credit_number_counter = 1; + $settings->vendor_number_counter = 1; + $settings->ticket_number_counter = 1; + $settings->payment_number_counter = 1; + $settings->project_number_counter = 1; + $settings->task_number_counter = 1; + $settings->expense_number_counter = 1; + $settings->recurring_expense_number_counter =1; + + $company->settings = $settings; + $company->save(); + } + + /** + * Formats a entity number by pattern + * + * @param BaseModel $entity The entity object + * @param string $counter The counter + * @param null|string $pattern The pattern + * + * @return string The formatted number pattern + */ + private function applyNumberPattern($entity, string $counter, $pattern) :string + { + if (! $pattern) { + return $counter; + } + + $search = ['{$year}']; + $replace = [date('Y')]; + + $search[] = '{$counter}'; + $replace[] = $counter; + + $search[] = '{$client_counter}'; + $replace[] = $counter; + + $search[] = '{$clientCounter}'; + $replace[] = $counter; + + $search[] = '{$group_counter}'; + $replace[] = $counter; + + $search[] = '{$year}'; + $replace[] = date('Y'); + + if (strstr($pattern, '{$user_id}') || strstr($pattern, '{$userId}')) { + $user_id = $entity->user_id ? $entity->user_id : 0; + $search[] = '{$user_id}'; + $replace[] = str_pad(($user_id), 2, '0', STR_PAD_LEFT); + $search[] = '{$userId}'; + $replace[] = str_pad(($user_id), 2, '0', STR_PAD_LEFT); + } + + $matches = false; + preg_match('/{\$date:(.*?)}/', $pattern, $matches); + if (count($matches) > 1) { + $format = $matches[1]; + $search[] = $matches[0]; + + /* The following adjusts for the company timezone - may bork tests depending on the time of day the tests are run!!!!!!*/ + $date = Carbon::now($entity->company->timezone()->name)->format($format); + $replace[] = str_replace($format, $date, $matches[1]); + } + + if ($entity instanceof Vendor) { + $search[] = '{$vendor_id_number}'; + $replace[] = $entity->id_number; + } + + if ($entity instanceof Expense) { + if ($entity->vendor) { + $search[] = '{$vendor_id_number}'; + $replace[] = $entity->vendor->id_number; + + $search[] = '{$vendor_number}'; + $replace[] = $entity->vendor->number; + + $search[] = '{$vendor_custom1}'; + $replace[] = $entity->vendor->custom_value1; + + $search[] = '{$vendor_custom2}'; + $replace[] = $entity->vendor->custom_value2; + + $search[] = '{$vendor_custom3}'; + $replace[] = $entity->vendor->custom_value3; + + $search[] = '{$vendor_custom4}'; + $replace[] = $entity->vendor->custom_value4; + } + + $search[] = '{$expense_id_number}'; + $replace[] = $entity->id_number; + } + + if ($entity->client || ($entity instanceof Client)) { + $client = $entity->client ?: $entity; + + $search[] = '{$client_custom1}'; + $replace[] = $client->custom_value1; + + $search[] = '{$clientCustom1}'; + $replace[] = $client->custom_value1; + + $search[] = '{$client_custom2}'; + $replace[] = $client->custom_value2; + + $search[] = '{$clientCustom2}'; + $replace[] = $client->custom_value2; + + $search[] = '{$client_custom3}'; + $replace[] = $client->custom_value3; + + $search[] = '{$client_custom4}'; + $replace[] = $client->custom_value4; + + $search[] = '{$client_number}'; + $replace[] = $client->number; + + $search[] = '{$client_id_number}'; + $replace[] = $client->id_number; + + $search[] = '{$clientIdNumber}'; + $replace[] = $client->id_number; + } + + return str_replace($search, $replace, $pattern); + } + + private function replaceUserVars($entity, $pattern) + { + + if(!$entity) + return $pattern; + + $search = []; + $replace = []; + + $search[] = '{$user_custom1}'; + $replace[] = $entity->user->custom_value1; + + $search[] = '{$user_custom2}'; + $replace[] = $entity->user->custom_value2; + + $search[] = '{$user_custom3}'; + $replace[] = $entity->user->custom_value3; + + $search[] = '{$user_custom4}'; + $replace[] = $entity->user->custom_value4; + + return str_replace($search, $replace, $pattern); + + } +} diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index d84793295f..57180e986f 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -293,26 +293,9 @@ trait GeneratesCounter */ public function getNextProjectNumber(Project $project) :string { - // 08/12/2021 - allows projects to have client counters. - - // $this->resetCompanyCounters($project->company); - - // $counter = $project->company->settings->project_number_counter; - // $setting_entity = $project->company->settings->project_number_counter; - - // $project_number = $this->checkEntityNumber(Project::class, $project, $counter, $project->company->settings->counter_padding, $project->company->settings->project_number_pattern); - - // $this->incrementCounter($project->company, 'project_number_counter'); - - // $entity_number = $project_number; - - // return $this->replaceUserVars($project, $entity_number); - $entity_number = $this->getNextEntityNumber(Project::class, $project->client, false); return $this->replaceUserVars($project, $entity_number); - - } diff --git a/tests/Unit/GeneratesConvertedQuoteCounterTest.php b/tests/Unit/GeneratesConvertedQuoteCounterTest.php new file mode 100644 index 0000000000..f16a6e40bf --- /dev/null +++ b/tests/Unit/GeneratesConvertedQuoteCounterTest.php @@ -0,0 +1,178 @@ +faker = \Faker\Factory::create(); + Model::reguard(); + + } + + public function testCounterExtraction() + { + + $user = User::whereEmail('user@example.com')->first(); + + $user_id = $user->id; + + $this->account = Account::factory()->create([ + 'hosted_client_count' => 1000, + 'hosted_company_count' => 1000 + ]); + + $this->account->num_users = 3; + $this->account->save(); + + $this->company = Company::factory()->create([ + 'account_id' => $this->account->id, + ]); + + $this->client = Client::factory()->create([ + 'user_id' => $user_id, + 'company_id' => $this->company->id, + ]); + + $contact = ClientContact::factory()->create([ + 'user_id' => $user_id, + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'is_primary' => 1, + 'send_email' => true, + ]); + + $settings = $this->client->getMergedSettings(); + $settings->invoice_number_counter = 1; + $settings->invoice_number_pattern = '{$year}-I{$counter}'; + $settings->quote_number_pattern = '{$year}-Q{$counter}'; + $settings->shared_invoice_quote_counter = 1; + $this->company->settings = $settings; + + $this->company->save(); + + $this->client->settings = $settings; + $this->client->save(); + + $quote = Quote::factory()->create([ + 'user_id' => $this->client->user_id, + 'company_id' => $this->client->company_id, + 'client_id' => $this->client->id + ]); + + $quote = $quote->service()->markSent()->convert()->save(); + + $invoice = Invoice::find($quote->invoice_id); + + $this->assertNotNull($invoice); + + $this->assertEquals('2022-Q0001', $quote->number); + $this->assertEquals('2022-I0001', $invoice->number); + + } + + // public function testResetCounter() + // { + // $timezone = Timezone::find(1); + + // $date_formatted = now($timezone->name)->format('Ymd'); + + // $settings = $this->company->settings; + // $settings->invoice_number_pattern = '{$date:Ymd}-{$counter}'; + // $settings->timezone_id = 1; + // $this->company->settings = $settings; + // $this->company->save(); + + // $this->client->settings = $settings; + // $this->client->save(); + + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0001", $invoice_number); + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0002", $invoice_number); + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0003", $invoice_number); + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0004", $invoice_number); + + // $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); + // $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; + // $this->company->settings = $settings; + // $this->company->save(); + + // $this->client->settings = $settings; + // $this->client->save(); + + // $this->travel(5)->days(); + // $date_formatted = now($timezone->name)->format('Ymd'); + + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0001", $invoice_number); + + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0002", $invoice_number); + + // $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); + // $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; + // $this->company->settings = $settings; + // $this->company->save(); + + // $this->travel(5)->days(); + // $date_formatted = now($timezone->name)->format('Ymd'); + + // $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); + // $this->assertEquals($date_formatted."-0001", $invoice_number); + + // $this->travelBack(); + + // } + + // public function testHasSharedCounter() + // { + // $this->assertFalse($this->hasSharedCounter($this->client,)); + // } + + +}