mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
f02ee29a47
@ -92,6 +92,20 @@ class ExpenseFilters extends QueryFilters
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of expenses that can be matched to bank transactions
|
||||
*/
|
||||
public function match_transactions($value = '')
|
||||
{
|
||||
|
||||
if($value == 'true')
|
||||
{
|
||||
return $this->builder->where('is_deleted',0)->whereNull('transaction_id');
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
|
@ -81,6 +81,20 @@ class PaymentFilters extends QueryFilters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of payments that can be matched to bank transactions
|
||||
*/
|
||||
public function match_transactions($value = '')
|
||||
{
|
||||
|
||||
if($value == 'true')
|
||||
{
|
||||
return $this->builder->where('is_deleted',0)->whereNull('transaction_id');
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
|
@ -49,7 +49,7 @@ class InvoiceSum
|
||||
/**
|
||||
* Constructs the object with Invoice and Settings object.
|
||||
*
|
||||
* @param Invoice $invoice The invoice
|
||||
* @param \App\Models\RecurringInvoice|\App\Models\Quote|\App\Models\Credit|\App\Models\PurchaseOrder|\App\Models\Invoice $invoice The entity
|
||||
*/
|
||||
public function __construct($invoice)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ class InvoiceSumInclusive
|
||||
/**
|
||||
* Constructs the object with Invoice and Settings object.
|
||||
*
|
||||
* @param Invoice $invoice The invoice
|
||||
* @param \App\Models\RecurringInvoice|\App\Models\Quote|\App\Models\Credit|\App\Models\PurchaseOrder|\App\Models\Invoice $invoice The entity
|
||||
*/
|
||||
public function __construct($invoice)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
|
||||
class BillingPortalPurchasev2 extends Component
|
||||
@ -97,7 +98,6 @@ class BillingPortalPurchasev2 extends Component
|
||||
*/
|
||||
public $payment_method_id;
|
||||
|
||||
private $user_coupon;
|
||||
|
||||
/**
|
||||
* List of steps that frontend form follows.
|
||||
@ -188,12 +188,19 @@ class BillingPortalPurchasev2 extends Component
|
||||
public $optional_recurring_products;
|
||||
public $optional_products;
|
||||
public $total;
|
||||
public $discount;
|
||||
public $sub_total;
|
||||
public $authenticated = false;
|
||||
public $otp;
|
||||
public $login;
|
||||
public $value;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
$this->quantity = 1;
|
||||
$this->discount = 0;
|
||||
$this->sub_total = 0;
|
||||
|
||||
$this->data = [];
|
||||
|
||||
@ -212,17 +219,71 @@ class BillingPortalPurchasev2 extends Component
|
||||
$this->optional_recurring_products = $this->subscription->service()->optional_recurring_products();
|
||||
$this->optional_products = $this->subscription->service()->optional_products();
|
||||
|
||||
// $this->buildBundle();
|
||||
$this->bundle = collect();
|
||||
|
||||
}
|
||||
|
||||
public function loginValidation()
|
||||
{
|
||||
$this->resetErrorBag('login');
|
||||
$this->resetValidation('login');
|
||||
}
|
||||
|
||||
public function handleLogin()
|
||||
{
|
||||
|
||||
$code = Cache::get("subscriptions:otp:{$this->email}");
|
||||
|
||||
$this->validateOnly('login', ['login' => ['required',Rule::in([$code])]], ['login' => ctrans('texts.invalid_code')]);
|
||||
|
||||
$contact = ClientContact::where('email', $this->email)->first();
|
||||
|
||||
if($contact){
|
||||
Auth::guard('contact')->loginUsingId($contact->id, true);
|
||||
$this->contact = $contact;
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function handleEmail()
|
||||
{
|
||||
$this->validateOnly('email', ['email' => 'required|bail|email:rfc']);
|
||||
|
||||
$rand = rand(100000,999999);
|
||||
|
||||
$email_hash = "subscriptions:otp:{$this->email}";
|
||||
|
||||
Cache::put($email_hash, $rand, 120);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a coupon being entered into the checkout
|
||||
*/
|
||||
public function handleCoupon()
|
||||
{
|
||||
|
||||
if($this->coupon == $this->subscription->promo_code)
|
||||
$this->buildBundle();
|
||||
else
|
||||
$this->discount = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the bundle in the checkout
|
||||
*/
|
||||
public function buildBundle()
|
||||
{
|
||||
$this->bundle = collect();
|
||||
|
||||
$data = $this->data;
|
||||
|
||||
/* Recurring products can have a variable quantity */
|
||||
foreach($this->recurring_products as $key => $p)
|
||||
{
|
||||
|
||||
@ -234,10 +295,11 @@ class BillingPortalPurchasev2 extends Component
|
||||
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
|
||||
'total' => $total,
|
||||
'qty' => $qty,
|
||||
'is_recurring' => true
|
||||
'is_recurring' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/* One time products can only have a single quantity */
|
||||
foreach($this->products as $key => $p)
|
||||
{
|
||||
|
||||
@ -251,10 +313,13 @@ class BillingPortalPurchasev2 extends Component
|
||||
'qty' => $qty,
|
||||
'is_recurring' => false
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
foreach($this->data as $key => $value)
|
||||
{
|
||||
|
||||
/* Optional recurring products can have a variable quantity */
|
||||
if(isset($this->data[$key]['optional_recurring_qty']))
|
||||
{
|
||||
$p = $this->optional_recurring_products->first(function ($v,$k) use($key){
|
||||
@ -278,6 +343,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
|
||||
}
|
||||
|
||||
/* Optional products can have a variable quantity */
|
||||
if(isset($this->data[$key]['optional_qty']))
|
||||
{
|
||||
$p = $this->optional_products->first(function ($v,$k) use($key){
|
||||
@ -300,41 +366,67 @@ class BillingPortalPurchasev2 extends Component
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$this->total = Number::formatMoney($this->bundle->sum('total'), $this->subscription->company);
|
||||
$this->sub_total = Number::formatMoney($this->bundle->sum('total'), $this->subscription->company);
|
||||
$this->total = $this->sub_total;
|
||||
|
||||
if($this->coupon == $this->subscription->promo_code)
|
||||
{
|
||||
|
||||
if($this->subscription->is_amount_discount)
|
||||
$discount = $this->subscription->promo_discount;
|
||||
else
|
||||
$discount = round($this->bundle->sum('total') * ($this->subscription->promo_discount / 100), 2);
|
||||
|
||||
$this->discount = Number::formatMoney($discount, $this->subscription->company);
|
||||
|
||||
$this->total = Number::formatMoney(($this->bundle->sum('total') - $discount), $this->subscription->company);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function updatedData()
|
||||
private function createClientContact()
|
||||
{
|
||||
}
|
||||
|
||||
public function updating($prop)
|
||||
{
|
||||
// $this->resetValidation($prop);
|
||||
// $this->resetErrorBag($prop);
|
||||
}
|
||||
$company = $this->subscription->company;
|
||||
$user = $this->subscription->user;
|
||||
$user->setCompany($company);
|
||||
|
||||
$client_repo = new ClientRepository(new ClientContactRepository());
|
||||
$data = [
|
||||
'name' => '',
|
||||
'contacts' => [
|
||||
['email' => $this->email],
|
||||
],
|
||||
'client_hash' => Str::random(40),
|
||||
'settings' => ClientSettings::defaults(),
|
||||
];
|
||||
|
||||
$client = $client_repo->save($data, ClientFactory::create($company->id, $user->id));
|
||||
|
||||
$this->contact = $client->fresh()->contacts()->first();
|
||||
Auth::guard('contact')->loginUsingId($this->contact->id, true);
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public function updated($propertyName)
|
||||
{
|
||||
$x = $this->validateOnly($propertyName, $this->rules(), [], $this->attributes());
|
||||
if(in_array($propertyName, ['login','email']))
|
||||
return;
|
||||
|
||||
// // $validatedData = $this->validate();
|
||||
$this->buildBundle();
|
||||
|
||||
// $order_validator = Validator::make($this->all(), $this->rules(), [], $this->attributes());
|
||||
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = [
|
||||
'data.*.recurring_qty' => 'numeric|between:0,1000',
|
||||
'data.*.optional_recurring_qty' => 'numeric|between:0,1000',
|
||||
'data.*.optional_qty' => 'numeric|between:0,1000',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
@ -343,9 +435,6 @@ class BillingPortalPurchasev2 extends Component
|
||||
public function attributes()
|
||||
{
|
||||
$attributes = [
|
||||
'data.*.recurring_qty' => 'recurring_qty',
|
||||
'data.*.optional_recurring_qty' => 'optional_recurring_qty',
|
||||
'data.*.optional_qty' => 'optional_qty',
|
||||
];
|
||||
|
||||
return $attributes;
|
||||
@ -390,6 +479,9 @@ class BillingPortalPurchasev2 extends Component
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a blank client. Used for new customers purchasing.
|
||||
*
|
||||
@ -526,7 +618,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
]],
|
||||
'user_input_promo_code' => $this->coupon,
|
||||
'coupon' => empty($this->subscription->promo_code) ? '' : $this->coupon,
|
||||
'quantity' => $this->quantity,
|
||||
// 'quantity' => $this->quantity,
|
||||
];
|
||||
|
||||
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||
@ -588,7 +680,6 @@ class BillingPortalPurchasev2 extends Component
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
return $this->subscription->service()->handleNoPaymentRequired([
|
||||
'email' => $this->email ?? $this->contact->email,
|
||||
'quantity' => $this->quantity,
|
||||
@ -598,55 +689,6 @@ class BillingPortalPurchasev2 extends Component
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update quantity property.
|
||||
*
|
||||
* @param string $option
|
||||
* @return int
|
||||
*/
|
||||
public function updateQuantity(string $option): int
|
||||
{
|
||||
$this->handleCoupon();
|
||||
|
||||
if ($this->quantity == 1 && $option == 'decrement') {
|
||||
$this->price = $this->price * 1;
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
if ($this->quantity > $this->subscription->max_seats_limit && $option == 'increment') {
|
||||
$this->price = $this->price * $this->subscription->max_seats_limit;
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
if ($option == 'increment') {
|
||||
$this->quantity++;
|
||||
$this->price = $this->price * $this->quantity;
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
$this->quantity--;
|
||||
$this->price = $this->price * $this->quantity;
|
||||
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
public function handleCoupon()
|
||||
{
|
||||
|
||||
if($this->steps['discount_applied']){
|
||||
$this->price = $this->subscription->promo_price;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->coupon == $this->subscription->promo_code) {
|
||||
$this->price = $this->subscription->promo_price;
|
||||
$this->quantity = 1;
|
||||
$this->steps['discount_applied'] = true;
|
||||
}
|
||||
else
|
||||
$this->price = $this->subscription->price;
|
||||
}
|
||||
|
||||
public function passwordlessLogin()
|
||||
{
|
||||
$this->passwordless_login_btn = true;
|
||||
@ -681,10 +723,10 @@ class BillingPortalPurchasev2 extends Component
|
||||
return render('components.livewire.billing-portal-purchasev2');
|
||||
}
|
||||
|
||||
public function changeData()
|
||||
{
|
||||
// public function changeData()
|
||||
// {
|
||||
|
||||
nlog($this->data);
|
||||
// nlog($this->data);
|
||||
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
namespace App\Http\Livewire\RecurringInvoices;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use Livewire\Component;
|
||||
|
||||
class UpdateAutoBilling extends Component
|
||||
@ -24,6 +25,12 @@ class UpdateAutoBilling extends Component
|
||||
if ($this->invoice->auto_bill == 'optin' || $this->invoice->auto_bill == 'optout') {
|
||||
$this->invoice->auto_bill_enabled = ! $this->invoice->auto_bill_enabled;
|
||||
$this->invoice->saveQuietly();
|
||||
|
||||
Invoice::where('recurring_id', $this->invoice->id)
|
||||
->whereIn('status_id', [2,3])
|
||||
->where('is_deleted',0)
|
||||
->where('balance', '>', 0)
|
||||
->update(['auto_bill_enabled' => $this->invoice->auto_bill_enabled]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,8 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->transformer = new BankTransformer($this->company);
|
||||
$bank_transaction_count = $this->ingest($data, $entity_type);
|
||||
$this->entity_count['bank_transactions'] = $bank_transaction_count;
|
||||
|
||||
nlog("bank matching co id = {$this->company->id}");
|
||||
|
||||
BankMatchingService::dispatchSync($this->company->id, $this->company->db);
|
||||
|
||||
|
@ -56,6 +56,7 @@ class PaymentType extends StaticModel
|
||||
const INSTANT_BANK_PAY = 45;
|
||||
const FPX = 46;
|
||||
const KLARNA = 47;
|
||||
const Interac_E_Transfer = 48;
|
||||
|
||||
public static function parseCardType($cardName)
|
||||
{
|
||||
|
@ -52,6 +52,8 @@ class CreditCard
|
||||
{
|
||||
$amount = $this->mollie->convertToMollieAmount((float) $this->mollie->payment_hash->data->amount_with_fee);
|
||||
|
||||
$description = sprintf('%s: %s', ctrans('texts.invoices'), \implode(', ', collect($this->mollie->payment_hash->invoices())->pluck('invoice_number')->toArray()));
|
||||
|
||||
$this->mollie->payment_hash
|
||||
->withData('gateway_type_id', GatewayType::CREDIT_CARD)
|
||||
->withData('client_id', $this->mollie->client->id);
|
||||
@ -68,7 +70,7 @@ class CreditCard
|
||||
'mandateId' => $request->token,
|
||||
'customerId' => $cgt->gateway_customer_reference,
|
||||
'sequenceType' => 'recurring',
|
||||
'description' => \sprintf('Hash: %s', $this->mollie->payment_hash->hash),
|
||||
'description' => $description,
|
||||
'webhookUrl' => $this->mollie->company_gateway->webhookUrl(),
|
||||
'idempotencyKey' => uniqid("st",true),
|
||||
'metadata' => [
|
||||
@ -91,7 +93,11 @@ class CreditCard
|
||||
if ($payment->status === 'open') {
|
||||
$this->mollie->payment_hash->withData('payment_id', $payment->id);
|
||||
|
||||
return redirect($payment->getCheckoutUrl());
|
||||
if(!$payment->getCheckoutUrl())
|
||||
return render('gateways.mollie.mollie_placeholder');
|
||||
else
|
||||
return redirect()->away($payment->getCheckoutUrl());
|
||||
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->processUnsuccessfulPayment($e);
|
||||
@ -104,7 +110,7 @@ class CreditCard
|
||||
'currency' => $this->mollie->client->currency()->code,
|
||||
'value' => $amount,
|
||||
],
|
||||
'description' => \sprintf('Hash: %s', $this->mollie->payment_hash->hash),
|
||||
'description' => $description,
|
||||
'redirectUrl' => route('mollie.3ds_redirect', [
|
||||
'company_key' => $this->mollie->client->company->company_key,
|
||||
'company_gateway_id' => $this->mollie->company_gateway->hashed_id,
|
||||
@ -151,7 +157,13 @@ class CreditCard
|
||||
if ($payment->status === 'open') {
|
||||
$this->mollie->payment_hash->withData('payment_id', $payment->id);
|
||||
|
||||
return redirect($payment->getCheckoutUrl());
|
||||
nlog("Mollie");
|
||||
nlog($payment);
|
||||
|
||||
if(!$payment->getCheckoutUrl())
|
||||
return render('gateways.mollie.mollie_placeholder');
|
||||
else
|
||||
return redirect()->away($payment->getCheckoutUrl());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->processUnsuccessfulPayment($e);
|
||||
|
@ -173,9 +173,9 @@ class ACH
|
||||
->first();
|
||||
|
||||
if ($invoice) {
|
||||
$description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
} else {
|
||||
$description = ctrans('texts.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
}
|
||||
|
||||
|
||||
@ -211,9 +211,9 @@ class ACH
|
||||
->first();
|
||||
|
||||
if ($invoice) {
|
||||
$description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
} else {
|
||||
$description = ctrans('texts.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
}
|
||||
|
||||
if (substr($cgt->token, 0, 2) === 'pm') {
|
||||
@ -455,9 +455,9 @@ class ACH
|
||||
->first();
|
||||
|
||||
if ($invoice) {
|
||||
$description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
} else {
|
||||
$description = ctrans('texts.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
}
|
||||
|
||||
if (substr($source->token, 0, 2) === 'pm') {
|
||||
|
@ -63,9 +63,9 @@ class Charge
|
||||
$invoice = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))->withTrashed()->first();
|
||||
|
||||
if ($invoice) {
|
||||
$description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
} else {
|
||||
$description = ctrans('texts.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
}
|
||||
|
||||
$this->stripe->init();
|
||||
|
@ -63,7 +63,7 @@ class CreditCard
|
||||
|
||||
// $description = $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')) . " for client {$this->stripe->client->present()->name()}";
|
||||
$invoice_numbers = collect($data['invoices'])->pluck('invoice_number')->implode(',');
|
||||
$description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice_numbers, 'amount' => Number::formatMoney($data['total']['amount_with_fee'], $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text', ['invoicenumber' => $invoice_numbers, 'amount' => Number::formatMoney($data['total']['amount_with_fee'], $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
|
||||
$payment_intent_data = [
|
||||
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
||||
|
@ -53,9 +53,9 @@ class Klarna
|
||||
$invoice_numbers = collect($data['invoices'])->pluck('invoice_number');
|
||||
|
||||
if ($invoice_numbers->count() > 0) {
|
||||
$description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice_numbers->implode(', '), 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text', ['invoicenumber' => $invoice_numbers->implode(', '), 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
} else {
|
||||
$description = ctrans('texts.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
$description = ctrans('texts.stripe_payment_text_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
|
||||
}
|
||||
|
||||
$intent = \Stripe\PaymentIntent::create([
|
||||
|
@ -98,7 +98,7 @@ class StripePaymentDriver extends BaseDriver
|
||||
GatewayType::BECS => BECS::class,
|
||||
GatewayType::ACSS => ACSS::class,
|
||||
GatewayType::FPX => FPX::class,
|
||||
GatewayType::KLARNA => KLARNA::class,
|
||||
GatewayType::KLARNA => Klarna::class,
|
||||
];
|
||||
|
||||
const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE;
|
||||
|
@ -37,6 +37,8 @@ class BankMatchingService implements ShouldQueue
|
||||
|
||||
protected $db;
|
||||
|
||||
protected $middleware_key;
|
||||
|
||||
public function __construct($company_id, $db)
|
||||
{
|
||||
$this->company_id = $company_id;
|
||||
|
@ -44,8 +44,6 @@ class ProcessBankRules extends AbstractService
|
||||
private function matchCredit()
|
||||
{
|
||||
|
||||
$this->credit_rules = $this->bank_transaction->company->credit_rules();
|
||||
|
||||
$this->invoices = Invoice::where('company_id', $this->bank_transaction->company_id)
|
||||
->whereIn('status_id', [1,2,3])
|
||||
->where('is_deleted', 0)
|
||||
@ -65,6 +63,8 @@ class ProcessBankRules extends AbstractService
|
||||
return;
|
||||
}
|
||||
|
||||
$this->credit_rules = $this->bank_transaction->company->credit_rules();
|
||||
|
||||
//stub for credit rules
|
||||
foreach($this->credit_rules as $rule)
|
||||
{
|
||||
@ -81,11 +81,16 @@ class ProcessBankRules extends AbstractService
|
||||
|
||||
$this->categories = collect(Cache::get('bank_categories'));
|
||||
|
||||
|
||||
|
||||
foreach($this->debit_rules as $bank_transaction_rule)
|
||||
{
|
||||
|
||||
$matches = 0;
|
||||
|
||||
if(!is_array($bank_transaction_rule['rules']))
|
||||
continue;
|
||||
|
||||
foreach($bank_transaction_rule['rules'] as $rule)
|
||||
{
|
||||
$rule_count = count($bank_transaction_rule['rules']);
|
||||
|
@ -145,8 +145,6 @@ class UpdateReminder extends AbstractService
|
||||
$reminder_date = $this->addTimeInterval($this->invoice->last_sent_date, (int) $this->settings->endless_reminder_frequency_id);
|
||||
|
||||
if ($reminder_date) {
|
||||
// $reminder_date->addSeconds($offset);
|
||||
|
||||
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
|
||||
$date_collection->push($reminder_date);
|
||||
}
|
||||
|
@ -285,6 +285,9 @@ class HtmlEngine
|
||||
$data['$amount_raw'] = ['value' => $this->entity->amount, 'label' => ctrans('texts.amount')];
|
||||
}
|
||||
|
||||
// $data['$amount_in_words'] = ['value' => (new \NumberFormatter($this->client->locale(), \NumberFormatter::SPELLOUT))->format($this->entity->amount), 'label' => ''];
|
||||
// $data['$balance_in_words'] = ['value' => (new \NumberFormatter($this->client->locale(), \NumberFormatter::SPELLOUT))->format($this->entity->balance), 'label' => ''];
|
||||
|
||||
// $data['$balance_due'] = $data['$balance_due'];
|
||||
$data['$outstanding'] = &$data['$balance_due'];
|
||||
$data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: ' ', 'label' => ctrans('texts.partial_due')];
|
||||
|
@ -21,9 +21,11 @@ class PDF extends FPDI
|
||||
{
|
||||
$this->SetXY(0, -5);
|
||||
$this->SetFont('Arial', 'I', 9);
|
||||
|
||||
$this->SetTextColor(135, 135, 135);
|
||||
|
||||
$trans = ctrans('texts.pdf_page_info', ['current' => $this->PageNo(), 'total' => '{nb}']);
|
||||
$trans = iconv('UTF-8', 'ISO-8859-7', $trans);
|
||||
$this->Cell(0, 5, $trans, 0, 0, $this->text_alignment);
|
||||
}
|
||||
|
||||
|
@ -14,21 +14,37 @@ return new class extends Migration {
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('payment_types', function (Blueprint $table) {
|
||||
$type = new PaymentType();
|
||||
$pt = PaymentType::find(47);
|
||||
|
||||
if(!$pt)
|
||||
{
|
||||
$type = new PaymentType();
|
||||
$type->id = 47;
|
||||
$type->name = 'Klarna';
|
||||
$type->gateway_type_id = GatewayType::KLARNA;
|
||||
|
||||
$type->save();
|
||||
});
|
||||
$type = new GatewayType();
|
||||
}
|
||||
|
||||
$type->id = 23;
|
||||
$type->alias = 'klarna';
|
||||
$type->name = 'Klarna';
|
||||
|
||||
$type->save();
|
||||
$pt = PaymentType::find(48);
|
||||
|
||||
if(!$pt)
|
||||
{
|
||||
$type = new PaymentType();
|
||||
$type->id = 48;
|
||||
$type->name = 'Interac E-Transfer';
|
||||
$type->save();
|
||||
}
|
||||
|
||||
$gt = GatewayType::find(23);
|
||||
|
||||
if(!$gt)
|
||||
{
|
||||
$type = new GatewayType();
|
||||
$type->id = 23;
|
||||
$type->alias = 'klarna';
|
||||
$type->name = 'Klarna';
|
||||
$type->save();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -17,5 +17,6 @@ return new class extends Migration
|
||||
$table->string('matomo_url',191)->nullable();
|
||||
$table->bigInteger('matomo_id')->nullable();
|
||||
});
|
||||
|
||||
}
|
||||
};
|
@ -254,8 +254,8 @@ $LANG = array(
|
||||
'notification_invoice_paid' => 'A payment of :amount was made by client :client towards Invoice :invoice.',
|
||||
'notification_invoice_sent' => 'The following client :client was emailed Invoice :invoice for :amount.',
|
||||
'notification_invoice_viewed' => 'The following client :client viewed Invoice :invoice for :amount.',
|
||||
'stripe_paymenttext' => 'Invoice :invoicenumber for :amount for client :client',
|
||||
'stripe_paymenttext_without_invoice' => 'Payment with no invoice for amount :amount for client :client',
|
||||
'stripe_payment_text' => 'Invoice :invoicenumber for :amount for client :client',
|
||||
'stripe_payment_text_without_invoice' => 'Payment with no invoice for amount :amount for client :client',
|
||||
'reset_password' => 'You can reset your account password by clicking the following button:',
|
||||
'secure_payment' => 'Secure Payment',
|
||||
'card_number' => 'Card Number',
|
||||
@ -4778,7 +4778,7 @@ $LANG = array(
|
||||
'invoice_task_project' => 'Invoice Task Project',
|
||||
'invoice_task_project_help' => 'Add the project to the invoice line items',
|
||||
'bulk_action' => 'Bulk Action',
|
||||
'phone_validation_error' => 'This mobile/cell phone number is not valid, please enter in E.164 format',
|
||||
'phone_validation_error' => 'This mobile (cell) phone number is not valid, please enter in E.164 format',
|
||||
'transaction' => 'Transaction',
|
||||
'disable_2fa' => 'Disable 2FA',
|
||||
'change_number' => 'Change Number',
|
||||
@ -4891,7 +4891,11 @@ $LANG = array(
|
||||
'restored_transaction_rule' => 'Successfully restored transaction rule',
|
||||
'search_transaction_rule' => 'Search Transaction Rule',
|
||||
'search_transaction_rules' => 'Search Transaction Rules',
|
||||
|
||||
'payment_type_Interac E-Transfer' => 'Interac E-Transfer',
|
||||
'delete_bank_account' => 'Delete Bank Account',
|
||||
'archive_transaction' => 'Archive Transaction',
|
||||
'delete_transaction' => 'Delete Transaction',
|
||||
'otp_code_message' => 'Enter the code emailed.'
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -14,9 +14,9 @@
|
||||
@if(!empty($subscription->recurring_product_ids))
|
||||
@foreach($recurring_products as $index => $product)
|
||||
<li class="flex py-6">
|
||||
@if(false)
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200">
|
||||
<img src="https://tailwindui.com/img/ecommerce-images/shopping-cart-page-04-product-01.jpg" alt="Salmon orange fabric pouch with match zipper, gray zipper pull, and adjustable hip belt." class="h-full w-full object-cover object-center">
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
@ -34,8 +34,15 @@
|
||||
<p class="text-gray-500 w-full"></p>
|
||||
<div class="flex place-content-end">
|
||||
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
||||
<input wire:model.debounce.300ms="data.{{ $index }}.recurring_qty" type="text" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0"/>
|
||||
|
||||
<select wire:model.debounce.300ms="data.{{ $index }}.recurring_qty" class="rounded-md border-gray-300 shadow-sm sm:text-sm">
|
||||
<option value="1" selected="selected">1</option>
|
||||
@for ($i = 2; $i <= $subscription->max_seats_limit; $i++)
|
||||
<option value="{{$i}}">{{$i}}</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
</div>
|
||||
@error("data.{$index}.recurring_qty")
|
||||
@ -52,9 +59,9 @@
|
||||
@if(!empty($subscription->product_ids))
|
||||
@foreach($products as $product)
|
||||
<li class="flex py-6">
|
||||
@if(false)
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200">
|
||||
<img src="https://tailwindui.com/img/ecommerce-images/shopping-cart-page-04-product-01.jpg" alt="Salmon orange fabric pouch with match zipper, gray zipper pull, and adjustable hip belt." class="h-full w-full object-cover object-center">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
@ -79,10 +86,11 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@if(!empty($subscription->optional_recurring_product_ids) || !empty($subscription->optional_product_ids))
|
||||
<div class="w-full p-4 md:max-w-3xl">
|
||||
<h2 class="text-2xl font-normal text-left border-b-4">Optional products</h2>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
<div class="w-full px-4 md:max-w-3xl">
|
||||
|
||||
<!-- Optional Recurring Products-->
|
||||
@ -90,33 +98,41 @@
|
||||
@if(!empty($subscription->optional_recurring_product_ids))
|
||||
@foreach($optional_recurring_products as $index => $product)
|
||||
<li class="flex py-6">
|
||||
@if(false)
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="https://tailwindui.com/img/ecommerce-images/shopping-cart-page-04-product-01.jpg" alt="Salmon orange fabric pouch with match zipper, gray zipper pull, and adjustable hip belt." class="h-full w-full object-cover object-center">
|
||||
</div>
|
||||
@endif
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
<div>
|
||||
<div class="flex justify-between text-base font-medium text-gray-900">
|
||||
<h3>{!! nl2br($product->notes) !!}</h3>
|
||||
<p class="ml-0">{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }} </p>
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-gray-500"></p>
|
||||
|
||||
</div>
|
||||
<div class="flex content-end text-sm mt-1">
|
||||
<p class="text-gray-500 w-full"></p>
|
||||
<div class="flex justify-between text-sm mt-1">
|
||||
@if(is_numeric($product->custom_value2))
|
||||
<p class="text-gray-500 w-3/4"></p>
|
||||
<div class="flex place-content-end">
|
||||
@if($subscription->use_inventory_management && $product->in_stock_quantity == 0)
|
||||
<p class="w-full text-sm font-light text-red-500 text-right mr-2 mt-2">Out of stock</p>
|
||||
@else
|
||||
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
||||
<input wire:model.debounce.300ms="data.{{ $index }}.optional_recurring_qty" type="text" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0"/>
|
||||
@endif
|
||||
<select wire:model.debounce.300ms="data.{{ $index }}.optional_recurring_qty" class="rounded-md border-gray-300 shadow-sm sm:text-sm"
|
||||
@if($subscription->use_inventory_management && $product->in_stock_quantity == 0)
|
||||
disabled
|
||||
@endif
|
||||
>
|
||||
<option value="0" selected="selected">0</option>
|
||||
@for ($i = 1; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity,$product->custom_value2) : $product->custom_value2); $i++)
|
||||
<option value="{{$i}}">{{$i}}</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@error("data.{$index}.optional_recurring_qty")
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||
<span class="block sm:inline">{{ $message }} </span>
|
||||
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
@ -124,11 +140,11 @@
|
||||
@if(!empty($subscription->optional_product_ids))
|
||||
@foreach($optional_products as $index => $product)
|
||||
<li class="flex py-6">
|
||||
@if(false)
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="https://tailwindui.com/img/ecommerce-images/shopping-cart-page-04-product-01.jpg" alt="Salmon orange fabric pouch with match zipper, gray zipper pull, and adjustable hip belt." class="h-full w-full object-cover object-center">
|
||||
</div>
|
||||
@endif
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
<div>
|
||||
<div class="flex justify-between text-base font-medium text-gray-900">
|
||||
@ -137,19 +153,25 @@
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-gray-500"></p>
|
||||
</div>
|
||||
<div class="flex content-end text-sm mt-1">
|
||||
<p class="text-gray-500 w-full"></p>
|
||||
<div class="flex justify-between text-sm mt-1">
|
||||
@if(is_numeric($product->custom_value2))
|
||||
<p class="text-gray-500 w-3/4"></p>
|
||||
<div class="flex place-content-end">
|
||||
@if($subscription->use_inventory_management && $product->in_stock_quantity == 0)
|
||||
<p class="w-full text-sm font-light text-red-500 text-right mr-2 mt-2">Out of stock</p>
|
||||
@else
|
||||
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
||||
<input type="text" wire:model.debounce.300ms="data.{{ $index }}.optional_qty" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0">
|
||||
@endif
|
||||
<select wire:model.debounce.300ms="data.{{ $index }}.optional_qty" class="rounded-md border-gray-300 shadow-sm sm:text-sm">
|
||||
<option value="0" selected="selected">0</option>
|
||||
@for ($i = 1; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity,$product->custom_value2) : $product->custom_value2); $i++)
|
||||
<option value="{{$i}}">{{$i}}</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
</div>
|
||||
@error("data.{$index}.optional_qty")
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||
<span class="block sm:inline">{{ $message }} </span>
|
||||
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
@ -173,33 +195,142 @@
|
||||
@endforeach
|
||||
|
||||
@if(!empty($subscription->promo_code) && !$subscription->trial_enabled)
|
||||
<form wire:submit.prevent="handleCoupon" class="">
|
||||
@csrf
|
||||
<div class="mt-2">
|
||||
<label for="email" class="block text-sm font-medium text-white">{{ ctrans('texts.promo_code') }}</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<div class="relative flex flex-grow items-stretch focus-within:z-10">
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<form wire:submit.prevent="handleCoupon" class="">
|
||||
@csrf
|
||||
<div class="mt-4">
|
||||
<label for="coupon" class="block text-sm font-medium text-white">{{ ctrans('texts.promo_code') }}</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<div class="relative flex flex-grow items-stretch focus-within:z-10">
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
</div>
|
||||
<input type="text" wire:model.defer="coupon" class="block w-full rounded-none rounded-l-md border-gray-300 pl-2 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm text-gray-700" placeholder="">
|
||||
</div>
|
||||
<button class="relative -ml-px inline-flex items-center space-x-2 rounded-r-md border border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
|
||||
|
||||
<span>{{ ctrans('texts.apply') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<input type="text" wire:model.debounce.300ms="coupon" class="block w-full rounded-none rounded-l-md border-gray-300 pl-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" placeholder="">
|
||||
</div>
|
||||
<button type="button" class="relative -ml-px inline-flex items-center space-x-2 rounded-r-md border border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
|
||||
|
||||
<span>{{ ctrans('texts.apply') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
<div class="border-t-2 border-gray-200 border-opacity-50 mt-8">
|
||||
<div class="flex font-semibold justify-between py-6 text-sm uppercase">
|
||||
<span>{{ ctrans('texts.total') }}</span>
|
||||
<span>{{ $total }}</span>
|
||||
</div>
|
||||
<button class="bg-white font-semibold hover:bg-gray-600 py-3 text-sm text-blue-500 uppercase w-full">Checkout</button>
|
||||
<div class="border-t-2 border-gray-200 border-opacity-50 mt-4">
|
||||
@if($discount)
|
||||
<div class="flex font-semibold justify-between py-1 text-sm uppercase">
|
||||
<span>{{ ctrans('texts.subtotal') }}</span>
|
||||
<span>{{ $sub_total }}</span>
|
||||
</div>
|
||||
<div class="flex font-semibold justify-between py-1 text-sm uppercase">
|
||||
<span>{{ ctrans('texts.discount') }}</span>
|
||||
<span>{{ $discount }}</span>
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex font-semibold justify-between py-1 text-sm uppercase border-t-2">
|
||||
<span>{{ ctrans('texts.total') }}</span>
|
||||
<span>{{ $total }}</span>
|
||||
</div>
|
||||
|
||||
@if($authenticated)
|
||||
<button class="bg-white font-semibold hover:bg-gray-600 py-3 text-sm text-blue-500 uppercase w-full">Checkout</button>
|
||||
@else
|
||||
<form wire:submit.prevent="handleEmail" class="">
|
||||
@csrf
|
||||
<div class="mt-4">
|
||||
<label for="email" class="block text-sm font-medium text-white">{{ ctrans('texts.email') }}</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<div class="relative flex flex-grow items-stretch focus-within:z-10">
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
</div>
|
||||
<input type="text" wire:model.defer="email" class="block w-full rounded-none rounded-l-md border-gray-300 pl-2 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm text-gray-700" placeholder="">
|
||||
</div>
|
||||
<button class="relative -ml-px inline-flex items-center space-x-2 rounded-r-md border border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
|
||||
|
||||
<span>{{ ctrans('texts.login') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
@error("email")
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||
<span class="block sm:inline">{{ $message }} </span>
|
||||
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
|
||||
</div>
|
||||
@enderror
|
||||
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
@if($email && !$errors->has('email'))
|
||||
<div class="py-6 px-6 w-80 border mx-auto text-center my-6">
|
||||
<form wire:submit.prevent="handleLogin" class="" x-data="otpForm()">
|
||||
<p class="mb-4">{{ ctrans('texts.otp_code_message')}}</p>
|
||||
<div class="flex justify-between">
|
||||
<template x-for="(input, index) in length" :key="index">
|
||||
<input
|
||||
type="text"
|
||||
maxlength="1"
|
||||
class="border border-gray-500 w-10 h-10 text-center text-gray-700"
|
||||
:x-ref="index"
|
||||
x-on:input="handleInput($event)"
|
||||
x-on:paste="handlePaste($event)"
|
||||
x-on:keydown.backspace="$event.target.value || handleBackspace($event.target.getAttribute('x-ref'))"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</form>
|
||||
@error("login")
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||
<span class="block sm:inline">{{ $message }} </span>
|
||||
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function otpForm() {
|
||||
return {
|
||||
length: 6,
|
||||
login: "",
|
||||
|
||||
handleInput(e) {
|
||||
const input = e.target;
|
||||
|
||||
this.login = Array.from(Array(this.length), (element, i) => {
|
||||
return this.$refs[i].value || "";
|
||||
}).join("");
|
||||
|
||||
if (input.nextElementSibling && input.value) {
|
||||
input.nextElementSibling.focus();
|
||||
input.nextElementSibling.select();
|
||||
}
|
||||
|
||||
if(this.login.length == 6){
|
||||
this.$wire.handleLogin(this.login);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
handlePaste(e) {
|
||||
const paste = e.clipboardData.getData('text');
|
||||
this.value = paste;
|
||||
|
||||
const inputs = Array.from(Array(this.length));
|
||||
|
||||
inputs.forEach((element, i) => {
|
||||
this.$refs[i].value = paste[i] || '';
|
||||
});
|
||||
},
|
||||
|
||||
handleBackspace(e) {
|
||||
const previous = parseInt(e, 10) - 1;
|
||||
this.$refs[previous] && this.$refs[previous].focus();
|
||||
this.$wire.loginValidation();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
@extends('portal.ninja2020.layout.clean')
|
||||
@section('meta_title', 'Mollie')
|
||||
|
||||
@section('body')
|
||||
<div class="grid lg:grid-cols-3">
|
||||
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
|
||||
<img src="{{ asset('images/client-portal-new-image.jpg') }}"
|
||||
class="w-full h-screen object-cover"
|
||||
alt="Background image">
|
||||
</div>
|
||||
|
||||
<div class="col-span-2 h-screen flex">
|
||||
<div class="m-auto md:w-1/2 lg:w-1/4 flex flex-col items-center">
|
||||
<span class="flex items-center text-2xl">
|
||||
{{ ctrans('texts.payment_error_code',['code' => 500]) }}
|
||||
</span>
|
||||
|
||||
<a class="button-link text-sm mt-2" href="{{ url(request()->getSchemeAndHttpHost() . '/client') }}">
|
||||
{{ ctrans('texts.back_to', ['url' => parse_url(request()->getHttpHost())['host'] ?? request()->getHttpHost()]) }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
@ -66,8 +66,6 @@
|
||||
<script src="{{ asset('vendor/alpinejs@2.8.2/alpine.js') }}" defer></script>
|
||||
|
||||
<!-- Fonts -->
|
||||
{{-- <link rel="dns-prefetch" href="https://fonts.gstatic.com"> --}}
|
||||
{{-- <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet" type="text/css" defer> --}}
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<!-- Error: {{ session('error') }} -->
|
||||
@if (isset($company) && $company->matomo_url && $company->matomo_id)
|
||||
@if (isset($company) && $company->matomo_url && $company->matomo_id)
|
||||
<script>
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
@ -66,9 +66,6 @@
|
||||
<script src="{{ asset('vendor/alpinejs@2.8.2/alpine.js') }}" defer></script>
|
||||
|
||||
<!-- Fonts -->
|
||||
{{-- <link rel="dns-prefetch" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet" type="text/css" defer>
|
||||
--}}
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
|
Loading…
x
Reference in New Issue
Block a user