mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-04 07:57:33 -05:00 
			
		
		
		
	
						commit
						bc4e3b1738
					
				@ -1 +1 @@
 | 
				
			|||||||
5.1.26
 | 
					5.1.27
 | 
				
			||||||
							
								
								
									
										47
									
								
								app/DataMapper/Billing/WebhookConfiguration.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/DataMapper/Billing/WebhookConfiguration.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\DataMapper\Billing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WebhookConfiguration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public $return_url = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public $post_purchase_url = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public $post_purchase_headers = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public $post_purchase_body =  '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static $casts = [
 | 
				
			||||||
 | 
					        'return_url' => 'string',
 | 
				
			||||||
 | 
					        'post_purchase_url' => 'string',
 | 
				
			||||||
 | 
					        'post_purchase_headers' => 'array',
 | 
				
			||||||
 | 
					        'post_purchase_body' => 'object',
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -142,11 +142,11 @@ class ActivityController extends BaseController
 | 
				
			|||||||
        $pdf = $this->makePdf(null, null, $backup->html_backup);
 | 
					        $pdf = $this->makePdf(null, null, $backup->html_backup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($activity->invoice_id)) {
 | 
					        if (isset($activity->invoice_id)) {
 | 
				
			||||||
            $filename = $activity->invoice->number.'.pdf';
 | 
					            $filename = $activity->invoice->numberFormatter().'.pdf';
 | 
				
			||||||
        } elseif (isset($activity->quote_id)) {
 | 
					        } elseif (isset($activity->quote_id)) {
 | 
				
			||||||
            $filename = $activity->quote->number.'.pdf';
 | 
					            $filename = $activity->quote->numberFormatter().'.pdf';
 | 
				
			||||||
        } elseif (isset($activity->credit_id)) {
 | 
					        } elseif (isset($activity->credit_id)) {
 | 
				
			||||||
            $filename = $activity->credit->number.'.pdf';
 | 
					            $filename = $activity->credit->numberFormatter().'.pdf';
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $filename = 'backup.pdf';
 | 
					            $filename = 'backup.pdf';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers\ClientPortal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
 | 
					use App\Models\BillingSubscription;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillingSubscriptionPurchaseController extends Controller
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function index(BillingSubscription $billing_subscription)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return view('billing-portal.purchase', [
 | 
				
			||||||
 | 
					            'billing_subscription' => $billing_subscription,
 | 
				
			||||||
 | 
					            'hash' => Str::uuid()->toString(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -29,6 +29,7 @@ use App\Utils\Traits\MakesHash;
 | 
				
			|||||||
use Illuminate\Contracts\View\Factory;
 | 
					use Illuminate\Contracts\View\Factory;
 | 
				
			||||||
use Illuminate\Http\RedirectResponse;
 | 
					use Illuminate\Http\RedirectResponse;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
use Illuminate\Support\Str;
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
use Illuminate\View\View;
 | 
					use Illuminate\View\View;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -237,11 +238,18 @@ class PaymentController extends Controller
 | 
				
			|||||||
                ->get();
 | 
					                ->get();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $hash_data = ['invoices' => $payable_invoices->toArray(), 'credits' => $credit_totals];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($request->query('hash')) {
 | 
				
			||||||
 | 
					            $hash_data['billing_context'] = Cache::get($request->query('hash'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $payment_hash = new PaymentHash;
 | 
					        $payment_hash = new PaymentHash;
 | 
				
			||||||
        $payment_hash->hash = Str::random(128);
 | 
					        $payment_hash->hash = Str::random(128);
 | 
				
			||||||
        $payment_hash->data = ['invoices' => $payable_invoices->toArray(), 'credits' => $credit_totals];
 | 
					        $payment_hash->data = $hash_data;
 | 
				
			||||||
        $payment_hash->fee_total = $fee_totals;
 | 
					        $payment_hash->fee_total = $fee_totals;
 | 
				
			||||||
        $payment_hash->fee_invoice_id = $first_invoice->id;
 | 
					        $payment_hash->fee_invoice_id = $first_invoice->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $payment_hash->save();
 | 
					        $payment_hash->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $totals = [
 | 
					        $totals = [
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										171
									
								
								app/Http/Livewire/BillingPortalPurchase.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								app/Http/Livewire/BillingPortalPurchase.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,171 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Livewire;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Factory\ClientFactory;
 | 
				
			||||||
 | 
					use App\Models\ClientContact;
 | 
				
			||||||
 | 
					use App\Repositories\ClientContactRepository;
 | 
				
			||||||
 | 
					use App\Repositories\ClientRepository;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Auth;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
 | 
					use Livewire\Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillingPortalPurchase extends Component
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public $hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $heading_text = 'Log in';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $password;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $billing_subscription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $rules = [
 | 
				
			||||||
 | 
					        'email' => ['required', 'email'],
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $company_gateway_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $payment_method_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $steps = [
 | 
				
			||||||
 | 
					        'passed_email' => false,
 | 
				
			||||||
 | 
					        'existing_user' => false,
 | 
				
			||||||
 | 
					        'fetched_payment_methods' => false,
 | 
				
			||||||
 | 
					        'fetched_client' => false,
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $methods = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $coupon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function authenticate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->validate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $contact = ClientContact::where('email', $this->email)->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($contact && $this->steps['existing_user'] === false) {
 | 
				
			||||||
 | 
					            return $this->steps['existing_user'] = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($contact && $this->steps['existing_user']) {
 | 
				
			||||||
 | 
					            $attempt = Auth::guard('contact')->attempt(['email' => $this->email, 'password' => $this->password]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $attempt
 | 
				
			||||||
 | 
					                ? $this->getPaymentMethods($contact)
 | 
				
			||||||
 | 
					                : session()->flash('message', 'These credentials do not match our records.');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->steps['existing_user'] = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $contact = $this->createBlankClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($contact && $contact instanceof ClientContact) {
 | 
				
			||||||
 | 
					            $this->getPaymentMethods($contact);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function createBlankClient()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $company = $this->billing_subscription->company;
 | 
				
			||||||
 | 
					        $user = $this->billing_subscription->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client_repo = new ClientRepository(new ClientContactRepository());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client = $client_repo->save([
 | 
				
			||||||
 | 
					            'name' => 'Client Name',
 | 
				
			||||||
 | 
					            'contacts' => [
 | 
				
			||||||
 | 
					                ['email' => $this->email],
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ], ClientFactory::create($company->id, $user->id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $client->contacts->first();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function getPaymentMethods(ClientContact $contact): self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->steps['fetched_payment_methods'] = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->methods = $contact->client->service()->getPaymentMethods(1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->heading_text = 'Pick a payment method';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Auth::guard('contact')->login($contact);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->contact = $contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handleMethodSelectingEvent($company_gateway_id, $gateway_type_id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->company_gateway_id = $company_gateway_id;
 | 
				
			||||||
 | 
					        $this->payment_method_id = $gateway_type_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->handleBeforePaymentEvents();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handleBeforePaymentEvents()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //stubs
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'client_id' => $this->contact->client->id,
 | 
				
			||||||
 | 
					            'date' => now()->format('Y-m-d'),
 | 
				
			||||||
 | 
					            'invitations' => [[
 | 
				
			||||||
 | 
					                'key' => '',
 | 
				
			||||||
 | 
					                'client_contact_id' => $this->contact->hashed_id,
 | 
				
			||||||
 | 
					            ]],
 | 
				
			||||||
 | 
					            'user_input_promo_code' => $this->coupon,
 | 
				
			||||||
 | 
					            'quantity' => 1, // Option to increase quantity
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->invoice = $this->billing_subscription
 | 
				
			||||||
 | 
					            ->service()
 | 
				
			||||||
 | 
					            ->createInvoice($data)
 | 
				
			||||||
 | 
					            ->service()
 | 
				
			||||||
 | 
					            ->markSent()
 | 
				
			||||||
 | 
					            ->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cache::put($this->hash, [
 | 
				
			||||||
 | 
					            'email' => $this->email ?? $this->contact->email,
 | 
				
			||||||
 | 
					            'client_id' => $this->contact->client->id,
 | 
				
			||||||
 | 
					            'invoice_id' => $this->invoice->id],
 | 
				
			||||||
 | 
					            now()->addMinutes(60)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->emit('beforePaymentEventsCompleted');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //this isn't managed here - this is taken care of in the BS
 | 
				
			||||||
 | 
					    public function applyCouponCode()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        dd('Applying coupon code: ' . $this->coupon);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function render()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->contact instanceof ClientContact) {
 | 
				
			||||||
 | 
					            $this->getPaymentMethods($this->contact);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return render('components.livewire.billing-portal-purchase');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -25,6 +25,7 @@ use App\Models\RecurringInvoiceInvitation;
 | 
				
			|||||||
use App\Services\PdfMaker\Design as PdfDesignModel;
 | 
					use App\Services\PdfMaker\Design as PdfDesignModel;
 | 
				
			||||||
use App\Services\PdfMaker\Design as PdfMakerDesign;
 | 
					use App\Services\PdfMaker\Design as PdfMakerDesign;
 | 
				
			||||||
use App\Services\PdfMaker\PdfMaker as PdfMakerService;
 | 
					use App\Services\PdfMaker\PdfMaker as PdfMakerService;
 | 
				
			||||||
 | 
					use App\Utils\HostedPDF\NinjaPdf;
 | 
				
			||||||
use App\Utils\HtmlEngine;
 | 
					use App\Utils\HtmlEngine;
 | 
				
			||||||
use App\Utils\Ninja;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Utils\PhantomJS\Phantom;
 | 
					use App\Utils\PhantomJS\Phantom;
 | 
				
			||||||
@ -115,7 +116,7 @@ class CreateEntityPdf implements ShouldQueue
 | 
				
			|||||||
            $entity_design_id = 'invoice_design_id';
 | 
					            $entity_design_id = 'invoice_design_id';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_path = $path.$this->entity->number.'.pdf';
 | 
					        $file_path = $path.$this->entity->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id));
 | 
					        $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -160,7 +161,13 @@ class CreateEntityPdf implements ShouldQueue
 | 
				
			|||||||
        $pdf = null;
 | 
					        $pdf = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(config('ninja.invoiceninja_hosted_pdf_generation')){
 | 
				
			||||||
 | 
					                $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true));
 | 
					                $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } catch (\Exception $e) {
 | 
					        } catch (\Exception $e) {
 | 
				
			||||||
            nlog(print_r($e->getMessage(), 1));
 | 
					            nlog(print_r($e->getMessage(), 1));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -186,6 +186,15 @@ class BaseModel extends Model
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getFileName($extension = 'pdf')
 | 
					    public function getFileName($extension = 'pdf')
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->number.'.'.$extension;
 | 
					        return $this->numberFormatter().'.'.$extension;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function numberFormatter()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $formatted_number =  mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $this->number);
 | 
				
			||||||
 | 
					        // Remove any runs of periods (thanks falstro!)
 | 
				
			||||||
 | 
					        $formatted_number = mb_ereg_replace("([\.]{2,})", '', $formatted_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $formatted_number;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -73,5 +73,4 @@ class BillingSubscription extends BaseModel
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->belongsTo(Product::class);
 | 
					        return $this->belongsTo(Product::class);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
 | 
				
			|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
 | 
					use Illuminate\Database\Eloquent\Relations\HasMany;
 | 
				
			||||||
use Illuminate\Notifications\Notification;
 | 
					use Illuminate\Notifications\Notification;
 | 
				
			||||||
use Laracasts\Presenter\PresentableTrait;
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Company extends BaseModel
 | 
					class Company extends BaseModel
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -342,12 +343,13 @@ class Company extends BaseModel
 | 
				
			|||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return BelongsTo
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function currency()
 | 
					    public function currency()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->belongsTo(Currency::class);
 | 
					        $currencies = Cache::get('currencies');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $currencies->filter(function ($item) {
 | 
				
			||||||
 | 
					            return $item->id == $this->settings->currency_id;
 | 
				
			||||||
 | 
					        })->first();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -248,9 +248,9 @@ class Credit extends BaseModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function pdf_file_path($invitation = null)
 | 
					    public function pdf_file_path($invitation = null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $storage_path = Storage::url($this->client->credit_filepath().$this->number.'.pdf');
 | 
					        $storage_path = Storage::url($this->client->credit_filepath().$this->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Storage::exists($this->client->credit_filepath().$this->number.'.pdf')) {
 | 
					        if (Storage::exists($this->client->credit_filepath().$this->numberFormatter().'.pdf')) {
 | 
				
			||||||
            return $storage_path;
 | 
					            return $storage_path;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -126,9 +126,9 @@ class CreditInvitation extends BaseModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function pdf_file_path()
 | 
					    public function pdf_file_path()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $storage_path = Storage::url($this->credit->client->quote_filepath().$this->credit->number.'.pdf');
 | 
					        $storage_path = Storage::url($this->credit->client->quote_filepath().$this->credit->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Storage::exists($this->credit->client->credit_filepath().$this->credit->number.'.pdf')) {
 | 
					        if (! Storage::exists($this->credit->client->credit_filepath().$this->credit->numberFormatter().'.pdf')) {
 | 
				
			||||||
            event(new CreditWasUpdated($this, $this->company, Ninja::eventVars()));
 | 
					            event(new CreditWasUpdated($this, $this->company, Ninja::eventVars()));
 | 
				
			||||||
            CreateEntityPdf::dispatchNow($this);
 | 
					            CreateEntityPdf::dispatchNow($this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -388,9 +388,9 @@ class Invoice extends BaseModel
 | 
				
			|||||||
            $invitation = $this->invitations->first();
 | 
					            $invitation = $this->invitations->first();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $storage_path = Storage::$type($this->client->invoice_filepath().$this->number.'.pdf');
 | 
					        $storage_path = Storage::$type($this->client->invoice_filepath().$this->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Storage::exists($this->client->invoice_filepath().$this->number.'.pdf')) {
 | 
					        if (! Storage::exists($this->client->invoice_filepath().$this->numberFormatter().'.pdf')) {
 | 
				
			||||||
            event(new InvoiceWasUpdated($this, $this->company, Ninja::eventVars()));
 | 
					            event(new InvoiceWasUpdated($this, $this->company, Ninja::eventVars()));
 | 
				
			||||||
            CreateEntityPdf::dispatchNow($invitation);
 | 
					            CreateEntityPdf::dispatchNow($invitation);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -140,9 +140,9 @@ class InvoiceInvitation extends BaseModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function pdf_file_path()
 | 
					    public function pdf_file_path()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $storage_path = Storage::url($this->invoice->client->invoice_filepath().$this->invoice->number.'.pdf');
 | 
					        $storage_path = Storage::url($this->invoice->client->invoice_filepath().$this->invoice->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Storage::exists($this->invoice->client->invoice_filepath().$this->invoice->number.'.pdf')) {
 | 
					        if (! Storage::exists($this->invoice->client->invoice_filepath().$this->invoice->numberFormatter().'.pdf')) {
 | 
				
			||||||
            event(new InvoiceWasUpdated($this->invoice, $this->company, Ninja::eventVars()));
 | 
					            event(new InvoiceWasUpdated($this->invoice, $this->company, Ninja::eventVars()));
 | 
				
			||||||
            CreateEntityPdf::dispatchNow($this);
 | 
					            CreateEntityPdf::dispatchNow($this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -208,11 +208,11 @@ class Quote extends BaseModel
 | 
				
			|||||||
            $invitation = $this->invitations->first();
 | 
					            $invitation = $this->invitations->first();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $storage_path = Storage::$type($this->client->quote_filepath().$this->number.'.pdf');
 | 
					        $storage_path = Storage::$type($this->client->quote_filepath().$this->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        nlog($storage_path);
 | 
					        nlog($storage_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Storage::exists($this->client->quote_filepath().$this->number.'.pdf')) {
 | 
					        if (! Storage::exists($this->client->quote_filepath().$this->numberFormatter().'.pdf')) {
 | 
				
			||||||
            event(new QuoteWasUpdated($this, $this->company, Ninja::eventVars()));
 | 
					            event(new QuoteWasUpdated($this, $this->company, Ninja::eventVars()));
 | 
				
			||||||
            CreateEntityPdf::dispatchNow($invitation);
 | 
					            CreateEntityPdf::dispatchNow($invitation);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -130,9 +130,9 @@ class QuoteInvitation extends BaseModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function pdf_file_path()
 | 
					    public function pdf_file_path()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $storage_path = Storage::url($this->quote->client->quote_filepath().$this->quote->number.'.pdf');
 | 
					        $storage_path = Storage::url($this->quote->client->quote_filepath().$this->quote->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Storage::exists($this->quote->client->quote_filepath().$this->quote->number.'.pdf')) {
 | 
					        if (! Storage::exists($this->quote->client->quote_filepath().$this->quote->numberFormatter().'.pdf')) {
 | 
				
			||||||
            event(new QuoteWasUpdated($this->quote, $this->company, Ninja::eventVars()));
 | 
					            event(new QuoteWasUpdated($this->quote, $this->company, Ninja::eventVars()));
 | 
				
			||||||
            CreateEntityPdf::dispatchNow($this);
 | 
					            CreateEntityPdf::dispatchNow($this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,7 @@ class InvoiceObserver
 | 
				
			|||||||
            WebhookHandler::dispatch(Webhook::EVENT_UPDATE_INVOICE, $invoice, $invoice->company);
 | 
					            WebhookHandler::dispatch(Webhook::EVENT_UPDATE_INVOICE, $invoice, $invoice->company);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        // UnlinkFile::dispatchNow(config('filesystems.default'), $invoice->client->invoice_filepath() . $invoice->number.'.pdf');
 | 
					        // UnlinkFile::dispatchNow(config('filesystems.default'), $invoice->client->invoice_filepath() . $invoice->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ use App\Models\Invoice;
 | 
				
			|||||||
use App\Models\Payment;
 | 
					use App\Models\Payment;
 | 
				
			||||||
use App\Models\PaymentHash;
 | 
					use App\Models\PaymentHash;
 | 
				
			||||||
use App\Models\SystemLog;
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
 | 
					use App\Services\BillingSubscription\BillingSubscriptionService;
 | 
				
			||||||
use App\Utils\Ninja;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
use App\Utils\Traits\SystemLogTrait;
 | 
					use App\Utils\Traits\SystemLogTrait;
 | 
				
			||||||
@ -240,6 +241,8 @@ class BaseDriver extends AbstractPaymentDriver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
 | 
					        event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BillingSubscriptionService::completePurchase($this->payment_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $payment->service()->applyNumber()->save();
 | 
					        return $payment->service()->applyNumber()->save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ class ClientContactRepository extends BaseRepository
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->is_primary = true;
 | 
					        $this->is_primary = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Set first record to primary - always */
 | 
					        /* Set first record to primary - always */
 | 
				
			||||||
        $contacts = $contacts->sortByDesc('is_primary')->map(function ($contact) {
 | 
					        $contacts = $contacts->sortByDesc('is_primary')->map(function ($contact) {
 | 
				
			||||||
            $contact['is_primary'] = $this->is_primary;
 | 
					            $contact['is_primary'] = $this->is_primary;
 | 
				
			||||||
 | 
				
			|||||||
@ -15,12 +15,13 @@ use App\DataMapper\InvoiceItem;
 | 
				
			|||||||
use App\Factory\InvoiceFactory;
 | 
					use App\Factory\InvoiceFactory;
 | 
				
			||||||
use App\Models\BillingSubscription;
 | 
					use App\Models\BillingSubscription;
 | 
				
			||||||
use App\Models\ClientSubscription;
 | 
					use App\Models\ClientSubscription;
 | 
				
			||||||
 | 
					use App\Models\PaymentHash;
 | 
				
			||||||
use App\Models\Product;
 | 
					use App\Models\Product;
 | 
				
			||||||
use App\Repositories\InvoiceRepository;
 | 
					use App\Repositories\InvoiceRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BillingSubscriptionService
 | 
					class BillingSubscriptionService
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    /** @var BillingSubscription */
 | 
				
			||||||
    private $billing_subscription;
 | 
					    private $billing_subscription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(BillingSubscription $billing_subscription)
 | 
					    public function __construct(BillingSubscription $billing_subscription)
 | 
				
			||||||
@ -28,21 +29,29 @@ class BillingSubscriptionService
 | 
				
			|||||||
        $this->billing_subscription = $billing_subscription;
 | 
					        $this->billing_subscription = $billing_subscription;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function createInvoice($data)
 | 
					    public function completePurchase(PaymentHash $payment_hash)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create client subscription record 
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // create recurring invoice if is_recurring
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        // s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function startTrial(array $data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function createInvoice($data): ?\App\Models\Invoice
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        $invoice_repo = new InvoiceRepository();
 | 
					        $invoice_repo = new InvoiceRepository();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // $data = [
 | 
					        $data['line_items'] = $this->createLineItems($data['quantity']);
 | 
				
			||||||
        //     'client_id' =>,
 | 
					 | 
				
			||||||
        //     'date' => Y-m-d,
 | 
					 | 
				
			||||||
        //     'invitations' => [
 | 
					 | 
				
			||||||
        //                         'client_contact_id' => hashed_id
 | 
					 | 
				
			||||||
        //                      ],
 | 
					 | 
				
			||||||
        //      'line_items' => [],        
 | 
					 | 
				
			||||||
        // ];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invoice = $invoice_repo->save($data, InvoiceFactory::create($this->billing_subscription->company_id, $this->billing_subscription->user_id));
 | 
					 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        If trial_enabled -> return early
 | 
					        If trial_enabled -> return early
 | 
				
			||||||
@ -56,11 +65,11 @@ class BillingSubscriptionService
 | 
				
			|||||||
            2. What is the quantity? ie is this a multi seat product ( does this mean we need this value stored in the client sub?)
 | 
					            2. What is the quantity? ie is this a multi seat product ( does this mean we need this value stored in the client sub?)
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       return $invoice;
 | 
					        return $invoice_repo->save($data, InvoiceFactory::create($this->billing_subscription->company_id, $this->billing_subscription->user_id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function createLineItems($quantity)
 | 
					    private function createLineItems($quantity): array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $line_items = [];
 | 
					        $line_items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -108,4 +117,14 @@ class BillingSubscriptionService
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        //scan for any notification we are required to send
 | 
					        //scan for any notification we are required to send
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function completePurchase(PaymentHash $payment_hash)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!property_exists($payment_hash, 'billing_context')) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // At this point we have some state carried from the billing page
 | 
				
			||||||
 | 
					        // to this, available as $payment_hash->data->billing_context. Make something awesome ⭐
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@ class CreditService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function deletePdf()
 | 
					    public function deletePdf()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        UnlinkFile::dispatchNow(config('filesystems.default'), $this->credit->client->credit_filepath() . $this->credit->number.'.pdf');
 | 
					        UnlinkFile::dispatchNow(config('filesystems.default'), $this->credit->client->credit_filepath() . $this->credit->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@ class GetCreditPdf extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $path = $this->credit->client->credit_filepath();
 | 
					        $path = $this->credit->client->credit_filepath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_path = $path.$this->credit->number.'.pdf';
 | 
					        $file_path = $path.$this->credit->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $disk = config('filesystems.default');
 | 
					        $disk = config('filesystems.default');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ class GetInvoicePdf extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $path = $this->invoice->client->invoice_filepath();
 | 
					        $path = $this->invoice->client->invoice_filepath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_path = $path.$this->invoice->number.'.pdf';
 | 
					        $file_path = $path.$this->invoice->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $disk = config('filesystems.default');
 | 
					        $disk = config('filesystems.default');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -274,8 +274,8 @@ class InvoiceService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function deletePdf()
 | 
					    public function deletePdf()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        //UnlinkFile::dispatchNow(config('filesystems.default'), $this->invoice->client->invoice_filepath() . $this->invoice->number.'.pdf');
 | 
					        //UnlinkFile::dispatchNow(config('filesystems.default'), $this->invoice->client->invoice_filepath() . $this->invoice->numberFormatter().'.pdf');
 | 
				
			||||||
        Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath() . $this->invoice->number.'.pdf');
 | 
					        Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath() . $this->invoice->numberFormatter().'.pdf');
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ class GetQuotePdf extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $path = $this->quote->client->quote_filepath();
 | 
					        $path = $this->quote->client->quote_filepath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_path = $path.$this->quote->number.'.pdf';
 | 
					        $file_path = $path.$this->quote->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $disk = config('filesystems.default');
 | 
					        $disk = config('filesystems.default');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -178,7 +178,7 @@ class QuoteService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function deletePdf()
 | 
					    public function deletePdf()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        UnlinkFile::dispatchNow(config('filesystems.default'), $this->quote->client->quote_filepath() . $this->quote->number.'.pdf');
 | 
					        UnlinkFile::dispatchNow(config('filesystems.default'), $this->quote->client->quote_filepath() . $this->quote->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -87,7 +87,7 @@ class RecurringService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function deletePdf()
 | 
					    public function deletePdf()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        UnlinkFile::dispatchNow(config('filesystems.default'), $this->recurring_entity->client->recurring_invoice_filepath() . $this->recurring_entity->number.'.pdf');
 | 
					        UnlinkFile::dispatchNow(config('filesystems.default'), $this->recurring_entity->client->recurring_invoice_filepath() . $this->recurring_entity->numberFormatter().'.pdf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,7 @@ class BillingSubscriptionTransformer extends EntityTransformer
 | 
				
			|||||||
            'plan_map' => (string)$billing_subscription->plan_map,
 | 
					            'plan_map' => (string)$billing_subscription->plan_map,
 | 
				
			||||||
            'refund_period' => (int)$billing_subscription->refund_period,
 | 
					            'refund_period' => (int)$billing_subscription->refund_period,
 | 
				
			||||||
            'webhook_configuration' => (string)$billing_subscription->webhook_configuration,
 | 
					            'webhook_configuration' => (string)$billing_subscription->webhook_configuration,
 | 
				
			||||||
 | 
					            'purchase_page' => (string)route('client.subscription.purchase', $billing_subscription->hashed_id),
 | 
				
			||||||
            'is_deleted' => (bool)$billing_subscription->is_deleted,
 | 
					            'is_deleted' => (bool)$billing_subscription->is_deleted,
 | 
				
			||||||
            'created_at' => (int)$billing_subscription->created_at,
 | 
					            'created_at' => (int)$billing_subscription->created_at,
 | 
				
			||||||
            'updated_at' => (int)$billing_subscription->updated_at,
 | 
					            'updated_at' => (int)$billing_subscription->updated_at,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										37
									
								
								app/Utils/HostedPDF/NinjaPdf.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Utils/HostedPDF/NinjaPdf.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Utils\HostedPDF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use GuzzleHttp\RequestOptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NinjaPdf
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private $url = 'https://pdf.invoicing.co/api/';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function build($html)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client =  new \GuzzleHttp\Client(['headers' => 
 | 
				
			||||||
 | 
					            [ 
 | 
				
			||||||
 | 
					            'X-Ninja-Token' => 'test_token_for_now',        
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response = $client->post($this->url,[
 | 
				
			||||||
 | 
					            RequestOptions::JSON => ['html' => $html]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $response->getBody();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Utils;
 | 
					namespace App\Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Company;
 | 
				
			||||||
use App\Models\Currency;
 | 
					use App\Models\Currency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -88,12 +89,12 @@ class Number
 | 
				
			|||||||
     * Formats a given value based on the clients currency AND country.
 | 
					     * Formats a given value based on the clients currency AND country.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param floatval $value The number to be formatted
 | 
					     * @param floatval $value The number to be formatted
 | 
				
			||||||
     * @param $client
 | 
					     * @param $entity
 | 
				
			||||||
     * @return string           The formatted value
 | 
					     * @return string           The formatted value
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function formatMoney($value, $client) :string
 | 
					    public static function formatMoney($value, $entity) :string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $currency = $client->currency();
 | 
					        $currency = $entity->currency();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $thousand = $currency->thousand_separator;
 | 
					        $thousand = $currency->thousand_separator;
 | 
				
			||||||
        $decimal = $currency->decimal_separator;
 | 
					        $decimal = $currency->decimal_separator;
 | 
				
			||||||
@ -101,29 +102,38 @@ class Number
 | 
				
			|||||||
        $code = $currency->code;
 | 
					        $code = $currency->code;
 | 
				
			||||||
        $swapSymbol = $currency->swap_currency_symbol;
 | 
					        $swapSymbol = $currency->swap_currency_symbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // App\Models\Client::country() returns instance of BelongsTo.
 | 
				
			||||||
 | 
					        // App\Models\Company::country() returns record for the country, that's why we check for the instance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($entity instanceof Company) {
 | 
				
			||||||
 | 
					            $country = $entity->country();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $country = $entity->country;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Country settings override client settings */
 | 
					        /* Country settings override client settings */
 | 
				
			||||||
        if (isset($client->country->thousand_separator) && strlen($client->country->thousand_separator) >= 1) {
 | 
					        if (isset($country->thousand_separator) && strlen($country->thousand_separator) >= 1) {
 | 
				
			||||||
            $thousand = $client->country->thousand_separator;
 | 
					            $thousand = $country->thousand_separator;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($client->country->decimal_separator) && strlen($client->country->decimal_separator) >= 1) {
 | 
					        if (isset($country->decimal_separator) && strlen($country->decimal_separator) >= 1) {
 | 
				
			||||||
            $decimal = $client->country->decimal_separator;
 | 
					            $decimal = $country->decimal_separator;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($client->country->swap_currency_symbol) && strlen($client->country->swap_currency_symbol) >= 1) {
 | 
					        if (isset($country->swap_currency_symbol) && strlen($country->swap_currency_symbol) >= 1) {
 | 
				
			||||||
            $swapSymbol = $client->country->swap_currency_symbol;
 | 
					            $swapSymbol = $country->swap_currency_symbol;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $value = number_format($value, $precision, $decimal, $thousand);
 | 
					        $value = number_format($value, $precision, $decimal, $thousand);
 | 
				
			||||||
        $symbol = $currency->symbol;
 | 
					        $symbol = $currency->symbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($client->getSetting('show_currency_code') === true && $currency->code == 'CHF') {
 | 
					        if ($entity->getSetting('show_currency_code') === true && $currency->code == 'CHF') {
 | 
				
			||||||
            return "{$code} {$value}";
 | 
					            return "{$code} {$value}";
 | 
				
			||||||
        } elseif ($client->getSetting('show_currency_code') === true) {
 | 
					        } elseif ($entity->getSetting('show_currency_code') === true) {
 | 
				
			||||||
            return "{$value} {$code}";
 | 
					            return "{$value} {$code}";
 | 
				
			||||||
        } elseif ($swapSymbol) {
 | 
					        } elseif ($swapSymbol) {
 | 
				
			||||||
            return "{$value} ".trim($symbol);
 | 
					            return "{$value} ".trim($symbol);
 | 
				
			||||||
        } elseif ($client->getSetting('show_currency_code') === false) {
 | 
					        } elseif ($entity->getSetting('show_currency_code') === false) {
 | 
				
			||||||
            return "{$symbol}{$value}";
 | 
					            return "{$symbol}{$value}";
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return self::formatValue($value, $currency);
 | 
					            return self::formatValue($value, $currency);
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,7 @@ class Phantom
 | 
				
			|||||||
            $path = $entity_obj->client->recurring_invoice_filepath();
 | 
					            $path = $entity_obj->client->recurring_invoice_filepath();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_path = $path.$entity_obj->number.'.pdf';
 | 
					        $file_path = $path.$entity_obj->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $url = config('ninja.app_url').'/phantom/'.$entity.'/'.$invitation->key.'?phantomjs_secret='.config('ninja.phantomjs_secret');
 | 
					        $url = config('ninja.app_url').'/phantom/'.$entity.'/'.$invitation->key.'?phantomjs_secret='.config('ninja.phantomjs_secret');
 | 
				
			||||||
        info($url);
 | 
					        info($url);
 | 
				
			||||||
@ -91,8 +91,8 @@ class Phantom
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        $instance = Storage::disk(config('filesystems.default'))->put($file_path, $pdf);
 | 
					        $instance = Storage::disk(config('filesystems.default'))->put($file_path, $pdf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nlog($instance);
 | 
					// nlog($instance);
 | 
				
			||||||
nlog($file_path);
 | 
					// nlog($file_path);
 | 
				
			||||||
        return $file_path;
 | 
					        return $file_path;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -65,6 +65,7 @@
 | 
				
			|||||||
        "predis/predis": "^1.1",
 | 
					        "predis/predis": "^1.1",
 | 
				
			||||||
        "sentry/sentry-laravel": "^2",
 | 
					        "sentry/sentry-laravel": "^2",
 | 
				
			||||||
        "stripe/stripe-php": "^7.50",
 | 
					        "stripe/stripe-php": "^7.50",
 | 
				
			||||||
 | 
					        "symfony/http-client": "^5.2",
 | 
				
			||||||
        "turbo124/beacon": "^1.0",
 | 
					        "turbo124/beacon": "^1.0",
 | 
				
			||||||
        "webpatser/laravel-countries": "dev-master#75992ad",
 | 
					        "webpatser/laravel-countries": "dev-master#75992ad",
 | 
				
			||||||
        "wildbit/swiftmailer-postmark": "^3.3"
 | 
					        "wildbit/swiftmailer-postmark": "^3.3"
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ return [
 | 
				
			|||||||
    'require_https' => env('REQUIRE_HTTPS', true),
 | 
					    'require_https' => env('REQUIRE_HTTPS', true),
 | 
				
			||||||
    'app_url' => rtrim(env('APP_URL', ''), '/'),
 | 
					    'app_url' => rtrim(env('APP_URL', ''), '/'),
 | 
				
			||||||
    'app_domain' => env('APP_DOMAIN', ''),
 | 
					    'app_domain' => env('APP_DOMAIN', ''),
 | 
				
			||||||
    'app_version' => '5.1.26',
 | 
					    'app_version' => '5.1.27',
 | 
				
			||||||
    'minimum_client_version' => '5.0.16',
 | 
					    'minimum_client_version' => '5.0.16',
 | 
				
			||||||
    'terms_version' => '1.0.1',
 | 
					    'terms_version' => '1.0.1',
 | 
				
			||||||
    'api_secret' => env('API_SECRET', false),
 | 
					    'api_secret' => env('API_SECRET', false),
 | 
				
			||||||
@ -144,4 +144,5 @@ return [
 | 
				
			|||||||
    'flutter_canvas_kit' => env('FLUTTER_CANVAS_KIT', false),
 | 
					    'flutter_canvas_kit' => env('FLUTTER_CANVAS_KIT', false),
 | 
				
			||||||
    'webcron_secret' => env('WEBCRON_SECRET', false),
 | 
					    'webcron_secret' => env('WEBCRON_SECRET', false),
 | 
				
			||||||
    'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false),
 | 
					    'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false),
 | 
				
			||||||
 | 
					    'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false),
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
 | 
					    "/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
 | 
				
			||||||
    "/css/app.css": "/css/app.css?id=745170b7d7a4dc7469f2",
 | 
					    "/css/app.css": "/css/app.css?id=e8d6d5e8cb60bc2f15b3",
 | 
				
			||||||
    "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
 | 
					    "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
 | 
				
			||||||
    "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
 | 
					    "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
 | 
				
			||||||
    "/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
 | 
					    "/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								resources/views/billing-portal/purchase.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								resources/views/billing-portal/purchase.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					@extends('portal.ninja2020.layout.clean')
 | 
				
			||||||
 | 
					@section('meta_title', $billing_subscription->product->product_key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@section('body')
 | 
				
			||||||
 | 
					    @livewire('billing-portal-purchase', ['billing_subscription' => $billing_subscription, 'contact' => auth('contact')->user(), 'hash' => $hash])
 | 
				
			||||||
 | 
					@stop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@push('footer')
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        function updateGatewayFields(companyGatewayId, paymentMethodId) {
 | 
				
			||||||
 | 
					            document.getElementById('company_gateway_id').value = companyGatewayId;
 | 
				
			||||||
 | 
					            document.getElementById('payment_method_id').value = paymentMethodId;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Livewire.on('beforePaymentEventsCompleted', () => document.getElementById('payment-method-form').submit());
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					@endpush
 | 
				
			||||||
@ -8,7 +8,9 @@
 | 
				
			|||||||
    @include('portal.ninja2020.components.general.sidebar.mobile')
 | 
					    @include('portal.ninja2020.components.general.sidebar.mobile')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Static sidebar for desktop -->
 | 
					    <!-- Static sidebar for desktop -->
 | 
				
			||||||
 | 
					    @unless(request()->query('sidebar') === 'hidden')
 | 
				
			||||||
        @include('portal.ninja2020.components.general.sidebar.desktop')
 | 
					        @include('portal.ninja2020.components.general.sidebar.desktop')
 | 
				
			||||||
 | 
					    @endunless
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="flex flex-col w-0 flex-1 overflow-hidden">
 | 
					    <div class="flex flex-col w-0 flex-1 overflow-hidden">
 | 
				
			||||||
        @include('portal.ninja2020.components.general.sidebar.header')
 | 
					        @include('portal.ninja2020.components.general.sidebar.header')
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,127 @@
 | 
				
			|||||||
 | 
					<div class="grid grid-cols-12">
 | 
				
			||||||
 | 
					    <div class="col-span-12 lg:col-span-6 bg-gray-50 shadow-lg lg:h-screen flex flex-col items-center">
 | 
				
			||||||
 | 
					        <div class="w-full p-10 lg:w-1/2 lg:mt-48 lg:p-0">
 | 
				
			||||||
 | 
					            <img class="h-8" src="{{ $billing_subscription->company->present()->logo }}"
 | 
				
			||||||
 | 
					                 alt="{{ $billing_subscription->company->present()->name }}">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <h1 id="billing-page-company-logo" class="text-3xl font-bold tracking-wide mt-8">
 | 
				
			||||||
 | 
					                {{ $billing_subscription->product->product_key }}
 | 
				
			||||||
 | 
					            </h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <p class="my-6">{{ $billing_subscription->product->notes }}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <span class="text-sm uppercase font-bold">{{ ctrans('texts.total') }}:</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <h1 class="text-2xl font-bold tracking-wide">{{ App\Utils\Number::formatMoney($billing_subscription->product->price, $billing_subscription->company) }}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @if(auth('contact')->user())
 | 
				
			||||||
 | 
					                <a href="{{ route('client.invoices.index') }}" class="block mt-16 inline-flex items-center space-x-2">
 | 
				
			||||||
 | 
					                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
 | 
				
			||||||
 | 
					                         stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
 | 
				
			||||||
 | 
					                         class="feather feather-arrow-left">
 | 
				
			||||||
 | 
					                        <line x1="19" y1="12" x2="5" y2="12"></line>
 | 
				
			||||||
 | 
					                        <polyline points="12 19 5 12 12 5"></polyline>
 | 
				
			||||||
 | 
					                    </svg>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <span>{{ ctrans('texts.client_portal') }}</span>
 | 
				
			||||||
 | 
					                </a>
 | 
				
			||||||
 | 
					            @endif
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col-span-12 lg:col-span-6 bg-white lg:shadow-lg lg:h-screen">
 | 
				
			||||||
 | 
					        <div class="grid grid-cols-12 flex flex-col p-10 lg:mt-48 lg:ml-16">
 | 
				
			||||||
 | 
					            <div class="col-span-12 w-full lg:col-span-6">
 | 
				
			||||||
 | 
					                <h2 class="text-2xl font-bold tracking-wide">{{ $heading_text }}</h2>
 | 
				
			||||||
 | 
					                @if (session()->has('message'))
 | 
				
			||||||
 | 
					                    @component('portal.ninja2020.components.message')
 | 
				
			||||||
 | 
					                        {{ session('message') }}
 | 
				
			||||||
 | 
					                    @endcomponent
 | 
				
			||||||
 | 
					                @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                @if($this->steps['fetched_payment_methods'])
 | 
				
			||||||
 | 
					                    <div class="flex items-center mt-4 text-sm">
 | 
				
			||||||
 | 
					                        <form action="{{ route('client.payments.process', ['hash' => $hash, 'sidebar' => 'hidden']) }}"
 | 
				
			||||||
 | 
					                              method="post"
 | 
				
			||||||
 | 
					                              id="payment-method-form">
 | 
				
			||||||
 | 
					                            @csrf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            @if($invoice instanceof \App\Models\Invoice)
 | 
				
			||||||
 | 
					                                <input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">
 | 
				
			||||||
 | 
					                                <input type="hidden" name="payable_invoices[0][amount]"
 | 
				
			||||||
 | 
					                                       value="{{ $invoice->partial > 0 ? \App\Utils\Number::formatValue($invoice->partial, $invoice->client->currency()) : \App\Utils\Number::formatValue($invoice->balance, $invoice->client->currency()) }}">
 | 
				
			||||||
 | 
					                                <input type="hidden" name="payable_invoices[0][invoice_id]"
 | 
				
			||||||
 | 
					                                       value="{{ $invoice->hashed_id }}">
 | 
				
			||||||
 | 
					                            @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            <input type="hidden" name="action" value="payment">
 | 
				
			||||||
 | 
					                            <input type="hidden" name="company_gateway_id" value="{{ $company_gateway_id }}"/>
 | 
				
			||||||
 | 
					                            <input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}"/>
 | 
				
			||||||
 | 
					                        </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        @foreach($this->methods as $method)
 | 
				
			||||||
 | 
					                            <button
 | 
				
			||||||
 | 
					                                wire:click="handleMethodSelectingEvent('{{ $method['company_gateway_id'] }}', '{{ $method['gateway_type_id'] }}')"
 | 
				
			||||||
 | 
					                                class="px-3 py-2 border rounded mr-4 hover:border-blue-600">
 | 
				
			||||||
 | 
					                                {{ $method['label'] }}
 | 
				
			||||||
 | 
					                            </button>
 | 
				
			||||||
 | 
					                        @endforeach
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                @else
 | 
				
			||||||
 | 
					                    <form wire:submit.prevent="authenticate" class="mt-8">
 | 
				
			||||||
 | 
					                        @csrf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        <label for="email_address">
 | 
				
			||||||
 | 
					                            <span class="input-label">{{ ctrans('texts.email_address') }}</span>
 | 
				
			||||||
 | 
					                            <input wire:model.defer="email" type="email" class="input w-full"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            @error('email')
 | 
				
			||||||
 | 
					                            <p class="validation validation-fail block w-full" role="alert">
 | 
				
			||||||
 | 
					                                {{ $message }}
 | 
				
			||||||
 | 
					                            </p>
 | 
				
			||||||
 | 
					                            @enderror
 | 
				
			||||||
 | 
					                        </label>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        @if($steps['existing_user'])
 | 
				
			||||||
 | 
					                            <label for="password" class="block mt-2">
 | 
				
			||||||
 | 
					                                <span class="input-label">{{ ctrans('texts.password') }}</span>
 | 
				
			||||||
 | 
					                                <input wire:model.defer="password" type="password" class="input w-full" autofocus/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                @error('password')
 | 
				
			||||||
 | 
					                                <p class="validation validation-fail block w-full" role="alert">
 | 
				
			||||||
 | 
					                                    {{ $message }}
 | 
				
			||||||
 | 
					                                </p>
 | 
				
			||||||
 | 
					                                @enderror
 | 
				
			||||||
 | 
					                            </label>
 | 
				
			||||||
 | 
					                        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        <button type="submit"
 | 
				
			||||||
 | 
					                                class="button button-block bg-primary text-white mt-4">{{ ctrans('texts.next') }}</button>
 | 
				
			||||||
 | 
					                    </form>
 | 
				
			||||||
 | 
					                @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div class="relative mt-8">
 | 
				
			||||||
 | 
					                    <div class="absolute inset-0 flex items-center">
 | 
				
			||||||
 | 
					                        <div class="w-full border-t border-gray-300"></div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <div class="relative flex justify-center text-sm leading-5">
 | 
				
			||||||
 | 
					                        <span class="px-2 text-gray-700 bg-white">Have a coupon code?</span>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <form wire:submit.prevent="applyCouponCode" class="mt-4">
 | 
				
			||||||
 | 
					                    @csrf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <div class="flex items-center">
 | 
				
			||||||
 | 
					                        <label class="w-full mr-2">
 | 
				
			||||||
 | 
					                            <input type="text" wire:model.defer="coupon" class="input w-full m-0" />
 | 
				
			||||||
 | 
					                        </label>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        <button class="button bg-primary m-0 text-white">{{ ctrans('texts.apply') }}</button>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </form>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
@ -63,6 +63,8 @@
 | 
				
			|||||||
        {{-- Feel free to push anything to header using @push('header') --}}
 | 
					        {{-- Feel free to push anything to header using @push('header') --}}
 | 
				
			||||||
        @stack('head')
 | 
					        @stack('head')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @livewireStyles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" />
 | 
					        <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" />
 | 
				
			||||||
    </head>
 | 
					    </head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,6 +79,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        @yield('body')
 | 
					        @yield('body')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @livewireScripts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>
 | 
					        <script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>
 | 
				
			||||||
        <script>
 | 
					        <script>
 | 
				
			||||||
            window.addEventListener("load", function(){
 | 
					            window.addEventListener("load", function(){
 | 
				
			||||||
 | 
				
			|||||||
@ -31,10 +31,13 @@
 | 
				
			|||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
                @yield('gateway_content')
 | 
					                @yield('gateway_content')
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @if(Request::isSecure())
 | 
				
			||||||
                <span class="block mx-4 mb-4 text-xs inline-flex items-center">
 | 
					                <span class="block mx-4 mb-4 text-xs inline-flex items-center">
 | 
				
			||||||
                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-green-600"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
 | 
					                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-green-600"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
 | 
				
			||||||
                    <span class="ml-1">Secure 256-bit encryption</span>
 | 
					                    <span class="ml-1">Secure 256-bit encryption</span>
 | 
				
			||||||
                </span>
 | 
					                </span>
 | 
				
			||||||
 | 
					            @endif
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@endsection
 | 
					@endsection
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,8 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence
 | 
				
			|||||||
    Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout');
 | 
					    Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout');
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Route::get('client/subscription/{billing_subscription}/purchase', 'ClientPortal\BillingSubscriptionPurchaseController@index')->name('client.subscription.purchase');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'client.'], function () {
 | 
					Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'client.'], function () {
 | 
				
			||||||
    /*Invitation catches*/
 | 
					    /*Invitation catches*/
 | 
				
			||||||
    Route::get('recurring_invoice/{invitation_key}', 'ClientPortal\InvitationController@recurringRouter');
 | 
					    Route::get('recurring_invoice/{invitation_key}', 'ClientPortal\InvitationController@recurringRouter');
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user