From 515e93250f0c15b8f999c91790da44d3989b1e4a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 19 Dec 2022 23:25:48 +1100 Subject: [PATCH] Purchase Order Notifications --- .../Controllers/PurchaseOrderController.php | 2 +- ....php => PurchaseOrderAcceptedListener.php} | 4 +- .../PurchaseOrderCreatedListener.php | 81 ++++++++++++++++++ .../PurchaseOrderEmailedNotification.php | 85 +++++++++++++++++++ app/Mail/Admin/EntityCreatedObject.php | 74 +++++++++++++--- app/Mail/Admin/EntitySentObject.php | 52 ++++++++++-- app/Providers/EventServiceProvider.php | 17 ++-- lang/en/texts.php | 5 +- 8 files changed, 287 insertions(+), 33 deletions(-) rename app/Listeners/PurchaseOrder/{PurchaseOrderAcceptedNotification.php => PurchaseOrderAcceptedListener.php} (96%) create mode 100644 app/Listeners/PurchaseOrder/PurchaseOrderCreatedListener.php create mode 100644 app/Listeners/PurchaseOrder/PurchaseOrderEmailedNotification.php diff --git a/app/Http/Controllers/PurchaseOrderController.php b/app/Http/Controllers/PurchaseOrderController.php index d08d51077c44..452c5895374d 100644 --- a/app/Http/Controllers/PurchaseOrderController.php +++ b/app/Http/Controllers/PurchaseOrderController.php @@ -195,7 +195,7 @@ class PurchaseOrderController extends BaseController ->fillDefaults() ->triggeredActions($request) ->save(); - + event(new PurchaseOrderWasCreated($purchase_order, $purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); return $this->itemResponse($purchase_order->fresh()); diff --git a/app/Listeners/PurchaseOrder/PurchaseOrderAcceptedNotification.php b/app/Listeners/PurchaseOrder/PurchaseOrderAcceptedListener.php similarity index 96% rename from app/Listeners/PurchaseOrder/PurchaseOrderAcceptedNotification.php rename to app/Listeners/PurchaseOrder/PurchaseOrderAcceptedListener.php index d65681cc5ec4..ff64295ee7b5 100644 --- a/app/Listeners/PurchaseOrder/PurchaseOrderAcceptedNotification.php +++ b/app/Listeners/PurchaseOrder/PurchaseOrderAcceptedListener.php @@ -21,12 +21,10 @@ use App\Notifications\Admin\EntitySentNotification; use App\Utils\Traits\Notifications\UserNotifies; use Illuminate\Contracts\Queue\ShouldQueue; -class PurchaseOrderAcceptedNotification implements ShouldQueue +class PurchaseOrderAcceptedListener implements ShouldQueue { use UserNotifies; - public $delay = 5; - public function __construct() { } diff --git a/app/Listeners/PurchaseOrder/PurchaseOrderCreatedListener.php b/app/Listeners/PurchaseOrder/PurchaseOrderCreatedListener.php new file mode 100644 index 000000000000..088aaf81c380 --- /dev/null +++ b/app/Listeners/PurchaseOrder/PurchaseOrderCreatedListener.php @@ -0,0 +1,81 @@ +company->db); + + $first_notification_sent = true; + + $purchase_order = $event->purchase_order; + + $nmo = new NinjaMailerObject; + $nmo->mailable = new NinjaMailer((new EntityCreatedObject($purchase_order, 'purchase_order'))->build()); + $nmo->company = $purchase_order->company; + $nmo->settings = $purchase_order->company->settings; + + /* We loop through each user and determine whether they need to be notified */ + foreach ($event->company->company_users as $company_user) { + + /* The User */ + $user = $company_user->user; + + if (! $user) { + continue; + } + + /* This is only here to handle the alternate message channels - ie Slack */ + // $notification = new EntitySentNotification($event->invitation, 'purchase_order'); + + /* Returns an array of notification methods */ + $methods = $this->findUserNotificationTypes($purchase_order->invitations()->first(), $company_user, 'purchase_order', ['all_notifications', 'purchase_order_created', 'purchase_order_created_all']); + /* If one of the methods is email then we fire the EntitySentMailer */ + + if (($key = array_search('mail', $methods)) !== false) { + unset($methods[$key]); + + $nmo->to_user = $user; + + NinjaMailerJob::dispatch($nmo); + + /* This prevents more than one notification being sent */ + $first_notification_sent = false; + } + } + } +} diff --git a/app/Listeners/PurchaseOrder/PurchaseOrderEmailedNotification.php b/app/Listeners/PurchaseOrder/PurchaseOrderEmailedNotification.php new file mode 100644 index 000000000000..36cc203526cf --- /dev/null +++ b/app/Listeners/PurchaseOrder/PurchaseOrderEmailedNotification.php @@ -0,0 +1,85 @@ +company->db); + + $first_notification_sent = true; + + $purchase_order = $event->invitation->purchase_order->fresh(); + $purchase_order->last_sent_date = now(); + $purchase_order->saveQuietly(); + + $nmo = new NinjaMailerObject; + $nmo->mailable = new NinjaMailer((new EntitySentObject($event->invitation, 'purchase_order', 'purchase_order'))->build()); + $nmo->company = $purchase_order->company; + $nmo->settings = $purchase_order->company->settings; + + /* We loop through each user and determine whether they need to be notified */ + foreach ($event->invitation->company->company_users as $company_user) { + + /* The User */ + $user = $company_user->user; + + /* This is only here to handle the alternate message channels - ie Slack */ + // $notification = new EntitySentNotification($event->invitation, 'purchase_order'); + + /* Returns an array of notification methods */ + $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'purchase_order', ['all_notifications', 'purchase_order_sent', 'purchase_order_sent_all']); + + /* If one of the methods is email then we fire the EntitySentMailer */ + if (($key = array_search('mail', $methods)) !== false) { + unset($methods[$key]); + + $nmo->to_user = $user; + + NinjaMailerJob::dispatch($nmo); + + /* This prevents more than one notification being sent */ + $first_notification_sent = false; + } + + /* Override the methods in the Notification Class */ + // $notification->method = $methods; + + // Notify on the alternate channels + // $user->notify($notification); + } + } +} diff --git a/app/Mail/Admin/EntityCreatedObject.php b/app/Mail/Admin/EntityCreatedObject.php index 38555b06d1ec..2cec34303b6a 100644 --- a/app/Mail/Admin/EntityCreatedObject.php +++ b/app/Mail/Admin/EntityCreatedObject.php @@ -13,6 +13,7 @@ namespace App\Mail\Admin; use App\Utils\Ninja; use App\Utils\Number; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Support\Facades\App; use stdClass; @@ -38,7 +39,11 @@ class EntityCreatedObject $this->entity = $entity; } - public function build() + /** + * @return stdClass + * @throws BindingResolutionException + */ + public function build() :stdClass { App::forgetInstance('translator'); /* Init a new copy of the translator*/ @@ -47,26 +52,64 @@ class EntityCreatedObject App::setLocale($this->entity->company->getLocale()); /* Set customized translations _NOW_ */ $t->replace(Ninja::transformTranslations($this->entity->company->settings)); - - $this->entity->load('client.country', 'client.company'); - $this->client = $this->entity->client; + $this->setTemplate(); $this->company = $this->entity->company; - $this->setTemplate(); + if($this->entity_type == 'purchase_order') + { - $mail_obj = new stdClass; - $mail_obj->amount = $this->getAmount(); - $mail_obj->subject = $this->getSubject(); - $mail_obj->data = $this->getData(); - $mail_obj->markdown = 'email.admin.generic'; - $mail_obj->tag = $this->company->company_key; + $this->entity->load('vendor.company'); + $mail_obj = new stdClass; + $mail_obj->amount = Number::formatMoney($this->entity->amount, $this->entity->vendor); + + $mail_obj->subject = ctrans($this->template_subject, + [ + 'vendor' => $this->entity->vendor->present()->name(), + 'purchase_order' => $this->entity->number, + ] + ); + + $mail_obj->markdown = 'email.admin.generic'; + $mail_obj->tag = $this->company->company_key; + $mail_obj->data = [ + 'title' => $mail_obj->subject, + 'message' => ctrans($this->template_body, + [ + 'amount' => $mail_obj->amount, + 'vendor' => $this->entity->vendor->present()->name(), + 'purchase_order' => $this->entity->number, + ] + ), + 'url' => $this->entity->invitations()->first()->getAdminLink(), + 'button' => ctrans("texts.view_{$this->entity_type}"), + 'signature' => $this->company->settings->email_signature, + 'logo' => $this->company->present()->logo(), + 'settings' => $this->company->settings, + 'whitelabel' => $this->company->account->isPaid() ? true : false, + ]; + + + } + else { + + $this->entity->load('client.country', 'client.company'); + $this->client = $this->entity->client; + + $mail_obj = new stdClass; + $mail_obj->amount = $this->getAmount(); + $mail_obj->subject = $this->getSubject(); + $mail_obj->data = $this->getData(); + $mail_obj->markdown = 'email.admin.generic'; + $mail_obj->tag = $this->entity->company->company_key; + + } + return $mail_obj; } private function setTemplate() { - // nlog($this->template); switch ($this->entity_type) { case 'invoice': @@ -81,7 +124,10 @@ class EntityCreatedObject $this->template_subject = 'texts.notification_credit_created_subject'; $this->template_body = 'texts.notification_credit_created_body'; break; - + case 'purchase_order': + $this->template_subject = 'texts.notification_purchase_order_created_subject'; + $this->template_body = 'texts.notification_purchase_order_created_body'; + break; default: $this->template_subject = 'texts.notification_invoice_created_subject'; $this->template_body = 'texts.notification_invoice_created_body'; @@ -89,7 +135,7 @@ class EntityCreatedObject } } - private function getAmount() + private function getAmount() { return Number::formatMoney($this->entity->amount, $this->entity->client); } diff --git a/app/Mail/Admin/EntitySentObject.php b/app/Mail/Admin/EntitySentObject.php index b960270ad717..fe636efc571c 100644 --- a/app/Mail/Admin/EntitySentObject.php +++ b/app/Mail/Admin/EntitySentObject.php @@ -58,13 +58,48 @@ class EntitySentObject $this->setTemplate(); - $mail_obj = new stdClass; - $mail_obj->amount = $this->getAmount(); - $mail_obj->subject = $this->getSubject(); - $mail_obj->data = $this->getData(); - $mail_obj->markdown = 'email.admin.generic'; - $mail_obj->tag = $this->company->company_key; + if($this->template == 'purchase_order') + { + $mail_obj = new stdClass; + $mail_obj->amount = Number::formatMoney($this->entity->amount, $this->entity->vendor); + $mail_obj->subject = ctrans($this->template_subject, + [ + 'vendor' => $this->contact->vendor->present()->name(), + 'purchase_order' => $this->entity->number, + ] + ); + $mail_obj->data = [ + 'title' => $mail_obj->subject, + 'message' => ctrans($this->template_body, + [ + 'amount' => $mail_obj->amount, + 'vendor' => $this->contact->vendor->present()->name(), + 'purchase_order' => $this->entity->number, + ] + ), + 'url' => $this->invitation->getAdminLink(), + 'button' => ctrans("texts.view_{$this->entity_type}"), + 'signature' => $this->company->settings->email_signature, + 'logo' => $this->company->present()->logo(), + 'settings' => $this->company->settings, + 'whitelabel' => $this->company->account->isPaid() ? true : false, + ]; + $mail_obj->markdown = 'email.admin.generic'; + $mail_obj->tag = $this->company->company_key; + + } + else { + + $mail_obj = new stdClass; + $mail_obj->amount = $this->getAmount(); + $mail_obj->subject = $this->getSubject(); + $mail_obj->data = $this->getData(); + $mail_obj->markdown = 'email.admin.generic'; + $mail_obj->tag = $this->company->company_key; + + } + return $mail_obj; } @@ -101,7 +136,10 @@ class EntitySentObject $this->template_subject = 'texts.notification_credit_sent_subject'; $this->template_body = 'texts.notification_credit_sent'; break; - + case 'purchase_order': + $this->template_subject = 'texts.notification_purchase_order_sent_subject'; + $this->template_body = 'texts.notification_purchase_order_sent'; + break; default: $this->template_subject = 'texts.notification_invoice_sent_subject'; $this->template_body = 'texts.notification_invoice_sent'; diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index cc3a02d52079..2e7b59ebc4cc 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -157,15 +157,14 @@ use App\Listeners\Credit\CreditRestoredActivity; use App\Listeners\Credit\CreditViewedActivity; use App\Listeners\Document\DeleteCompanyDocuments; use App\Listeners\Invoice\CreateInvoiceActivity; -use App\Listeners\Invoice\CreateInvoiceHtmlBackup; use App\Listeners\Invoice\CreateInvoicePdf; use App\Listeners\Invoice\InvoiceArchivedActivity; use App\Listeners\Invoice\InvoiceCancelledActivity; use App\Listeners\Invoice\InvoiceCreatedNotification; use App\Listeners\Invoice\InvoiceDeletedActivity; use App\Listeners\Invoice\InvoiceEmailActivity; -use App\Listeners\Invoice\InvoiceEmailedNotification; use App\Listeners\Invoice\InvoiceEmailFailedActivity; +use App\Listeners\Invoice\InvoiceEmailedNotification; use App\Listeners\Invoice\InvoiceFailedEmailNotification; use App\Listeners\Invoice\InvoicePaidActivity; use App\Listeners\Invoice\InvoiceReminderEmailActivity; @@ -175,18 +174,21 @@ use App\Listeners\Invoice\InvoiceViewedActivity; use App\Listeners\Invoice\UpdateInvoiceActivity; use App\Listeners\Mail\MailSentListener; use App\Listeners\Misc\InvitationViewedListener; -use App\Listeners\Payment\PaymentEmailedActivity; use App\Listeners\Payment\PaymentEmailFailureActivity; +use App\Listeners\Payment\PaymentEmailedActivity; use App\Listeners\Payment\PaymentNotification; use App\Listeners\Payment\PaymentRestoredActivity; use App\Listeners\PurchaseOrder\CreatePurchaseOrderActivity; use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedNotification; +use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedListener; use App\Listeners\PurchaseOrder\PurchaseOrderArchivedActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderCreatedListener; use App\Listeners\PurchaseOrder\PurchaseOrderDeletedActivity; use App\Listeners\PurchaseOrder\PurchaseOrderEmailActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderEmailedNotification; use App\Listeners\PurchaseOrder\PurchaseOrderRestoredActivity; use App\Listeners\PurchaseOrder\PurchaseOrderViewedActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderViewedNotification; use App\Listeners\PurchaseOrder\UpdatePurchaseOrderActivity; use App\Listeners\Quote\QuoteApprovedActivity; use App\Listeners\Quote\QuoteApprovedNotification; @@ -219,8 +221,8 @@ use App\Listeners\User\ArchivedUserActivity; use App\Listeners\User\CreatedUserActivity; use App\Listeners\User\DeletedUserActivity; use App\Listeners\User\RestoredUserActivity; -use App\Listeners\User\UpdatedUserActivity; use App\Listeners\User\UpdateUserLastLogin; +use App\Listeners\User\UpdatedUserActivity; use App\Models\Account; use App\Models\Client; use App\Models\Company; @@ -398,7 +400,6 @@ class EventServiceProvider extends ServiceProvider ], //Invoices InvoiceWasMarkedSent::class => [ - CreateInvoiceHtmlBackup::class, ], InvoiceWasUpdated::class => [ UpdateInvoiceActivity::class, @@ -458,12 +459,14 @@ class EventServiceProvider extends ServiceProvider ], PurchaseOrderWasCreated::class => [ CreatePurchaseOrderActivity::class, + PurchaseOrderCreatedListener::class, ], PurchaseOrderWasDeleted::class => [ PurchaseOrderDeletedActivity::class, ], PurchaseOrderWasEmailed::class => [ PurchaseOrderEmailActivity::class, + PurchaseOrderEmailedNotification::class, ], PurchaseOrderWasRestored::class => [ PurchaseOrderRestoredActivity::class, @@ -475,8 +478,8 @@ class EventServiceProvider extends ServiceProvider PurchaseOrderViewedActivity::class, ], PurchaseOrderWasAccepted::class => [ + PurchaseOrderAcceptedListener::class, PurchaseOrderAcceptedActivity::class, - PurchaseOrderAcceptedNotification::class, ], CompanyDocumentsDeleted::class => [ DeleteCompanyDocuments::class, diff --git a/lang/en/texts.php b/lang/en/texts.php index 03e365511598..04d4e52a2605 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -4906,7 +4906,10 @@ $LANG = array( 'backup_restore' => 'Backup | Restore', 'export_company' => 'Create company backup', 'backup' => 'Backup', - + 'notification_purchase_order_created_body' => 'The following purchase_order :purchase_order was created for vendor :vendor for :amount.', + 'notification_purchase_order_created_subject' => 'Purchase Order :purchase_order was created for :vendor', + 'notification_purchase_order_sent_subject' => 'Purchase Order :purchase_order was sent to :vendor', + 'notification_purchase_order_sent' => 'The following vendor :vendor was emailed Purchase Order :purchase_order for :amount.', ); return $LANG;