mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Fixes for Storing Quotes (#3159)
* Return blank object for group settings * Implement Quote Store * Clean up Logging
This commit is contained in:
parent
da49880733
commit
556b2ab1c9
@ -47,8 +47,8 @@ class CloneInvoiceToQuoteFactory
|
|||||||
$quote->last_viewed = $invoice->last_viewed;
|
$quote->last_viewed = $invoice->last_viewed;
|
||||||
|
|
||||||
$quote->status_id = Quote::STATUS_DRAFT;
|
$quote->status_id = Quote::STATUS_DRAFT;
|
||||||
$quote->quote_number = '';
|
$quote->number = '';
|
||||||
$quote->quote_date = null;
|
$quote->date = null;
|
||||||
$quote->due_date = null;
|
$quote->due_date = null;
|
||||||
$quote->partial_due_date = null;
|
$quote->partial_due_date = null;
|
||||||
$quote->balance = $invoice->amount;
|
$quote->balance = $invoice->amount;
|
||||||
|
@ -22,7 +22,7 @@ class QuoteFactory
|
|||||||
{
|
{
|
||||||
$quote = new Quote();
|
$quote = new Quote();
|
||||||
$quote->status_id = Quote::STATUS_DRAFT;
|
$quote->status_id = Quote::STATUS_DRAFT;
|
||||||
$quote->quote_number = '';
|
$quote->number = '';
|
||||||
$quote->discount = 0;
|
$quote->discount = 0;
|
||||||
$quote->is_amount_discount = true;
|
$quote->is_amount_discount = true;
|
||||||
$quote->po_number = '';
|
$quote->po_number = '';
|
||||||
@ -30,8 +30,8 @@ class QuoteFactory
|
|||||||
$quote->terms = '';
|
$quote->terms = '';
|
||||||
$quote->public_notes = '';
|
$quote->public_notes = '';
|
||||||
$quote->private_notes = '';
|
$quote->private_notes = '';
|
||||||
$quote->quote_date = null;
|
$quote->date = null;
|
||||||
$quote->valid_until = null;
|
$quote->due_date = null;
|
||||||
$quote->partial_due_date = null;
|
$quote->partial_due_date = null;
|
||||||
$quote->is_deleted = false;
|
$quote->is_deleted = false;
|
||||||
$quote->line_items = json_encode([]);
|
$quote->line_items = json_encode([]);
|
||||||
|
42
app/Factory/QuoteInvitationFactory.php
Normal file
42
app/Factory/QuoteInvitationFactory.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Quote Ninja (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2019. Quote Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Factory;
|
||||||
|
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class QuoteInvitationFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
public static function create(int $company_id, int $user_id) :QuoteInvitation
|
||||||
|
{
|
||||||
|
$qi = new QuoteInvitation;
|
||||||
|
$qi->company_id = $company_id;
|
||||||
|
$qi->user_id = $user_id;
|
||||||
|
$qi->client_contact_id = null;
|
||||||
|
$qi->quote_id = null;
|
||||||
|
$qi->key = Str::random(config('ninja.key_length'));
|
||||||
|
$qi->transaction_reference = null;
|
||||||
|
$qi->message_id = null;
|
||||||
|
$qi->email_error = '';
|
||||||
|
$qi->signature_base64 = '';
|
||||||
|
$qi->signature_date = null;
|
||||||
|
$qi->sent_date = null;
|
||||||
|
$qi->viewed_date = null;
|
||||||
|
$qi->opened_date = null;
|
||||||
|
|
||||||
|
return $qi;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@ class QuoteController extends BaseController
|
|||||||
public function store(StoreQuoteRequest $request)
|
public function store(StoreQuoteRequest $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$quote = $this->quote_repo->save($request, QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
$quote = $this->quote_repo->save($request->all(), QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||||
|
|
||||||
return $this->itemResponse($quote);
|
return $this->itemResponse($quote);
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ class QuoteController extends BaseController
|
|||||||
public function update(UpdateQuoteRequest $request, Quote $quote)
|
public function update(UpdateQuoteRequest $request, Quote $quote)
|
||||||
{
|
{
|
||||||
|
|
||||||
$quote = $this->quote_repo->save(request(), $quote);
|
$quote = $this->quote_repo->save($request->all(), $quote);
|
||||||
|
|
||||||
return $this->itemResponse($quote);
|
return $this->itemResponse($quote);
|
||||||
|
|
||||||
|
@ -13,9 +13,12 @@ namespace App\Http\Requests\Quote;
|
|||||||
|
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
class StoreQuoteRequest extends Request
|
class StoreQuoteRequest extends Request
|
||||||
{
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the user is authorized to make this request.
|
* Determine if the user is authorized to make this request.
|
||||||
*
|
*
|
||||||
@ -27,26 +30,25 @@ class StoreQuoteRequest extends Request
|
|||||||
return auth()->user()->can('create', Quote::class);
|
return auth()->user()->can('create', Quote::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation()
|
||||||
|
{
|
||||||
|
$input = $this->all();
|
||||||
|
|
||||||
|
if(isset($input['client_id']))
|
||||||
|
$input['client_id'] = $this->decodePrimaryKey($input['client_id']);
|
||||||
|
|
||||||
|
$this->replace($input);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx',
|
'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx',
|
||||||
'client_id' => 'required|integer',
|
'client_id' => 'required',
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function sanitize()
|
|
||||||
{
|
|
||||||
//do post processing of Quote request here, ie. Quote_items
|
|
||||||
}
|
|
||||||
|
|
||||||
public function messages()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class CreateInvoiceInvitations implements ShouldQueue
|
|||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
public $invoice;
|
private $invoice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
|
67
app/Jobs/Quote/CreateQuoteInvitations.php
Normal file
67
app/Jobs/Quote/CreateQuoteInvitations.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Quote Ninja (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2019. Quote Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Jobs\Quote;
|
||||||
|
|
||||||
|
use App\Factory\QuoteInvitationFactory;
|
||||||
|
use App\Models\Quote;
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||||
|
|
||||||
|
class CreateQuoteInvitations implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private $quote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Quote $quote)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->quote = $quote;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
|
||||||
|
$contacts = $this->quote->client->contacts;
|
||||||
|
|
||||||
|
$contacts->each(function ($contact) {
|
||||||
|
|
||||||
|
$invitation = QuoteInvitation::whereCompanyId($this->quote->company_id)
|
||||||
|
->whereClientContactId($contact->id)
|
||||||
|
->whereQuoteId($this->quote->id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if(!$invitation && $contact->send_invoice) {
|
||||||
|
$ii = QuoteInvitationFactory::create($this->quote->company_id, $this->quote->user_id);
|
||||||
|
$ii->quote_id = $this->quote->id;
|
||||||
|
$ii->client_contact_id = $contact->id;
|
||||||
|
$ii->save();
|
||||||
|
}
|
||||||
|
else if($invitation && !$contact->send_invoice) {
|
||||||
|
$invitation->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||||
use App\Models\Filterable;
|
use App\Models\Filterable;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@ -22,37 +24,37 @@ class Quote extends BaseModel
|
|||||||
use Filterable;
|
use Filterable;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'client_id',
|
'number',
|
||||||
'quote_number',
|
|
||||||
'discount',
|
'discount',
|
||||||
'is_amount_discount',
|
|
||||||
'po_number',
|
'po_number',
|
||||||
'quote_date',
|
'date',
|
||||||
'valid_until',
|
'due_date',
|
||||||
'line_items',
|
|
||||||
'settings',
|
|
||||||
'footer',
|
|
||||||
'public_note',
|
|
||||||
'private_notes',
|
|
||||||
'terms',
|
'terms',
|
||||||
|
'public_notes',
|
||||||
|
'private_notes',
|
||||||
|
'invoice_type_id',
|
||||||
'tax_name1',
|
'tax_name1',
|
||||||
'tax_name2',
|
|
||||||
'tax_name3',
|
|
||||||
'tax_rate1',
|
'tax_rate1',
|
||||||
|
'tax_name2',
|
||||||
'tax_rate2',
|
'tax_rate2',
|
||||||
|
'tax_name3',
|
||||||
'tax_rate3',
|
'tax_rate3',
|
||||||
|
'is_amount_discount',
|
||||||
|
'footer',
|
||||||
|
'partial',
|
||||||
|
'partial_due_date',
|
||||||
'custom_value1',
|
'custom_value1',
|
||||||
'custom_value2',
|
'custom_value2',
|
||||||
'custom_value3',
|
'custom_value3',
|
||||||
'custom_value4',
|
'custom_value4',
|
||||||
'amount',
|
'line_items',
|
||||||
'partial',
|
'client_id',
|
||||||
'partial_due_date',
|
'footer',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'settings' => 'object',
|
'line_items' => 'object',
|
||||||
'updated_at' => 'timestamp',
|
'updated_at' => 'timestamp',
|
||||||
'created_at' => 'timestamp',
|
'created_at' => 'timestamp',
|
||||||
'deleted_at' => 'timestamp',
|
'deleted_at' => 'timestamp',
|
||||||
@ -94,4 +96,22 @@ class Quote extends BaseModel
|
|||||||
return $this->morphMany(Document::class, 'documentable');
|
return $this->morphMany(Document::class, 'documentable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the quote calculator object
|
||||||
|
*
|
||||||
|
* @return object The quote calculator object getters
|
||||||
|
*/
|
||||||
|
public function calc()
|
||||||
|
{
|
||||||
|
$quote_calc = null;
|
||||||
|
|
||||||
|
if($this->uses_inclusive_taxes)
|
||||||
|
$quote_calc = new InvoiceSumInclusive($this);
|
||||||
|
else
|
||||||
|
$quote_calc = new InvoiceSum($this);
|
||||||
|
|
||||||
|
return $quote_calc->build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Quote;
|
||||||
use App\Utils\Traits\MakesDates;
|
use App\Utils\Traits\MakesDates;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
@ -19,6 +20,17 @@ class QuoteInvitation extends BaseModel
|
|||||||
|
|
||||||
use MakesDates;
|
use MakesDates;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id',
|
||||||
|
'client_contact_id',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function entityType()
|
||||||
|
{
|
||||||
|
return Quote::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -91,7 +91,10 @@ class InvoiceRepository extends BaseRepository
|
|||||||
|
|
||||||
foreach($data['invitations'] as $invitation)
|
foreach($data['invitations'] as $invitation)
|
||||||
{
|
{
|
||||||
$inv = InvoiceInvitation::whereKey($invitation['key'])->first();
|
$inv = false;
|
||||||
|
|
||||||
|
if(array_key_exists ('key', $invitation))
|
||||||
|
$inv = InvoiceInvitation::whereKey($invitation['key'])->first();
|
||||||
|
|
||||||
if(!$inv)
|
if(!$inv)
|
||||||
{
|
{
|
||||||
|
@ -11,9 +11,13 @@
|
|||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Factory\QuoteInvitationFactory;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Jobs\Quote\CreateQuoteInvitations;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
|
use App\Models\ClientContact;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,21 +32,77 @@ class QuoteRepository extends BaseRepository
|
|||||||
return Quote::class;
|
return Quote::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save(Request $request, Quote $quote) : ?Quote
|
public function save($data, Quote $quote) : ?Quote
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* Always carry forward the initial invoice amount this is important for tracking client balance changes later......*/
|
||||||
|
$starting_amount = $quote->amount;
|
||||||
|
|
||||||
$quote->fill($request->input());
|
$quote->fill($data);
|
||||||
|
|
||||||
$quote->save();
|
$quote->save();
|
||||||
|
|
||||||
$invoice_calc = new InvoiceSum($quote);
|
if(isset($data['client_contacts']))
|
||||||
|
{
|
||||||
|
foreach($data['client_contacts'] as $contact)
|
||||||
|
{
|
||||||
|
if($contact['send_invoice'] == 1)
|
||||||
|
{
|
||||||
|
$client_contact = ClientContact::find($this->decodePrimaryKey($contact['id']));
|
||||||
|
$client_contact->send_invoice = true;
|
||||||
|
$client_contact->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$quote = $invoice_calc->build()->getInvoice();
|
|
||||||
|
|
||||||
//fire events here that cascading from the saving of an invoice
|
if(isset($data['invitations']))
|
||||||
//ie. client balance update...
|
{
|
||||||
|
|
||||||
|
$invitations = collect($data['invitations']);
|
||||||
|
|
||||||
|
/* Get array of Keyss which have been removed from the invitations array and soft delete each invitation */
|
||||||
|
collect($quote->invitations->pluck('key'))->diff($invitations->pluck('key'))->each(function($invitation){
|
||||||
|
|
||||||
|
QuoteInvitation::destroy($invitation);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
foreach($data['invitations'] as $invitation)
|
||||||
|
{
|
||||||
|
$inv = false;
|
||||||
|
|
||||||
|
if(array_key_exists ('key', $invitation))
|
||||||
|
$inv = QuoteInvitation::whereKey($invitation['key'])->first();
|
||||||
|
|
||||||
|
if(!$inv)
|
||||||
|
{
|
||||||
|
$invitation['client_contact_id'] = $this->decodePrimaryKey($invitation['client_contact_id']);
|
||||||
|
|
||||||
|
$new_invitation = QuoteInvitationFactory::create($quote->company_id, $quote->user_id);
|
||||||
|
$new_invitation->fill($invitation);
|
||||||
|
$new_invitation->quote_id = $quote->id;
|
||||||
|
$new_invitation->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no invitations have been created, this is our fail safe to maintain state*/
|
||||||
|
if($quote->invitations->count() == 0)
|
||||||
|
CreateQuoteInvitations::dispatchNow($quote);
|
||||||
|
|
||||||
|
$quote = $quote->calc()->getInvoice();
|
||||||
|
|
||||||
return $quote;
|
$quote->save();
|
||||||
|
|
||||||
|
$finished_amount = $quote->amount;
|
||||||
|
//todo need answers on this
|
||||||
|
// $quote = ApplyInvoiceNumber::dispatchNow($quote, $quote->client->getMergedSettings());
|
||||||
|
|
||||||
|
return $quote->fresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ class GroupSettingTransformer extends EntityTransformer
|
|||||||
return [
|
return [
|
||||||
'id' => $this->encodePrimaryKey($group_setting->id),
|
'id' => $this->encodePrimaryKey($group_setting->id),
|
||||||
'name' => (string)$group_setting->name ?: '',
|
'name' => (string)$group_setting->name ?: '',
|
||||||
'settings' => $group_setting->settings ?: '',
|
'settings' => $group_setting->settings ?: new \stdClass,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -747,6 +747,38 @@ class CreateUsersTable extends Migration
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Schema::create('quote_invitations', function ($t) {
|
||||||
|
$t->increments('id');
|
||||||
|
$t->unsignedInteger('company_id');
|
||||||
|
$t->unsignedInteger('user_id');
|
||||||
|
$t->unsignedInteger('client_contact_id');
|
||||||
|
$t->unsignedInteger('quote_id')->index();
|
||||||
|
$t->string('key')->index();
|
||||||
|
$t->string('transaction_reference')->nullable();
|
||||||
|
$t->string('message_id')->nullable();
|
||||||
|
$t->mediumText('email_error')->nullable();
|
||||||
|
$t->text('signature_base64')->nullable();
|
||||||
|
$t->datetime('signature_date')->nullable();
|
||||||
|
|
||||||
|
$t->datetime('sent_date')->nullable();
|
||||||
|
$t->datetime('viewed_date')->nullable();
|
||||||
|
$t->datetime('opened_date')->nullable();
|
||||||
|
|
||||||
|
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
$t->foreign('client_contact_id')->references('id')->on('client_contacts')->onDelete('cascade');
|
||||||
|
$t->foreign('quote_id')->references('id')->on('quotes')->onDelete('cascade');
|
||||||
|
$t->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||||
|
|
||||||
|
$t->timestamps(6);
|
||||||
|
$t->softDeletes('deleted_at', 6);
|
||||||
|
|
||||||
|
$t->index(['deleted_at', 'quote_id']);
|
||||||
|
$t->unique(['client_contact_id', 'quote_id']);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
Schema::create('tax_rates', function ($t) {
|
Schema::create('tax_rates', function ($t) {
|
||||||
|
|
||||||
$t->increments('id');
|
$t->increments('id');
|
||||||
|
@ -116,7 +116,7 @@ class ClientApiTest extends TestCase
|
|||||||
])->post('/api/v1/clients/bulk?action=archive', $data);
|
])->post('/api/v1/clients/bulk?action=archive', $data);
|
||||||
|
|
||||||
$arr = $response->json();
|
$arr = $response->json();
|
||||||
|
\Log::error($arr);
|
||||||
$this->assertNotNull($arr['data'][0]['deleted_at']);
|
$this->assertNotNull($arr['data'][0]['deleted_at']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ use App\DataMapper\ClientSettings;
|
|||||||
use App\DataMapper\CompanySettings;
|
use App\DataMapper\CompanySettings;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
|
use App\Models\ClientContact;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@ -110,7 +111,7 @@ class QuoteTest extends TestCase
|
|||||||
$data = [
|
$data = [
|
||||||
'first_name' => $this->faker->firstName,
|
'first_name' => $this->faker->firstName,
|
||||||
'last_name' => $this->faker->lastName,
|
'last_name' => $this->faker->lastName,
|
||||||
'name' => $this->faker->company,
|
'name' => $this->faker->company,
|
||||||
'email' => $this->faker->unique()->safeEmail,
|
'email' => $this->faker->unique()->safeEmail,
|
||||||
'password' => 'ALongAndBrilliantPassword123',
|
'password' => 'ALongAndBrilliantPassword123',
|
||||||
'_token' => csrf_token(),
|
'_token' => csrf_token(),
|
||||||
@ -197,6 +198,26 @@ class QuoteTest extends TestCase
|
|||||||
|
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
|
|
||||||
|
$client_contact = ClientContact::whereClientId($client->id)->first();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'client_id' => $this->encodePrimaryKey($client->id),
|
||||||
|
'date' => "2019-12-14",
|
||||||
|
'line_items' => [],
|
||||||
|
'invitations' => [
|
||||||
|
['client_contact_id' => $this->encodePrimaryKey($client_contact->id)]
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $token,
|
||||||
|
])->post('/api/v1/quotes', $data);
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user