mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 17:57:33 -04:00 
			
		
		
		
	Merge pull request #6626 from turbo124/v5-develop
Approve Quote Webhook
This commit is contained in:
		
						commit
						cad16eb629
					
				
							
								
								
									
										24
									
								
								app/Exceptions/SystemError.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Exceptions/SystemError.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace App\Exceptions; | ||||||
|  | 
 | ||||||
|  | use Exception; | ||||||
|  | 
 | ||||||
|  | class SystemError extends Exception | ||||||
|  | { | ||||||
|  |     public function report() | ||||||
|  |     { | ||||||
|  |         // ..
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function render($request) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         return view('errors.guest', [ | ||||||
|  |             'message' => $this->getMessage(), | ||||||
|  |             'code' => $this->getCode(), | ||||||
|  |         ]); | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -35,7 +35,7 @@ class NinjaPlanController extends Controller | |||||||
| 
 | 
 | ||||||
|         $account = $company->account; |         $account = $company->account; | ||||||
| 
 | 
 | ||||||
|         if (Ninja::isHosted() && MultiDB::findAndSetDbByContactKey($contact_key) && $client_contact = ClientContact::where('contact_key', $contact_key)->first()) |         if (MultiDB::findAndSetDbByContactKey($contact_key) && $client_contact = ClientContact::where('contact_key', $contact_key)->first()) | ||||||
|         {             |         {             | ||||||
|          |          | ||||||
|             nlog("Ninja Plan Controller - Found and set Client Contact"); |             nlog("Ninja Plan Controller - Found and set Client Contact"); | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ use App\DataMapper\Analytics\AccountDeleted; | |||||||
| use App\DataMapper\CompanySettings; | use App\DataMapper\CompanySettings; | ||||||
| use App\DataMapper\DefaultSettings; | use App\DataMapper\DefaultSettings; | ||||||
| use App\Http\Requests\Company\CreateCompanyRequest; | use App\Http\Requests\Company\CreateCompanyRequest; | ||||||
|  | use App\Http\Requests\Company\DefaultCompanyRequest; | ||||||
| use App\Http\Requests\Company\DestroyCompanyRequest; | use App\Http\Requests\Company\DestroyCompanyRequest; | ||||||
| use App\Http\Requests\Company\EditCompanyRequest; | use App\Http\Requests\Company\EditCompanyRequest; | ||||||
| use App\Http\Requests\Company\ShowCompanyRequest; | use App\Http\Requests\Company\ShowCompanyRequest; | ||||||
| @ -598,8 +599,66 @@ class CompanyController extends BaseController | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // public function default(DefaultCompanyRequest $request, Company $company)
 | /** | ||||||
|     // {
 |      * Update the specified resource in storage. | ||||||
|          |      * | ||||||
|     // }
 |      * @param UploadCompanyRequest $request | ||||||
|  |      * @param Company $client | ||||||
|  |      * @return Response | ||||||
|  |      * | ||||||
|  |      * | ||||||
|  |      * | ||||||
|  |      * @OA\Post( | ||||||
|  |      *      path="/api/v1/companies/{company}/default", | ||||||
|  |      *      operationId="setDefaultCompany", | ||||||
|  |      *      tags={"companies"}, | ||||||
|  |      *      summary="Sets the company as the default company.", | ||||||
|  |      *      description="Sets the company as the default company.", | ||||||
|  |      *      @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), | ||||||
|  |      *      @OA\Parameter(ref="#/components/parameters/X-Api-Token"), | ||||||
|  |      *      @OA\Parameter(ref="#/components/parameters/X-Requested-With"), | ||||||
|  |      *      @OA\Parameter(ref="#/components/parameters/include"), | ||||||
|  |      *      @OA\Parameter( | ||||||
|  |      *          name="company", | ||||||
|  |      *          in="path", | ||||||
|  |      *          description="The Company Hashed ID", | ||||||
|  |      *          example="D2J234DFA", | ||||||
|  |      *          required=true, | ||||||
|  |      *          @OA\Schema( | ||||||
|  |      *              type="string", | ||||||
|  |      *              format="string", | ||||||
|  |      *          ), | ||||||
|  |      *      ), | ||||||
|  |      *      @OA\Response( | ||||||
|  |      *          response=200, | ||||||
|  |      *          description="Returns the company object", | ||||||
|  |      *          @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), | ||||||
|  |      *          @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), | ||||||
|  |      *          @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), | ||||||
|  |      *          @OA\JsonContent(ref="#/components/schemas/Company"), | ||||||
|  |      *       ), | ||||||
|  |      *       @OA\Response( | ||||||
|  |      *          response=422, | ||||||
|  |      *          description="Validation error", | ||||||
|  |      *          @OA\JsonContent(ref="#/components/schemas/ValidationError"), | ||||||
|  |      * | ||||||
|  |      *       ), | ||||||
|  |      *       @OA\Response( | ||||||
|  |      *           response="default", | ||||||
|  |      *           description="Unexpected Error", | ||||||
|  |      *           @OA\JsonContent(ref="#/components/schemas/Error"), | ||||||
|  |      *       ), | ||||||
|  |      *     ) | ||||||
|  |      */ | ||||||
|  |     public function default(DefaultCompanyRequest $request, Company $company) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $account = $company->account; | ||||||
|  |         $account->default_company_id = $company->id; | ||||||
|  |         $account->save();   | ||||||
|  | 
 | ||||||
|  |         return $this->itemResponse($company->fresh()); | ||||||
|  |        | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ | |||||||
| namespace App\Http\Controllers; | namespace App\Http\Controllers; | ||||||
| 
 | 
 | ||||||
| use App\DataMapper\FeesAndLimits; | use App\DataMapper\FeesAndLimits; | ||||||
|  | use App\Exceptions\SystemError; | ||||||
| use App\Factory\CompanyGatewayFactory; | use App\Factory\CompanyGatewayFactory; | ||||||
| use App\Http\Requests\StripeConnect\InitializeStripeConnectRequest; | use App\Http\Requests\StripeConnect\InitializeStripeConnectRequest; | ||||||
| use App\Libraries\MultiDB; | use App\Libraries\MultiDB; | ||||||
| @ -20,6 +21,7 @@ use App\Models\Company; | |||||||
| use App\Models\CompanyGateway; | use App\Models\CompanyGateway; | ||||||
| use App\Models\GatewayType; | use App\Models\GatewayType; | ||||||
| use App\PaymentDrivers\Stripe\Connect\Account; | use App\PaymentDrivers\Stripe\Connect\Account; | ||||||
|  | use Exception; | ||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| use Stripe\Exception\ApiErrorException; | use Stripe\Exception\ApiErrorException; | ||||||
| 
 | 
 | ||||||
| @ -78,7 +80,7 @@ class StripeConnectController extends BaseController | |||||||
|         { |         { | ||||||
|              |              | ||||||
|             nlog($e->getMessage()); |             nlog($e->getMessage()); | ||||||
|          |             throw new SystemError($e->getMessage(), 500); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); |         MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								app/Http/Requests/Company/DefaultCompanyRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Http/Requests/Company/DefaultCompanyRequest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | <?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://www.elastic.co/licensing/elastic-license | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | namespace App\Http\Requests\Company; | ||||||
|  | 
 | ||||||
|  | use App\Http\Requests\Request; | ||||||
|  | 
 | ||||||
|  | class DefaultCompanyRequest extends Request | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Determine if the user is authorized to make this request. | ||||||
|  |      * | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function authorize() : bool | ||||||
|  |     { | ||||||
|  |         return auth()->user()->isAdmin() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function rules() | ||||||
|  |     { | ||||||
|  |     	 | ||||||
|  |     	$rules = []; | ||||||
|  | 
 | ||||||
|  |     	return $rules; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -233,7 +233,7 @@ class Import implements ShouldQueue | |||||||
|         $account->save(); |         $account->save(); | ||||||
| 
 | 
 | ||||||
|         //company size check
 |         //company size check
 | ||||||
|         if ($this->company->invoices()->count() > 1000 || $this->company->products()->count() > 1000 || $this->company->clients()->count() > 1000) { |         if ($this->company->invoices()->count() > 500 || $this->company->products()->count() > 500 || $this->company->clients()->count() > 500) { | ||||||
|             $this->company->is_large = true; |             $this->company->is_large = true; | ||||||
|             $this->company->save(); |             $this->company->save(); | ||||||
|         } |         } | ||||||
| @ -261,9 +261,6 @@ class Import implements ShouldQueue | |||||||
|          |          | ||||||
|         /*After a migration first some basic jobs to ensure the system is up to date*/ |         /*After a migration first some basic jobs to ensure the system is up to date*/ | ||||||
|         VersionCheck::dispatch(); |         VersionCheck::dispatch(); | ||||||
|          |  | ||||||
|         // CreateCompanyPaymentTerms::dispatchNow($sp035a66, $spaa9f78);
 |  | ||||||
|         // CreateCompanyTaskStatuses::dispatchNow($this->company, $this->user);
 |  | ||||||
| 
 | 
 | ||||||
|         info('Completed🚀🚀🚀🚀🚀 at '.now()); |         info('Completed🚀🚀🚀🚀🚀 at '.now()); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										47
									
								
								app/Listeners/Quote/QuoteApprovedWebhook.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/Listeners/Quote/QuoteApprovedWebhook.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Quote Ninja (https://quoteninja.com). | ||||||
|  |  * | ||||||
|  |  * @link https://github.com/quoteninja/quoteninja source repository | ||||||
|  |  * | ||||||
|  |  * @copyright Copyright (c) 2021. Quote Ninja LLC (https://quoteninja.com) | ||||||
|  |  * | ||||||
|  |  * @license https://www.elastic.co/licensing/elastic-license | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | namespace App\Listeners\Quote; | ||||||
|  | 
 | ||||||
|  | use App\Jobs\Util\WebhookHandler; | ||||||
|  | use App\Libraries\MultiDB; | ||||||
|  | use App\Models\Webhook; | ||||||
|  | use Illuminate\Contracts\Queue\ShouldQueue; | ||||||
|  | 
 | ||||||
|  | class QuoteApprovedWebhook implements ShouldQueue | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     public function __construct() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Handle the event. | ||||||
|  |      * | ||||||
|  |      * @param  object  $event | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function handle($event) | ||||||
|  |     { | ||||||
|  |         MultiDB::setDb($event->company->db); | ||||||
|  | 
 | ||||||
|  |         $quote = $event->quote; | ||||||
|  | 
 | ||||||
|  |         $subscriptions = Webhook::where('company_id', $quote->company_id) | ||||||
|  |                         ->where('event_id', Webhook::EVENT_APPROVE_QUOTE) | ||||||
|  |                         ->exists(); | ||||||
|  | 
 | ||||||
|  |         if ($subscriptions) { | ||||||
|  |             WebhookHandler::dispatch(Webhook::EVENT_APPROVE_QUOTE, $quote, $quote->company); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -123,7 +123,7 @@ class TemplateEmail extends Mailable | |||||||
| 
 | 
 | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         if($this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_DOCUMENTS)){ |         if($this->invitation && $this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_DOCUMENTS)){ | ||||||
| 
 | 
 | ||||||
|             $ubl_string = CreateUbl::dispatchNow($this->invitation->invoice); |             $ubl_string = CreateUbl::dispatchNow($this->invitation->invoice); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -161,6 +161,7 @@ use App\Listeners\Payment\PaymentEmailedActivity; | |||||||
| use App\Listeners\Payment\PaymentNotification; | use App\Listeners\Payment\PaymentNotification; | ||||||
| use App\Listeners\Payment\PaymentRestoredActivity; | use App\Listeners\Payment\PaymentRestoredActivity; | ||||||
| use App\Listeners\Quote\QuoteApprovedActivity; | use App\Listeners\Quote\QuoteApprovedActivity; | ||||||
|  | use App\Listeners\Quote\QuoteApprovedWebhook; | ||||||
| use App\Listeners\Quote\QuoteArchivedActivity; | use App\Listeners\Quote\QuoteArchivedActivity; | ||||||
| use App\Listeners\Quote\QuoteCreatedNotification; | use App\Listeners\Quote\QuoteCreatedNotification; | ||||||
| use App\Listeners\Quote\QuoteDeletedActivity; | use App\Listeners\Quote\QuoteDeletedActivity; | ||||||
| @ -385,6 +386,7 @@ class EventServiceProvider extends ServiceProvider | |||||||
|         QuoteWasApproved::class => [ |         QuoteWasApproved::class => [ | ||||||
|             ReachWorkflowSettings::class, |             ReachWorkflowSettings::class, | ||||||
|             QuoteApprovedActivity::class, |             QuoteApprovedActivity::class, | ||||||
|  |             QuoteApprovedWebhook::class, | ||||||
|         ], |         ], | ||||||
|         QuoteWasCreated::class => [ |         QuoteWasCreated::class => [ | ||||||
|             CreatedQuoteActivity::class, |             CreatedQuoteActivity::class, | ||||||
|  | |||||||
| @ -40,7 +40,7 @@ | |||||||
|         "coconutcraig/laravel-postmark": "^2.10", |         "coconutcraig/laravel-postmark": "^2.10", | ||||||
|         "codedge/laravel-selfupdater": "^3.2", |         "codedge/laravel-selfupdater": "^3.2", | ||||||
|         "composer/composer": "^2", |         "composer/composer": "^2", | ||||||
|         "doctrine/dbal": "^2.10", |         "doctrine/dbal": "^3.0", | ||||||
|         "eway/eway-rapid-php": "^1.3", |         "eway/eway-rapid-php": "^1.3", | ||||||
|         "fakerphp/faker": "^1.14", |         "fakerphp/faker": "^1.14", | ||||||
|         "fideloper/proxy": "^4.2", |         "fideloper/proxy": "^4.2", | ||||||
|  | |||||||
							
								
								
									
										722
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										722
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -15,7 +15,7 @@ input:checked ~ .dot { | |||||||
|   background-color: #48bb78;
 |   background-color: #48bb78;
 | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
| <div class="container flex flex-wrap pt-4 pb-10 m-auto mt-6 md:mt-15 lg:px-12 xl:px-16" x-data="{show: true}"> | <div id="datadiv" class="container flex flex-wrap pt-2 pb-10 m-auto mt-2 md:mt-5 lg:px-16 xl:px-16" x-data="{show: true}"> | ||||||
|     <div class="w-full px-0 lg:px-4"> |     <div class="w-full px-0 lg:px-4"> | ||||||
|       <h2 class="px-12 text-base font-bold text-center md:text-2xl text-blue-700"> |       <h2 class="px-12 text-base font-bold text-center md:text-2xl text-blue-700"> | ||||||
|         Choose your plan |         Choose your plan | ||||||
| @ -61,14 +61,28 @@ input:checked ~ .dot { | |||||||
|               <p class="text-xs text-center uppercase text-white"> |               <p class="text-xs text-center uppercase text-white"> | ||||||
|                 monthly |                 monthly | ||||||
|               </p> |               </p> | ||||||
|  | 
 | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Unlimited clients, invoices, quotes, recurring invoices</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">10 professional invoice & quote template designs</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Remove "Created by Invoice Ninja" from invoices</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Enable emails to be sent via Gmail</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Integrate with Zapier, Integromat or API</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">+ Much more!</div> | ||||||
|  | 
 | ||||||
|             </div> |             </div> | ||||||
|  | 
 | ||||||
|             <div class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700"> |             <div class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700"> | ||||||
|               <p class="text-xl text-white"> |               <p class="text-xl text-white"> | ||||||
|                 Sign up! |                 Single User | ||||||
|               </p> |               </p> | ||||||
|               <a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/WJxbojagwO/purchase"> |               <button id="handleProMonthlyClick" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500"> | ||||||
|                 Purchase |                 Purchase | ||||||
|               </a> |               </button> | ||||||
|             </div> |             </div> | ||||||
|           </label> |           </label> | ||||||
|         </div> |         </div> | ||||||
| @ -78,33 +92,46 @@ input:checked ~ .dot { | |||||||
|           <label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl"> |           <label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl"> | ||||||
|             <div class="w-full px-4 py-8 rounded-t-lg bg-blue-500"> |             <div class="w-full px-4 py-8 rounded-t-lg bg-blue-500"> | ||||||
|               <h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white"> |               <h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white"> | ||||||
|                 Enterprise (1-2 Users) |                 Enterprise Plan | ||||||
|               </h3> |               </h3> | ||||||
|               <p class="text-5xl font-bold text-center text-white"> |               <p class="text-5xl font-bold text-center text-white" id="m_plan_price"> | ||||||
|                 $14 |                 $14 | ||||||
|               </p> |               </p> | ||||||
|               <p class="text-xs text-center uppercase text-white"> |               <p class="text-xs text-center uppercase text-white"> | ||||||
|                 monthly |                 monthly | ||||||
|               </p> |               </p> | ||||||
|  | 
 | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Multiple users and advanced permissions per user</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Attach documents to emails & client side portal!</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Branded client portal: "https://billing.yourcompany.com"</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Custom background for invoices & quotes</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Integrate with Zapier, Integromat or API</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">+ Much more!</div> | ||||||
|  | 
 | ||||||
|             </div> |             </div> | ||||||
|             <div class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700"> |             <div class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700"> | ||||||
|               <p class="text-xl text-white"> |               <p class="text-xl text-white"> | ||||||
|                 Sign up! |                 <select id="users_monthly" class="bg-white text-black appearance-none border-none inline-block py-0 pl-3 pr-2 rounded leading-tight w-full"> | ||||||
|  |                   <option value="7LDdwRb1YK" selected>1-2 Users</option> | ||||||
|  |                   <option value="MVyb8mdvAZ">3-5 Users</option> | ||||||
|  |                   <option value="WpmbkR5azJ">6-10 Users</option> | ||||||
|  |                   <option value="k8mepY2aMy">11-20 Users</option> | ||||||
|  |                 </select> | ||||||
|               </p> |               </p> | ||||||
|               <a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/7LDdwRb1YK/purchase"> |               <button id="handleMonthlyClick" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500"> | ||||||
|                 Purchase |                 Purchase | ||||||
|               </a> |               </button> | ||||||
|             </div> |             </div> | ||||||
|           </label> |           </label> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|       <!-- Annual Plans --> |       <!-- Annual Plans --> | ||||||
|       <div class="flex flex-wrap items-center justify-center py-4 pt-0" x-show=" !show "> |       <div class="flex flex-wrap items-center justify-center py-4 pt-0" x-show=" !show "> | ||||||
|         <div class="w-full p-4 md:w-1/2 lg:w-1/2"> |         <div class="w-full p-4 md:w-1/2 lg:w-1/2"> | ||||||
| @ -119,6 +146,19 @@ input:checked ~ .dot { | |||||||
|               <p class="text-xs text-center uppercase text-white"> |               <p class="text-xs text-center uppercase text-white"> | ||||||
|                 yearly |                 yearly | ||||||
|               </p> |               </p> | ||||||
|  | 
 | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Unlimited clients, invoices, quotes, recurring invoices</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">10 professional invoice & quote template designs</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Remove "Created by Invoice Ninja" from invoices</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Enable emails to be sent via Gmail</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Integrate with Zapier, Integromat or API</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">+ Much more!</div> | ||||||
|  | 
 | ||||||
|             </div> |             </div> | ||||||
|             <div |             <div | ||||||
|               class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700" |               class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700" | ||||||
| @ -126,9 +166,9 @@ input:checked ~ .dot { | |||||||
|               <p class="text-xl text-white"> |               <p class="text-xl text-white"> | ||||||
|                 Buy 10 months get 2 free! |                 Buy 10 months get 2 free! | ||||||
|               </p> |               </p> | ||||||
|                 <a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/q9wdL9wejP/purchase"> |                 <button id="handleProYearlyClick" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500"> | ||||||
|                 Purchase |                 Purchase | ||||||
|               </a> |               </button> | ||||||
|             </div> |             </div> | ||||||
|           </label> |           </label> | ||||||
|         </div> |         </div> | ||||||
| @ -137,24 +177,42 @@ input:checked ~ .dot { | |||||||
|           <label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl"> |           <label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl"> | ||||||
|             <div class="w-full px-4 py-8 rounded-t-lg bg-blue-500"> |             <div class="w-full px-4 py-8 rounded-t-lg bg-blue-500"> | ||||||
|               <h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white"> |               <h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white"> | ||||||
|                 Enterprise (1-2 Users) |                 Enterprise Plan | ||||||
|               </h3> |               </h3> | ||||||
|               <p class="text-5xl font-bold text-center text-white"> |               <p class="text-5xl font-bold text-center text-white" id="y_plan_price"> | ||||||
|                 $140 |                 $140 | ||||||
|               </p> |               </p> | ||||||
|               <p class="text-xs text-center uppercase text-white"> |               <p class="text-xs text-center uppercase text-white"> | ||||||
|                 yearly |                 yearly | ||||||
|               </p> |               </p> | ||||||
|  | 
 | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Multiple users and advanced permissions per user</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Attach documents to emails & client side portal!</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Branded client portal: "https://billing.yourcompany.com"</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Custom background for invoices & quotes</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">Integrate with Zapier, Integromat or API</div> | ||||||
|  |               <hr> | ||||||
|  |               <div class="py-2 text-sm my-3 text-white">+ Much more!</div> | ||||||
|  | 
 | ||||||
|             </div> |             </div> | ||||||
|             <div |             <div | ||||||
|               class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700" |               class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700" | ||||||
|             > |             > | ||||||
|               <p class="text-xl text-white"> |               <p class="text-xl text-white"> | ||||||
|                 Buy 10 months get 2 free! |                 <select id="users_yearly" class="bg-white text-black appearance-none border-none inline-block py-0 pl-3 pr-2 rounded leading-tight w-full"> | ||||||
|  |                   <option value="LYqaQWldnj" selected>1-2 Users</option> | ||||||
|  |                   <option value="kQBeX6mbyK">3-5 Users</option> | ||||||
|  |                   <option value="GELe32Qd69">6-10 Users</option> | ||||||
|  |                   <option value="MVyb86oevA">11-20 Users</option> | ||||||
|  |                 </select> | ||||||
|               </p> |               </p> | ||||||
|                 <a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/LYqaQWldnj/purchase"> |               <button id="handleYearlyClick" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" > | ||||||
|                 Purchase |                 Purchase | ||||||
|               </a> |               </button> | ||||||
|             </div> |             </div> | ||||||
|           </label> |           </label> | ||||||
|         </div> |         </div> | ||||||
| @ -167,5 +225,68 @@ input:checked ~ .dot { | |||||||
| 
 | 
 | ||||||
| @push('footer') | @push('footer') | ||||||
| 
 | 
 | ||||||
|  | <script type="text/javascript"> | ||||||
|  | 
 | ||||||
|  | var users_yearly = 'LYqaQWldnj'; | ||||||
|  | var users_monthly = '7LDdwRb1YK'; | ||||||
|  | 
 | ||||||
|  | document.getElementById('users_yearly').options[0].selected = true; | ||||||
|  | document.getElementById('users_monthly').options[0].selected = true; | ||||||
|  | 
 | ||||||
|  | document.getElementById("toggleB").addEventListener('change', function() { | ||||||
|  | 
 | ||||||
|  |   document.getElementById('users_yearly').options[0].selected = true; | ||||||
|  |   document.getElementById('users_monthly').options[0].selected = true; | ||||||
|  |   document.getElementById('y_plan_price').innerHTML = price_map.get('LYqaQWldnj'); | ||||||
|  |   document.getElementById('m_plan_price').innerHTML = price_map.get('7LDdwRb1YK'); | ||||||
|  | 
 | ||||||
|  |   users_yearly = 'LYqaQWldnj'; | ||||||
|  |   users_monthly = '7LDdwRb1YK'; | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | document.getElementById('users_yearly').addEventListener('change', function() { | ||||||
|  |   users_yearly = this.value; | ||||||
|  |   document.getElementById('y_plan_price').innerHTML = price_map.get(this.value); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | document.getElementById('users_monthly').addEventListener('change', function() { | ||||||
|  |   users_monthly = this.value; | ||||||
|  |   document.getElementById('m_plan_price').innerHTML = price_map.get(this.value); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | document.getElementById('handleYearlyClick').addEventListener('click', function() { | ||||||
|  |   document.getElementById("toggleB").checked = false; | ||||||
|  |   location.href = 'https://invoiceninja.invoicing.co/client/subscriptions/' + users_yearly + '/purchase'; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | document.getElementById('handleMonthlyClick').addEventListener('click', function() { | ||||||
|  |   document.getElementById("toggleB").checked = false; | ||||||
|  |   location.href = 'https://invoiceninja.invoicing.co/client/subscriptions/' + users_monthly + '/purchase'; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | document.getElementById('handleProMonthlyClick').addEventListener('click', function() { | ||||||
|  |   document.getElementById("toggleB").checked = false; | ||||||
|  |   location.href = 'https://invoiceninja.invoicing.co/client/subscriptions/WJxbojagwO/purchase'; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | document.getElementById('handleProYearlyClick').addEventListener('click', function() { | ||||||
|  |   document.getElementById("toggleB").checked = false; | ||||||
|  |   location.href = 'https://invoiceninja.invoicing.co/client/subscriptions/q9wdL9wejP/purchase'; | ||||||
|  | }); | ||||||
|  | const price_map = new Map(); | ||||||
|  | //monthly
 | ||||||
|  | price_map.set('7LDdwRb1YK', '$14'); | ||||||
|  | price_map.set('MVyb8mdvAZ', '$26'); | ||||||
|  | price_map.set('WpmbkR5azJ', '$36'); | ||||||
|  | price_map.set('k8mepY2aMy', '$44'); | ||||||
|  | //yearly
 | ||||||
|  | price_map.set('LYqaQWldnj', '$140'); | ||||||
|  | price_map.set('kQBeX6mbyK', '$260'); | ||||||
|  | price_map.set('GELe32Qd69', '$360'); | ||||||
|  | price_map.set('MVyb86oevA', '$440'); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
| 
 | 
 | ||||||
| @endpush | @endpush | ||||||
|  | |||||||
| @ -51,6 +51,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a | |||||||
|     Route::resource('companies', 'CompanyController'); // name = (companies. index / create / show / update / destroy / edit
 |     Route::resource('companies', 'CompanyController'); // name = (companies. index / create / show / update / destroy / edit
 | ||||||
|      |      | ||||||
|     Route::put('companies/{company}/upload', 'CompanyController@upload'); |     Route::put('companies/{company}/upload', 'CompanyController@upload'); | ||||||
|  |     Route::post('companies/{company}/default', 'CompanyController@default'); | ||||||
| 
 | 
 | ||||||
|     Route::get('company_ledger', 'CompanyLedgerController@index')->name('company_ledger.index'); |     Route::get('company_ledger', 'CompanyLedgerController@index')->name('company_ledger.index'); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -98,7 +98,7 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie | |||||||
|     Route::get('quote/{invitation_key}/download_pdf', 'QuoteController@downloadPdf')->name('quote.download_invitation_key'); |     Route::get('quote/{invitation_key}/download_pdf', 'QuoteController@downloadPdf')->name('quote.download_invitation_key'); | ||||||
|     Route::get('credit/{invitation_key}/download_pdf', 'CreditController@downloadPdf')->name('credit.download_invitation_key'); |     Route::get('credit/{invitation_key}/download_pdf', 'CreditController@downloadPdf')->name('credit.download_invitation_key'); | ||||||
|     Route::get('{entity}/{invitation_key}/download', 'ClientPortal\InvitationController@routerForDownload'); |     Route::get('{entity}/{invitation_key}/download', 'ClientPortal\InvitationController@routerForDownload'); | ||||||
|     Route::get('{entity}/{client_hash}/{invitation_key}', 'ClientPortal\InvitationController@routerForIframe')->name('invoice.client_hash_and_invitation_key'); //should never need this
 |     // Route::get('{entity}/{client_hash}/{invitation_key}', 'ClientPortal\InvitationController@routerForIframe')->name('invoice.client_hash_and_invitation_key'); //should never need this
 | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user