2022-11-23 07:27:43 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
2024-04-12 06:15:41 +02:00
|
|
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
2022-11-23 07:27:43 +01:00
|
|
|
*
|
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
|
|
|
*/
|
|
|
|
|
2023-12-13 17:52:49 +01:00
|
|
|
namespace App\Livewire;
|
2022-11-23 07:27:43 +01:00
|
|
|
|
2022-12-07 06:45:25 +01:00
|
|
|
use App\DataMapper\ClientSettings;
|
2022-11-23 07:27:43 +01:00
|
|
|
use App\Factory\ClientFactory;
|
|
|
|
use App\Jobs\Mail\NinjaMailerJob;
|
|
|
|
use App\Jobs\Mail\NinjaMailerObject;
|
|
|
|
use App\Libraries\MultiDB;
|
2022-12-10 02:28:54 +01:00
|
|
|
use App\Mail\Subscription\OtpCode;
|
2022-11-23 07:27:43 +01:00
|
|
|
use App\Models\Client;
|
|
|
|
use App\Models\ClientContact;
|
|
|
|
use App\Models\Invoice;
|
2022-12-07 06:45:25 +01:00
|
|
|
use App\Models\RecurringInvoice;
|
2022-11-23 07:27:43 +01:00
|
|
|
use App\Models\Subscription;
|
|
|
|
use App\Repositories\ClientContactRepository;
|
|
|
|
use App\Repositories\ClientRepository;
|
2022-12-07 06:45:25 +01:00
|
|
|
use App\Utils\Number;
|
2023-07-31 03:17:36 +02:00
|
|
|
use App\Utils\Traits\MakesHash;
|
2022-11-23 07:27:43 +01:00
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
use Illuminate\Support\Str;
|
2022-12-15 05:42:37 +01:00
|
|
|
use InvalidArgumentException;
|
2023-02-16 02:36:09 +01:00
|
|
|
use Laracasts\Presenter\Exceptions\PresenterException;
|
2022-11-23 07:27:43 +01:00
|
|
|
use Livewire\Component;
|
|
|
|
|
|
|
|
class BillingPortalPurchasev2 extends Component
|
|
|
|
{
|
2023-07-31 03:17:36 +02:00
|
|
|
use MakesHash;
|
2022-11-23 07:27:43 +01:00
|
|
|
/**
|
|
|
|
* Random hash generated by backend to handle the tracking of state.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $hash;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* E-mail address model for user input.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $email;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instance of subscription.
|
|
|
|
*
|
2023-08-07 07:07:52 +02:00
|
|
|
* @var \App\Models\Subscription
|
2022-11-23 07:27:43 +01:00
|
|
|
*/
|
|
|
|
public $subscription;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instance of client contact.
|
|
|
|
*
|
|
|
|
* @var null|ClientContact
|
|
|
|
*/
|
|
|
|
public $contact;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Id for CompanyGateway record.
|
|
|
|
*
|
|
|
|
* @var string|integer
|
|
|
|
*/
|
|
|
|
public $company_gateway_id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Id for GatewayType.
|
|
|
|
*
|
|
|
|
* @var string|integer
|
|
|
|
*/
|
|
|
|
public $payment_method_id;
|
|
|
|
|
|
|
|
/**
|
2022-12-15 05:42:37 +01:00
|
|
|
* Array of front end variables for
|
|
|
|
* the subscription
|
2022-11-23 07:27:43 +01:00
|
|
|
*/
|
2022-12-01 20:59:16 +01:00
|
|
|
public $data = [];
|
|
|
|
|
2022-11-23 07:27:43 +01:00
|
|
|
/**
|
|
|
|
* List of payment methods fetched from client.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
public $methods = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instance of \App\Models\Invoice
|
|
|
|
*
|
|
|
|
* @var Invoice
|
|
|
|
*/
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2024-01-07 10:37:03 +01:00
|
|
|
public \App\Models\Invoice $invoice;
|
2022-11-23 07:27:43 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Coupon model for user input
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $coupon;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Quantity for seats
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
public $quantity;
|
|
|
|
|
2024-01-07 10:37:03 +01:00
|
|
|
public $invoice_hashed_id = '';
|
|
|
|
|
|
|
|
public $payable_amount = 0;
|
2022-11-23 07:27:43 +01:00
|
|
|
/**
|
|
|
|
* First-hit request data (queries, locales...).
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2022-12-23 01:33:14 +01:00
|
|
|
public $request_data = [];
|
2022-11-23 07:27:43 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Instance of company.
|
|
|
|
*
|
2023-08-06 09:41:40 +02:00
|
|
|
* @var \App\Models\Company
|
2022-11-23 07:27:43 +01:00
|
|
|
*/
|
|
|
|
public $company;
|
|
|
|
|
2022-12-23 01:33:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Instance of company.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public string $db;
|
2022-12-22 06:53:48 +01:00
|
|
|
|
2022-11-23 07:27:43 +01:00
|
|
|
/**
|
|
|
|
* Campaign reference.
|
|
|
|
*
|
|
|
|
* @var string|null
|
|
|
|
*/
|
|
|
|
public $campaign;
|
|
|
|
|
2022-12-07 06:45:25 +01:00
|
|
|
public $bundle;
|
|
|
|
public $recurring_products;
|
|
|
|
public $products;
|
|
|
|
public $optional_recurring_products;
|
|
|
|
public $optional_products;
|
|
|
|
public $total;
|
2023-03-01 07:57:52 +01:00
|
|
|
public $non_recurring_total;
|
|
|
|
public $recurring_total;
|
2022-12-09 03:47:54 +01:00
|
|
|
public $discount;
|
2022-12-09 04:36:39 +01:00
|
|
|
public $sub_total;
|
2022-12-09 05:41:54 +01:00
|
|
|
public $authenticated = false;
|
|
|
|
public $login;
|
2022-12-10 04:25:46 +01:00
|
|
|
public $float_amount_total;
|
2022-12-10 06:31:31 +01:00
|
|
|
public $payment_started = false;
|
2022-12-12 06:00:39 +01:00
|
|
|
public $valid_coupon = false;
|
2022-12-15 02:16:50 +01:00
|
|
|
public $payable_invoices = [];
|
2022-12-15 05:42:37 +01:00
|
|
|
public $payment_confirmed = false;
|
2022-12-18 10:57:32 +01:00
|
|
|
public $is_eligible = true;
|
|
|
|
public $not_eligible_message = '';
|
2024-07-29 02:10:02 +02:00
|
|
|
public $check_rff = false;
|
|
|
|
|
|
|
|
public ?string $contact_first_name;
|
|
|
|
public ?string $contact_last_name;
|
|
|
|
public ?string $contact_email;
|
|
|
|
public ?string $client_city;
|
|
|
|
public ?string $client_postal_code;
|
2024-01-07 10:37:03 +01:00
|
|
|
|
2022-11-23 07:27:43 +01:00
|
|
|
public function mount()
|
|
|
|
{
|
2022-12-22 06:53:48 +01:00
|
|
|
MultiDB::setDb($this->db);
|
|
|
|
|
2023-08-07 06:33:47 +02:00
|
|
|
$this->subscription = Subscription::query()->with('company')->find($this->subscription);
|
2022-12-22 06:53:48 +01:00
|
|
|
|
|
|
|
$this->company = $this->subscription->company;
|
2022-11-23 07:27:43 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if (auth()->guard('contact')->check()) {
|
2022-12-20 05:50:02 +01:00
|
|
|
$this->email = auth()->guard('contact')->user()->email;
|
|
|
|
$this->contact = auth()->guard('contact')->user();
|
|
|
|
$this->authenticated = true;
|
|
|
|
$this->payment_started = true;
|
2023-03-18 08:24:56 +01:00
|
|
|
} else {
|
2023-03-01 09:14:04 +01:00
|
|
|
$this->bundle = collect();
|
|
|
|
}
|
2022-12-20 05:50:02 +01:00
|
|
|
|
2022-12-09 03:47:54 +01:00
|
|
|
$this->discount = 0;
|
2022-12-09 04:36:39 +01:00
|
|
|
$this->sub_total = 0;
|
2022-12-10 04:25:46 +01:00
|
|
|
$this->float_amount_total = 0;
|
2022-11-23 07:27:43 +01:00
|
|
|
|
2024-01-07 10:37:03 +01:00
|
|
|
$this->invoice_hashed_id = '';
|
|
|
|
$this->payable_amount = 0;
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2022-12-01 20:59:16 +01:00
|
|
|
$this->data = [];
|
|
|
|
|
2022-12-10 06:31:31 +01:00
|
|
|
$this->price = $this->subscription->price; // ?
|
2022-12-07 06:45:25 +01:00
|
|
|
|
|
|
|
$this->recurring_products = $this->subscription->service()->recurring_products();
|
|
|
|
$this->products = $this->subscription->service()->products();
|
|
|
|
$this->optional_recurring_products = $this->subscription->service()->optional_recurring_products();
|
|
|
|
$this->optional_products = $this->subscription->service()->optional_products();
|
|
|
|
|
2022-12-07 06:48:40 +01:00
|
|
|
$this->bundle = collect();
|
2022-12-10 06:31:31 +01:00
|
|
|
|
|
|
|
//every thing below is redundant
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if (request()->query('coupon')) {
|
2022-12-10 06:31:31 +01:00
|
|
|
$this->coupon = request()->query('coupon');
|
|
|
|
$this->handleCoupon();
|
2023-02-16 02:36:09 +01:00
|
|
|
} elseif (isset($this->subscription->promo_code) && strlen($this->subscription->promo_code) == 0 && $this->subscription->promo_discount > 0) {
|
|
|
|
$this->price = $this->subscription->promo_price;
|
2022-12-10 06:31:31 +01:00
|
|
|
}
|
2022-11-23 07:27:43 +01:00
|
|
|
}
|
|
|
|
|
2022-12-09 09:39:27 +01:00
|
|
|
public function loginValidation()
|
|
|
|
{
|
|
|
|
$this->resetErrorBag('login');
|
2023-02-16 02:36:09 +01:00
|
|
|
$this->resetValidation('login');
|
2022-12-09 09:39:27 +01:00
|
|
|
}
|
2022-12-09 05:41:54 +01:00
|
|
|
|
2022-12-10 02:28:54 +01:00
|
|
|
public function handleLogin($user_code)
|
2022-12-09 05:41:54 +01:00
|
|
|
{
|
2022-12-10 02:28:54 +01:00
|
|
|
$this->resetErrorBag('login');
|
|
|
|
$this->resetValidation('login');
|
|
|
|
|
2022-12-09 09:39:27 +01:00
|
|
|
$code = Cache::get("subscriptions:otp:{$this->email}");
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($user_code != $code) {
|
2022-12-10 02:28:54 +01:00
|
|
|
$errors = $this->getErrorBag();
|
|
|
|
$errors->add('login', ctrans('texts.invalid_code'));
|
2022-12-10 06:31:31 +01:00
|
|
|
return $this;
|
2022-12-10 02:28:54 +01:00
|
|
|
}
|
2022-12-09 09:39:27 +01:00
|
|
|
|
2022-12-15 05:42:37 +01:00
|
|
|
$contact = ClientContact::where('email', $this->email)
|
|
|
|
->where('company_id', $this->subscription->company_id)
|
|
|
|
->first();
|
2022-12-09 09:39:27 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($contact) {
|
2022-12-09 09:39:27 +01:00
|
|
|
Auth::guard('contact')->loginUsingId($contact->id, true);
|
|
|
|
$this->contact = $contact;
|
2023-02-16 02:36:09 +01:00
|
|
|
} else {
|
2022-12-10 02:28:54 +01:00
|
|
|
$this->createClientContact();
|
2022-12-09 09:39:27 +01:00
|
|
|
}
|
|
|
|
|
2022-12-10 04:25:46 +01:00
|
|
|
$this->getPaymentMethods();
|
|
|
|
|
2022-12-15 05:42:37 +01:00
|
|
|
$this->authenticated = true;
|
|
|
|
$this->payment_started = true;
|
2022-12-09 05:41:54 +01:00
|
|
|
}
|
|
|
|
|
2022-12-10 04:25:46 +01:00
|
|
|
public function resetEmail()
|
|
|
|
{
|
2022-12-19 04:57:44 +01:00
|
|
|
$this->resetErrorBag('login');
|
2023-02-16 02:36:09 +01:00
|
|
|
$this->resetValidation('login');
|
2022-12-10 04:25:46 +01:00
|
|
|
$this->email = null;
|
|
|
|
}
|
|
|
|
|
2022-12-09 05:41:54 +01:00
|
|
|
public function handleEmail()
|
|
|
|
{
|
2023-02-16 02:36:09 +01:00
|
|
|
$this->validateOnly('email', ['email' => 'required|bail|email:rfc']);
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$rand = rand(100000, 999999);
|
2022-12-09 05:41:54 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$email_hash = "subscriptions:otp:{$this->email}";
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
Cache::put($email_hash, $rand, 120);
|
2022-12-09 05:41:54 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$this->emailOtpCode($rand);
|
2022-12-10 02:28:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function emailOtpCode($code)
|
|
|
|
{
|
|
|
|
$cc = new ClientContact();
|
|
|
|
$cc->email = $this->email;
|
|
|
|
|
2024-01-14 05:05:00 +01:00
|
|
|
$nmo = new NinjaMailerObject();
|
2022-12-10 02:28:54 +01:00
|
|
|
$nmo->mailable = new OtpCode($this->subscription->company, $this->contact, $code);
|
|
|
|
$nmo->company = $this->subscription->company;
|
|
|
|
$nmo->settings = $this->subscription->company->settings;
|
|
|
|
$nmo->to_user = $cc;
|
|
|
|
NinjaMailerJob::dispatch($nmo);
|
2022-12-09 05:41:54 +01:00
|
|
|
}
|
|
|
|
|
2022-12-09 04:36:39 +01:00
|
|
|
/**
|
|
|
|
* Handle a coupon being entered into the checkout
|
|
|
|
*/
|
|
|
|
public function handleCoupon()
|
|
|
|
{
|
2023-03-01 04:47:04 +01:00
|
|
|
$this->resetErrorBag('coupon');
|
|
|
|
$this->resetValidation('coupon');
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($this->coupon == $this->subscription->promo_code) {
|
2022-12-12 06:00:39 +01:00
|
|
|
$this->valid_coupon = true;
|
2022-12-15 02:16:50 +01:00
|
|
|
$this->buildBundle();
|
2023-02-16 02:36:09 +01:00
|
|
|
} else {
|
2022-12-09 04:36:39 +01:00
|
|
|
$this->discount = 0;
|
2022-12-12 06:00:39 +01:00
|
|
|
$this->valid_coupon = false;
|
2022-12-15 02:16:50 +01:00
|
|
|
$this->buildBundle();
|
2023-03-01 04:47:04 +01:00
|
|
|
$errors = $this->getErrorBag();
|
|
|
|
$errors->add('coupon', ctrans('texts.invalid_coupon'));
|
|
|
|
return $this;
|
2022-12-12 06:00:39 +01:00
|
|
|
}
|
2022-12-09 04:36:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Build the bundle in the checkout
|
|
|
|
*/
|
2022-12-07 06:45:25 +01:00
|
|
|
public function buildBundle()
|
2022-12-01 20:59:16 +01:00
|
|
|
{
|
2023-02-16 02:36:09 +01:00
|
|
|
$this->bundle = collect();
|
|
|
|
|
|
|
|
$data = $this->data;
|
|
|
|
|
|
|
|
/* Recurring products can have a variable quantity */
|
|
|
|
foreach ($this->recurring_products as $key => $p) {
|
|
|
|
$qty = isset($data[$key]['recurring_qty']) ? $data[$key]['recurring_qty'] : 1;
|
|
|
|
$total = $p->price * $qty;
|
|
|
|
|
|
|
|
$this->bundle->push([
|
|
|
|
'description' => $p->notes,
|
|
|
|
'product_key' => $p->product_key,
|
|
|
|
'unit_cost' => $p->price,
|
2023-03-18 08:13:49 +01:00
|
|
|
'product' => substr(strip_tags($p->markdownNotes()), 0, 50),
|
2023-02-16 02:36:09 +01:00
|
|
|
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
|
|
|
|
'total' => $total,
|
|
|
|
'qty' => $qty,
|
|
|
|
'is_recurring' => true,
|
|
|
|
'product_image' => $p->product_image,
|
|
|
|
]);
|
|
|
|
}
|
2022-12-07 06:45:25 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
/* One time products can only have a single quantity */
|
|
|
|
foreach ($this->products as $key => $p) {
|
|
|
|
$qty = 1;
|
|
|
|
$total = $p->price * $qty;
|
|
|
|
|
|
|
|
$this->bundle->push([
|
|
|
|
'description' => $p->notes,
|
|
|
|
'product_key' => $p->product_key,
|
|
|
|
'unit_cost' => $p->price,
|
2023-03-18 08:13:49 +01:00
|
|
|
'product' => substr(strip_tags($p->markdownNotes()), 0, 50),
|
2023-02-16 02:36:09 +01:00
|
|
|
'price' => Number::formatMoney($total, $this->subscription->company),
|
|
|
|
'total' => $total,
|
|
|
|
'qty' => $qty,
|
|
|
|
'is_recurring' => false
|
|
|
|
]);
|
|
|
|
}
|
2022-12-07 06:45:25 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
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) {
|
|
|
|
return $k == $key;
|
|
|
|
});
|
2022-12-07 06:45:25 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$qty = isset($this->data[$key]['optional_recurring_qty']) ? $this->data[$key]['optional_recurring_qty'] : false;
|
2022-12-07 06:45:25 +01:00
|
|
|
$total = $p->price * $qty;
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($qty) {
|
|
|
|
$this->bundle->push([
|
|
|
|
'description' => $p->notes,
|
|
|
|
'product_key' => $p->product_key,
|
|
|
|
'unit_cost' => $p->price,
|
2023-03-18 08:13:49 +01:00
|
|
|
'product' => substr(strip_tags($p->markdownNotes()), 0, 50),
|
2023-02-16 02:36:09 +01:00
|
|
|
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
|
|
|
|
'total' => $total,
|
|
|
|
'qty' => $qty,
|
|
|
|
'is_recurring' => true
|
|
|
|
]);
|
|
|
|
}
|
2022-12-07 06:45:25 +01:00
|
|
|
}
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
/* Optional products can have a variable quantity */
|
|
|
|
if (isset($this->data[$key]['optional_qty'])) {
|
|
|
|
$p = $this->optional_products->first(function ($v, $k) use ($key) {
|
|
|
|
return $k == $key;
|
|
|
|
});
|
2022-12-07 06:45:25 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$qty = isset($this->data[$key]['optional_qty']) ? $this->data[$key]['optional_qty'] : false;
|
2022-12-07 06:45:25 +01:00
|
|
|
$total = $p->price * $qty;
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($qty) {
|
|
|
|
$this->bundle->push([
|
|
|
|
'description' => $p->notes,
|
|
|
|
'product_key' => $p->product_key,
|
|
|
|
'unit_cost' => $p->price,
|
2023-03-18 08:13:49 +01:00
|
|
|
'product' => substr(strip_tags($p->markdownNotes()), 0, 50),
|
2023-02-16 02:36:09 +01:00
|
|
|
'price' => Number::formatMoney($total, $this->subscription->company),
|
|
|
|
'total' => $total,
|
|
|
|
'qty' => $qty,
|
|
|
|
'is_recurring' => false
|
|
|
|
]);
|
2022-12-07 06:45:25 +01:00
|
|
|
}
|
|
|
|
}
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2022-12-07 06:45:25 +01:00
|
|
|
|
2022-12-09 04:36:39 +01:00
|
|
|
$this->sub_total = Number::formatMoney($this->bundle->sum('total'), $this->subscription->company);
|
2023-03-01 07:57:52 +01:00
|
|
|
$this->recurring_total = Number::formatMoney($this->bundle->where('is_recurring', true)->sum('total'), $this->subscription->company);
|
|
|
|
$this->non_recurring_total = Number::formatMoney($this->bundle->where('is_recurring', false)->sum('total'), $this->subscription->company);
|
2022-12-09 04:36:39 +01:00
|
|
|
$this->total = $this->sub_total;
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($this->valid_coupon) {
|
|
|
|
if ($this->subscription->is_amount_discount) {
|
2022-12-09 04:36:39 +01:00
|
|
|
$discount = $this->subscription->promo_discount;
|
2023-02-16 02:36:09 +01:00
|
|
|
} else {
|
2022-12-09 04:36:39 +01:00
|
|
|
$discount = round($this->bundle->sum('total') * ($this->subscription->promo_discount / 100), 2);
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2022-12-09 04:36:39 +01:00
|
|
|
|
|
|
|
$this->discount = Number::formatMoney($discount, $this->subscription->company);
|
|
|
|
|
|
|
|
$this->total = Number::formatMoney(($this->bundle->sum('total') - $discount), $this->subscription->company);
|
|
|
|
|
2022-12-10 04:25:46 +01:00
|
|
|
$this->float_amount_total = ($this->bundle->sum('total') - $discount);
|
2023-02-16 02:36:09 +01:00
|
|
|
} else {
|
2022-12-15 02:16:50 +01:00
|
|
|
$this->float_amount_total = $this->bundle->sum('total');
|
|
|
|
$this->total = Number::formatMoney($this->float_amount_total, $this->subscription->company);
|
|
|
|
}
|
2022-12-09 04:36:39 +01:00
|
|
|
|
2022-12-07 06:45:25 +01:00
|
|
|
return $this;
|
2022-12-01 20:59:16 +01:00
|
|
|
}
|
|
|
|
|
2022-12-15 05:42:37 +01:00
|
|
|
/**
|
2023-02-16 02:36:09 +01:00
|
|
|
* @return $this
|
|
|
|
* @throws PresenterException
|
|
|
|
* @throws InvalidArgumentException
|
2022-12-15 05:42:37 +01:00
|
|
|
*/
|
2022-12-09 09:39:27 +01:00
|
|
|
private function createClientContact()
|
2022-12-01 20:59:16 +01:00
|
|
|
{
|
2022-12-09 09:39:27 +01:00
|
|
|
$company = $this->subscription->company;
|
|
|
|
$user = $this->subscription->user;
|
|
|
|
$user->setCompany($company);
|
2022-12-07 06:45:25 +01:00
|
|
|
|
2022-12-09 09:39:27 +01:00
|
|
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
|
|
|
$data = [
|
|
|
|
'name' => '',
|
2023-08-08 01:32:21 +02:00
|
|
|
'group_settings_id' => $this->subscription->group_id,
|
2022-12-09 09:39:27 +01:00
|
|
|
'contacts' => [
|
|
|
|
['email' => $this->email],
|
|
|
|
],
|
|
|
|
'client_hash' => Str::random(40),
|
|
|
|
'settings' => ClientSettings::defaults(),
|
|
|
|
];
|
2022-12-09 03:47:54 +01:00
|
|
|
|
2022-12-09 09:39:27 +01:00
|
|
|
$client = $client_repo->save($data, ClientFactory::create($company->id, $user->id));
|
|
|
|
|
|
|
|
$this->contact = $client->fresh()->contacts()->first();
|
2022-12-15 05:42:37 +01:00
|
|
|
|
2022-12-09 09:39:27 +01:00
|
|
|
Auth::guard('contact')->loginUsingId($this->contact->id, true);
|
|
|
|
|
2022-12-10 02:28:54 +01:00
|
|
|
return $this;
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2022-12-09 09:39:27 +01:00
|
|
|
|
2022-12-01 20:59:16 +01:00
|
|
|
|
2022-12-15 05:42:37 +01:00
|
|
|
/**
|
2023-02-16 02:36:09 +01:00
|
|
|
* @param mixed $propertyName
|
|
|
|
*
|
|
|
|
* @return BillingPortalPurchasev2
|
2022-12-15 05:42:37 +01:00
|
|
|
*/
|
2024-01-14 05:05:00 +01:00
|
|
|
public function updated($propertyName): self
|
2022-12-01 20:59:16 +01:00
|
|
|
{
|
2023-02-16 02:36:09 +01:00
|
|
|
if (in_array($propertyName, ['login','email'])) {
|
2022-12-15 05:42:37 +01:00
|
|
|
return $this;
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2022-12-07 06:45:25 +01:00
|
|
|
|
|
|
|
$this->buildBundle();
|
2022-12-01 20:59:16 +01:00
|
|
|
|
2022-12-15 05:42:37 +01:00
|
|
|
return $this;
|
2022-12-01 20:59:16 +01:00
|
|
|
}
|
|
|
|
|
2022-12-10 06:31:31 +01:00
|
|
|
/**
|
|
|
|
* Fetching payment methods from the client.
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
2024-01-14 05:05:00 +01:00
|
|
|
protected function getPaymentMethods(): self
|
2022-12-10 06:31:31 +01:00
|
|
|
{
|
2023-01-18 10:42:46 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($this->float_amount_total == 0) {
|
2023-01-18 10:42:46 +01:00
|
|
|
$this->methods = [];
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2023-01-18 10:42:46 +01:00
|
|
|
|
2024-08-06 11:21:42 +02:00
|
|
|
if ($this->contact && $this->float_amount_total >= 0) {
|
2022-12-15 05:42:37 +01:00
|
|
|
$this->methods = $this->contact->client->service()->getPaymentMethods($this->float_amount_total);
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-07-29 02:10:02 +02:00
|
|
|
foreach($this->methods as $method) {
|
|
|
|
|
|
|
|
if($method['is_paypal'] == '1' && !$this->check_rff) {
|
|
|
|
$this->rff();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function rff()
|
|
|
|
{
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-07-29 02:10:02 +02:00
|
|
|
$this->contact_first_name = $this->contact->first_name;
|
|
|
|
$this->contact_last_name = $this->contact->last_name;
|
|
|
|
$this->contact_email = $this->contact->email;
|
|
|
|
$this->client_city = $this->contact->client->city;
|
|
|
|
$this->client_postal_code = $this->contact->client->postal_code;
|
|
|
|
|
|
|
|
if(
|
|
|
|
strlen($this->contact_first_name ?? '') == 0 ||
|
|
|
|
strlen($this->contact_last_name ?? '') == 0 ||
|
|
|
|
strlen($this->contact_email ?? '') == 0 ||
|
|
|
|
strlen($this->client_city ?? '') == 0 ||
|
|
|
|
strlen($this->client_postal_code ?? '') == 0
|
2024-08-22 08:45:06 +02:00
|
|
|
) {
|
2024-07-29 02:10:02 +02:00
|
|
|
$this->check_rff = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function handleRff()
|
|
|
|
{
|
|
|
|
|
|
|
|
$validated = $this->validate([
|
|
|
|
'contact_first_name' => ['required'],
|
|
|
|
'contact_last_name' => ['required'],
|
|
|
|
'client_city' => ['required'],
|
|
|
|
'client_postal_code' => ['required'],
|
|
|
|
'contact_email' => ['required', 'email'],
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->check_rff = false;
|
|
|
|
|
|
|
|
$this->contact->first_name = $validated['contact_first_name'];
|
|
|
|
$this->contact->last_name = $validated['contact_last_name'];
|
|
|
|
$this->contact->email = $validated['contact_email'];
|
|
|
|
$this->contact->client->postal_code = $validated['client_postal_code'];
|
|
|
|
$this->contact->client->city = $validated['client_city'];
|
|
|
|
|
|
|
|
$this->contact->pushQuietly();
|
|
|
|
|
|
|
|
$this->refreshComponent();
|
2022-12-10 06:31:31 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2024-07-29 02:10:02 +02:00
|
|
|
protected function refreshComponent()
|
|
|
|
{
|
|
|
|
$this->dispatch('$refresh');
|
|
|
|
}
|
|
|
|
|
2022-12-10 06:31:31 +01:00
|
|
|
/**
|
|
|
|
* Middle method between selecting payment method &
|
|
|
|
* submitting the from to the backend.
|
|
|
|
*
|
|
|
|
* @param $company_gateway_id
|
|
|
|
* @param $gateway_type_id
|
|
|
|
*/
|
|
|
|
public function handleMethodSelectingEvent($company_gateway_id, $gateway_type_id)
|
|
|
|
{
|
2022-12-15 05:42:37 +01:00
|
|
|
$this->payment_confirmed = true;
|
2022-12-15 02:16:50 +01:00
|
|
|
|
2022-12-10 06:31:31 +01:00
|
|
|
$this->company_gateway_id = $company_gateway_id;
|
|
|
|
$this->payment_method_id = $gateway_type_id;
|
|
|
|
|
|
|
|
$this->handleBeforePaymentEvents();
|
2024-01-07 10:37:03 +01:00
|
|
|
|
|
|
|
$this->dispatch('beforePaymentEventsCompleted');
|
|
|
|
|
2022-12-10 06:31:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method to handle events before payments.
|
|
|
|
*
|
2023-08-06 09:41:40 +02:00
|
|
|
* @return self
|
2022-12-10 06:31:31 +01:00
|
|
|
*/
|
2024-01-07 10:37:03 +01:00
|
|
|
public function handleBeforePaymentEvents(): self
|
2022-12-10 06:31:31 +01:00
|
|
|
{
|
2022-12-18 10:57:32 +01:00
|
|
|
$eligibility_check = $this->subscription->service()->isEligible($this->contact);
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if (is_array($eligibility_check) && $eligibility_check['message'] != 'Success') {
|
2022-12-18 10:57:32 +01:00
|
|
|
$this->is_eligible = false;
|
2022-12-19 04:57:44 +01:00
|
|
|
$this->not_eligible_message = $eligibility_check['message'];
|
2022-12-18 10:57:32 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-12-12 05:27:22 +01:00
|
|
|
$data = [
|
2023-01-18 06:52:32 +01:00
|
|
|
'client_id' => $this->contact->client->hashed_id,
|
2022-12-12 05:27:22 +01:00
|
|
|
'date' => now()->format('Y-m-d'),
|
|
|
|
'invitations' => [[
|
|
|
|
'key' => '',
|
|
|
|
'client_contact_id' => $this->contact->hashed_id,
|
|
|
|
]],
|
|
|
|
'user_input_promo_code' => $this->coupon,
|
|
|
|
'coupon' => empty($this->subscription->promo_code) ? '' : $this->coupon,
|
2022-12-18 10:57:32 +01:00
|
|
|
];
|
2022-12-10 06:31:31 +01:00
|
|
|
|
2022-12-12 05:27:22 +01:00
|
|
|
$this->invoice = $this->subscription
|
|
|
|
->service()
|
2022-12-12 06:00:39 +01:00
|
|
|
->createInvoiceV2($this->bundle, $this->contact->client_id, $this->valid_coupon)
|
2022-12-12 05:27:22 +01:00
|
|
|
->service()
|
2022-12-15 02:16:50 +01:00
|
|
|
->markSent()
|
2022-12-12 05:27:22 +01:00
|
|
|
->fillDefaults()
|
|
|
|
->adjustInventory()
|
|
|
|
->save();
|
2022-12-10 06:31:31 +01:00
|
|
|
|
2024-01-07 10:37:03 +01:00
|
|
|
$this->payable_amount = $this->invoice->partial > 0 ? \App\Utils\Number::formatValue($this->invoice->partial, $this->invoice->client->currency()) : \App\Utils\Number::formatValue($this->invoice->balance, $this->invoice->client->currency());
|
|
|
|
$this->invoice_hashed_id = $this->invoice->hashed_id;
|
|
|
|
|
2022-12-15 02:16:50 +01:00
|
|
|
Cache::put($this->hash, [
|
2023-01-18 06:52:32 +01:00
|
|
|
'subscription_id' => $this->subscription->hashed_id,
|
2022-12-15 02:16:50 +01:00
|
|
|
'email' => $this->email ?? $this->contact->email,
|
2023-01-18 06:52:32 +01:00
|
|
|
'client_id' => $this->contact->client->hashed_id,
|
|
|
|
'invoice_id' => $this->invoice->hashed_id,
|
2022-12-15 02:16:50 +01:00
|
|
|
'context' => 'purchase',
|
|
|
|
'campaign' => $this->campaign,
|
|
|
|
'bundle' => $this->bundle,
|
|
|
|
], now()->addMinutes(60));
|
2022-12-10 06:31:31 +01:00
|
|
|
|
2022-12-18 10:57:32 +01:00
|
|
|
return $this;
|
2022-12-10 06:31:31 +01:00
|
|
|
}
|
|
|
|
|
2023-01-19 00:23:42 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the trial
|
2023-02-16 02:36:09 +01:00
|
|
|
*
|
2023-01-19 00:23:42 +01:00
|
|
|
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
|
|
|
|
*/
|
2022-12-16 06:21:14 +01:00
|
|
|
public function handleTrial()
|
|
|
|
{
|
|
|
|
return $this->subscription->service()->startTrial([
|
|
|
|
'email' => $this->email ?? $this->contact->email,
|
|
|
|
'quantity' => $this->quantity,
|
2023-01-18 06:52:32 +01:00
|
|
|
'contact_id' => $this->contact->hashed_id,
|
|
|
|
'client_id' => $this->contact->client->hashed_id,
|
2022-12-16 06:21:14 +01:00
|
|
|
'bundle' => $this->bundle,
|
|
|
|
]);
|
|
|
|
}
|
2022-12-10 06:31:31 +01:00
|
|
|
|
2023-01-19 00:23:42 +01:00
|
|
|
/**
|
2023-02-16 02:36:09 +01:00
|
|
|
* When the subscription total comes to $0 we
|
2023-01-19 00:23:42 +01:00
|
|
|
* pass back a $0 Invoice.
|
|
|
|
*
|
|
|
|
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
|
|
|
|
*/
|
2023-01-18 10:42:46 +01:00
|
|
|
public function handlePaymentNotRequired()
|
|
|
|
{
|
|
|
|
$eligibility_check = $this->subscription->service()->isEligible($this->contact);
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if (is_array($eligibility_check) && $eligibility_check['message'] != 'Success') {
|
2023-01-18 10:42:46 +01:00
|
|
|
$this->is_eligible = false;
|
|
|
|
$this->not_eligible_message = $eligibility_check['message'];
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
$invoice = $this->subscription
|
|
|
|
->service()
|
|
|
|
->createInvoiceV2($this->bundle, $this->contact->client_id, $this->valid_coupon)
|
|
|
|
->service()
|
|
|
|
->fillDefaults()
|
|
|
|
->adjustInventory()
|
|
|
|
->save();
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$invoice->number = null;
|
2023-01-19 00:14:10 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
$invoice->service()
|
|
|
|
->markPaid()
|
|
|
|
->save();
|
2023-01-18 10:42:46 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
return $this->subscription
|
|
|
|
->service()
|
|
|
|
->handleNoPaymentFlow($invoice, $this->bundle, $this->contact);
|
2023-01-18 10:42:46 +01:00
|
|
|
}
|
|
|
|
|
2022-12-10 06:31:31 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-12-10 02:28:54 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2022-12-01 20:59:16 +01:00
|
|
|
public function rules()
|
|
|
|
{
|
2022-12-07 06:45:25 +01:00
|
|
|
$rules = [
|
2022-12-01 20:59:16 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
return $rules;
|
|
|
|
}
|
|
|
|
|
2022-12-07 06:45:25 +01:00
|
|
|
public function attributes()
|
|
|
|
{
|
|
|
|
$attributes = [
|
|
|
|
];
|
|
|
|
|
|
|
|
return $attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function store()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-11-23 07:27:43 +01:00
|
|
|
/**
|
|
|
|
* Create a blank client. Used for new customers purchasing.
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
* @throws \Laracasts\Presenter\Exceptions\PresenterException
|
|
|
|
*/
|
|
|
|
protected function createBlankClient()
|
|
|
|
{
|
|
|
|
$company = $this->subscription->company;
|
|
|
|
$user = $this->subscription->user;
|
|
|
|
$user->setCompany($company);
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2022-11-23 07:27:43 +01:00
|
|
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
|
|
|
|
|
|
|
$data = [
|
|
|
|
'name' => '',
|
|
|
|
'contacts' => [
|
|
|
|
['email' => $this->email],
|
|
|
|
],
|
|
|
|
'client_hash' => Str::random(40),
|
|
|
|
'settings' => ClientSettings::defaults(),
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach ($this->request_data as $field => $value) {
|
|
|
|
if (in_array($field, Client::$subscriptions_fillable)) {
|
|
|
|
$data[$field] = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in_array($field, ClientContact::$subscription_fillable)) {
|
|
|
|
$data['contacts'][0][$field] = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if (array_key_exists('currency_id', $this->request_data)) {
|
2024-06-18 02:24:03 +02:00
|
|
|
|
|
|
|
/** @var \Illuminate\Support\Collection<\App\Models\Currency> */
|
|
|
|
$currencies = app('currencies');
|
|
|
|
|
|
|
|
$currency = $currencies->first(function ($item) {
|
2022-11-23 07:27:43 +01:00
|
|
|
return $item->id == $this->request_data['currency_id'];
|
2024-06-18 02:24:03 +02:00
|
|
|
});
|
2022-11-23 07:27:43 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($currency) {
|
2022-11-23 07:27:43 +01:00
|
|
|
$data['settings']->currency_id = $currency->id;
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
|
|
|
} elseif ($this->subscription->group_settings && property_exists($this->subscription->group_settings->settings, 'currency_id')) {
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-06-18 02:24:03 +02:00
|
|
|
/** @var \Illuminate\Support\Collection<\App\Models\Currency> */
|
|
|
|
$currencies = app('currencies');
|
|
|
|
|
|
|
|
$currency = $currencies->first(function ($item) {
|
2022-11-23 07:27:43 +01:00
|
|
|
return $item->id == $this->subscription->group_settings->settings->currency_id;
|
2024-06-18 02:24:03 +02:00
|
|
|
});
|
2022-11-23 07:27:43 +01:00
|
|
|
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($currency) {
|
2022-11-23 07:27:43 +01:00
|
|
|
$data['settings']->currency_id = $currency->id;
|
2023-02-16 02:36:09 +01:00
|
|
|
}
|
2022-11-23 07:27:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (array_key_exists('locale', $this->request_data)) {
|
|
|
|
$request = $this->request_data;
|
|
|
|
|
2024-06-18 02:24:03 +02:00
|
|
|
/** @var \Illuminate\Support\Collection<\App\Models\Language> */
|
|
|
|
$languages = app('languages');
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-06-18 02:24:03 +02:00
|
|
|
$record = $languages->first(function ($item) use ($request) {
|
2022-11-23 07:27:43 +01:00
|
|
|
return $item->locale == $request['locale'];
|
2024-06-18 02:24:03 +02:00
|
|
|
});
|
2022-11-23 07:27:43 +01:00
|
|
|
|
|
|
|
if ($record) {
|
|
|
|
$data['settings']['language_id'] = (string)$record->id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$client = $client_repo->save($data, ClientFactory::create($company->id, $user->id));
|
|
|
|
|
|
|
|
return $client->fresh()->contacts->first();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2022-11-23 07:27:43 +01:00
|
|
|
/**
|
|
|
|
* Proxy method for starting the trial.
|
|
|
|
*
|
|
|
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
|
|
*/
|
|
|
|
|
|
|
|
public function render()
|
|
|
|
{
|
|
|
|
if (array_key_exists('email', $this->request_data)) {
|
|
|
|
$this->email = $this->request_data['email'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->contact instanceof ClientContact) {
|
2022-12-15 05:42:37 +01:00
|
|
|
$this->getPaymentMethods();
|
2022-11-23 07:27:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return render('components.livewire.billing-portal-purchasev2');
|
|
|
|
}
|
|
|
|
}
|