mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Support automatic client ids
This commit is contained in:
parent
9dd64f83e0
commit
69369619af
@ -977,10 +977,12 @@ class AccountController extends BaseController
|
||||
private function saveInvoiceSettings()
|
||||
{
|
||||
if (Auth::user()->account->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||
$rules = [
|
||||
'invoice_number_pattern' => 'has_counter',
|
||||
'quote_number_pattern' => 'has_counter',
|
||||
];
|
||||
$rules = [];
|
||||
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_CLIENT] as $entityType) {
|
||||
if (Input::get("{$entityType}_number_type") == 'pattern') {
|
||||
$rules["{$entityType}_number_pattern"] = 'has_counter';
|
||||
}
|
||||
}
|
||||
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
|
||||
@ -1015,6 +1017,10 @@ class AccountController extends BaseController
|
||||
$account->auto_convert_quote = Input::get('auto_convert_quote');
|
||||
$account->recurring_invoice_number_prefix = Input::get('recurring_invoice_number_prefix');
|
||||
|
||||
$account->client_number_prefix = trim(Input::get('client_number_prefix'));
|
||||
$account->client_number_pattern = trim(Input::get('client_number_pattern'));
|
||||
$account->client_number_counter = Input::get('client_number_counter');
|
||||
|
||||
if (Input::has('recurring_hour')) {
|
||||
$account->recurring_hour = Input::get('recurring_hour');
|
||||
}
|
||||
@ -1023,20 +1029,14 @@ class AccountController extends BaseController
|
||||
$account->quote_number_counter = Input::get('quote_number_counter');
|
||||
}
|
||||
|
||||
if (Input::get('invoice_number_type') == 'prefix') {
|
||||
$account->invoice_number_prefix = trim(Input::get('invoice_number_prefix'));
|
||||
$account->invoice_number_pattern = null;
|
||||
} else {
|
||||
$account->invoice_number_pattern = trim(Input::get('invoice_number_pattern'));
|
||||
$account->invoice_number_prefix = null;
|
||||
}
|
||||
|
||||
if (Input::get('quote_number_type') == 'prefix') {
|
||||
$account->quote_number_prefix = trim(Input::get('quote_number_prefix'));
|
||||
$account->quote_number_pattern = null;
|
||||
} else {
|
||||
$account->quote_number_pattern = trim(Input::get('quote_number_pattern'));
|
||||
$account->quote_number_prefix = null;
|
||||
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_CLIENT] as $entityType) {
|
||||
if (Input::get("{$entityType}_number_type") == 'prefix') {
|
||||
$account->{"{$entityType}_number_prefix"} = trim(Input::get("{$entityType}_number_prefix"));
|
||||
$account->{"{$entityType}_number_pattern"} = null;
|
||||
} else {
|
||||
$account->{"{$entityType}_number_pattern"} = trim(Input::get("{$entityType}_number_pattern"));
|
||||
$account->{"{$entityType}_number_prefix"} = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$account->share_counter
|
||||
|
@ -19,8 +19,14 @@ class CreateClientRequest extends ClientRequest
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
$rules = [
|
||||
'contacts' => 'valid_contacts',
|
||||
];
|
||||
|
||||
if ($this->user()->account->client_number_counter) {
|
||||
$rules['id_number'] = 'unique:clients,id_number,,id,account_id,' . $this->user()->account_id;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Client;
|
||||
|
||||
class CreateInvoiceAPIRequest extends InvoiceRequest
|
||||
{
|
||||
/**
|
||||
@ -31,6 +33,11 @@ class CreateInvoiceAPIRequest extends InvoiceRequest
|
||||
//'end_date' => 'date',
|
||||
];
|
||||
|
||||
if ($this->user()->account->client_number_counter) {
|
||||
$clientId = Client::getPrivateId(request()->input('client')['public_id']);
|
||||
$rules['client.id_number'] = 'unique:clients,id_number,'.$clientId.',id,account_id,' . $this->user()->account_id;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Client;
|
||||
|
||||
class CreateInvoiceRequest extends InvoiceRequest
|
||||
{
|
||||
/**
|
||||
@ -30,6 +32,11 @@ class CreateInvoiceRequest extends InvoiceRequest
|
||||
//'end_date' => 'date',
|
||||
];
|
||||
|
||||
if ($this->user()->account->client_number_counter) {
|
||||
$clientId = Client::getPrivateId(request()->input('client')['public_id']);
|
||||
$rules['client.id_number'] = 'unique:clients,id_number,'.$clientId.',id,account_id,' . $this->user()->account_id;
|
||||
}
|
||||
|
||||
/* There's a problem parsing the dates
|
||||
if (Request::get('is_recurring') && Request::get('start_date') && Request::get('end_date')) {
|
||||
$rules['end_date'] = 'after' . Request::get('start_date');
|
||||
|
@ -19,8 +19,14 @@ class UpdateClientRequest extends ClientRequest
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
$rules = [
|
||||
'contacts' => 'valid_contacts',
|
||||
];
|
||||
|
||||
if ($this->user()->account->client_number_counter) {
|
||||
$rules['id_number'] = 'unique:clients,id_number,'.$this->entity()->id.',id,account_id,' . $this->user()->account_id;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Client;
|
||||
|
||||
class UpdateInvoiceAPIRequest extends InvoiceRequest
|
||||
{
|
||||
/**
|
||||
@ -35,6 +37,11 @@ class UpdateInvoiceAPIRequest extends InvoiceRequest
|
||||
//'end_date' => 'date',
|
||||
];
|
||||
|
||||
if ($this->user()->account->client_number_counter) {
|
||||
$clientId = Client::getPrivateId(request()->input('client')['public_id']);
|
||||
$rules['client.id_number'] = 'unique:clients,id_number,'.$clientId.',id,account_id,' . $this->user()->account_id;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Client;
|
||||
|
||||
class UpdateInvoiceRequest extends InvoiceRequest
|
||||
{
|
||||
/**
|
||||
@ -32,6 +34,11 @@ class UpdateInvoiceRequest extends InvoiceRequest
|
||||
//'end_date' => 'date',
|
||||
];
|
||||
|
||||
if ($this->user()->account->client_number_counter) {
|
||||
$clientId = Client::getPrivateId(request()->input('client')['public_id']);
|
||||
$rules['client.id_number'] = 'unique:clients,id_number,'.$clientId.',id,account_id,' . $this->user()->account_id;
|
||||
}
|
||||
|
||||
/* There's a problem parsing the dates
|
||||
if (Request::get('is_recurring') && Request::get('start_date') && Request::get('end_date')) {
|
||||
$rules['end_date'] = 'after' . Request::get('start_date');
|
||||
|
@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use App\Models\Traits\PresentsInvoice;
|
||||
use App\Models\Traits\GeneratesNumbers;
|
||||
|
||||
/**
|
||||
* Class Account
|
||||
@ -22,6 +23,7 @@ class Account extends Eloquent
|
||||
use PresentableTrait;
|
||||
use SoftDeletes;
|
||||
use PresentsInvoice;
|
||||
use GeneratesNumbers;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -874,190 +876,6 @@ class Account extends Eloquent
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_type_id
|
||||
* @return string
|
||||
*/
|
||||
public function getNumberPrefix($invoice_type_id)
|
||||
{
|
||||
if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return ($invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_prefix : $this->invoice_number_prefix) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_type_id
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNumberPattern($invoice_type_id)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
* @return string
|
||||
*/
|
||||
public function hasClientNumberPattern($invoice)
|
||||
{
|
||||
$pattern = $invoice->invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_pattern : $this->invoice_number_pattern;
|
||||
|
||||
return strstr($pattern, '$custom');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function getNumberPattern($invoice)
|
||||
{
|
||||
$pattern = $invoice->invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_pattern : $this->invoice_number_pattern;
|
||||
|
||||
if (!$pattern) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$search = ['{$year}'];
|
||||
$replace = [date('Y')];
|
||||
|
||||
$search[] = '{$counter}';
|
||||
$replace[] = str_pad($this->getCounter($invoice->invoice_type_id), $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);
|
||||
}
|
||||
|
||||
$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]);
|
||||
}
|
||||
|
||||
$pattern = str_replace($search, $replace, $pattern);
|
||||
|
||||
if ($invoice->client_id) {
|
||||
$pattern = $this->getClientInvoiceNumber($pattern, $invoice);
|
||||
}
|
||||
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $pattern
|
||||
* @param $invoice
|
||||
* @return mixed
|
||||
*/
|
||||
private function getClientInvoiceNumber($pattern, $invoice)
|
||||
{
|
||||
if (!$invoice->client) {
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
$search = [
|
||||
'{$custom1}',
|
||||
'{$custom2}',
|
||||
];
|
||||
|
||||
$replace = [
|
||||
$invoice->client->custom_value1,
|
||||
$invoice->client->custom_value2,
|
||||
];
|
||||
|
||||
return str_replace($search, $replace, $pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_type_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCounter($invoice_type_id)
|
||||
{
|
||||
return $invoice_type_id == INVOICE_TYPE_QUOTE && !$this->share_counter ? $this->quote_number_counter : $this->invoice_number_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $entityType
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function previewNextInvoiceNumber($entityType = ENTITY_INVOICE)
|
||||
{
|
||||
$invoice = $this->createInvoice($entityType);
|
||||
return $this->getNextInvoiceNumber($invoice);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
* @param bool $validateUnique
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function getNextInvoiceNumber($invoice, $validateUnique = true)
|
||||
{
|
||||
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;
|
||||
|
||||
// confirm the invoice number isn't already taken
|
||||
do {
|
||||
$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 ($invoice->recurring_invoice_id) {
|
||||
$number = $this->recurring_invoice_number_prefix . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
*/
|
||||
public function incrementCounter($invoice)
|
||||
{
|
||||
// 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) {
|
||||
$this->quote_number_counter += 1;
|
||||
} else {
|
||||
$this->invoice_number_counter += 1;
|
||||
}
|
||||
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $client
|
||||
*/
|
||||
|
@ -535,6 +535,7 @@ class Client extends EntityModel
|
||||
|
||||
Client::creating(function ($client) {
|
||||
$client->setNullValues();
|
||||
$client->account->incrementClientCounter();
|
||||
});
|
||||
|
||||
Client::updating(function ($client) {
|
||||
|
273
app/Models/Traits/GeneratesNumbers.php
Normal file
273
app/Models/Traits/GeneratesNumbers.php
Normal file
@ -0,0 +1,273 @@
|
||||
<?php namespace App\Models\Traits;
|
||||
|
||||
use Auth;
|
||||
use Carbon;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Client;
|
||||
|
||||
/**
|
||||
* Class GeneratesNumbers
|
||||
*/
|
||||
trait GeneratesNumbers
|
||||
{
|
||||
/**
|
||||
* @param $invoice
|
||||
* @param bool $validateUnique
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function getNextInvoiceNumber($invoice, $validateUnique = true)
|
||||
{
|
||||
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;
|
||||
|
||||
// confirm the invoice number isn't already taken
|
||||
do {
|
||||
$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 ($invoice->recurring_invoice_id) {
|
||||
$number = $this->recurring_invoice_number_prefix . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_type_id
|
||||
* @return string
|
||||
*/
|
||||
public function getNumberPrefix($invoice_type_id)
|
||||
{
|
||||
if ( ! $this->hasFeature(FEATURE_INVOICE_SETTINGS)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return ($invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_prefix : $this->invoice_number_prefix) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_type_id
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNumberPattern($invoice_type_id)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
* @return string
|
||||
*/
|
||||
public function hasClientNumberPattern($invoice)
|
||||
{
|
||||
$pattern = $invoice->invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_pattern : $this->invoice_number_pattern;
|
||||
|
||||
return strstr($pattern, '$custom');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function getNumberPattern($invoice)
|
||||
{
|
||||
$pattern = $invoice->invoice_type_id == INVOICE_TYPE_QUOTE ? $this->quote_number_pattern : $this->invoice_number_pattern;
|
||||
|
||||
if (!$pattern) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$search = ['{$year}'];
|
||||
$replace = [date('Y')];
|
||||
|
||||
$search[] = '{$counter}';
|
||||
$replace[] = str_pad($this->getCounter($invoice->invoice_type_id), $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);
|
||||
}
|
||||
|
||||
$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]);
|
||||
}
|
||||
|
||||
$pattern = str_replace($search, $replace, $pattern);
|
||||
|
||||
if ($invoice->client_id) {
|
||||
$pattern = $this->getClientInvoiceNumber($pattern, $invoice);
|
||||
}
|
||||
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $pattern
|
||||
* @param $invoice
|
||||
* @return mixed
|
||||
*/
|
||||
private function getClientInvoiceNumber($pattern, $invoice)
|
||||
{
|
||||
if (!$invoice->client) {
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
$search = [
|
||||
'{$custom1}',
|
||||
'{$custom2}',
|
||||
];
|
||||
|
||||
$replace = [
|
||||
$invoice->client->custom_value1,
|
||||
$invoice->client->custom_value2,
|
||||
];
|
||||
|
||||
return str_replace($search, $replace, $pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_type_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCounter($invoice_type_id)
|
||||
{
|
||||
return $invoice_type_id == INVOICE_TYPE_QUOTE && !$this->share_counter ? $this->quote_number_counter : $this->invoice_number_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $entityType
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function previewNextInvoiceNumber($entityType = ENTITY_INVOICE)
|
||||
{
|
||||
$invoice = $this->createInvoice($entityType);
|
||||
return $this->getNextInvoiceNumber($invoice);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice
|
||||
*/
|
||||
public function incrementCounter($invoice)
|
||||
{
|
||||
// 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) {
|
||||
$this->quote_number_counter += 1;
|
||||
} else {
|
||||
$this->invoice_number_counter += 1;
|
||||
}
|
||||
|
||||
$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()
|
||||
{
|
||||
return $this->hasFeature(FEATURE_INVOICE_SETTINGS) && $this->client_number_counter;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
use DB;
|
||||
use Cache;
|
||||
use Auth;
|
||||
use App\Models\Client;
|
||||
use App\Models\Contact;
|
||||
use App\Events\ClientWasCreated;
|
||||
@ -77,6 +78,9 @@ class ClientRepository extends BaseRepository
|
||||
// do nothing
|
||||
} 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();
|
||||
}
|
||||
} else {
|
||||
$client = Client::scope($publicId)->with('contacts')->firstOrFail();
|
||||
}
|
||||
|
@ -2298,7 +2298,10 @@ $LANG = array(
|
||||
'phantomjs_help' => 'In certain cases the app uses :link_phantom to generate the PDF, install :link_docs to generate it locally.',
|
||||
'phantomjs_local' => 'Using local PhantomJS',
|
||||
'client_number' => 'Client Number',
|
||||
|
||||
'client_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the client number.',
|
||||
'next_client_number' => 'The next client number is :number.',
|
||||
'generated_numbers' => 'Generated Numbers',
|
||||
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{!! trans('texts.invoice_quote_number') !!}</h3>
|
||||
<h3 class="panel-title">{!! trans('texts.generated_numbers') !!}</h3>
|
||||
</div>
|
||||
<div class="panel-body form-padding-right">
|
||||
|
||||
@ -133,7 +133,9 @@
|
||||
->label(trans('texts.pattern')) !!}
|
||||
{!! Former::text('client_number_counter')
|
||||
->label(trans('texts.counter'))
|
||||
->addGroupClass('pad-checkbox') !!}
|
||||
->addGroupClass('pad-checkbox')
|
||||
->help(trans('texts.client_number_help') . ' ' .
|
||||
trans('texts.next_client_number', ['number' => $account->getNextClientNumber()])) !!}
|
||||
|
||||
@if ( ! $account->client_number_counter)
|
||||
</div>
|
||||
|
@ -24,6 +24,8 @@
|
||||
@if ($client)
|
||||
{!! Former::populate($client) !!}
|
||||
{!! Former::hidden('public_id') !!}
|
||||
@elseif ($account->client_number_counter)
|
||||
{!! Former::populateField('id_number', $account->getNextClientNumber()) !!}
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
@ -37,9 +39,9 @@
|
||||
<div class="panel-body">
|
||||
|
||||
{!! Former::text('name')->data_bind("attr { placeholder: placeholderName }") !!}
|
||||
{!! Former::text('id_number') !!}
|
||||
{!! Former::text('vat_number') !!}
|
||||
{!! Former::text('website') !!}
|
||||
{!! Former::text('id_number')->placeholder($account->useClientNumbers() ? $account->getNextClientNumber() : ' ') !!}
|
||||
{!! Former::text('vat_number') !!}
|
||||
{!! Former::text('website') !!}
|
||||
{!! Former::text('work_phone') !!}
|
||||
|
||||
@if (Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS))
|
||||
|
@ -616,11 +616,20 @@
|
||||
->data_bind("value: name, valueUpdate: 'afterkeydown', attr { placeholder: name.placeholder }")
|
||||
->label('client_name') !!}
|
||||
|
||||
@if ( ! $account->client_number_counter)
|
||||
<span data-bind="visible: $root.showMore">
|
||||
@endif
|
||||
|
||||
{!! Former::text('client[id_number]')
|
||||
{!! Former::text('client[id_number]')
|
||||
->label('id_number')
|
||||
->placeholder($account->useClientNumbers() ? $account->getNextClientNumber() : ' ')
|
||||
->data_bind("value: id_number, valueUpdate: 'afterkeydown'") !!}
|
||||
|
||||
@if ( ! $account->client_number_counter)
|
||||
</span>
|
||||
@endif
|
||||
|
||||
<span data-bind="visible: $root.showMore">
|
||||
{!! Former::text('client[vat_number]')
|
||||
->label('vat_number')
|
||||
->data_bind("value: vat_number, valueUpdate: 'afterkeydown'") !!}
|
||||
|
@ -151,8 +151,15 @@ function ViewModel(data) {
|
||||
}
|
||||
|
||||
function InvoiceModel(data) {
|
||||
if (data) {
|
||||
var clientModel = false;
|
||||
} else {
|
||||
var clientModel = new ClientModel();
|
||||
clientModel.id_number("{{ $account->getNextClientNumber() }}");
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.client = ko.observable(data ? false : new ClientModel());
|
||||
this.client = ko.observable(clientModel);
|
||||
this.is_public = ko.observable(0);
|
||||
self.account = {!! $account !!};
|
||||
self.id = ko.observable('');
|
||||
|
@ -1,5 +1,5 @@
|
||||
<iframe id="theFrame" style="display:block" frameborder="1" width="100%" height="{{ isset($pdfHeight) ? $pdfHeight : 1180 }}px"></iframe>
|
||||
<div style="width:100%;background-color:#525659;border:solid 2px #9a9a9a;padding-top:48px;text-align:center">
|
||||
<div style="width:100%;background-color:#525659;border:solid 2px #9a9a9a;padding-top:40px;text-align:center">
|
||||
<canvas id="theCanvas" style="display:none;max-width:100%;border:solid 1px #CCCCCC;"></canvas>
|
||||
</div>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user