Merge Invoice and Bill into Document
This commit is contained in:
		
							
								
								
									
										25
									
								
								app/Listeners/Document/CreateDocumentCreatedHistory.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Listeners/Document/CreateDocumentCreatedHistory.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentCreated as Event;
 | 
			
		||||
use App\Jobs\Document\CreateDocumentHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class CreateDocumentCreatedHistory
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $message = trans('messages.success.added', ['type' => $event->document->document_number]);
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateDocumentHistory($event->document, 0, $message));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +1,13 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\PaymentReceived as Event;
 | 
			
		||||
use App\Jobs\Banking\CreateDocumentTransaction;
 | 
			
		||||
use App\Events\Document\PaymentReceived as Event;
 | 
			
		||||
use App\Jobs\Banking\CreateBankingDocumentTransaction;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class CreateInvoiceTransaction
 | 
			
		||||
class CreateDocumentTransaction
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
@@ -18,26 +19,28 @@ class CreateInvoiceTransaction
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = $event->invoice;
 | 
			
		||||
        $document = $event->document;
 | 
			
		||||
        $request = $event->request;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $this->dispatch(new CreateDocumentTransaction($invoice, $request));
 | 
			
		||||
            $this->dispatch(new CreateBankingDocumentTransaction($document, $request));
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $message = $e->getMessage();
 | 
			
		||||
 | 
			
		||||
            $user = user();
 | 
			
		||||
 | 
			
		||||
            $type = Str::plural($event->document->type);
 | 
			
		||||
 | 
			
		||||
            if (empty($user)) {
 | 
			
		||||
                flash($message)->error();
 | 
			
		||||
 | 
			
		||||
                redirect()->route('signed.invoices.show', $invoice->id)->send();
 | 
			
		||||
                redirect()->route("signed.$type.show", $document->id)->send();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($user->can('read-client-portal')) {
 | 
			
		||||
                flash($message)->error();
 | 
			
		||||
 | 
			
		||||
                redirect()->route('portal.invoices.show', $invoice->id)->send();
 | 
			
		||||
                redirect()->route("portal.$type.show", $document->id)->send();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            throw new \Exception($message);
 | 
			
		||||
							
								
								
									
										23
									
								
								app/Listeners/Document/IncreaseNextDocumentNumber.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/Listeners/Document/IncreaseNextDocumentNumber.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentCreated as Event;
 | 
			
		||||
use App\Traits\Documents;
 | 
			
		||||
 | 
			
		||||
class IncreaseNextDocumentNumber
 | 
			
		||||
{
 | 
			
		||||
    use Documents;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        // Update next invoice number
 | 
			
		||||
        $this->increaseNextDocumentNumber($event->document->type);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								app/Listeners/Document/MarkDocumentCancelled.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Listeners/Document/MarkDocumentCancelled.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentCancelled as Event;
 | 
			
		||||
use App\Jobs\Document\CancelDocument;
 | 
			
		||||
use App\Jobs\Document\CreateDocumentHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class MarkDocumentCancelled
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $this->dispatch(new CancelDocument($event->document));
 | 
			
		||||
 | 
			
		||||
        $type = Str::plural($event->document->type);
 | 
			
		||||
        $this->dispatch(new CreateDocumentHistory($event->document, 0, trans("$type.messages.marked_cancelled")));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								app/Listeners/Document/MarkDocumentReceived.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/Listeners/Document/MarkDocumentReceived.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentReceived as Event;
 | 
			
		||||
use App\Jobs\Document\CreateDocumentHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class MarkDocumentReceived
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        if ($event->document->status != 'partial') {
 | 
			
		||||
            $event->document->status = 'received';
 | 
			
		||||
 | 
			
		||||
            $event->document->save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $type = Str::plural($event->document->type);
 | 
			
		||||
        $this->dispatch(new CreateDocumentHistory($event->document, 0, trans("$type.messages.marked_received")));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								app/Listeners/Document/MarkDocumentSent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Listeners/Document/MarkDocumentSent.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentSent as Event;
 | 
			
		||||
use App\Jobs\Document\CreateDocumentHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class MarkDocumentSent
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        if ($event->document->status != 'partial') {
 | 
			
		||||
            $event->document->status = 'sent';
 | 
			
		||||
 | 
			
		||||
            $event->document->save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $type = Str::plural($event->document->type);
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateDocumentHistory($event->document, 0, trans("$type.messages.marked_sent")));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								app/Listeners/Document/MarkDocumentViewed.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Listeners/Document/MarkDocumentViewed.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentViewed as Event;
 | 
			
		||||
use App\Jobs\Document\CreateDocumentHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class MarkDocumentViewed
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $document = $event->document;
 | 
			
		||||
 | 
			
		||||
        if ($document->status != 'sent') {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unset($document->paid);
 | 
			
		||||
 | 
			
		||||
        $document->status = 'viewed';
 | 
			
		||||
        $document->save();
 | 
			
		||||
 | 
			
		||||
        $type = Str::plural($document->type);
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateDocumentHistory($event->document, 0, trans("$type.messages.marked_viewed")));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								app/Listeners/Document/SendDocumentPaymentNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Listeners/Document/SendDocumentPaymentNotification.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\PaymentReceived as Event;
 | 
			
		||||
use App\Notifications\Portal\PaymentReceived as Notification;
 | 
			
		||||
 | 
			
		||||
class SendDocumentPaymentNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $document = $event->document;
 | 
			
		||||
        $transaction = $document->transactions()->latest()->first();
 | 
			
		||||
 | 
			
		||||
        // Notify the customer
 | 
			
		||||
        if ($document->contact && !empty($document->contact_email)) {
 | 
			
		||||
            $document->contact->notify(new Notification($document, $transaction, "{$document->type}_payment_customer"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($document->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($document, $transaction, "{$document->type}_payment_admin"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								app/Listeners/Document/SendDocumentRecurringNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Listeners/Document/SendDocumentRecurringNotification.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentRecurring as Event;
 | 
			
		||||
use App\Notifications\Sale\Invoice as Notification;
 | 
			
		||||
 | 
			
		||||
class SendDocumentRecurringNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $document = $event->document;
 | 
			
		||||
 | 
			
		||||
        // Notify the customer
 | 
			
		||||
        if ($document->contact && !empty($document->contact_email)) {
 | 
			
		||||
            $document->contact->notify(new Notification($document, "{$document->type}_recur_customer"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($document->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($document, "{$document->type}_recur_admin"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								app/Listeners/Document/SendDocumentReminderNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Listeners/Document/SendDocumentReminderNotification.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Document;
 | 
			
		||||
 | 
			
		||||
use App\Events\Document\DocumentReminded as Event;
 | 
			
		||||
use App\Models\Document\Document;
 | 
			
		||||
use App\Notifications\Sale\Invoice as InvoiceNotification;
 | 
			
		||||
use App\Notifications\Purchase\Bill as BillNotification;
 | 
			
		||||
 | 
			
		||||
class SendDocumentReminderNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $document = $event->document;
 | 
			
		||||
 | 
			
		||||
        $notification = InvoiceNotification::class;
 | 
			
		||||
        if ($document->type === Document::BILL_TYPE) {
 | 
			
		||||
            $notification = BillNotification::class;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify the customer
 | 
			
		||||
        if ($document->contact && !empty($document->contact_email)) {
 | 
			
		||||
            $document->contact->notify(new $notification($document, "{$document->type}_remind_customer"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($document->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new $notification($document, "{$document->type}_remind_admin"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Purchase;
 | 
			
		||||
 | 
			
		||||
use App\Events\Purchase\BillCreated as Event;
 | 
			
		||||
use App\Jobs\Purchase\CreateBillHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class CreateBillCreatedHistory
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $message = trans('messages.success.added', ['type' => $event->bill->bill_number]);
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateBillHistory($event->bill, 0, $message));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Purchase;
 | 
			
		||||
 | 
			
		||||
use App\Events\Purchase\BillCreated as Event;
 | 
			
		||||
use App\Traits\Purchases;
 | 
			
		||||
 | 
			
		||||
class IncreaseNextBillNumber
 | 
			
		||||
{
 | 
			
		||||
    use Purchases;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        // Update next bill number
 | 
			
		||||
        $this->increaseNextBillNumber();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Purchase;
 | 
			
		||||
 | 
			
		||||
use App\Events\Purchase\BillCancelled as Event;
 | 
			
		||||
use App\Jobs\Purchase\CancelBill;
 | 
			
		||||
use App\Jobs\Purchase\CreateBillHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class MarkBillCancelled
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $this->dispatch(new CancelBill($event->bill));
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateBillHistory($event->bill, 0, trans('bills.messages.marked_cancelled')));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Purchase;
 | 
			
		||||
 | 
			
		||||
use App\Events\Purchase\BillReceived as Event;
 | 
			
		||||
use App\Jobs\Purchase\CreateBillHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class MarkBillReceived
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        if ($event->bill->status != 'partial') {
 | 
			
		||||
            $event->bill->status = 'received';
 | 
			
		||||
 | 
			
		||||
            $event->bill->save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateBillHistory($event->bill, 0, trans('bills.messages.marked_received')));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Purchase;
 | 
			
		||||
 | 
			
		||||
use App\Events\Purchase\BillRecurring as Event;
 | 
			
		||||
use App\Notifications\Purchase\Bill as Notification;
 | 
			
		||||
 | 
			
		||||
class SendBillRecurringNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $bill = $event->bill;
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($bill->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($bill, 'bill_recur_admin'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Purchase;
 | 
			
		||||
 | 
			
		||||
use App\Events\Purchase\BillReminded as Event;
 | 
			
		||||
use App\Notifications\Purchase\Bill as Notification;
 | 
			
		||||
 | 
			
		||||
class SendBillReminderNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $bill = $event->bill;
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($bill->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($bill, 'bill_remind_admin'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceCreated as Event;
 | 
			
		||||
use App\Jobs\Sale\CreateInvoiceHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class CreateInvoiceCreatedHistory
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $message = trans('messages.success.added', ['type' => $event->invoice->invoice_number]);
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateInvoiceHistory($event->invoice, 0, $message));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceCreated as Event;
 | 
			
		||||
use App\Traits\Sales;
 | 
			
		||||
 | 
			
		||||
class IncreaseNextInvoiceNumber
 | 
			
		||||
{
 | 
			
		||||
    use Sales;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        // Update next invoice number
 | 
			
		||||
        $this->increaseNextInvoiceNumber();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceCancelled as Event;
 | 
			
		||||
use App\Jobs\Sale\CancelInvoice;
 | 
			
		||||
use App\Jobs\Sale\CreateInvoiceHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class MarkInvoiceCancelled
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $this->dispatch(new CancelInvoice($event->invoice));
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateInvoiceHistory($event->invoice, 0, trans('invoices.messages.marked_cancelled')));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceSent as Event;
 | 
			
		||||
use App\Jobs\Sale\CreateInvoiceHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class MarkInvoiceSent
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        if ($event->invoice->status != 'partial') {
 | 
			
		||||
            $event->invoice->status = 'sent';
 | 
			
		||||
 | 
			
		||||
            $event->invoice->save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateInvoiceHistory($event->invoice, 0, trans('invoices.messages.marked_sent')));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,34 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceViewed as Event;
 | 
			
		||||
use App\Jobs\Sale\CreateInvoiceHistory;
 | 
			
		||||
use App\Traits\Jobs;
 | 
			
		||||
 | 
			
		||||
class MarkInvoiceViewed
 | 
			
		||||
{
 | 
			
		||||
    use Jobs;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = $event->invoice;
 | 
			
		||||
 | 
			
		||||
        if ($invoice->status != 'sent') {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unset($invoice->paid);
 | 
			
		||||
 | 
			
		||||
        $invoice->status = 'viewed';
 | 
			
		||||
        $invoice->save();
 | 
			
		||||
 | 
			
		||||
        $this->dispatch(new CreateInvoiceHistory($event->invoice, 0, trans('invoices.messages.marked_viewed')));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\PaymentReceived as Event;
 | 
			
		||||
use App\Notifications\Portal\PaymentReceived as Notification;
 | 
			
		||||
 | 
			
		||||
class SendInvoicePaymentNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = $event->invoice;
 | 
			
		||||
        $transaction = $invoice->transactions()->latest()->first();
 | 
			
		||||
 | 
			
		||||
        // Notify the customer
 | 
			
		||||
        if ($invoice->contact && !empty($invoice->contact_email)) {
 | 
			
		||||
            $invoice->contact->notify(new Notification($invoice, $transaction, 'invoice_payment_customer'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($invoice->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($invoice, $transaction, 'invoice_payment_admin'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,34 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceRecurring as Event;
 | 
			
		||||
use App\Notifications\Sale\Invoice as Notification;
 | 
			
		||||
 | 
			
		||||
class SendInvoiceRecurringNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = $event->invoice;
 | 
			
		||||
 | 
			
		||||
        // Notify the customer
 | 
			
		||||
        if ($invoice->contact && !empty($invoice->contact_email)) {
 | 
			
		||||
            $invoice->contact->notify(new Notification($invoice, 'invoice_recur_customer'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($invoice->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($invoice, 'invoice_recur_admin'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,34 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Listeners\Sale;
 | 
			
		||||
 | 
			
		||||
use App\Events\Sale\InvoiceReminded as Event;
 | 
			
		||||
use App\Notifications\Sale\Invoice as Notification;
 | 
			
		||||
 | 
			
		||||
class SendInvoiceReminderNotification
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $event
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Event $event)
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = $event->invoice;
 | 
			
		||||
 | 
			
		||||
        // Notify the customer
 | 
			
		||||
        if ($invoice->contact && !empty($invoice->contact_email)) {
 | 
			
		||||
            $invoice->contact->notify(new Notification($invoice, 'invoice_remind_customer'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Notify all users assigned to this company
 | 
			
		||||
        foreach ($invoice->company->users as $user) {
 | 
			
		||||
            if (!$user->can('read-notifications')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $user->notify(new Notification($invoice, 'invoice_remind_admin'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -4,10 +4,16 @@ namespace App\Listeners\Update\V21;
 | 
			
		||||
 | 
			
		||||
use App\Abstracts\Listeners\Update as Listener;
 | 
			
		||||
use App\Events\Install\UpdateFinished as Event;
 | 
			
		||||
use App\Models\Setting\Category;
 | 
			
		||||
use App\Models\Common\Company;
 | 
			
		||||
use App\Models\Document\Document;
 | 
			
		||||
use App\Models\Setting\Category;
 | 
			
		||||
use App\Utilities\Overrider;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Artisan;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class Version210 extends Listener
 | 
			
		||||
{
 | 
			
		||||
@@ -15,6 +21,44 @@ class Version210 extends Listener
 | 
			
		||||
 | 
			
		||||
    const VERSION = '2.1.0';
 | 
			
		||||
 | 
			
		||||
    private $tables = [
 | 
			
		||||
        Document::INVOICE_TYPE => [
 | 
			
		||||
            'estimate_invoice',
 | 
			
		||||
            'foriba_earchive_one_steps',
 | 
			
		||||
            'foriba_earchive_three_steps',
 | 
			
		||||
            'foriba_earchive_two_steps',
 | 
			
		||||
            'foriba_incoming_invoice_histories',
 | 
			
		||||
            'foriba_invoices',
 | 
			
		||||
            'inventory_invoice_items',
 | 
			
		||||
            'iyzico_invoice_refunds',
 | 
			
		||||
            'iyzico_invoices',
 | 
			
		||||
            'iyzico_order',
 | 
			
		||||
            'nesbilgi_bill_histories',
 | 
			
		||||
            'nesbilgi_earchive_one_steps',
 | 
			
		||||
            'nesbilgi_earchive_three_steps',
 | 
			
		||||
            'nesbilgi_earchive_two_steps',
 | 
			
		||||
            'nesbilgi_invoice_histories',
 | 
			
		||||
            'nesbilgi_invoices',
 | 
			
		||||
            'project_invoices',
 | 
			
		||||
        ],
 | 
			
		||||
        Document::BILL_TYPE => [
 | 
			
		||||
            'foriba_incoming_invoice_histories',
 | 
			
		||||
            'inventory_bill_items',
 | 
			
		||||
            'nesbilgi_bill_histories',
 | 
			
		||||
            'project_bills',
 | 
			
		||||
        ],
 | 
			
		||||
        self::ESTIMATE_TYPE => [
 | 
			
		||||
            'proposals',
 | 
			
		||||
            'estimate_invoice',
 | 
			
		||||
        ],
 | 
			
		||||
        self::CREDIT_NOTE_TYPE => [],
 | 
			
		||||
        self::DEBIT_NOTE_TYPE => []
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    private const ESTIMATE_TYPE = 'estimate';
 | 
			
		||||
    private const CREDIT_NOTE_TYPE = 'credit-note';
 | 
			
		||||
    private const DEBIT_NOTE_TYPE = 'debit-note';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the event.
 | 
			
		||||
     *
 | 
			
		||||
@@ -31,9 +75,521 @@ class Version210 extends Listener
 | 
			
		||||
 | 
			
		||||
        Artisan::call('migrate', ['--force' => true]);
 | 
			
		||||
 | 
			
		||||
        $this->copyDocuments();
 | 
			
		||||
 | 
			
		||||
        #todo remove tax_id column
 | 
			
		||||
        $this->copyItemTax();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyDocuments()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->addForeignKeys();
 | 
			
		||||
 | 
			
		||||
            DB::transaction(function () {
 | 
			
		||||
                $totals = collect($this->getTotals(['invoices', 'bills', 'estimates', 'credit_notes', 'debit_notes']));
 | 
			
		||||
 | 
			
		||||
                // Sort table's count by ascending to improve performance.
 | 
			
		||||
                foreach ($totals->sort() as $table => $count) {
 | 
			
		||||
                    $method = 'copy' . Str::studly($table);
 | 
			
		||||
                    $this->$method();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $this->updateCreditNoteTransactionsTable();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            $this->revertTableRenaming();
 | 
			
		||||
 | 
			
		||||
            Log::error($e);
 | 
			
		||||
        } finally {
 | 
			
		||||
            $this->removeForeignKeys();
 | 
			
		||||
            foreach (['estimate', 'bill', 'invoice'] as $item) {
 | 
			
		||||
                $this->removeDocumentIdForeignKeys($item);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function updateCreditNoteTransactionsTable(): void
 | 
			
		||||
    {
 | 
			
		||||
        if (!Schema::hasTable('credits_transactions')) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $invoices = DB::table('credits_transactions')
 | 
			
		||||
                      ->join('invoices_v20', 'credits_transactions.document_id', '=', 'invoices_v20.id')
 | 
			
		||||
                      ->where('credits_transactions.type', 'expense')
 | 
			
		||||
                      ->get(
 | 
			
		||||
                          [
 | 
			
		||||
                              'credits_transactions.id as credits_transactions_id',
 | 
			
		||||
                              'invoices_v20.company_id',
 | 
			
		||||
                              'invoice_number',
 | 
			
		||||
                              'invoices_v20.deleted_at',
 | 
			
		||||
                          ]
 | 
			
		||||
                      );
 | 
			
		||||
 | 
			
		||||
        foreach ($invoices as $invoice) {
 | 
			
		||||
            $documentId = DB::table('documents')
 | 
			
		||||
                            ->where('document_number', $invoice->invoice_number)
 | 
			
		||||
                            ->where('deleted_at', $invoice->deleted_at)
 | 
			
		||||
                            ->where('company_id', $invoice->company_id)
 | 
			
		||||
                            ->where('type', Document::INVOICE_TYPE)
 | 
			
		||||
                            ->pluck('id')
 | 
			
		||||
                            ->first();
 | 
			
		||||
 | 
			
		||||
            DB::table('credits_transactions')
 | 
			
		||||
              ->where('id', $invoice->credits_transactions_id)->update(['document_id' => $documentId]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $credit_notes = DB::table('credits_transactions')
 | 
			
		||||
                          ->join('credit_notes_v20', 'credits_transactions.document_id', '=', 'credit_notes_v20.id')
 | 
			
		||||
                          ->where('credits_transactions.type', 'income')
 | 
			
		||||
                          ->get(
 | 
			
		||||
                              [
 | 
			
		||||
                                  'credits_transactions.id as credits_transactions_id',
 | 
			
		||||
                                  'credit_notes_v20.company_id',
 | 
			
		||||
                                  'credit_note_number',
 | 
			
		||||
                                  'credit_notes_v20.deleted_at',
 | 
			
		||||
                              ]
 | 
			
		||||
                          );
 | 
			
		||||
 | 
			
		||||
        foreach ($credit_notes as $credit_note) {
 | 
			
		||||
            $documentId = DB::table('documents')
 | 
			
		||||
                            ->where('document_number', $credit_note->credit_note_number)
 | 
			
		||||
                            ->where('deleted_at', $credit_note->deleted_at)
 | 
			
		||||
                            ->where('company_id', $credit_note->company_id)
 | 
			
		||||
                            ->where('type', self::CREDIT_NOTE_TYPE)
 | 
			
		||||
                            ->pluck('id')
 | 
			
		||||
                            ->first();
 | 
			
		||||
 | 
			
		||||
            DB::table('credits_transactions')
 | 
			
		||||
              ->where('id', $credit_note->credits_transactions_id)->update(['document_id' => $documentId]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function revertTableRenaming(): void
 | 
			
		||||
    {
 | 
			
		||||
        $tables = [
 | 
			
		||||
            'bill_histories',
 | 
			
		||||
            'bill_item_taxes',
 | 
			
		||||
            'bill_items',
 | 
			
		||||
            'bill_totals',
 | 
			
		||||
            'bills',
 | 
			
		||||
            'credit_note_histories',
 | 
			
		||||
            'credit_note_item_taxes',
 | 
			
		||||
            'credit_note_items',
 | 
			
		||||
            'credit_note_totals',
 | 
			
		||||
            'credit_notes',
 | 
			
		||||
            'debit_note_histories',
 | 
			
		||||
            'debit_note_item_taxes',
 | 
			
		||||
            'debit_note_items',
 | 
			
		||||
            'debit_note_totals',
 | 
			
		||||
            'debit_notes',
 | 
			
		||||
            'estimate_histories',
 | 
			
		||||
            'estimate_item_taxes',
 | 
			
		||||
            'estimate_items',
 | 
			
		||||
            'estimate_totals',
 | 
			
		||||
            'estimates',
 | 
			
		||||
            'invoice_histories',
 | 
			
		||||
            'invoice_item_taxes',
 | 
			
		||||
            'invoice_items',
 | 
			
		||||
            'invoice_totals',
 | 
			
		||||
            'invoices',
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($tables as $table) {
 | 
			
		||||
            if (Schema::hasTable("{$table}_v20")) {
 | 
			
		||||
                Schema::rename("{$table}_v20", $table);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTotals(array $tables): array
 | 
			
		||||
    {
 | 
			
		||||
        $counts = [];
 | 
			
		||||
        foreach ($tables as $table) {
 | 
			
		||||
            if (!Schema::hasTable($table)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $counts[$table] = DB::table($table)->count();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $counts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function batchCopyRelations(string $table, string $type): void
 | 
			
		||||
    {
 | 
			
		||||
        $offset = 0;
 | 
			
		||||
        $limit = 500000;
 | 
			
		||||
        $new_table = Str::replaceFirst(Str::replaceFirst('-', '_', $type), 'document', $table);
 | 
			
		||||
 | 
			
		||||
        // To be able to update relation ids
 | 
			
		||||
        if (in_array($new_table, ['document_items', 'documents']) && DB::table($new_table)->count() > 0) {
 | 
			
		||||
            // Delete document's items which are not found in documents table by document_id
 | 
			
		||||
            $builder = DB::table('document_items')
 | 
			
		||||
                         ->join('documents', 'documents.id', '=', 'document_items.document_id', 'left')
 | 
			
		||||
                         ->whereNull('documents.id');
 | 
			
		||||
 | 
			
		||||
            if ($builder->count()) {
 | 
			
		||||
                $builder->delete();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $documentType = DB::table($new_table)->orderBy('id')->pluck('type')->first();
 | 
			
		||||
 | 
			
		||||
            // To be able to update TYPE_id relations
 | 
			
		||||
            $this->addDocumentIdForeignKeys($documentType);
 | 
			
		||||
 | 
			
		||||
            // Update relation ids
 | 
			
		||||
            DB::table($new_table)
 | 
			
		||||
              ->orderByDesc('id')
 | 
			
		||||
              ->increment('id', DB::table($table)->orderByDesc('id')->pluck('id')->first());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $insertColumns = collect(Schema::getColumnListing($new_table));
 | 
			
		||||
 | 
			
		||||
        $insertColumns = $insertColumns->reject(function ($value) use ($new_table, $table) {
 | 
			
		||||
            // Remove only primary keys
 | 
			
		||||
            if ($value === 'id' && !in_array($new_table, ['document_items', 'documents'])) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($value === 'description' && $new_table === 'document_items') {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($value === 'footer' && in_array($table, ['bills', 'debit_notes'])) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($value === 'order_number' && in_array($table, ['estimates', 'credit_notes', 'debit_notes'])) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($value === 'due_at' && in_array($table, ['estimates', 'credit_notes', 'debit_notes'])) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($value === 'parent_id' && in_array($table, ['estimates', 'credit_notes', 'debit_notes'])) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($table === 'estimate_items' && in_array($value, ['discount_type', 'discount_rate'])) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $selectColumns = $insertColumns->map(function ($column) use($type) {
 | 
			
		||||
            if ($column === 'type') {
 | 
			
		||||
                return "'$type'";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (Str::contains($column, 'document')) {
 | 
			
		||||
                return Str::replaceFirst('document', Str::replaceFirst('-', '_', $type), $column) . ' as ' . $column;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($column === 'issued_at') {
 | 
			
		||||
                switch ($type) {
 | 
			
		||||
                    case Document::INVOICE_TYPE:
 | 
			
		||||
                        return "invoiced_at as $column";
 | 
			
		||||
                    case Document::BILL_TYPE:
 | 
			
		||||
                        return "billed_at as $column";
 | 
			
		||||
                    case self::ESTIMATE_TYPE:
 | 
			
		||||
                        return "estimated_at as $column";
 | 
			
		||||
                    case self::DEBIT_NOTE_TYPE:
 | 
			
		||||
                    case self::CREDIT_NOTE_TYPE:
 | 
			
		||||
                        return "issued_at as $column";
 | 
			
		||||
                    default:
 | 
			
		||||
                        return $column;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $column;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Remove only primary keys
 | 
			
		||||
        if (!in_array($new_table, ['document_items', 'documents'])) {
 | 
			
		||||
            $selectColumns = $selectColumns->reject(function ($value) {
 | 
			
		||||
                return $value === 'id';
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $builder = DB::table($table)->selectRaw($selectColumns->implode(','))->limit($limit)->offset($offset);
 | 
			
		||||
 | 
			
		||||
        while ($builder->cursor()->count()) {
 | 
			
		||||
            Schema::disableForeignKeyConstraints();
 | 
			
		||||
            DB::table($new_table)->insertUsing($insertColumns->toArray(), $builder);
 | 
			
		||||
            Schema::enableForeignKeyConstraints();
 | 
			
		||||
 | 
			
		||||
            $offset += $limit;
 | 
			
		||||
            $builder->limit($limit)->offset($offset);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Schema::rename($table, "{$table}_v20");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyInvoices(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->batchCopyRelations('invoices', Document::INVOICE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('invoice_items', Document::INVOICE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('invoice_item_taxes', Document::INVOICE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('invoice_histories', Document::INVOICE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('invoice_totals', Document::INVOICE_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyBills(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->batchCopyRelations('bills', Document::BILL_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('bill_items', Document::BILL_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('bill_item_taxes', Document::BILL_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('bill_histories', Document::BILL_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('bill_totals', Document::BILL_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyEstimates(): void
 | 
			
		||||
    {
 | 
			
		||||
        $has_estimates = Schema::hasTable('estimates');
 | 
			
		||||
 | 
			
		||||
        if ($has_estimates === false) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->batchCopyRelations('estimates', self::ESTIMATE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('estimate_items', self::ESTIMATE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('estimate_item_taxes', self::ESTIMATE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('estimate_histories', self::ESTIMATE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('estimate_totals', self::ESTIMATE_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyCreditNotes(): void
 | 
			
		||||
    {
 | 
			
		||||
        $has_credit_notes = Schema::hasTable('credit_notes');
 | 
			
		||||
 | 
			
		||||
        if ($has_credit_notes === false) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->batchCopyRelations('credit_notes', self::CREDIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('credit_note_items', self::CREDIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('credit_note_item_taxes', self::CREDIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('credit_note_histories', self::CREDIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('credit_note_totals', self::CREDIT_NOTE_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function copyDebitNotes(): void
 | 
			
		||||
    {
 | 
			
		||||
        $has_debit_notes = Schema::hasTable('debit_notes');
 | 
			
		||||
 | 
			
		||||
        if ($has_debit_notes === false) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->batchCopyRelations('debit_notes', self::DEBIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('debit_note_items', self::DEBIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('debit_note_item_taxes', self::DEBIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('debit_note_histories', self::DEBIT_NOTE_TYPE);
 | 
			
		||||
        $this->batchCopyRelations('debit_note_totals', self::DEBIT_NOTE_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function addForeignKeys(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::disableForeignKeyConstraints();
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_items',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->unsignedInteger('id')->change();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'documents',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->unsignedInteger('id')->change();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_histories',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->foreign('document_id')
 | 
			
		||||
                      ->references('id')
 | 
			
		||||
                      ->on('documents')
 | 
			
		||||
                      ->cascadeOnUpdate();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_items',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->foreign('document_id')
 | 
			
		||||
                      ->references('id')
 | 
			
		||||
                      ->on('documents')
 | 
			
		||||
                      ->cascadeOnUpdate();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_item_taxes',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->foreign('document_id')
 | 
			
		||||
                      ->references('id')
 | 
			
		||||
                      ->on('documents')
 | 
			
		||||
                      ->cascadeOnUpdate();
 | 
			
		||||
 | 
			
		||||
                $table->foreign('document_item_id')
 | 
			
		||||
                      ->references('id')
 | 
			
		||||
                      ->on('document_items')
 | 
			
		||||
                      ->cascadeOnUpdate();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_totals',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->foreign('document_id')
 | 
			
		||||
                      ->references('id')
 | 
			
		||||
                      ->on('documents')
 | 
			
		||||
                      ->cascadeOnUpdate();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::enableForeignKeyConstraints();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function removeForeignKeys(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::disableForeignKeyConstraints();
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_histories',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->dropForeign(['document_id']);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_items',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->dropForeign(['document_id']);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_item_taxes',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->dropForeign(['document_id']);
 | 
			
		||||
                $table->dropForeign(['document_item_id']);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_totals',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->dropForeign(['document_id']);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'documents',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->increments('id')->change();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::table(
 | 
			
		||||
            'document_items',
 | 
			
		||||
            function (Blueprint $table) {
 | 
			
		||||
                $table->increments('id')->change();
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Schema::enableForeignKeyConstraints();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function addDocumentIdForeignKeys(string $type): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::disableForeignKeyConstraints();
 | 
			
		||||
 | 
			
		||||
        foreach ($this->tables[$type] as $table) {
 | 
			
		||||
            if (!Schema::hasTable($table)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $column = "{$type}_id";
 | 
			
		||||
            if ($table === 'proposals') {
 | 
			
		||||
                $column = 'estimates_id';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Schema::table(
 | 
			
		||||
                $table,
 | 
			
		||||
                function (Blueprint $table) use ($column) {
 | 
			
		||||
                    $table->unsignedInteger($column)->change();
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            Schema::table(
 | 
			
		||||
                $table,
 | 
			
		||||
                function (Blueprint $table) use ($column) {
 | 
			
		||||
                    $connection = Schema::getConnection();
 | 
			
		||||
                    $d_table = $connection->getDoctrineSchemaManager()->listTableDetails(
 | 
			
		||||
                        $connection->getTablePrefix() . $table->getTable()
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    if (!$d_table->hasForeignKey("{$connection->getTablePrefix()}{$table->getTable()}_{$column}_foreign")) {
 | 
			
		||||
                        $table->foreign($column)
 | 
			
		||||
                              ->references('id')
 | 
			
		||||
                              ->on('documents')
 | 
			
		||||
                              ->cascadeOnUpdate();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Schema::enableForeignKeyConstraints();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function removeDocumentIdForeignKeys(string $type): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::disableForeignKeyConstraints();
 | 
			
		||||
 | 
			
		||||
        foreach ($this->tables[$type] as $table) {
 | 
			
		||||
            if (!Schema::hasTable($table)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $column = "{$type}_id";
 | 
			
		||||
            if ($table === 'proposals') {
 | 
			
		||||
                $column = 'estimates_id';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Schema::table(
 | 
			
		||||
                $table,
 | 
			
		||||
                function (Blueprint $table) use ($column) {
 | 
			
		||||
                    $connection = Schema::getConnection();
 | 
			
		||||
                    $d_table = $connection->getDoctrineSchemaManager()->listTableDetails(
 | 
			
		||||
                        $connection->getTablePrefix() . $table->getTable()
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    if ($d_table->hasForeignKey("{$connection->getTablePrefix()}{$table->getTable()}_{$column}_foreign")) {
 | 
			
		||||
                        $table->dropForeign([$column]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            Schema::table(
 | 
			
		||||
                $table,
 | 
			
		||||
                function (Blueprint $table) use ($column) {
 | 
			
		||||
                    $table->integer($column)->change();
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Schema::enableForeignKeyConstraints();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function updateCompanies()
 | 
			
		||||
    {
 | 
			
		||||
        $company_id = session('company_id');
 | 
			
		||||
@@ -73,15 +629,19 @@ class Version210 extends Listener
 | 
			
		||||
    {
 | 
			
		||||
        $items = DB::table('items')->cursor();
 | 
			
		||||
 | 
			
		||||
        foreach ($items as $item) {
 | 
			
		||||
            DB::table('item_taxes')->insert([
 | 
			
		||||
                'company_id' => $item->company_id,
 | 
			
		||||
                'item_id'    => $item->id,
 | 
			
		||||
                'tax_id'     => $item->tax_id,
 | 
			
		||||
                'created_at' => $item->created_at,
 | 
			
		||||
                'updated_at' => $item->updated_at,
 | 
			
		||||
                'deleted_at' => $item->deleted_at,
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
        DB::transaction(function () use ($items) {
 | 
			
		||||
            foreach ($items as $item) {
 | 
			
		||||
                DB::table('item_taxes')->insert(
 | 
			
		||||
                    [
 | 
			
		||||
                        'company_id' => $item->company_id,
 | 
			
		||||
                        'item_id'    => $item->id,
 | 
			
		||||
                        'tax_id'     => $item->tax_id,
 | 
			
		||||
                        'created_at' => $item->created_at,
 | 
			
		||||
                        'updated_at' => $item->updated_at,
 | 
			
		||||
                        'deleted_at' => $item->deleted_at,
 | 
			
		||||
                    ]
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user