mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-04 04:07:32 -05:00 
			
		
		
		
	
						commit
						7791110bac
					
				@ -1 +1 @@
 | 
				
			|||||||
5.3.41
 | 
					5.3.42
 | 
				
			||||||
							
								
								
									
										103
									
								
								app/Http/Controllers/ClientPortal/ApplePayDomainController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								app/Http/Controllers/ClientPortal/ApplePayDomainController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					<?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\Controllers\ClientPortal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
 | 
					use App\Models\Company;
 | 
				
			||||||
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ApplePayDomainController extends Controller
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private array $stripe_keys = ['d14dd26a47cecc30fdd65700bfb67b34', 'd14dd26a37cecc30fdd65700bfb55b23'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function showAppleMerchantId(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Self Host */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(Ninja::isSelfHost()){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $cgs = CompanyGateway::whereIn('gateway_key', $this->stripe_keys)
 | 
				
			||||||
 | 
					                                 ->where('is_deleted', false)
 | 
				
			||||||
 | 
					                                 ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach($cgs as $cg)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if($cg->getConfigField('appleDomainVerification')){
 | 
				
			||||||
 | 
					                   return response($cg->getConfigField('appleDomainVerification'),200);
 | 
				
			||||||
 | 
					                                    
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return response('', 400);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Hosted */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain_name = $request->getHost();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (strpos($domain_name, 'invoicing.co') !== false) 
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            $subdomain = explode('.', $domain_name)[0];
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            $query = [
 | 
				
			||||||
 | 
					                'subdomain' => $subdomain,
 | 
				
			||||||
 | 
					                'portal_mode' => 'subdomain',
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if($company = MultiDB::findAndSetDbByDomain($query)){
 | 
				
			||||||
 | 
					               return $this->resolveAppleMerchantId($company);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       $query = [
 | 
				
			||||||
 | 
					            'portal_domain' => $request->getSchemeAndHttpHost(),
 | 
				
			||||||
 | 
					            'portal_mode' => 'domain',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($company = MultiDB::findAndSetDbByDomain($query)){
 | 
				
			||||||
 | 
					            return $this->resolveAppleMerchantId($company);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response('', 400);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function resolveAppleMerchantId($company)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $cgs = $company->company_gateways()
 | 
				
			||||||
 | 
					                       ->whereIn('gateway_key', $this->stripe_keys)
 | 
				
			||||||
 | 
					                       ->where('is_deleted', false)
 | 
				
			||||||
 | 
					                       ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach($cgs as $cg)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if($cg->getConfigField('appleDomainVerification')){
 | 
				
			||||||
 | 
					               return response($cg->getConfigField('appleDomainVerification'),200);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response('', 400);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,13 @@
 | 
				
			|||||||
<?php
 | 
					<?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\Controllers\ClientPortal;
 | 
					namespace App\Http\Controllers\ClientPortal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,7 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
 | 
				
			|||||||
use ZipStream\Option\Archive;
 | 
					use ZipStream\Option\Archive;
 | 
				
			||||||
use ZipStream\ZipStream;
 | 
					use ZipStream\ZipStream;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use Illuminate\Support\Carbon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QuoteController extends Controller
 | 
					class QuoteController extends Controller
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -55,6 +56,8 @@ class QuoteController extends Controller
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function show(ShowQuoteRequest $request, Quote $quote)
 | 
					    public function show(ShowQuoteRequest $request, Quote $quote)
 | 
				
			||||||
    {   
 | 
					    {   
 | 
				
			||||||
 | 
					        /* If the quote is expired, convert the status here */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
            'quote' => $quote,
 | 
					            'quote' => $quote,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ use App\Http\Requests\CompanyGateway\EditCompanyGatewayRequest;
 | 
				
			|||||||
use App\Http\Requests\CompanyGateway\ShowCompanyGatewayRequest;
 | 
					use App\Http\Requests\CompanyGateway\ShowCompanyGatewayRequest;
 | 
				
			||||||
use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest;
 | 
					use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest;
 | 
				
			||||||
use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
 | 
					use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
 | 
				
			||||||
 | 
					use App\Jobs\Util\ApplePayDomain;
 | 
				
			||||||
use App\Models\Client;
 | 
					use App\Models\Client;
 | 
				
			||||||
use App\Models\CompanyGateway;
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
use App\Repositories\CompanyRepository;
 | 
					use App\Repositories\CompanyRepository;
 | 
				
			||||||
@ -45,6 +46,9 @@ class CompanyGatewayController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $forced_includes = [];
 | 
					    public $forced_includes = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private array $stripe_keys = ['d14dd26a47cecc30fdd65700bfb67b34', 'd14dd26a37cecc30fdd65700bfb55b23'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * CompanyGatewayController constructor.
 | 
					     * CompanyGatewayController constructor.
 | 
				
			||||||
     * @param CompanyRepository $company_repo
 | 
					     * @param CompanyRepository $company_repo
 | 
				
			||||||
@ -206,6 +210,8 @@ class CompanyGatewayController extends BaseController
 | 
				
			|||||||
            $company_gateway->save();
 | 
					            $company_gateway->save();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->itemResponse($company_gateway);
 | 
					        return $this->itemResponse($company_gateway);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -379,6 +385,8 @@ class CompanyGatewayController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $company_gateway->save();
 | 
					        $company_gateway->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->itemResponse($company_gateway);
 | 
					        return $this->itemResponse($company_gateway);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -304,6 +304,7 @@ class MigrationController extends BaseController
 | 
				
			|||||||
            App::forgetInstance('translator');
 | 
					            App::forgetInstance('translator');
 | 
				
			||||||
            $t = app('translator');
 | 
					            $t = app('translator');
 | 
				
			||||||
            $t->replace(Ninja::transformTranslations($user->account->companies()->first()->settings));
 | 
					            $t->replace(Ninja::transformTranslations($user->account->companies()->first()->settings));
 | 
				
			||||||
 | 
					            App::setLocale($user->account->companies()->first()->getLocale());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!$existing_company && $company_count >=10) {
 | 
					            if(!$existing_company && $company_count >=10) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,8 @@ use App\Models\InvoiceInvitation;
 | 
				
			|||||||
use App\Models\QuoteInvitation;
 | 
					use App\Models\QuoteInvitation;
 | 
				
			||||||
use App\Models\RecurringInvoiceInvitation;
 | 
					use App\Models\RecurringInvoiceInvitation;
 | 
				
			||||||
use App\Models\SystemLog;
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
 | 
					use App\Notifications\Ninja\EmailBounceNotification;
 | 
				
			||||||
 | 
					use App\Notifications\Ninja\EmailSpamNotification;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
use Turbo124\Beacon\Facades\LightLogs;
 | 
					use Turbo124\Beacon\Facades\LightLogs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -173,6 +175,10 @@ class PostMarkController extends BaseController
 | 
				
			|||||||
        LightLogs::create($bounce)->queue();
 | 
					        LightLogs::create($bounce)->queue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
 | 
					        SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(config('ninja.notification.slack'))
 | 
				
			||||||
 | 
					            $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// {
 | 
					// {
 | 
				
			||||||
@ -215,6 +221,10 @@ class PostMarkController extends BaseController
 | 
				
			|||||||
        LightLogs::create($spam)->queue();
 | 
					        LightLogs::create($spam)->queue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
 | 
					        SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(config('ninja.notification.slack'))
 | 
				
			||||||
 | 
					            $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function discoverInvitation($message_id)
 | 
					    private function discoverInvitation($message_id)
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@ use App\Http\Requests\Token\StoreTokenRequest;
 | 
				
			|||||||
use App\Http\Requests\Token\UpdateTokenRequest;
 | 
					use App\Http\Requests\Token\UpdateTokenRequest;
 | 
				
			||||||
use App\Models\CompanyToken;
 | 
					use App\Models\CompanyToken;
 | 
				
			||||||
use App\Repositories\TokenRepository;
 | 
					use App\Repositories\TokenRepository;
 | 
				
			||||||
 | 
					use App\Transformers\CompanyTokenHashedTransformer;
 | 
				
			||||||
use App\Transformers\CompanyTokenTransformer;
 | 
					use App\Transformers\CompanyTokenTransformer;
 | 
				
			||||||
use App\Utils\Traits\ChecksEntityStatus;
 | 
					use App\Utils\Traits\ChecksEntityStatus;
 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
@ -93,6 +94,8 @@ class TokenController extends BaseController
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function index(TokenFilters $filters)
 | 
					    public function index(TokenFilters $filters)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $this->entity_transformer = CompanyTokenHashedTransformer::class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $tokens = CompanyToken::filter($filters);
 | 
					        $tokens = CompanyToken::filter($filters);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->listResponse($tokens);
 | 
					        return $this->listResponse($tokens);
 | 
				
			||||||
@ -205,6 +208,8 @@ class TokenController extends BaseController
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function edit(EditTokenRequest $request, CompanyToken $token)
 | 
					    public function edit(EditTokenRequest $request, CompanyToken $token)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $this->entity_transformer = CompanyTokenHashedTransformer::class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->itemResponse($token);
 | 
					        return $this->itemResponse($token);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -265,6 +270,8 @@ class TokenController extends BaseController
 | 
				
			|||||||
            return $request->disallowUpdate();
 | 
					            return $request->disallowUpdate();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->entity_transformer = CompanyTokenHashedTransformer::class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $token = $this->token_repo->save($request->all(), $token);
 | 
					        $token = $this->token_repo->save($request->all(), $token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->itemResponse($token->fresh());
 | 
					        return $this->itemResponse($token->fresh());
 | 
				
			||||||
@ -419,6 +426,8 @@ class TokenController extends BaseController
 | 
				
			|||||||
        //may not need these destroy routes as we are using actions to 'archive/delete'
 | 
					        //may not need these destroy routes as we are using actions to 'archive/delete'
 | 
				
			||||||
        $token->delete();
 | 
					        $token->delete();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->entity_transformer = CompanyTokenHashedTransformer::class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->itemResponse($token);
 | 
					        return $this->itemResponse($token);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -475,6 +484,9 @@ class TokenController extends BaseController
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function bulk()
 | 
					    public function bulk()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->entity_transformer = CompanyTokenHashedTransformer::class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $action = request()->input('action');
 | 
					        $action = request()->input('action');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $ids = request()->input('ids');
 | 
					        $ids = request()->input('ids');
 | 
				
			||||||
 | 
				
			|||||||
@ -42,13 +42,45 @@ class QuotesTable extends Component
 | 
				
			|||||||
            ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');
 | 
					            ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($this->status) > 0) {
 | 
					        if (count($this->status) > 0) {
 | 
				
			||||||
            $query = $query->whereIn('status_id', $this->status);
 | 
					            
 | 
				
			||||||
 | 
					            /* Special filter for expired*/
 | 
				
			||||||
 | 
					            if(in_array("-1", $this->status)){
 | 
				
			||||||
 | 
					                // $query->whereDate('due_date', '<=', now()->startOfDay());
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					                $query->where(function ($query){
 | 
				
			||||||
 | 
					                    $query->whereDate('due_date', '<=', now()->startOfDay())
 | 
				
			||||||
 | 
					                          ->whereNotNull('due_date')
 | 
				
			||||||
 | 
					                          ->where('status_id', '<>', Quote::STATUS_CONVERTED);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if(in_array("2", $this->status)){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $query->where(function ($query){
 | 
				
			||||||
 | 
					                    $query->whereDate('due_date', '>=', now()->startOfDay())
 | 
				
			||||||
 | 
					                          ->orWhereNull('due_date');
 | 
				
			||||||
 | 
					                })->where('status_id', Quote::STATUS_SENT);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(in_array("3", $this->status)){
 | 
				
			||||||
 | 
					                $query->whereIn('status_id', [Quote::STATUS_APPROVED, Quote::STATUS_CONVERTED]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $query = $query
 | 
					        $query = $query
 | 
				
			||||||
            ->where('company_id', $this->company->id)
 | 
					            ->where('company_id', $this->company->id)
 | 
				
			||||||
            ->where('client_id', auth('contact')->user()->client->id)
 | 
					            ->where('client_id', auth('contact')->user()->client->id)
 | 
				
			||||||
            ->where('status_id', '<>', Quote::STATUS_DRAFT)
 | 
					            ->where('status_id', '<>', Quote::STATUS_DRAFT)
 | 
				
			||||||
 | 
					            // ->where(function ($query){
 | 
				
			||||||
 | 
					            //     $query->whereDate('due_date', '>=', now())
 | 
				
			||||||
 | 
					            //           ->orWhereNull('due_date');
 | 
				
			||||||
 | 
					            // })
 | 
				
			||||||
            ->where('is_deleted', 0)
 | 
					            ->where('is_deleted', 0)
 | 
				
			||||||
            ->withTrashed()
 | 
					            ->withTrashed()
 | 
				
			||||||
            ->paginate($this->per_page);
 | 
					            ->paginate($this->per_page);
 | 
				
			||||||
 | 
				
			|||||||
@ -47,7 +47,7 @@ class StoreInvoiceRequest extends Request
 | 
				
			|||||||
            $rules['documents'] = 'file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000';
 | 
					            $rules['documents'] = 'file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id;
 | 
					        $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
 | 
				
			||||||
        // $rules['client_id'] = ['required', Rule::exists('clients')->where('company_id', auth()->user()->company()->id)];
 | 
					        // $rules['client_id'] = ['required', Rule::exists('clients')->where('company_id', auth()->user()->company()->id)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules['invitations.*.client_contact_id'] = 'distinct';
 | 
					        $rules['invitations.*.client_contact_id'] = 'distinct';
 | 
				
			||||||
 | 
				
			|||||||
@ -335,11 +335,12 @@ class CompanyImport implements ShouldQueue
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if($this->company->account->isFreeHostedClient() && $client_count = count($this->getObject('clients', true)) > config('ninja.quotas.free.clients')){
 | 
					            if($this->company->account->isFreeHostedClient() && (count($this->getObject('clients', true)) > config('ninja.quotas.free.clients')) ){
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                nlog("client quota busted");
 | 
					                nlog("client quota busted");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $client_limit = config('ninja.quotas.free.clients');
 | 
					                $client_limit = config('ninja.quotas.free.clients');
 | 
				
			||||||
 | 
					                $client_count = count($this->getObject('clients', true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $this->message = "You are attempting to import ({$client_count}) clients, your current plan allows a total of ({$client_limit})";
 | 
					                $this->message = "You are attempting to import ({$client_count}) clients, your current plan allows a total of ({$client_limit})";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
 | 
				
			|||||||
@ -135,7 +135,7 @@ class SendRecurring implements ShouldQueue
 | 
				
			|||||||
                if ($invitation->contact && !$invitation->contact->trashed() && strlen($invitation->contact->email) >=1 && $invoice->client->getSetting('auto_email_invoice')) {
 | 
					                if ($invitation->contact && !$invitation->contact->trashed() && strlen($invitation->contact->email) >=1 && $invoice->client->getSetting('auto_email_invoice')) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    try{
 | 
					                    try{
 | 
				
			||||||
                        EmailEntity::dispatch($invitation, $invoice->company)->delay(now()->addSeconds(1));
 | 
					                        EmailEntity::dispatch($invitation, $invoice->company);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    catch(\Exception $e) {
 | 
					                    catch(\Exception $e) {
 | 
				
			||||||
                        nlog($e->getMessage());
 | 
					                        nlog($e->getMessage());
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										100
									
								
								app/Jobs/Util/ApplePayDomain.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								app/Jobs/Util/ApplePayDomain.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					<?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\Jobs\Util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Jobs\Util\UnlinkFile;
 | 
				
			||||||
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ApplePayDomain implements ShouldQueue
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private CompanyGateway $company_gateway;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private string $db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private array $stripe_keys = ['d14dd26a47cecc30fdd65700bfb67b34', 'd14dd26a37cecc30fdd65700bfb55b23'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $tries = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(CompanyGateway $company_gateway, string $db)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        $this->db = $db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->company_gateway = $company_gateway;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Execute the job.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function handle()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        MultiDB::setDB($this->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(in_array($this->company_gateway->gateway_key, $this->stripe_keys))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            $domain = $this->getDomain();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try{
 | 
				
			||||||
 | 
					                $this->company_gateway->driver()->setApplePayDomain($domain);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch(\Exception $e){
 | 
				
			||||||
 | 
					                nlog("failed to set Apple Domain with Stripe " . $e->getMessage());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function getDomain()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(Ninja::isHosted())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if($this->company->portal_mode == 'domain'){
 | 
				
			||||||
 | 
					                $domain = $this->company->portal_domain;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else{
 | 
				
			||||||
 | 
					                $domain = $this->company->subdomain . '.' . config('ninja.app_domain');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $domain = config('ninja.app_url');
 | 
				
			||||||
 | 
					        }    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $parsed_url = parse_url($domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $parsed_url['host'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -471,8 +471,9 @@ class Import implements ShouldQueue
 | 
				
			|||||||
                    
 | 
					                    
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ($key == 'payment_terms' && $key = '') {
 | 
					                /* changes $key = '' to $value == '' and changed the return value from -1 to "0" 06/01/2022 */
 | 
				
			||||||
                    $value = -1;
 | 
					                if ($key == 'payment_terms' && $value == '') {
 | 
				
			||||||
 | 
					                    $value = "0";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $company_settings->{$key} = $value;
 | 
					                $company_settings->{$key} = $value;
 | 
				
			||||||
 | 
				
			|||||||
@ -343,7 +343,10 @@ class CompanyGateway extends BaseModel
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($fees_and_limits->fee_percent) {
 | 
					        if ($fees_and_limits->fee_percent) {
 | 
				
			||||||
            if ($fees_and_limits->adjust_fee_percent) {
 | 
					            if($fees_and_limits->fee_percent == 100){ //unusual edge case if the user wishes to charge a fee of 100% 09/01/2022
 | 
				
			||||||
 | 
					                $fee += $amount;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            elseif ($fees_and_limits->adjust_fee_percent) {
 | 
				
			||||||
                $fee += round(($amount / (1 - $fees_and_limits->fee_percent / 100) - $amount), 2);
 | 
					                $fee += round(($amount / (1 - $fees_and_limits->fee_percent / 100) - $amount), 2);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $fee += round(($amount * $fees_and_limits->fee_percent / 100), 2);
 | 
					                $fee += round(($amount * $fees_and_limits->fee_percent / 100), 2);
 | 
				
			||||||
@ -383,42 +386,6 @@ class CompanyGateway extends BaseModel
 | 
				
			|||||||
        return route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $this->hashed_id]);
 | 
					        return route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $this->hashed_id]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * we need to average out the gateway fees across all the invoices
 | 
					 | 
				
			||||||
     * so lets iterate.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * we MAY need to adjust the final fee to ensure our rounding makes sense!
 | 
					 | 
				
			||||||
     * @param $amount
 | 
					 | 
				
			||||||
     * @param $invoice_count
 | 
					 | 
				
			||||||
     * @return stdClass
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    // public function calcGatewayFeeObject($amount, $invoice_count)
 | 
					 | 
				
			||||||
    // {
 | 
					 | 
				
			||||||
    //     $total_gateway_fee = $this->calcGatewayFee($amount);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $fee_object = new stdClass;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $fees_and_limits = $this->getFeesAndLimits();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     if (! $fees_and_limits) {
 | 
					 | 
				
			||||||
    //         return $fee_object;
 | 
					 | 
				
			||||||
    //     }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $fee_component_amount = $fees_and_limits->fee_amount ?: 0;
 | 
					 | 
				
			||||||
    //     $fee_component_percent = $fees_and_limits->fee_percent ? ($amount * $fees_and_limits->fee_percent / 100) : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $combined_fee_component = $fee_component_amount + $fee_component_percent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $fee_component_tax_name1 = $fees_and_limits->fee_tax_name1 ?: '';
 | 
					 | 
				
			||||||
    //     $fee_component_tax_rate1 = $fees_and_limits->fee_tax_rate1 ? ($combined_fee_component * $fees_and_limits->fee_tax_rate1 / 100) : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $fee_component_tax_name2 = $fees_and_limits->fee_tax_name2 ?: '';
 | 
					 | 
				
			||||||
    //     $fee_component_tax_rate2 = $fees_and_limits->fee_tax_rate2 ? ($combined_fee_component * $fees_and_limits->fee_tax_rate2 / 100) : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     $fee_component_tax_name3 = $fees_and_limits->fee_tax_name3 ?: '';
 | 
					 | 
				
			||||||
    //     $fee_component_tax_rate3 = $fees_and_limits->fee_tax_rate3 ? ($combined_fee_component * $fees_and_limits->fee_tax_rate3 / 100) : 0;
 | 
					 | 
				
			||||||
    // }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function resolveRouteBinding($value, $field = null)
 | 
					    public function resolveRouteBinding($value, $field = null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this
 | 
					        return $this
 | 
				
			||||||
 | 
				
			|||||||
@ -101,6 +101,7 @@ class Invoice extends BaseModel
 | 
				
			|||||||
        'updated_at' => 'timestamp',
 | 
					        'updated_at' => 'timestamp',
 | 
				
			||||||
        'created_at' => 'timestamp',
 | 
					        'created_at' => 'timestamp',
 | 
				
			||||||
        'deleted_at' => 'timestamp',
 | 
					        'deleted_at' => 'timestamp',
 | 
				
			||||||
 | 
					        'is_deleted' => 'bool',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $with = [];
 | 
					    protected $with = [];
 | 
				
			||||||
@ -408,7 +409,19 @@ class Invoice extends BaseModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $file_path = $this->client->invoice_filepath($invitation).$this->numberFormatter().'.pdf';
 | 
					        $file_path = $this->client->invoice_filepath($invitation).$this->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(Ninja::isHosted() && $portal && Storage::disk(config('filesystems.default'))->exists($file_path)){
 | 
					        $file_exists = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Flysystem throws an exception if the path is "corrupted" so lets wrap it in a try catch and return a bool  06/01/2022*/
 | 
				
			||||||
 | 
					        try{
 | 
				
			||||||
 | 
					            $file_exists = Storage::disk(config('filesystems.default'))->exists($file_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch(\Exception $e){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nlog($e->getMessage());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(Ninja::isHosted() && $portal && $file_exists){
 | 
				
			||||||
            return Storage::disk(config('filesystems.default'))->{$type}($file_path);
 | 
					            return Storage::disk(config('filesystems.default'))->{$type}($file_path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elseif(Ninja::isHosted()){
 | 
					        elseif(Ninja::isHosted()){
 | 
				
			||||||
@ -416,7 +429,16 @@ class Invoice extends BaseModel
 | 
				
			|||||||
            return Storage::disk(config('filesystems.default'))->{$type}($file_path);
 | 
					            return Storage::disk(config('filesystems.default'))->{$type}($file_path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if(Storage::disk('public')->exists($file_path))
 | 
					        try{
 | 
				
			||||||
 | 
					            $file_exists = Storage::disk('public')->exists($file_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch(\Exception $e){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nlog($e->getMessage());
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($file_exists)
 | 
				
			||||||
            return Storage::disk('public')->{$type}($file_path);
 | 
					            return Storage::disk('public')->{$type}($file_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_path = CreateEntityPdf::dispatchNow($invitation);
 | 
					        $file_path = CreateEntityPdf::dispatchNow($invitation);
 | 
				
			||||||
 | 
				
			|||||||
@ -87,6 +87,7 @@ class Quote extends BaseModel
 | 
				
			|||||||
        'updated_at' => 'timestamp',
 | 
					        'updated_at' => 'timestamp',
 | 
				
			||||||
        'created_at' => 'timestamp',
 | 
					        'created_at' => 'timestamp',
 | 
				
			||||||
        'deleted_at' => 'timestamp',
 | 
					        'deleted_at' => 'timestamp',
 | 
				
			||||||
 | 
					        'is_deleted' => 'boolean',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $dates = [];
 | 
					    protected $dates = [];
 | 
				
			||||||
@ -117,6 +118,16 @@ class Quote extends BaseModel
 | 
				
			|||||||
        return $this->dateMutator($value);
 | 
					        return $this->dateMutator($value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getStatusIdAttribute($value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if($this->due_date && !$this->is_deleted && $value == Quote::STATUS_SENT && Carbon::parse($this->due_date)->lte(now()->startOfDay())){
 | 
				
			||||||
 | 
					            return Quote::STATUS_EXPIRED;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function company()
 | 
					    public function company()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->belongsTo(Company::class);
 | 
					        return $this->belongsTo(Company::class);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										88
									
								
								app/Notifications/Ninja/EmailBounceNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								app/Notifications/Ninja/EmailBounceNotification.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					<?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\Notifications\Ninja;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
 | 
					use Illuminate\Notifications\Messages\MailMessage;
 | 
				
			||||||
 | 
					use Illuminate\Notifications\Messages\SlackMessage;
 | 
				
			||||||
 | 
					use Illuminate\Notifications\Notification;
 | 
				
			||||||
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmailBounceNotification extends Notification 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new notification instance.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct($account)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->account = $account;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the notification's delivery channels.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  mixed  $notifiable
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function via($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ['slack'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the mail representation of the notification.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  mixed  $notifiable
 | 
				
			||||||
 | 
					     * @return MailMessage
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function toMail($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the array representation of the notification.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  mixed  $notifiable
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function toArray($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function toSlack($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $content = "Email bounce notification for Account {$this->account->key} \n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $owner = $this->account->companies()->first()->owner();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $content .= "Owner {$owner->present()->name() } | {$owner->email}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (new SlackMessage)
 | 
				
			||||||
 | 
					                ->success()
 | 
				
			||||||
 | 
					                ->from(ctrans('texts.notification_bot'))
 | 
				
			||||||
 | 
					                ->image('https://app.invoiceninja.com/favicon.png')
 | 
				
			||||||
 | 
					                ->content($content);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										88
									
								
								app/Notifications/Ninja/EmailSpamNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								app/Notifications/Ninja/EmailSpamNotification.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					<?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\Notifications\Ninja;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
 | 
					use Illuminate\Notifications\Messages\MailMessage;
 | 
				
			||||||
 | 
					use Illuminate\Notifications\Messages\SlackMessage;
 | 
				
			||||||
 | 
					use Illuminate\Notifications\Notification;
 | 
				
			||||||
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmailSpamNotification extends Notification 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new notification instance.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct($account)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->account = $account;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the notification's delivery channels.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  mixed  $notifiable
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function via($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ['slack'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the mail representation of the notification.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  mixed  $notifiable
 | 
				
			||||||
 | 
					     * @return MailMessage
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function toMail($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the array representation of the notification.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  mixed  $notifiable
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function toArray($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function toSlack($notifiable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $content = "Email SPAM notification for Account {$this->account->key} \n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $owner = $this->account->companies()->first()->owner();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $content .= "Owner {$owner->present()->name() } | {$owner->email}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (new SlackMessage)
 | 
				
			||||||
 | 
					                ->success()
 | 
				
			||||||
 | 
					                ->from(ctrans('texts.notification_bot'))
 | 
				
			||||||
 | 
					                ->image('https://app.invoiceninja.com/favicon.png')
 | 
				
			||||||
 | 
					                ->content($content);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -157,6 +157,7 @@ class AuthorizePaymentMethod
 | 
				
			|||||||
        $paymentOne->setOpaqueData($op);
 | 
					        $paymentOne->setOpaqueData($op);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $contact = $this->authorize->client->primary_contact()->first();
 | 
					        $contact = $this->authorize->client->primary_contact()->first();
 | 
				
			||||||
 | 
					        $billto = false;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if ($contact) {
 | 
					        if ($contact) {
 | 
				
			||||||
            // Create the Bill To info for new payment type
 | 
					            // Create the Bill To info for new payment type
 | 
				
			||||||
 | 
				
			|||||||
@ -256,13 +256,13 @@ class BaseDriver extends AbstractPaymentDriver
 | 
				
			|||||||
        $this->payment_hash->payment_id = $payment->id;
 | 
					        $this->payment_hash->payment_id = $payment->id;
 | 
				
			||||||
        $this->payment_hash->save();
 | 
					        $this->payment_hash->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->attachInvoices($payment, $this->payment_hash);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if($this->payment_hash->credits_total() > 0)
 | 
					        if($this->payment_hash->credits_total() > 0)
 | 
				
			||||||
            $payment = $payment->service()->applyCredits($this->payment_hash)->save();
 | 
					            $payment = $payment->service()->applyCredits($this->payment_hash)->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $payment->service()->updateInvoicePayment($this->payment_hash);
 | 
					        $payment->service()->updateInvoicePayment($this->payment_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->attachInvoices($payment, $this->payment_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        event('eloquent.created: App\Models\Payment', $payment);
 | 
					        event('eloquent.created: App\Models\Payment', $payment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->client->getSetting('client_online_payment_notification') && in_array($status, [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING]))
 | 
					        if ($this->client->getSetting('client_online_payment_notification') && in_array($status, [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING]))
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,8 @@ class PayFastPaymentDriver extends BaseDriver
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $types = [];
 | 
					        $types = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if($this->client->currency()->code == 'ZAR' || $this->client->currency()->code == 'USD')
 | 
					        // if($this->client->currency()->code == 'ZAR' || $this->client->currency()->code == 'USD')
 | 
				
			||||||
 | 
					        if($this->client->currency()->code == 'ZAR')
 | 
				
			||||||
            $types[] = GatewayType::CREDIT_CARD;
 | 
					            $types[] = GatewayType::CREDIT_CARD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $types;
 | 
					        return $types;
 | 
				
			||||||
 | 
				
			|||||||
@ -725,6 +725,17 @@ class StripePaymentDriver extends BaseDriver
 | 
				
			|||||||
        return (new Verify($this))->run();
 | 
					        return (new Verify($this))->run();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function setApplePayDomain($domain)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Stripe\ApplePayDomain::create([
 | 
				
			||||||
 | 
					          'domain_name' => $domain,
 | 
				
			||||||
 | 
					        ],$this->stripe_connect_auth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function disconnect()
 | 
					    public function disconnect()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if(!$this->stripe_connect)
 | 
					        if(!$this->stripe_connect)
 | 
				
			||||||
 | 
				
			|||||||
@ -47,9 +47,13 @@ class PaymentRepository extends BaseRepository {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function save(array $data, Payment $payment): ?Payment
 | 
					    public function save(array $data, Payment $payment): ?Payment
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($payment->amount >= 0) {
 | 
					        // if ($payment->amount >= 0) {
 | 
				
			||||||
 | 
					        //     return $this->applyPayment($data, $payment);
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return $this->applyPayment($data, $payment);
 | 
					            return $this->applyPayment($data, $payment);
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $payment;
 | 
					        return $payment;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -80,8 +84,8 @@ class PaymentRepository extends BaseRepository {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                $client->service()->updatePaidToDate($data['amount'])->save();
 | 
					                $client->service()->updatePaidToDate($data['amount'])->save();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            elseif($data['amount'] >0){
 | 
					            // elseif($data['amount'] >0){
 | 
				
			||||||
 | 
					            else{
 | 
				
			||||||
                //this fixes an edge case with unapplied payments
 | 
					                //this fixes an edge case with unapplied payments
 | 
				
			||||||
                $client->service()->updatePaidToDate($data['amount'])->save();
 | 
					                $client->service()->updatePaidToDate($data['amount'])->save();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -38,6 +38,7 @@ class TriggeredActions extends AbstractService
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
 | 
					        if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
 | 
				
			||||||
 | 
					            $this->credit = $this->credit->service()->markSent()->save();
 | 
				
			||||||
            $this->sendEmail();
 | 
					            $this->sendEmail();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -105,6 +105,7 @@ class AutoBillInvoice extends AbstractService
 | 
				
			|||||||
            $fee = 0;
 | 
					            $fee = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Build payment hash */
 | 
					        /* Build payment hash */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $payment_hash = PaymentHash::create([
 | 
					        $payment_hash = PaymentHash::create([
 | 
				
			||||||
            'hash' => Str::random(64),
 | 
					            'hash' => Str::random(64),
 | 
				
			||||||
            'data' => ['invoices' => [['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount, 'invoice_number' => $this->invoice->number]]],
 | 
					            'data' => ['invoices' => [['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount, 'invoice_number' => $this->invoice->number]]],
 | 
				
			||||||
@ -123,7 +124,8 @@ class AutoBillInvoice extends AbstractService
 | 
				
			|||||||
                                 ->tokenBilling($gateway_token, $payment_hash);
 | 
					                                 ->tokenBilling($gateway_token, $payment_hash);
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
         catch(\Exception $e){
 | 
					         catch(\Exception $e){
 | 
				
			||||||
            nlog($e->getMessage());
 | 
					            nlog("payment NOT captured for ". $this->invoice->number . " with error " . $e->getMessage());
 | 
				
			||||||
 | 
					            // nlog($e->getMessage());
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if($payment){
 | 
					        if($payment){
 | 
				
			||||||
 | 
				
			|||||||
@ -333,9 +333,10 @@ class InvoiceService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try{
 | 
					        try{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf');
 | 
					            if(Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf'))
 | 
				
			||||||
 | 
					                Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf');
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            if(Ninja::isHosted()) {
 | 
					            if(Ninja::isHosted() && Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf')) {
 | 
				
			||||||
                Storage::disk('public')->delete($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf');
 | 
					                Storage::disk('public')->delete($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -63,7 +63,8 @@ class MarkSent extends AbstractService
 | 
				
			|||||||
             ->service()
 | 
					             ->service()
 | 
				
			||||||
             ->applyNumber()
 | 
					             ->applyNumber()
 | 
				
			||||||
             ->setDueDate()
 | 
					             ->setDueDate()
 | 
				
			||||||
             ->deletePdf()
 | 
					             // ->deletePdf() //08-01-2022
 | 
				
			||||||
 | 
					             ->touchPdf() //08-01-2022
 | 
				
			||||||
             ->setReminder()
 | 
					             ->setReminder()
 | 
				
			||||||
             ->save();
 | 
					             ->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -49,6 +49,7 @@ class TriggeredActions extends AbstractService
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
 | 
					        if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
 | 
				
			||||||
 | 
					            $this->invoice->service()->markSent()->touchPdf()->save();
 | 
				
			||||||
            $this->sendEmail();
 | 
					            $this->sendEmail();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -38,6 +38,7 @@ class TriggeredActions extends AbstractService
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
 | 
					        if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
 | 
				
			||||||
 | 
					            $this->quote = $this->quote->service()->markSent()->save();
 | 
				
			||||||
            $this->sendEmail();
 | 
					            $this->sendEmail();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -42,4 +42,5 @@ trait Uploadable
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,8 @@ 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', 'invoicing.co'),
 | 
					    'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
 | 
				
			||||||
    'app_version' => '5.3.41',
 | 
					    'app_version' => '5.3.42',
 | 
				
			||||||
    'app_tag' => '5.3.41',
 | 
					    'app_tag' => '5.3.42',
 | 
				
			||||||
    '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', ''),
 | 
					    'api_secret' => env('API_SECRET', ''),
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ class StripeConnectGateway extends Migration
 | 
				
			|||||||
            'provider' => 'StripeConnect', 
 | 
					            'provider' => 'StripeConnect', 
 | 
				
			||||||
            'sort_order' => 1, 
 | 
					            'sort_order' => 1, 
 | 
				
			||||||
            'key' => 'd14dd26a47cecc30fdd65700bfb67b34', 
 | 
					            'key' => 'd14dd26a47cecc30fdd65700bfb67b34', 
 | 
				
			||||||
            'fields' => '{"account_id":""}'
 | 
					            'fields' => '{"account_id":"","appleDomainVerification":""}'
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Gateway::create($gateway);
 | 
					        Gateway::create($gateway);
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Gateway;
 | 
				
			||||||
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
 | 
					use Illuminate\Database\Migrations\Migration;
 | 
				
			||||||
 | 
					use Illuminate\Database\Schema\Blueprint;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddAppDomainIdToGatewaysTable extends Migration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Run the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function up()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(Ninja::isHosted()){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $stripe_connect = Gateway::find(56);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if($stripe_connect){
 | 
				
			||||||
 | 
					                $stripe_connect->fields = '{"account_id":"", "appleDomainVerification":""}';
 | 
				
			||||||
 | 
					                $stripe_connect->save();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $stripe_connect = Gateway::find(20);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if($stripe_connect){
 | 
				
			||||||
 | 
					                $stripe_connect->fields = '{"account_id":"", "appleDomainVerification":""}';
 | 
				
			||||||
 | 
					                $stripe_connect->save();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -44,7 +44,7 @@ class PaymentLibrariesSeeder extends Seeder
 | 
				
			|||||||
            ['id' => 17, 'name' => 'Pin', 'provider' => 'Pin', 'key' => '0749cb92a6b36c88bd9ff8aabd2efcab', 'fields' => '{"secretKey":"","testMode":false}'],
 | 
					            ['id' => 17, 'name' => 'Pin', 'provider' => 'Pin', 'key' => '0749cb92a6b36c88bd9ff8aabd2efcab', 'fields' => '{"secretKey":"","testMode":false}'],
 | 
				
			||||||
            ['id' => 18, 'name' => 'SagePay Direct', 'provider' => 'SagePay_Direct', 'key' => '4c8f4e5d0f353a122045eb9a60cc0f2d', 'fields' => '{"vendor":"","testMode":false,"referrerId":""}'],
 | 
					            ['id' => 18, 'name' => 'SagePay Direct', 'provider' => 'SagePay_Direct', 'key' => '4c8f4e5d0f353a122045eb9a60cc0f2d', 'fields' => '{"vendor":"","testMode":false,"referrerId":""}'],
 | 
				
			||||||
            ['id' => 19, 'name' => 'SecurePay DirectPost', 'provider' => 'SecurePay_DirectPost', 'key' => '8036a5aadb2bdaafb23502da8790b6a2', 'fields' => '{"merchantId":"","transactionPassword":"","testMode":false,"enable_ach":"","enable_sofort":"","enable_apple_pay":"","enable_alipay":""}'],
 | 
					            ['id' => 19, 'name' => 'SecurePay DirectPost', 'provider' => 'SecurePay_DirectPost', 'key' => '8036a5aadb2bdaafb23502da8790b6a2', 'fields' => '{"merchantId":"","transactionPassword":"","testMode":false,"enable_ach":"","enable_sofort":"","enable_apple_pay":"","enable_alipay":""}'],
 | 
				
			||||||
            ['id' => 20, 'name' => 'Stripe', 'provider' => 'Stripe', 'sort_order' => 1, 'key' => 'd14dd26a37cecc30fdd65700bfb55b23', 'fields' => '{"publishableKey":"","apiKey":""}'],
 | 
					            ['id' => 20, 'name' => 'Stripe', 'provider' => 'Stripe', 'sort_order' => 1, 'key' => 'd14dd26a37cecc30fdd65700bfb55b23', 'fields' => '{"publishableKey":"","apiKey":"","appleDomainVerification":""}'],
 | 
				
			||||||
            ['id' => 21, 'name' => 'TargetPay Direct eBanking', 'provider' => 'TargetPay_Directebanking', 'key' => 'd14dd26a37cdcc30fdd65700bfb55b23', 'fields' => '{"subAccountId":""}'],
 | 
					            ['id' => 21, 'name' => 'TargetPay Direct eBanking', 'provider' => 'TargetPay_Directebanking', 'key' => 'd14dd26a37cdcc30fdd65700bfb55b23', 'fields' => '{"subAccountId":""}'],
 | 
				
			||||||
            ['id' => 22, 'name' => 'TargetPay Ideal', 'provider' => 'TargetPay_Ideal', 'key' => 'ea3b328bd72d381387281c3bd83bd97c', 'fields' => '{"subAccountId":""}'],
 | 
					            ['id' => 22, 'name' => 'TargetPay Ideal', 'provider' => 'TargetPay_Ideal', 'key' => 'ea3b328bd72d381387281c3bd83bd97c', 'fields' => '{"subAccountId":""}'],
 | 
				
			||||||
            ['id' => 23, 'name' => 'TargetPay Mr Cash', 'provider' => 'TargetPay_Mrcash', 'key' => 'a0035fc0d87c4950fb82c73e2fcb825a', 'fields' => '{"subAccountId":""}'],
 | 
					            ['id' => 23, 'name' => 'TargetPay Mr Cash', 'provider' => 'TargetPay_Mrcash', 'key' => 'a0035fc0d87c4950fb82c73e2fcb825a', 'fields' => '{"subAccountId":""}'],
 | 
				
			||||||
 | 
				
			|||||||
@ -4342,7 +4342,7 @@ $LANG = array(
 | 
				
			|||||||
    'payment_type_instant_bank_pay' => 'Instant Bank Pay',
 | 
					    'payment_type_instant_bank_pay' => 'Instant Bank Pay',
 | 
				
			||||||
    'payment_type_iDEAL' => 'iDEAL',
 | 
					    'payment_type_iDEAL' => 'iDEAL',
 | 
				
			||||||
    'payment_type_Przelewy24' => 'Przelewy24',
 | 
					    'payment_type_Przelewy24' => 'Przelewy24',
 | 
				
			||||||
    'payment_type_Mollie Bank Transfer' => 'Bank Transfer',
 | 
					    'payment_type_Mollie Bank Transfer' => 'Mollie Bank Transfer',
 | 
				
			||||||
    'payment_type_KBC/CBC' => 'KBC/CBC',
 | 
					    'payment_type_KBC/CBC' => 'KBC/CBC',
 | 
				
			||||||
    'payment_type_Instant Bank Pay' => 'Instant Bank Pay',
 | 
					    'payment_type_Instant Bank Pay' => 'Instant Bank Pay',
 | 
				
			||||||
    'payment_type_Hosted Page' => 'Hosted Page',
 | 
					    'payment_type_Hosted Page' => 'Hosted Page',
 | 
				
			||||||
 | 
				
			|||||||
@ -117,17 +117,22 @@
 | 
				
			|||||||
    [data-ref="table"] > tbody > tr > td {
 | 
					    [data-ref="table"] > tbody > tr > td {
 | 
				
			||||||
        border-top: 1px solid #d8d8d8;
 | 
					        border-top: 1px solid #d8d8d8;
 | 
				
			||||||
        border-bottom: 1px solid #d8d8d8;
 | 
					        border-bottom: 1px solid #d8d8d8;
 | 
				
			||||||
        padding: 1.5rem;
 | 
					        padding: 1.5rem 1rem;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [data-ref="table"] > tbody > tr > td:first-child {
 | 
					    [data-ref="table"] > tbody > tr > td:first-child {
 | 
				
			||||||
        color: var(--primary-color);
 | 
					        color: var(--primary-color);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [data-ref="table"] > thead > tr > th:last-child,
 | 
				
			||||||
    [data-ref="table"] > tbody > tr > td:last-child {
 | 
					    [data-ref="table"] > tbody > tr > td:last-child {
 | 
				
			||||||
        text-align: right;
 | 
					        text-align: right;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [data-ref="table"] > thead > tr > th:last-child {
 | 
				
			||||||
 | 
					        padding-right: 1rem;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [data-ref="table"] > tbody > tr:nth-child(odd) {
 | 
					    [data-ref="table"] > tbody > tr:nth-child(odd) {
 | 
				
			||||||
        background-color: #f5f5f5;
 | 
					        background-color: #f5f5f5;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -208,6 +208,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
 | 
				
			|||||||
    Route::resource('subscriptions', 'SubscriptionController');
 | 
					    Route::resource('subscriptions', 'SubscriptionController');
 | 
				
			||||||
    Route::post('subscriptions/bulk', 'SubscriptionController@bulk')->name('subscriptions.bulk');
 | 
					    Route::post('subscriptions/bulk', 'SubscriptionController@bulk')->name('subscriptions.bulk');
 | 
				
			||||||
    Route::get('statics', 'StaticController');
 | 
					    Route::get('statics', 'StaticController');
 | 
				
			||||||
 | 
					    Route::post('apple_pay/upload_file','ApplyPayController@upload');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -44,3 +44,4 @@ Route::get('stripe/completed', 'StripeConnectController@completed')->name('strip
 | 
				
			|||||||
Route::get('checkout/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\Checkout3dsController@index')->name('checkout.3ds_redirect');
 | 
					Route::get('checkout/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\Checkout3dsController@index')->name('checkout.3ds_redirect');
 | 
				
			||||||
Route::get('mollie/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\Mollie3dsController@index')->name('mollie.3ds_redirect');
 | 
					Route::get('mollie/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\Mollie3dsController@index')->name('mollie.3ds_redirect');
 | 
				
			||||||
Route::get('gocardless/ibp_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\GoCardlessController@ibpRedirect')->name('gocardless.ibp_redirect');
 | 
					Route::get('gocardless/ibp_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\GoCardlessController@ibpRedirect')->name('gocardless.ibp_redirect');
 | 
				
			||||||
 | 
					Route::get('.well-known/apple-developer-merchantid-domain-association', 'ClientPortal\ApplePayDomainController@showAppleMerchantId');
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										92
									
								
								tests/Feature/ApplePayDomainMerchantUrlTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								tests/Feature/ApplePayDomainMerchantUrlTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					<?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 Tests\Feature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
				
			||||||
 | 
					use Illuminate\Routing\Middleware\ThrottleRequests;
 | 
				
			||||||
 | 
					use Tests\MockAccountData;
 | 
				
			||||||
 | 
					use Tests\TestCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @test
 | 
				
			||||||
 | 
					 * @covers App\Http\Controllers\ApplePayDomainController
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ApplePayDomainMerchantUrlTest extends TestCase
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use DatabaseTransactions;
 | 
				
			||||||
 | 
					    use MockAccountData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function setUp() :void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::setUp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->makeTestData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->withoutMiddleware(
 | 
				
			||||||
 | 
					            ThrottleRequests::class
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testMerchantFieldGet()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (! config('ninja.testvars.stripe')) {
 | 
				
			||||||
 | 
					            $this->markTestSkipped('Skip test no company gateways installed');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $config = new \stdClass;
 | 
				
			||||||
 | 
					        $config->publishableKey = "pk_test";
 | 
				
			||||||
 | 
					        $config->apiKey = "sk_test";
 | 
				
			||||||
 | 
					        $config->appleDomainVerification = "merchant_id";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $cg = new CompanyGateway;
 | 
				
			||||||
 | 
					        $cg->company_id = $this->company->id;
 | 
				
			||||||
 | 
					        $cg->user_id = $this->user->id;
 | 
				
			||||||
 | 
					        $cg->gateway_key = 'd14dd26a37cecc30fdd65700bfb55b23';
 | 
				
			||||||
 | 
					        $cg->require_cvv = true;
 | 
				
			||||||
 | 
					        $cg->require_billing_address = true;
 | 
				
			||||||
 | 
					        $cg->require_shipping_address = true;
 | 
				
			||||||
 | 
					        $cg->update_details = true;
 | 
				
			||||||
 | 
					        $cg->config = encrypt(json_encode($config));
 | 
				
			||||||
 | 
					        $cg->fees_and_limits = '';
 | 
				
			||||||
 | 
					        $cg->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response = $this->withHeaders([])->get('.well-known/apple-developer-merchantid-domain-association');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $response->getContent();
 | 
				
			||||||
 | 
					        $response->assertStatus(200);
 | 
				
			||||||
 | 
					        $this->assertEquals("merchant_id", $arr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testDomainParsing()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $domain = 'http://ninja.test:8000';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $parsed = parse_url($domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals('ninja.test', $parsed['host']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = 'ninja.test:8000';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $parsed = parse_url($domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals('ninja.test', $parsed['host']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = 'http://ninja.test:8000/afadf/dfdfdf/dfdfasf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $parsed = parse_url($domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals('ninja.test', $parsed['host']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										78
									
								
								tests/Feature/ClientDeletedInvoiceCreationTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tests/Feature/ClientDeletedInvoiceCreationTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					<?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 Tests\Feature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Client;
 | 
				
			||||||
 | 
					use App\Models\ClientContact;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Session;
 | 
				
			||||||
 | 
					use Tests\MockAccountData;
 | 
				
			||||||
 | 
					use Tests\TestCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @test
 | 
				
			||||||
 | 
					 * @covers App\Http\Controllers\InvoiceController
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ClientDeletedInvoiceCreationTest extends TestCase
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use MakesHash;
 | 
				
			||||||
 | 
					    use DatabaseTransactions;
 | 
				
			||||||
 | 
					    use MockAccountData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function setUp() :void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::setUp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->faker = \Faker\Factory::create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Model::reguard();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->makeTestData();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testClientedDeletedAttemptingToCreateInvoice()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					                /* Test fire new invoice */
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'client_id' => $this->client->hashed_id,
 | 
				
			||||||
 | 
					            'number' => 'dude',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->withHeaders([
 | 
				
			||||||
 | 
					            'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					            'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					        ])->post('/api/v1/invoices/', $data)
 | 
				
			||||||
 | 
					        ->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->client->is_deleted = true;
 | 
				
			||||||
 | 
					        $this->client->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'client_id' => $this->client->hashed_id,
 | 
				
			||||||
 | 
					            'number' => 'dude2',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->withHeaders([
 | 
				
			||||||
 | 
					            'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					            'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					        ])->post('/api/v1/invoices/', $data)
 | 
				
			||||||
 | 
					        ->assertStatus(302);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -319,6 +319,71 @@ class CompanyGatewayApiTest extends TestCase
 | 
				
			|||||||
        $this->assertEquals(10.2, $company_gateway->calcGatewayFee(10, GatewayType::CREDIT_CARD));
 | 
					        $this->assertEquals(10.2, $company_gateway->calcGatewayFee(10, GatewayType::CREDIT_CARD));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testFeesAndLimitsFeePercentAndAmountCalcuationOneHundredPercent()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //{"1":{"min_limit":1,"max_limit":1000000,"fee_amount":10,"fee_percent":2,"fee_tax_name1":"","fee_tax_name2":"","fee_tax_name3":"","fee_tax_rate1":0,"fee_tax_rate2":0,"fee_tax_rate3":0,"fee_cap":10,"adjust_fee_percent":true}}
 | 
				
			||||||
 | 
					        $fee = new FeesAndLimits;
 | 
				
			||||||
 | 
					        $fee->fee_amount = 0;
 | 
				
			||||||
 | 
					        $fee->fee_percent = 100;
 | 
				
			||||||
 | 
					        // $fee->fee_tax_name1 = 'GST';
 | 
				
			||||||
 | 
					        // $fee->fee_tax_rate1 = '10.0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $fee_arr[1] = (array) $fee;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'config' => 'random config',
 | 
				
			||||||
 | 
					            'gateway_key' => '3b6621f970ab18887c4f6dca78d3f8bb',
 | 
				
			||||||
 | 
					            'fees_and_limits' => $fee_arr,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* POST */
 | 
				
			||||||
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
 | 
					                'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					                'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					            ])->post('/api/v1/company_gateways', $data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $response->json();
 | 
				
			||||||
 | 
					        $id = $this->decodePrimaryKey($arr['data']['id']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $company_gateway = CompanyGateway::find($id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals(10, $company_gateway->calcGatewayFee(10, GatewayType::CREDIT_CARD));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testFeesAndLimitsFeePercentAndAmountCalcuationOneHundredPercentVariationOne()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $fee = new FeesAndLimits;
 | 
				
			||||||
 | 
					        $fee->fee_amount = 0;
 | 
				
			||||||
 | 
					        $fee->fee_percent = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $fee_arr[1] = (array) $fee;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'config' => 'random config',
 | 
				
			||||||
 | 
					            'gateway_key' => '3b6621f970ab18887c4f6dca78d3f8bb',
 | 
				
			||||||
 | 
					            'fees_and_limits' => $fee_arr,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* POST */
 | 
				
			||||||
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
 | 
					                'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					                'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					            ])->post('/api/v1/company_gateways', $data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $response->json();
 | 
				
			||||||
 | 
					        $id = $this->decodePrimaryKey($arr['data']['id']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $company_gateway = CompanyGateway::find($id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals(1, $company_gateway->calcGatewayFee(10, GatewayType::CREDIT_CARD));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function testFeesAndLimitsFeePercentAndAmountAndTaxCalcuation()
 | 
					    public function testFeesAndLimitsFeePercentAndAmountAndTaxCalcuation()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        //{"1":{"min_limit":1,"max_limit":1000000,"fee_amount":10,"fee_percent":2,"fee_tax_name1":"","fee_tax_name2":"","fee_tax_name3":"","fee_tax_rate1":0,"fee_tax_rate2":0,"fee_tax_rate3":0,"fee_cap":10,"adjust_fee_percent":true}}
 | 
					        //{"1":{"min_limit":1,"max_limit":1000000,"fee_amount":10,"fee_percent":2,"fee_tax_name1":"","fee_tax_name2":"","fee_tax_name3":"","fee_tax_rate1":0,"fee_tax_rate2":0,"fee_tax_rate3":0,"fee_cap":10,"adjust_fee_percent":true}}
 | 
				
			||||||
 | 
				
			|||||||
@ -220,4 +220,19 @@ class InvoiceTest extends TestCase
 | 
				
			|||||||
            ])->put('/api/v1/invoices/'.$arr['data']['id'], $data)
 | 
					            ])->put('/api/v1/invoices/'.$arr['data']['id'], $data)
 | 
				
			||||||
            ->assertStatus(200);
 | 
					            ->assertStatus(200);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testClientedDeletedAttemptingToCreateInvoice()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					                /* Test fire new invoice */
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'client_id' => $this->client->hashed_id,
 | 
				
			||||||
 | 
					            'number' => 'dude',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
 | 
					            'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					            'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					        ])->post('/api/v1/invoices/', $data)
 | 
				
			||||||
 | 
					        ->assertStatus(200);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user