diff --git a/app/Events/QuoteInvitationWasApproved.php b/app/Events/QuoteInvitationWasApproved.php index 954aa83b4cf2..5e69fe9c7895 100644 --- a/app/Events/QuoteInvitationWasApproved.php +++ b/app/Events/QuoteInvitationWasApproved.php @@ -9,6 +9,7 @@ class QuoteInvitationWasApproved extends Event { use SerializesModels; public $quote; + public $invoice; public $invitation; /** @@ -16,9 +17,10 @@ class QuoteInvitationWasApproved extends Event { * * @return void */ - public function __construct($quote, $invitation) + public function __construct($quote, $invoice, $invitation) { $this->quote = $quote; + $this->invoice = $invoice; $this->invitation = $invitation; } diff --git a/app/Http/Middleware/StartupCheck.php b/app/Http/Middleware/StartupCheck.php index c95b41101935..bf730af09e93 100644 --- a/app/Http/Middleware/StartupCheck.php +++ b/app/Http/Middleware/StartupCheck.php @@ -34,7 +34,6 @@ class StartupCheck // Ensure all request are over HTTPS in production if (Utils::requireHTTPS() && !Request::secure()) { - //return Redirect::secure(Request::getRequestUri()); return Redirect::secure(Request::path()); } diff --git a/app/Http/routes.php b/app/Http/routes.php index 71989afbd866..7c8fd031fa30 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -445,7 +445,7 @@ if (!defined('CONTACT_EMAIL')) { define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/api/browser/v2/'); define('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php'); define('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/'); - define('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup/overview'); + define('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup'); define('COUNT_FREE_DESIGNS', 4); define('COUNT_FREE_DESIGNS_SELF_HOST', 5); // include the custom design diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index e097ce447705..9e10021ab874 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -313,6 +313,15 @@ class Invoice extends EntityModel implements BalanceAffecting return $this->invoice_status_id >= INVOICE_STATUS_PAID; } + public function isOverdue() + { + if ( ! $this->due_date) { + return false; + } + + return time() > strtotime($this->due_date); + } + public function getRequestedAmount() { return $this->partial > 0 ? $this->partial : $this->balance; diff --git a/app/Ninja/Mailers/ContactMailer.php b/app/Ninja/Mailers/ContactMailer.php index 1d955935644b..36dcc6fb6cf6 100644 --- a/app/Ninja/Mailers/ContactMailer.php +++ b/app/Ninja/Mailers/ContactMailer.php @@ -172,7 +172,12 @@ class ContactMailer extends Mailer $data = [ 'body' => $this->processVariables($emailTemplate, $variables), + 'link' => $invitation->getLink(), + 'invoice' => $invoice, + 'client' => $client, 'account' => $account, + 'payment' => $payment, + 'entityType' => ENTITY_INVOICE, ]; if ($account->attatchPDF()) { diff --git a/app/Ninja/Mailers/UserMailer.php b/app/Ninja/Mailers/UserMailer.php index 21e8b0528631..ce0c5383410d 100644 --- a/app/Ninja/Mailers/UserMailer.php +++ b/app/Ninja/Mailers/UserMailer.php @@ -53,6 +53,7 @@ class UserMailer extends Mailer 'invoiceAmount' => $account->formatMoney($invoice->getRequestedAmount(), $client), 'invoiceNumber' => $invoice->invoice_number, 'invoiceLink' => SITE_URL."/{$entityType}s/{$invoice->public_id}", + 'account' => $account, ]; if ($payment) { @@ -70,6 +71,7 @@ class UserMailer extends Mailer public function sendEmailBounced(Invitation $invitation) { $user = $invitation->user; + $account = $user->account; $invoice = $invitation->invoice; $entityType = $invoice->getEntityType(); diff --git a/app/Ninja/Presenters/InvoicePresenter.php b/app/Ninja/Presenters/InvoicePresenter.php index 73a248355441..fb292a8859b9 100644 --- a/app/Ninja/Presenters/InvoicePresenter.php +++ b/app/Ninja/Presenters/InvoicePresenter.php @@ -26,6 +26,18 @@ class InvoicePresenter extends Presenter { } } + // https://schema.org/PaymentStatusType + public function paymentStatus() + { + if ( ! $this->entity->balance) { + return 'PaymentComplete'; + } elseif ($this->entity->isOverdue()) { + return 'PaymentPastDue'; + } else { + return 'PaymentDue'; + } + } + public function status() { $status = $this->entity->invoice_status ? $this->entity->invoice_status->name : 'draft'; diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index d1e4f3914d45..2142588ec99a 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -627,6 +627,8 @@ class InvoiceRepository extends BaseRepository if ($recurInvoice->auto_bill) { if ($this->paymentService->autoBillInvoice($invoice)) { + // update the invoice reference to match its actual state + // this is to ensure a 'payment received' email is sent $invoice->invoice_status_id = INVOICE_STATUS_PAID; } } diff --git a/app/Services/InvoiceService.php b/app/Services/InvoiceService.php index d2f73f58f65c..664180e5a95f 100644 --- a/app/Services/InvoiceService.php +++ b/app/Services/InvoiceService.php @@ -74,7 +74,7 @@ class InvoiceService extends BaseService return $invoice; } - event(new QuoteInvitationWasApproved($invoice, $invitation)); + event(new QuoteInvitationWasApproved($quote, $invoice, $invitation)); foreach ($invoice->invitations as $invoiceInvitation) { if ($invitation->contact_id == $invoiceInvitation->contact_id) { diff --git a/resources/views/accounts/email_settings.blade.php b/resources/views/accounts/email_settings.blade.php index 2bc11b45bb15..01269a4bb808 100644 --- a/resources/views/accounts/email_settings.blade.php +++ b/resources/views/accounts/email_settings.blade.php @@ -15,9 +15,20 @@