diff --git a/app/Events/Quote/QuoteWasMarkedApproved.php b/app/Events/Quote/QuoteWasMarkedApproved.php new file mode 100644 index 000000000000..087ad138b270 --- /dev/null +++ b/app/Events/Quote/QuoteWasMarkedApproved.php @@ -0,0 +1,31 @@ +quote = $quote; + $this->company = $company; + } +} diff --git a/app/Events/Quote/QuoteWasMarkedSent.php b/app/Events/Quote/QuoteWasMarkedSent.php new file mode 100644 index 000000000000..b27c59484df6 --- /dev/null +++ b/app/Events/Quote/QuoteWasMarkedSent.php @@ -0,0 +1,30 @@ +quote = $quote; + $this->company = $company; + } +} diff --git a/app/Factory/CloneQuoteToInvoiceFactory.php b/app/Factory/CloneQuoteToInvoiceFactory.php new file mode 100644 index 000000000000..56bf188ece3a --- /dev/null +++ b/app/Factory/CloneQuoteToInvoiceFactory.php @@ -0,0 +1,19 @@ +company_id = $company_id; + $invoice->client_id = $quote->client_id; + $invoice->user_id = $user_id; + $invoice->po_number = $quote->po_number; + $invoice->footer = $quote->footer; + return $invoice; + } +} diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 3f188a79c1ce..645dee4a66f1 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -14,6 +14,7 @@ namespace App\Models; use App\Helpers\Invoice\InvoiceSum; use App\Helpers\Invoice\InvoiceSumInclusive; use App\Models\Filterable; +use App\Services\Quote\QuoteService; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -23,7 +24,7 @@ class Quote extends BaseModel use MakesHash; use Filterable; use SoftDeletes; - + protected $fillable = [ 'number', 'discount', @@ -59,7 +60,7 @@ class Quote extends BaseModel 'created_at' => 'timestamp', 'deleted_at' => 'timestamp', ]; - + const STATUS_DRAFT = 1; const STATUS_SENT = 2; const STATUS_APPROVED = 3; @@ -84,7 +85,7 @@ class Quote extends BaseModel { return $this->belongsTo(User::class, 'assigned_user_id', 'id')->withTrashed(); } - + public function invitations() { return $this->hasMany(QuoteInvitation::class); @@ -112,4 +113,23 @@ class Quote extends BaseModel return $quote_calc->build(); } + + /** + * Updates Invites to SENT + * + */ + public function markInvitationsSent() + { + $this->invitations->each(function ($invitation) { + if (!isset($invitation->sent_date)) { + $invitation->sent_date = Carbon::now(); + $invitation->save(); + } + }); + } + + public function service(): QuoteService + { + return new QuoteService($this); + } } diff --git a/app/Services/Quote/ApplyNumber.php b/app/Services/Quote/ApplyNumber.php new file mode 100644 index 000000000000..0be47f4da2a0 --- /dev/null +++ b/app/Services/Quote/ApplyNumber.php @@ -0,0 +1,41 @@ +client = $client; + } + + public function __invoke($quote) + { + + if ($quote->number != '') + return $quote; + + switch ($this->client->getSetting('counter_number_applied')) { + case 'when_saved': + $quote->number = $this->getNextQuoteNumber($this->client); + break; + case 'when_sent': + if ($quote->status_id == Quote::STATUS_SENT) { + $quote->number = $this->getNextQuoteNumber($this->client); + } + break; + + default: + # code... + break; + } + + return $quote; + } +} diff --git a/app/Services/Quote/ConvertQuote.php b/app/Services/Quote/ConvertQuote.php new file mode 100644 index 000000000000..21ad8ff25b47 --- /dev/null +++ b/app/Services/Quote/ConvertQuote.php @@ -0,0 +1,31 @@ +client = $client; + $this->invoice_repo = $invoice_repo; + } + + /** + * @param $quote + * @return mixed + */ + public function __invoke($quote) + { + $invoice = CloneQuoteToInvoiceFactory::create($quote, $quote->user_id, $quote->company_id); + $this->invoice_repo->save([], $invoice); + + // maybe should return invoice here + return $quote; + } +} diff --git a/app/Services/Quote/CreateInvitations.php b/app/Services/Quote/CreateInvitations.php new file mode 100644 index 000000000000..24747dfd10c3 --- /dev/null +++ b/app/Services/Quote/CreateInvitations.php @@ -0,0 +1,37 @@ +client->contacts; + + $contacts->each(function ($contact) use($quote){ + $invitation = QuoteInvitation::whereCompanyId($quote->company_id) + ->whereClientContactId($contact->id) + ->whereQuoteId($quote->id) + ->first(); + + if (!$invitation && $contact->send_quote) { + $ii = QuoteInvitationFactory::create($quote->company_id, $quote->user_id); + $ii->quote_id = $quote->id; + $ii->client_contact_id = $contact->id; + $ii->save(); + } elseif ($invitation && !$contact->send_quote) { + $invitation->delete(); + } + }); + + return $quote; + } +} diff --git a/app/Services/Quote/MarkApproved.php b/app/Services/Quote/MarkApproved.php new file mode 100644 index 000000000000..acd0d43cd680 --- /dev/null +++ b/app/Services/Quote/MarkApproved.php @@ -0,0 +1,30 @@ +client = $client; + } + + public function __invoke($quote) + { + /* Return immediately if status is not draft */ + if ($quote->status_id != Quote::STATUS_SENT) { + return $quote; + } + + $quote->service()->setStatus(Quote::STATUS_APPROVED)->applyNumber()->save(); + + event(new QuoteWasMarkedApproved($quote, $quote->company)); + + return $quote; + } +} diff --git a/app/Services/Quote/MarkSent.php b/app/Services/Quote/MarkSent.php new file mode 100644 index 000000000000..d98665da8ed4 --- /dev/null +++ b/app/Services/Quote/MarkSent.php @@ -0,0 +1,34 @@ +client = $client; + } + + public function __invoke($quote) + { + + /* Return immediately if status is not draft */ + if ($quote->status_id != Quote::STATUS_DRAFT) { + return $quote; + } + + $quote->markInvitationsSent(); + + event(new QuoteWasMarkedSent($quote, $quote->company)); + + $quote->service()->setStatus(Quote::STATUS_SENT)->applyNumber()->save(); + + return $quote; + + } +} diff --git a/app/Services/Quote/QuoteService.php b/app/Services/Quote/QuoteService.php new file mode 100644 index 000000000000..ba9b31adc68c --- /dev/null +++ b/app/Services/Quote/QuoteService.php @@ -0,0 +1,76 @@ +quote = $quote; + } + + public function createInvitations() + { + $create_invitation = new CreateInvitations(); + + $this->quote = $create_invitation($this->quote); + + return $this; + } + + public function markApproved() + { + $mark_approved = new MarkApproved($this->quote->client); + + $this->quote = $mark_approved($this->quote); + + if($this->quote->client->getSetting('auto_convert_quote') === true) { + $convert_quote = new ConvertQuote($this->quote->client); + $this->quote = $convert_quote($this->quote); + } + + return $this; + } + + /** + * Applies the invoice number + * @return $this InvoiceService object + */ + public function applyNumber() + { + $apply_number = new ApplyNumber($this->quote->client); + + $this->quote = $apply_number($this->quote); + + return $this; + } + + public function markSent() + { + $mark_sent = new MarkSent($this->quote->client); + + $this->quote = $mark_sent($this->quote); + + return $this; + } + + public function setStatus($status) + { + $this->quote->status_id = $status; + + return $this; + } + + /** + * Saves the quote + * @return Quote|null + */ + public function save() : ?Quote + { + $this->quote->save(); + return $this->quote; + } +}