Fixes for recurring invoice cancellations

This commit is contained in:
David Bomba 2023-01-12 17:29:28 +11:00
parent 1d811c49b9
commit 7e7cffa8c8
5 changed files with 48 additions and 42 deletions

View File

@ -11,35 +11,33 @@
namespace App\Mail\RecurringInvoice;
use App\Models\ClientContact;
use App\Models\RecurringInvoice;
use App\Utils\Ninja;
use Illuminate\Support\Facades\App;
class ClientContactRequestCancellationObject
{
public $recurring_invoice;
public $client_contact;
private $company;
public function __construct($recurring_invoice, $client_contact)
{
$this->recurring_invoice = $recurring_invoice;
$this->client_contact = $client_contact;
$this->company = $recurring_invoice->company;
}
public function __construct(public RecurringInvoice $recurring_invoice, public ClientContact $client_contact, private bool $gateway_refund_attempted){}
public function build()
{
$this->company = $this->recurring_invoice->company;
App::forgetInstance('translator');
App::setLocale($this->company->getLocale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$content = ctrans('texts.recurring_cancellation_request_body', ['contact' => $this->client_contact->present()->name(), 'client' => $this->client_contact->client->present()->name(), 'invoice' => $this->recurring_invoice->number]);
if($this->gateway_refund_attempted)
$content .= "\n\n" . ctrans('texts.status') . " : " . ctrans('texts.payment_status_6');
$data = [
'title' => ctrans('texts.recurring_cancellation_request', ['contact' => $this->client_contact->present()->name()]),
'content' => ctrans('texts.recurring_cancellation_request_body', ['contact' => $this->client_contact->present()->name(), 'client' => $this->client_contact->client->present()->name(), 'invoice' => $this->recurring_invoice->number]),
'content' => $content,
'url' => config('ninja.web_url'),
'button' => ctrans('texts.account_login'),
'signature' => $this->company->settings->email_signature,

View File

@ -1179,11 +1179,15 @@ class SubscriptionService
{
$invoice_start_date = false;
$refund_end_date = false;
$gateway_refund_attempted = false;
//only refund if they are in the refund window.
$outstanding_invoice = Invoice::where('subscription_id', $this->subscription->id)
->where('client_id', $recurring_invoice->client_id)
->where('status_id', Invoice::STATUS_PAID)
->where('is_deleted', 0)
->where('is_proforma',0)
->where('balance',0)
->orderBy('id', 'desc')
->first();
@ -1199,7 +1203,7 @@ class SubscriptionService
$recurring_invoice_repo->archive($recurring_invoice);
/* Refund only if we are in the window - and there is nothing outstanding on the invoice */
if($refund_end_date && $refund_end_date->greaterThan(now()) && (int)$outstanding_invoice->balance == 0)
if($refund_end_date && $refund_end_date->greaterThan(now()))
{
if($outstanding_invoice->payments()->exists())
@ -1208,8 +1212,9 @@ class SubscriptionService
$data = [
'id' => $payment->id,
'gateway_refund' => true,
'gateway_refund' => $outstanding_invoice->amount >= 1 ? true : false,
'send_email' => true,
'email_receipt',
'invoices' => [
['invoice_id' => $outstanding_invoice->id, 'amount' => $outstanding_invoice->amount],
],
@ -1217,6 +1222,7 @@ class SubscriptionService
];
$payment->refund($data);
$gateway_refund_attempted = true;
}
}
@ -1232,7 +1238,7 @@ class SubscriptionService
$this->triggerWebhook($context);
$nmo = new NinjaMailerObject;
$nmo->mailable = (new NinjaMailer((new ClientContactRequestCancellationObject($recurring_invoice, auth()->guard('contact')->user()))->build()));
$nmo->mailable = (new NinjaMailer((new ClientContactRequestCancellationObject($recurring_invoice, auth()->guard('contact')->user(), $gateway_refund_attempted))->build()));
$nmo->company = $recurring_invoice->company;
$nmo->settings = $recurring_invoice->company->settings;

View File

@ -10,11 +10,21 @@
<script src="{{ asset('js/pdf.min.js') }}"></script>
@if(\App\Utils\Ninja::isHosted())
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<script type="text/javascript"
src="https://alcdn.msauth.net/browser/2.14.2/js/msal-browser.min.js"
integrity="sha384-ggh+EF1aSqm+Y4yvv2n17KpurNcZTeYtUZUvhPziElsstmIEubyEB6AIVpKLuZgr"
crossorigin="anonymous">
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-WMJ5W23');</script>
<!-- End Google Tag Manager -->
@endif
<script type="text/javascript">
pdfjsLib.GlobalWorkerOptions.workerSrc = "{{ asset('js/pdf.worker.min.js') }}";
@ -29,6 +39,13 @@
</head>
<body style="background-color:#888888;">
@if(\App\Utils\Ninja::isHosted())
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WMJ5W23"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
@endif
<style>
/* fix for blurry fonts

View File

@ -25,19 +25,19 @@
{{ ctrans('texts.frequency') }}
</p>
</th>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
<p role="button" wire:click="sortBy('number')" class="cursor-pointer">
{{ ctrans('texts.invoice') }}
</p>
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
<p role="button" wire:click="sortBy('amount')" class="cursor-pointer">
{{ ctrans('texts.amount') }}
</p>
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
<p role="button" wire:click="sortBy('date')" class="cursor-pointer">
{{ ctrans('texts.date') }}
<p role="button" wire:click="sortBy('auto_bill_enabled')" class="cursor-pointer">
{{ ctrans('texts.auto_bill') }}
</p>
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
<p role="button" wire:click="sortBy('next_send_date')" class="cursor-pointer">
{{ ctrans('texts.next_send_date') }}
</p>
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
@ -54,13 +54,10 @@
{{ \App\Models\RecurringInvoice::frequencyForKey($recurring_invoice->frequency_id) }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
<a href="{{ route('client.recurring_invoice.show', $recurring_invoice->hashed_id) }}"
class="button-link text-primary">
{{ $recurring_invoice->number }}
</a>
{{ App\Utils\Number::formatMoney($recurring_invoice->amount, $recurring_invoice->client) }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
{{ App\Utils\Number::formatMoney($recurring_invoice->amount, $recurring_invoice->client) }}
{{ $recurring_invoice->auto_bill_enabled ? ctrans('texts.yes') : ctrans('texts.no') }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
{{ $recurring_invoice->translateDate($recurring_invoice->date, $recurring_invoice->client->date_format(), $recurring_invoice->client->locale()) }}

View File

@ -6,11 +6,8 @@
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.subscription') }}
{{ $subscription->name }}.
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500" translate>
{{ ctrans('texts.details_of_recurring_invoice') }}.
</p>
</div>
<div>
<dl>
@ -77,8 +74,6 @@
@endif
@if($invoice->subscription && $invoice->subscription?->allow_cancellation)
{{-- INV2-591 --}}
{{-- @if(false) --}}
<div class="bg-white shadow sm:rounded-lg mt-4">
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
@ -86,14 +81,7 @@
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.cancellation') }}
</h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate>
{{ ctrans('texts.about_cancellation') }}
</p>
</div>
</div>
<div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center">
<div class="inline-flex rounded-md shadow-sm" x-data="{ open: false }">
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500" x-data="{ open: false }">
<button class="button button-danger" translate @click="open = true">{{ ctrans('texts.request_cancellation') }}
</button>
@include('portal.ninja2020.recurring_invoices.includes.modals.cancellation')
@ -106,7 +94,7 @@
@if($invoice->subscription && $invoice->subscription->allow_plan_changes)
<div class="bg-white shadow overflow-hidden px-4 py-5 lg:rounded-lg mt-4">
<h3 class="text-lg leading-6 font-medium text-gray-900">Switch Plans:</h3>
<h3 class="text-lg leading-6 font-medium text-gray-900">{{ ctrans('texts.change_plan') }}</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">Upgrade or downgrade your current plan.</p>
<div class="flex mt-4 space-x-2">