diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 153f76a656ae..052a1a3c9dcb 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -174,12 +174,7 @@ class PreviewController extends BaseController MultiDB::setDb($company->db); - if($request->input('entity') == 'invoice'){ - $repo = new InvoiceRepository(); - $entity_obj = InvoiceFactory::create($company->id, auth()->user()->id); - $class = Invoice::class; - } - elseif($request->input('entity') == 'quote'){ + if($request->input('entity') == 'quote'){ $repo = new QuoteRepository(); $entity_obj = QuoteFactory::create($company->id, auth()->user()->id); $class = Quote::class; @@ -195,7 +190,11 @@ class PreviewController extends BaseController $entity_obj = RecurringInvoiceFactory::create($company->id, auth()->user()->id); $class = RecurringInvoice::class; } - + else { //assume it is either an invoice or a null object + $repo = new InvoiceRepository(); + $entity_obj = InvoiceFactory::create($company->id, auth()->user()->id); + $class = Invoice::class; + } try { diff --git a/app/Listeners/Quote/QuoteApprovedNotification.php b/app/Listeners/Quote/QuoteApprovedNotification.php new file mode 100644 index 000000000000..59199d0c535d --- /dev/null +++ b/app/Listeners/Quote/QuoteApprovedNotification.php @@ -0,0 +1,86 @@ +company->db); + + $first_notification_sent = true; + + $quote = $event->quote; + + $nmo = new NinjaMailerObject; + $nmo->mailable = new NinjaMailer( (new QuoteApprovedObject($quote, $event->company))->build() ); + $nmo->company = $quote->company; + $nmo->settings = $quote->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, 'quote'); + + /* Returns an array of notification methods */ + $methods = $this->findUserNotificationTypes($quote->invitations()->first(), $company_user, 'quote', ['all_notifications', 'quote_approved', 'quote_approved_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/ClientPaymentFailureObject.php b/app/Mail/Admin/ClientPaymentFailureObject.php index f7f3ffbbfea6..ad2629c3f27a 100644 --- a/app/Mail/Admin/ClientPaymentFailureObject.php +++ b/app/Mail/Admin/ClientPaymentFailureObject.php @@ -69,7 +69,7 @@ class ClientPaymentFailureObject /* Set customized translations _NOW_ */ $t->replace(Ninja::transformTranslations($this->company->settings)); - $this->invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get(); + $this->invoices = Invoice::withTrashed()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get(); $mail_obj = new stdClass; $mail_obj->amount = $this->getAmount(); @@ -101,8 +101,13 @@ class ClientPaymentFailureObject private function getData() { + $invitation = $this->invoices->first()->invitations->first(); + + if(!$invitation) + throw new \Exception('Unable to find invitation for reference'); + $signature = $this->client->getSetting('email_signature'); - $html_variables = (new HtmlEngine($this->invoices->first()->invitations->first()))->makeValues(); + $html_variables = (new HtmlEngine($invitation))->makeValues(); $signature = str_replace(array_keys($html_variables), array_values($html_variables), $signature); $data = [ diff --git a/app/Mail/Admin/QuoteApprovedObject.php b/app/Mail/Admin/QuoteApprovedObject.php new file mode 100644 index 000000000000..a5c88e904de4 --- /dev/null +++ b/app/Mail/Admin/QuoteApprovedObject.php @@ -0,0 +1,103 @@ +quote = $quote; + $this->company = $company; + } + + public function build() + { + MultiDB::setDb($this->company->db); + + if(!$this->quote) + return; + + App::forgetInstance('translator'); + /* Init a new copy of the translator*/ + $t = app('translator'); + /* Set the locale*/ + App::setLocale($this->company->getLocale()); + /* Set customized translations _NOW_ */ + $t->replace(Ninja::transformTranslations($this->company->settings)); + + $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; + } + + private function getAmount() + { + return Number::formatMoney($this->quote->amount, $this->quote->client); + } + + private function getSubject() + { + return + ctrans( + "texts.notification_quote_approved_subject", + [ + 'client' => $this->quote->client->present()->name(), + 'invoice' => $this->quote->number, + ] + ); + } + + private function getData() + { + $settings = $this->quote->client->getMergedSettings(); + + $data = [ + 'title' => $this->getSubject(), + 'message' => ctrans( + "texts.notification_quote_approved", + [ + 'amount' => $this->getAmount(), + 'client' => $this->quote->client->present()->name(), + 'invoice' => $this->quote->number, + ] + ), + 'url' => $this->quote->invitations->first()->getAdminLink(), + 'button' => ctrans("texts.view_quote"), + 'signature' => $settings->email_signature, + 'logo' => $this->company->present()->logo(), + 'settings' => $settings, + 'whitelabel' => $this->company->account->isPaid() ? true : false, + ]; + + return $data; + } +} diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 15d2e927d09d..bddc4ad0e537 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -195,7 +195,7 @@ class BaseModel extends Model // Remove any runs of periods (thanks falstro!) $formatted_number = mb_ereg_replace("([\.]{2,})", '', $formatted_number); - $formatted_number = str_replace(" ", "", $formatted_number); + $formatted_number = str_replace(" ", "_", $formatted_number); return $formatted_number; } diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index 944a1038a197..bbb80d4b9369 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -222,6 +222,9 @@ class RecurringInvoice extends BaseModel return null; } + nlog("frequency = $this->frequency_id"); + nlog("frequency = $this->next_send_date"); + $offset = $this->client->timezone_offset(); /* diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 52b15e64ba81..5acc2f234388 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -171,6 +171,7 @@ use App\Listeners\Payment\PaymentEmailedActivity; use App\Listeners\Payment\PaymentNotification; use App\Listeners\Payment\PaymentRestoredActivity; use App\Listeners\Quote\QuoteApprovedActivity; +use App\Listeners\Quote\QuoteApprovedNotification; use App\Listeners\Quote\QuoteApprovedWebhook; use App\Listeners\Quote\QuoteArchivedActivity; use App\Listeners\Quote\QuoteCreatedNotification; @@ -437,6 +438,7 @@ class EventServiceProvider extends ServiceProvider ReachWorkflowSettings::class, QuoteApprovedActivity::class, QuoteApprovedWebhook::class, + QuoteApprovedNotification::class, ], QuoteWasCreated::class => [ CreatedQuoteActivity::class, diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index 178bdd25a9b3..7a8e54ba75e5 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -75,9 +75,9 @@ class SubscriptionService $recurring_invoice = $this->convertInvoiceToRecurring($payment_hash->payment->client_id); $recurring_invoice_repo = new RecurringInvoiceRepository(); - $recurring_invoice->next_send_date = now(); $recurring_invoice = $recurring_invoice_repo->save([], $recurring_invoice); - $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); + // $recurring_invoice->next_send_date = now()->format('Y-m-d'); + // $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); $recurring_invoice->auto_bill = $this->subscription->auto_bill; /* Start the recurring service */ @@ -594,7 +594,7 @@ class SubscriptionService $recurring_invoice = $this->convertInvoiceToRecurring($old_recurring_invoice->client_id); $recurring_invoice = $recurring_invoice_repo->save([], $recurring_invoice); - $recurring_invoice->next_send_date = now(); + $recurring_invoice->next_send_date = now()->format('Y-m-d'); $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); /* Start the recurring service */ @@ -722,7 +722,9 @@ class SubscriptionService $recurring_invoice->auto_bill = $client->getSetting('auto_bill'); $recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill); $recurring_invoice->due_date_days = 'terms'; - + $recurring_invoice->next_send_date = now()->format('Y-m-d'); + $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); + return $recurring_invoice; } @@ -1027,7 +1029,7 @@ class SubscriptionService 'subscription' => $this->subscription->hashed_id, 'recurring_invoice' => $recurring_invoice_hashed_id, 'client' => $invoice->client->hashed_id, - 'contact' => $invoice->client->primary_contact()->first() ? $invoice->client->primary_contact()->first(): $invoice->client->contacts->first(), + 'contact' => $invoice->client->primary_contact()->first() ? $invoice->client->primary_contact()->first()->hashed_id: $invoice->client->contacts->first()->hashed_id, 'invoice' => $invoice->hashed_id, ];