Replace variables in Terms for user acceptance in Client Portal

This commit is contained in:
David Bomba 2024-01-29 15:43:40 +11:00
parent f18ac57545
commit 50676394e0
15 changed files with 118 additions and 67 deletions

View File

@ -22,6 +22,7 @@ use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
use App\Utils\Number;
use App\Utils\Traits\MakesDates;
@ -68,11 +69,14 @@ class InvoiceController extends Controller
event(new InvoiceWasViewed($invitation, $invoice->company, Ninja::eventVars()));
}
$variables = ($invitation && auth()->guard('contact')->user()->client->getSetting('show_accept_invoice_terms')) ? (new HtmlEngine($invitation))->generateLabelsAndValues() : false;
$data = [
'invoice' => $invoice,
'invitation' => $invitation ?: $invoice->invitations->first(),
'key' => $invitation ? $invitation->key : false,
'hash' => $hash,
'variables' => $variables,
];
if ($request->query('mode') === 'fullscreen') {
@ -217,13 +221,21 @@ class InvoiceController extends Controller
//if there is only one payment method -> lets return straight to the payment page
$settings = auth()->guard('contact')->user()->client->getMergedSettings();
$variables = false;
if(($invitation = $invoices->first()->invitations()->first() ?? false) && $settings->show_accept_invoice_terms)
$variables = (new HtmlEngine($invitation))->generateLabelsAndValues();
$data = [
'settings' => auth()->guard('contact')->user()->client->getMergedSettings(),
'settings' => $settings,
'invoices' => $invoices,
'formatted_total' => $formatted_total,
'payment_methods' => $payment_methods,
'hashed_ids' => $invoices->pluck('hashed_id'),
'total' => $total,
'variables' => $variables,
];
return $this->render('invoices.payment', $data);

View File

@ -12,21 +12,22 @@
namespace App\Http\Controllers\ClientPortal;
use App\Events\Misc\InvitationWasViewed;
use App\Utils\Ninja;
use App\Models\Quote;
use App\Utils\HtmlEngine;
use Illuminate\View\View;
use Illuminate\Http\Request;
use App\Models\QuoteInvitation;
use App\Utils\Traits\MakesHash;
use App\Events\Quote\QuoteWasViewed;
use App\Http\Controllers\Controller;
use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest;
use App\Jobs\Invoice\InjectSignature;
use Illuminate\Contracts\View\Factory;
use App\Events\Misc\InvitationWasViewed;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use App\Http\Requests\ClientPortal\Quotes\ShowQuoteRequest;
use App\Http\Requests\ClientPortal\Quotes\ShowQuotesRequest;
use App\Jobs\Invoice\InjectSignature;
use App\Models\Quote;
use App\Models\QuoteInvitation;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest;
class QuoteController extends Controller
{
@ -54,11 +55,13 @@ class QuoteController extends Controller
/* If the quote is expired, convert the status here */
$invitation = $quote->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
$variables = ($invitation && auth()->guard('contact')->user()->client->getSetting('show_accept_quote_terms')) ? (new HtmlEngine($invitation))->generateLabelsAndValues() : false;
$data = [
'quote' => $quote,
'key' => $invitation ? $invitation->key : false,
'invitation' => $invitation
'invitation' => $invitation,
'variables' => $variables,
];
if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
@ -212,8 +215,18 @@ class QuoteController extends Controller
->withSuccess('Quote(s) approved successfully.');
}
$variables = false;
if($invitation = $quotes->first()->invitations()->first() ?? false) {
$variables = (new HtmlEngine($invitation))->generateLabelsAndValues();
}
$variables = ($invitation && auth()->guard('contact')->user()->client->getSetting('show_accept_quote_terms')) ? (new HtmlEngine($invitation))->generateLabelsAndValues() : false;
return $this->render('quotes.approve', [
'quotes' => $quotes,
'variables' => $variables,
]);
}
}

View File

@ -101,7 +101,9 @@ class PurchaseOrderController extends Controller
'settings' => $purchase_order->company->settings,
'sidebar' => $this->sidebarMenu(),
'company' => $purchase_order->company,
'invitation' => $invitation
'invitation' => $invitation,
'variables' => false,
];
if ($request->query('mode') === 'fullscreen') {

View File

@ -58,55 +58,54 @@ class EmailPayment implements ShouldQueue
*/
public function handle()
{
if ($this->company->is_disabled) {
if ($this->company->is_disabled || ($this->contact->email ?? false)) {
return;
}
if ($this->contact->email) {
MultiDB::setDb($this->company->db);
MultiDB::setDb($this->company->db);
$this->payment->load('invoices');
$this->payment->load('invoices');
if (!$this->contact) {
$this->contact = $this->payment->client->contacts()->orderBy('is_primary', 'desc')->first();
}
$this->contact->load('client');
$email_builder = (new PaymentEmailEngine($this->payment, $this->contact))->build();
if($this->payment->client->getSetting('payment_email_all_contacts') && $this->payment->invoices && $this->payment->invoices->count() >= 1) {
$this->emailAllContacts($email_builder);
return;
}
$invitation = null;
$nmo = new NinjaMailerObject();
if ($this->payment->invoices && $this->payment->invoices->count() >= 1) {
if($this->contact) {
$invitation = $this->payment->invoices->first()->invitations()->where('client_contact_id', $this->contact->id)->first();
} else {
$invitation = $this->payment->invoices->first()->invitations()->first();
}
if($invitation) {
$nmo->invitation = $invitation;
}
}
$nmo->mailable = new TemplateEmail($email_builder, $this->contact, $invitation);
$nmo->to_user = $this->contact;
$nmo->settings = $this->settings;
$nmo->company = $this->company;
$nmo->entity = $this->payment;
(new NinjaMailerJob($nmo))->handle();
event(new PaymentWasEmailed($this->payment, $this->payment->company, $this->contact, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
if (!$this->contact) {
$this->contact = $this->payment->client->contacts()->orderBy('is_primary', 'desc')->first();
}
$this->contact->load('client');
$email_builder = (new PaymentEmailEngine($this->payment, $this->contact))->build();
if($this->payment->client->getSetting('payment_email_all_contacts') && $this->payment->invoices && $this->payment->invoices->count() >= 1) {
$this->emailAllContacts($email_builder);
return;
}
$invitation = null;
$nmo = new NinjaMailerObject();
if ($this->payment->invoices && $this->payment->invoices->count() >= 1) {
if($this->contact) {
$invitation = $this->payment->invoices->first()->invitations()->where('client_contact_id', $this->contact->id)->first();
} else {
$invitation = $this->payment->invoices->first()->invitations()->first();
}
if($invitation) {
$nmo->invitation = $invitation;
}
}
$nmo->mailable = new TemplateEmail($email_builder, $this->contact, $invitation);
$nmo->to_user = $this->contact;
$nmo->settings = $this->settings;
$nmo->company = $this->company;
$nmo->entity = $this->payment;
(new NinjaMailerJob($nmo))->handle();
event(new PaymentWasEmailed($this->payment, $this->payment->company, $this->contact, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
}
private function emailAllContacts($email_builder): void

View File

@ -316,4 +316,24 @@ class BaseModel extends Model
return "data:application/pdf;base64,".base64_encode((new CreateRawPdf($invitation))->handle());
}
/**
* Takes a entity prop as first argument
* along with an array of variables and performs
* a string replace on the prop.
*
* @param string $field
* @param array $variables
* @return string
*/
public function parseHtmlVariables(string $field, array $variables): string
{
if(!$this->{$field})
return '';
$section = strtr($this->{$field}, $variables['labels']);
return strtr($section, $variables['values']);
}
}

View File

@ -401,6 +401,10 @@ trait DesignHelpers
);
}
/**
* @todo - this is being called directl, - not through the calling class!!!!
* @design_flaw
*/
public static function parseMarkdownToHtml(string $markdown): ?string
{
// Use setting to determinate if parsing should be done.

View File

@ -25,7 +25,6 @@ return new class extends Migration
->cursor()
->each(function (Invoice $invoice) {
$line_items = $invoice->line_items;
if(is_array($line_items))

File diff suppressed because one or more lines are too long

View File

@ -240,7 +240,7 @@
"src": "resources/js/setup/setup.js"
},
"resources/sass/app.scss": {
"file": "assets/app-b3536ce6.css",
"file": "assets/app-ec429add.css",
"isEntry": true,
"src": "resources/sass/app.scss"
}

View File

@ -4,7 +4,7 @@
</div>
<div x-show="open" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100" x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" class="bg-white rounded-lg px-4 pt-5 pb-4 overflow-hidden shadow-xl transform transition-all sm:max-w-lg sm:w-full sm:p-6">
<div class="sm:flex sm:items-start">
<div class="">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-xl leading-6 font-medium text-gray-900">
{{ ctrans('texts.terms') }}
@ -13,7 +13,9 @@
@foreach($entities as $entity)
<div class="mb-4">
<p class="text-sm leading-6 font-medium text-gray-500">{{ $entity_type }} {{ $entity->number }}:</p>
@if($entity->terms)
@if($variables && $entity->terms)
<h5 data-ref="entity-terms"{!! $entity->parseHtmlVariables('terms', $variables) !!}</h5>
@elseif($entity->terms)
<h5 data-ref="entity-terms" class="text-sm leading-5 text-gray-900">{!! $entity->terms !!}</h5>
@else
<i class="text-sm leading-5 text-gray-500">{{ ctrans('texts.not_specified') }}</i>

View File

@ -150,7 +150,7 @@
</div>
</form>
@include('portal.ninja2020.invoices.includes.terms', ['entities' => $invoices, 'entity_type' => ctrans('texts.invoice')])
@include('portal.ninja2020.invoices.includes.terms', ['entities' => $invoices, 'variables' => $variables, 'entity_type' => ctrans('texts.invoice')])
@include('portal.ninja2020.invoices.includes.signature')
@endsection

View File

@ -101,7 +101,7 @@
@section('footer')
@include('portal.ninja2020.invoices.includes.signature')
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$invoice], 'entity_type' => ctrans('texts.invoice')])
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$invoice], 'variables' => $variables, 'entity_type' => ctrans('texts.invoice')])
@endsection
@push('head')

View File

@ -51,7 +51,7 @@
@endsection
@section('footer')
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$purchase_order], 'entity_type' => ctrans('texts.purchase_order')])
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$purchase_order], 'variables' => $variables, 'entity_type' => ctrans('texts.purchase_order')])
@include('portal.ninja2020.invoices.includes.signature')
@endsection

View File

@ -87,7 +87,7 @@
@section('footer')
@include('portal.ninja2020.quotes.includes.user-input')
@include('portal.ninja2020.invoices.includes.terms', ['entities' => $quotes, 'entity_type' => ctrans('texts.quote')])
@include('portal.ninja2020.invoices.includes.terms', ['entities' => $quotes, 'variables' => $variables, 'entity_type' => ctrans('texts.quote')])
@include('portal.ninja2020.invoices.includes.signature')
@endsection

View File

@ -106,7 +106,7 @@
@section('footer')
@include('portal.ninja2020.quotes.includes.user-input')
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$quote], 'entity_type' => ctrans('texts.quote')])
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$quote], 'variables' => $variables, 'entity_type' => ctrans('texts.quote')])
@include('portal.ninja2020.invoices.includes.signature')
@endsection