mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 23:37:33 -05:00 
			
		
		
		
	Merge pull request #6998 from turbo124/v5-develop
Fixes for Mollie Direct Debit
This commit is contained in:
		
						commit
						ed28a764ff
					
				
							
								
								
									
										3
									
								
								.github/workflows/phpunit.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/phpunit.yml
									
									
									
									
										vendored
									
									
								
							@ -13,7 +13,7 @@ jobs:
 | 
				
			|||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        operating-system: ['ubuntu-18.04', 'ubuntu-20.04']
 | 
					        operating-system: ['ubuntu-18.04', 'ubuntu-20.04']
 | 
				
			||||||
        php-versions: ['7.4','8.0']
 | 
					        php-versions: ['7.4','8.0','8.1']
 | 
				
			||||||
        phpunit-versions: ['latest']
 | 
					        phpunit-versions: ['latest']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    env:
 | 
					    env:
 | 
				
			||||||
@ -106,6 +106,7 @@ jobs:
 | 
				
			|||||||
        vendor/bin/phpunit --testdox
 | 
					        vendor/bin/phpunit --testdox
 | 
				
			||||||
      env:
 | 
					      env:
 | 
				
			||||||
        DB_PORT: ${{ job.services.mysql.ports[3306] }}
 | 
					        DB_PORT: ${{ job.services.mysql.ports[3306] }}
 | 
				
			||||||
 | 
					        PHP_CS_FIXER_IGNORE_ENV: true
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    - name: Run php-cs-fixer
 | 
					    - name: Run php-cs-fixer
 | 
				
			||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
 | 
				
			|||||||
@ -52,12 +52,15 @@ class NinjaPlanController extends Controller
 | 
				
			|||||||
            
 | 
					            
 | 
				
			||||||
            Auth::guard('contact')->login($client_contact,true);
 | 
					            Auth::guard('contact')->login($client_contact,true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Current paid users get pushed straight to subscription overview page*/
 | 
					            // /* Current paid users get pushed straight to subscription overview page*/
 | 
				
			||||||
            if($account->isPaidHostedClient())
 | 
					            // if($account->isPaidHostedClient())
 | 
				
			||||||
                return redirect('/client/dashboard');
 | 
					            //     return redirect('/client/dashboard');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // /* Users that are not paid get pushed to a custom purchase page */
 | 
				
			||||||
 | 
					            // return $this->render('subscriptions.ninja_plan', ['settings' => $client_contact->company->settings]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->plan();
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            /* Users that are not paid get pushed to a custom purchase page */
 | 
					 | 
				
			||||||
            return $this->render('subscriptions.ninja_plan', ['settings' => $client_contact->company->settings]);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return redirect()->route('client.catchall');
 | 
					        return redirect()->route('client.catchall');
 | 
				
			||||||
@ -137,8 +140,7 @@ class NinjaPlanController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            return redirect()->route('client.catchall');
 | 
					            return redirect('/client/dashboard');
 | 
				
			||||||
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -107,7 +107,7 @@ class LicenseController extends BaseController
 | 
				
			|||||||
                        'message' => trans('texts.invalid_white_label_license'),
 | 
					                        'message' => trans('texts.invalid_white_label_license'),
 | 
				
			||||||
                        'errors' => new stdClass,
 | 
					                        'errors' => new stdClass,
 | 
				
			||||||
                    ];
 | 
					                    ];
 | 
				
			||||||
 | 
					                    $account = auth()->user()->account;
 | 
				
			||||||
                    $account->plan_term = Account::PLAN_TERM_YEARLY;
 | 
					                    $account->plan_term = Account::PLAN_TERM_YEARLY;
 | 
				
			||||||
                    $account->plan_paid = null;
 | 
					                    $account->plan_paid = null;
 | 
				
			||||||
                    $account->plan_expires = null;
 | 
					                    $account->plan_expires = null;
 | 
				
			||||||
@ -116,7 +116,7 @@ class LicenseController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    return response()->json($error, 400);
 | 
					                    return response()->json($error, 400);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    $account = auth()->user()->company()->account;
 | 
					                    $account = auth()->user()->account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $account->plan_term = Account::PLAN_TERM_YEARLY;
 | 
					                    $account->plan_term = Account::PLAN_TERM_YEARLY;
 | 
				
			||||||
                    $account->plan_paid = $data;
 | 
					                    $account->plan_paid = $data;
 | 
				
			||||||
@ -151,7 +151,7 @@ class LicenseController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function checkLicense()
 | 
					    private function checkLicense()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $account = auth()->user()->company()->account;
 | 
					        $account = auth()->user()->account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if($account->plan == 'white_label' && Carbon::parse($account->plan_expires)->lt(now())){
 | 
					        if($account->plan == 'white_label' && Carbon::parse($account->plan_expires)->lt(now())){
 | 
				
			||||||
            $account->plan = null;
 | 
					            $account->plan = null;
 | 
				
			||||||
 | 
				
			|||||||
@ -113,7 +113,6 @@ class PortalComposer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $data[] = ['title' => ctrans('texts.payment_methods'), 'url' => 'client.payment_methods.index', 'icon' => 'shield'];
 | 
					        $data[] = ['title' => ctrans('texts.payment_methods'), 'url' => 'client.payment_methods.index', 'icon' => 'shield'];
 | 
				
			||||||
        $data[] = ['title' => ctrans('texts.documents'), 'url' => 'client.documents.index', 'icon' => 'download'];
 | 
					        $data[] = ['title' => ctrans('texts.documents'), 'url' => 'client.documents.index', 'icon' => 'download'];
 | 
				
			||||||
        $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar'];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (auth('contact')->user()->client->getSetting('enable_client_portal_tasks')) {
 | 
					        if (auth('contact')->user()->client->getSetting('enable_client_portal_tasks')) {
 | 
				
			||||||
            $data[] = ['title' => ctrans('texts.tasks'), 'url' => 'client.tasks.index', 'icon' => 'clock'];
 | 
					            $data[] = ['title' => ctrans('texts.tasks'), 'url' => 'client.tasks.index', 'icon' => 'clock'];
 | 
				
			||||||
@ -123,6 +122,8 @@ class PortalComposer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if(Ninja::isHosted() && auth('contact')->user()->company->id == config('ninja.ninja_default_company_id'))
 | 
					        if(Ninja::isHosted() && auth('contact')->user()->company->id == config('ninja.ninja_default_company_id'))
 | 
				
			||||||
            $data[] = ['title' => ctrans('texts.plan'), 'url' => 'client.plan', 'icon' => 'credit-card'];
 | 
					            $data[] = ['title' => ctrans('texts.plan'), 'url' => 'client.plan', 'icon' => 'credit-card'];
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $data;
 | 
					        return $data;
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ use App\Mail\Admin\EntityNotificationMailer;
 | 
				
			|||||||
use App\Mail\Admin\PaymentFailureObject;
 | 
					use App\Mail\Admin\PaymentFailureObject;
 | 
				
			||||||
use App\Models\Client;
 | 
					use App\Models\Client;
 | 
				
			||||||
use App\Models\Company;
 | 
					use App\Models\Company;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
use App\Models\PaymentHash;
 | 
					use App\Models\PaymentHash;
 | 
				
			||||||
use App\Models\User;
 | 
					use App\Models\User;
 | 
				
			||||||
use App\Utils\Traits\Notifications\UserNotifies;
 | 
					use App\Utils\Traits\Notifications\UserNotifies;
 | 
				
			||||||
@ -75,15 +76,17 @@ class PaymentFailedMailer implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $settings = $this->client->getMergedSettings();
 | 
					        $settings = $this->client->getMergedSettings();
 | 
				
			||||||
        $amount = 0;
 | 
					        $amount = 0;
 | 
				
			||||||
 | 
					        $invoice = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if($this->payment_hash)
 | 
					        if($this->payment_hash){
 | 
				
			||||||
            $amount = array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
 | 
					            $amount = array_sum(array_column($this->payment_hash->invoices(), 'amount')) + $this->payment_hash->fee_total;
 | 
				
			||||||
 | 
					            $invoice = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))->withTrashed()->first();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //iterate through company_users
 | 
					        //iterate through company_users
 | 
				
			||||||
        $this->company->company_users->each(function ($company_user) use($amount, $settings){        
 | 
					        $this->company->company_users->each(function ($company_user) use($amount, $settings, $invoice){        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //determine if this user has the right permissions
 | 
					            $methods = $this->findUserEntityNotificationType($invoice ?: $this->client, $company_user, ['payment_failure_user', 'payment_failure_all', 'payment_failure', 'all_notifications']);
 | 
				
			||||||
            $methods = $this->findCompanyUserNotificationType($company_user, ['payment_failure','all_notifications']);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //if mail is a method type -fire mail!!
 | 
					            //if mail is a method type -fire mail!!
 | 
				
			||||||
            if (($key = array_search('mail', $methods)) !== false) {
 | 
					            if (($key = array_search('mail', $methods)) !== false) {
 | 
				
			||||||
 | 
				
			|||||||
@ -80,7 +80,7 @@ class PaymentFailureMailer implements ShouldQueue
 | 
				
			|||||||
        $this->company->company_users->each(function ($company_user) {        
 | 
					        $this->company->company_users->each(function ($company_user) {        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //determine if this user has the right permissions
 | 
					            //determine if this user has the right permissions
 | 
				
			||||||
            $methods = $this->findCompanyUserNotificationType($company_user, ['payment_failure','all_notifications']);
 | 
					            $methods = $this->findCompanyUserNotificationType($company_user, ['payment_failure_all','payment_failure', 'payment_failure_user', 'all_notifications']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //if mail is a method type -fire mail!!
 | 
					            //if mail is a method type -fire mail!!
 | 
				
			||||||
            if (($key = array_search('mail', $methods)) !== false) {
 | 
					            if (($key = array_search('mail', $methods)) !== false) {
 | 
				
			||||||
 | 
				
			|||||||
@ -59,7 +59,12 @@ class PaymentNotification implements ShouldQueue
 | 
				
			|||||||
        foreach ($payment->company->company_users as $company_user) {
 | 
					        foreach ($payment->company->company_users as $company_user) {
 | 
				
			||||||
            $user = $company_user->user;
 | 
					            $user = $company_user->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $methods = $this->findUserEntityNotificationType($payment, $company_user, ['payment_success', 'payment_success_all', 'all_notifications']);
 | 
					            $methods = $this->findUserEntityNotificationType($payment, $company_user, [
 | 
				
			||||||
 | 
					                'payment_success', 
 | 
				
			||||||
 | 
					                'payment_success_all', 
 | 
				
			||||||
 | 
					                'payment_success_user', 
 | 
				
			||||||
 | 
					                'all_notifications']
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (($key = array_search('mail', $methods)) !== false) {
 | 
					            if (($key = array_search('mail', $methods)) !== false) {
 | 
				
			||||||
                unset($methods[$key]);
 | 
					                unset($methods[$key]);
 | 
				
			||||||
 | 
				
			|||||||
@ -226,7 +226,7 @@ class BaseDriver extends AbstractPaymentDriver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $_payment = Payment::where('transaction_reference', $data['transaction_reference'])
 | 
					            $_payment = Payment::where('transaction_reference', $data['transaction_reference'])
 | 
				
			||||||
                               ->where('client_id', $this->client->id)
 | 
					                               ->where('client_id', $this->client->id)
 | 
				
			||||||
                               ->first();
 | 
					                               ->exists();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
           if($_payment)
 | 
					           if($_payment)
 | 
				
			||||||
            return $_payment;
 | 
					            return $_payment;
 | 
				
			||||||
@ -440,7 +440,7 @@ class BaseDriver extends AbstractPaymentDriver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $invoices->first()->invitations->each(function ($invitation) use ($nmo) {
 | 
					            $invoices->first()->invitations->each(function ($invitation) use ($nmo) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ($invitation->contact->email) {
 | 
					                if ((bool)$invitation->contact->send_email !== false && $invitation->contact->email) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $nmo->to_user = $invitation->contact;
 | 
					                    $nmo->to_user = $invitation->contact;
 | 
				
			||||||
                    NinjaMailerJob::dispatch($nmo);
 | 
					                    NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
 | 
				
			|||||||
@ -213,10 +213,10 @@ class CreditCard implements MethodInterface
 | 
				
			|||||||
            if ($response->status == 'Declined') {
 | 
					            if ($response->status == 'Declined') {
 | 
				
			||||||
                $this->checkout->unWindGatewayFees($this->checkout->payment_hash);
 | 
					                $this->checkout->unWindGatewayFees($this->checkout->payment_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $this->checkout->sendFailureMail($response->response_summary);
 | 
					                // $this->checkout->sendFailureMail($response->response_summary);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                //@todo - this will double up the checkout . com failed mails
 | 
					                //@todo - this will double up the checkout . com failed mails
 | 
				
			||||||
                $this->checkout->clientPaymentFailureMailer($response->status);
 | 
					                // $this->checkout->clientPaymentFailureMailer($response->status);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                return $this->processUnsuccessfulPayment($response);
 | 
					                return $this->processUnsuccessfulPayment($response);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -84,7 +84,8 @@ trait Utilities
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function processUnsuccessfulPayment(Payment $_payment, $throw_exception = true)
 | 
					    public function processUnsuccessfulPayment(Payment $_payment, $throw_exception = true)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->getParent()->sendFailureMail($_payment->status . " " . optional($_payment)->response_summary);
 | 
					        $this->getParent()->sendFailureMail($_payment->response_summary);
 | 
				
			||||||
 | 
					        // $this->getParent()->clientPaymentFailureMailer($_payment->status);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
        $message = [
 | 
					        $message = [
 | 
				
			||||||
            'server_response' => $_payment,
 | 
					            'server_response' => $_payment,
 | 
				
			||||||
 | 
				
			|||||||
@ -152,11 +152,8 @@ class DirectDebit implements MethodInterface
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function paymentResponse(PaymentResponseRequest $request)
 | 
					    public function paymentResponse(PaymentResponseRequest $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $token = ClientGatewayToken::find(
 | 
					 | 
				
			||||||
            $this->decodePrimaryKey($request->source)
 | 
					 | 
				
			||||||
        )->firstOrFail();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->go_cardless->ensureMandateIsReady($token);
 | 
					        $this->go_cardless->ensureMandateIsReady($request->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $payment = $this->go_cardless->gateway->payments()->create([
 | 
					            $payment = $this->go_cardless->gateway->payments()->create([
 | 
				
			||||||
@ -167,14 +164,14 @@ class DirectDebit implements MethodInterface
 | 
				
			|||||||
                        'payment_hash' => $this->go_cardless->payment_hash->hash,
 | 
					                        'payment_hash' => $this->go_cardless->payment_hash->hash,
 | 
				
			||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                    'links' => [
 | 
					                    'links' => [
 | 
				
			||||||
                        'mandate' => $token->token,
 | 
					                        'mandate' => $request->source,
 | 
				
			||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($payment->status === 'pending_submission') {
 | 
					            if ($payment->status === 'pending_submission') {
 | 
				
			||||||
                return $this->processPendingPayment($payment, ['token' => $token->hashed_id]);
 | 
					                return $this->processPendingPayment($payment, ['token' => $request->source]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return $this->processUnsuccessfulPayment($payment);
 | 
					            return $this->processUnsuccessfulPayment($payment);
 | 
				
			||||||
 | 
				
			|||||||
@ -265,10 +265,11 @@ class GoCardlessPaymentDriver extends BaseDriver
 | 
				
			|||||||
        return response()->json([], 200);
 | 
					        return response()->json([], 200);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function ensureMandateIsReady(ClientGatewayToken $cgt)
 | 
					    public function ensureMandateIsReady($token)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $mandate = $this->gateway->mandates()->get($cgt->token);
 | 
					            $this->init();
 | 
				
			||||||
 | 
					            $mandate = $this->gateway->mandates()->get($token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($mandate->status !== 'active') {
 | 
					            if ($mandate->status !== 'active') {
 | 
				
			||||||
                throw new \Exception(ctrans('texts.gocardless_mandate_not_ready'));
 | 
					                throw new \Exception(ctrans('texts.gocardless_mandate_not_ready'));
 | 
				
			||||||
 | 
				
			|||||||
@ -316,6 +316,10 @@ class MolliePaymentDriver extends BaseDriver
 | 
				
			|||||||
                nlog($payment);
 | 
					                nlog($payment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $client = Client::withTrashed()->find($this->decodePrimaryKey($payment->metadata->client_id));
 | 
					                $client = Client::withTrashed()->find($this->decodePrimaryKey($payment->metadata->client_id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // sometimes if the user is not returned to the site with a response from Mollie 
 | 
				
			||||||
 | 
					                // we may not have a payment record - in these cases we need to re-construct the payment
 | 
				
			||||||
 | 
					                // record from the meta data in the payment hash.
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $message = [
 | 
					            $message = [
 | 
				
			||||||
 | 
				
			|||||||
@ -136,6 +136,7 @@ class SquarePaymentDriver extends BaseDriver
 | 
				
			|||||||
        $amount_money->setCurrency($this->client->currency()->code);
 | 
					        $amount_money->setCurrency($this->client->currency()->code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $body = new \Square\Models\CreatePaymentRequest($cgt->token, \Illuminate\Support\Str::random(32), $amount_money);
 | 
					        $body = new \Square\Models\CreatePaymentRequest($cgt->token, \Illuminate\Support\Str::random(32), $amount_money);
 | 
				
			||||||
 | 
					        $body->setCustomerId($cgt->gateway_customer_reference);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** @var ApiResponse */
 | 
					        /** @var ApiResponse */
 | 
				
			||||||
        $response = $this->square->getPaymentsApi()->createPayment($body);
 | 
					        $response = $this->square->getPaymentsApi()->createPayment($body);
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ use App\Utils\PhantomJS\Phantom;
 | 
				
			|||||||
use App\Utils\Traits\Pdf\PdfMaker as PdfMakerTrait;
 | 
					use App\Utils\Traits\Pdf\PdfMaker as PdfMakerTrait;
 | 
				
			||||||
use Illuminate\Database\Eloquent\Collection;
 | 
					use Illuminate\Database\Eloquent\Collection;
 | 
				
			||||||
use Illuminate\Support\Facades\DB;
 | 
					use Illuminate\Support\Facades\DB;
 | 
				
			||||||
 | 
					use Illuminate\Support\LazyCollection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Statement
 | 
					class Statement
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -217,7 +218,7 @@ class Statement
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Invoice[]|\Illuminate\Database\Eloquent\Collection
 | 
					     * @return Invoice[]|\Illuminate\Database\Eloquent\Collection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getInvoices(): Collection
 | 
					    protected function getInvoices(): LazyCollection
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Invoice::withTrashed()
 | 
					        return Invoice::withTrashed()
 | 
				
			||||||
            ->where('is_deleted', false)
 | 
					            ->where('is_deleted', false)
 | 
				
			||||||
@ -226,7 +227,7 @@ class Statement
 | 
				
			|||||||
            ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL, Invoice::STATUS_PAID])
 | 
					            ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL, Invoice::STATUS_PAID])
 | 
				
			||||||
            ->whereBetween('date', [$this->options['start_date'], $this->options['end_date']])
 | 
					            ->whereBetween('date', [$this->options['start_date'], $this->options['end_date']])
 | 
				
			||||||
            ->orderBy('number', 'ASC')
 | 
					            ->orderBy('number', 'ASC')
 | 
				
			||||||
            ->get();
 | 
					            ->cursor();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -234,7 +235,7 @@ class Statement
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Payment[]|\Illuminate\Database\Eloquent\Collection
 | 
					     * @return Payment[]|\Illuminate\Database\Eloquent\Collection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getPayments(): Collection
 | 
					    protected function getPayments(): LazyCollection
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Payment::withTrashed()
 | 
					        return Payment::withTrashed()
 | 
				
			||||||
            ->with('client.country','invoices')
 | 
					            ->with('client.country','invoices')
 | 
				
			||||||
@ -244,7 +245,7 @@ class Statement
 | 
				
			|||||||
            ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
 | 
					            ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
 | 
				
			||||||
            ->whereBetween('date', [$this->options['start_date'], $this->options['end_date']])
 | 
					            ->whereBetween('date', [$this->options['start_date'], $this->options['end_date']])
 | 
				
			||||||
            ->orderBy('number', 'ASC')
 | 
					            ->orderBy('number', 'ASC')
 | 
				
			||||||
            ->get();
 | 
					            ->cursor();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -138,7 +138,7 @@ class InvoiceService
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        // $this->invoice = (new UpdateBalance($this->invoice, $balance_adjustment, $is_draft))->run();
 | 
					        // $this->invoice = (new UpdateBalance($this->invoice, $balance_adjustment, $is_draft))->run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->invoice->is_deleted) {
 | 
					        if ((bool)$this->invoice->is_deleted !== false) {
 | 
				
			||||||
            return $this;
 | 
					            return $this;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Utils\Traits\Notifications;
 | 
					namespace App\Utils\Traits\Notifications;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Client;
 | 
				
			||||||
 | 
					use App\Models\Credit;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\Payment;
 | 
				
			||||||
 | 
					use App\Models\Quote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class UserNotifies.
 | 
					 * Class UserNotifies.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -22,53 +28,100 @@ trait UserNotifies
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public function findUserNotificationTypes($invitation, $company_user, $entity_name, $required_permissions) :array
 | 
					    public function findUserNotificationTypes($invitation, $company_user, $entity_name, $required_permissions) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($company_user->company->is_disabled) {
 | 
					 | 
				
			||||||
            return [];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $notifiable_methods = [];
 | 
					        $notifiable_methods = [];
 | 
				
			||||||
        $notifications = $company_user->notifications;
 | 
					        $notifications = $company_user->notifications;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($company_user->company->is_disabled && is_array($notifications->email)) {
 | 
				
			||||||
 | 
					            return [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        //if a user owns this record or is assigned to it, they are attached the permission for notification.
 | 
					        //if a user owns this record or is assigned to it, they are attached the permission for notification.
 | 
				
			||||||
        if ($invitation->{$entity_name}->user_id == $company_user->_user_id || $invitation->{$entity_name}->assigned_user_id == $company_user->user_id) {
 | 
					        if ($invitation->{$entity_name}->user_id == $company_user->_user_id || $invitation->{$entity_name}->assigned_user_id == $company_user->user_id) {
 | 
				
			||||||
            array_push($required_permissions, 'all_user_notifications');
 | 
					            $required_permissions = $this->addSpecialUserPermissionForEntity($invitation->{$entity_name}, $required_permissions);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else{
 | 
				
			||||||
 | 
					            $required_permissions = $this->removeSpecialUserPermissionForEntity($invitation->{$entity_name}, $required_permissions);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count(array_intersect($required_permissions, $notifications->email)) >= 1 || count(array_intersect(['all_user_notifications'], $notifications->email)) >= 1 || count(array_intersect(['all_notifications'],$notifications->email)) >= 1) {
 | 
					        if (count(array_intersect($required_permissions, $notifications->email)) >= 1) {
 | 
				
			||||||
            array_push($notifiable_methods, 'mail');
 | 
					            array_push($notifiable_methods, 'mail');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // if(count(array_intersect($required_permissions, $notifications->slack)) >=1)
 | 
					 | 
				
			||||||
        //     array_push($notifiable_methods, 'slack');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $notifiable_methods;
 | 
					        return $notifiable_methods;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function findUserEntityNotificationType($entity, $company_user, $required_permissions) :array
 | 
					    public function findUserEntityNotificationType($entity, $company_user, array $required_permissions) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($company_user->company->is_disabled) {
 | 
					 | 
				
			||||||
            return [];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $notifiable_methods = [];
 | 
					        $notifiable_methods = [];
 | 
				
			||||||
        $notifications = $company_user->notifications;
 | 
					        $notifications = $company_user->notifications;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $notifications) {
 | 
					        if ($company_user->company->is_disabled || ! $notifications) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($entity->user_id == $company_user->_user_id || $entity->assigned_user_id == $company_user->user_id) {
 | 
					        if ($entity->user_id == $company_user->_user_id || $entity->assigned_user_id == $company_user->user_id) {
 | 
				
			||||||
            array_push($required_permissions, 'all_user_notifications');
 | 
					            $required_permissions = $this->addSpecialUserPermissionForEntity($entity, $required_permissions);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else{
 | 
				
			||||||
 | 
					            $required_permissions = $this->removeSpecialUserPermissionForEntity($entity, $required_permissions);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count(array_intersect($required_permissions, $notifications->email)) >= 1 || count(array_intersect(['all_user_notifications'], $notifications->email)) >= 1 || count(array_intersect(['all_notifications'],$notifications->email)) >= 1) {
 | 
					        if (count(array_intersect($required_permissions, $notifications->email)) >= 1) {
 | 
				
			||||||
            array_push($notifiable_methods, 'mail');
 | 
					            array_push($notifiable_methods, 'mail');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $notifiable_methods;
 | 
					        return $notifiable_methods;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function addSpecialUserPermissionForEntity($entity, array $required_permissions) :array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        array_merge($required_permissions, ["all_notifications"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch ($entity) {
 | 
				
			||||||
 | 
					            case ($entity instanceof Payment || $entity instanceof Client): //we pass client also as this is the proxy for Payment Failures (ie, there is no payment)
 | 
				
			||||||
 | 
					                return array_merge($required_permissions, ["all_notifications","all_user_notifications","payment_failure_user","payment_success_user"]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ($entity instanceof Invoice):
 | 
				
			||||||
 | 
					                return array_merge($required_permissions, ["all_notifications","all_user_notifications","invoice_created_user","invoice_sent_user","invoice_viewed_user","invoice_late_user"]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ($entity instanceof Quote):
 | 
				
			||||||
 | 
					                return array_merge($required_permissions, ["all_notifications","all_user_notifications","quote_created_user","quote_sent_user","quote_viewed_user","quote_approved_user","quote_expired_user"]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ($entity instanceof Credit):
 | 
				
			||||||
 | 
					                return array_merge($required_permissions, ["all_notifications","all_user_notifications","credit_created_user","credit_sent_user","credit_viewed_user"]);
 | 
				
			||||||
 | 
					                break;            
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                return [];
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function removeSpecialUserPermissionForEntity($entity, $required_permissions)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array_merge($required_permissions, ["all_notifications"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch ($entity) {
 | 
				
			||||||
 | 
					            case ($entity instanceof Payment || $entity instanceof Client): //we pass client also as this is the proxy for Payment Failures (ie, there is no payment)
 | 
				
			||||||
 | 
					                return array_diff($required_permissions, ["all_user_notifications","payment_failure_user","payment_success_user"]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ($entity instanceof Invoice):
 | 
				
			||||||
 | 
					                return array_diff($required_permissions, ["all_user_notifications","invoice_created_user","invoice_sent_user","invoice_viewed_user","invoice_late_user"]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ($entity instanceof Quote):
 | 
				
			||||||
 | 
					                return array_diff($required_permissions, ["all_user_notifications","quote_created_user","quote_sent_user","quote_viewed_user","quote_approved_user","quote_expired_user"]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ($entity instanceof Credit):
 | 
				
			||||||
 | 
					                return array_diff($required_permissions, ["all_user_notifications","credit_created_user","credit_sent_user","credit_viewed_user"]);
 | 
				
			||||||
 | 
					                break;            
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                // code...
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function findCompanyUserNotificationType($company_user, $required_permissions) :array
 | 
					    public function findCompanyUserNotificationType($company_user, $required_permissions) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "type": "project",
 | 
					    "type": "project",
 | 
				
			||||||
    "require": {
 | 
					    "require": {
 | 
				
			||||||
        "php": "^7.4|^8.0",
 | 
					        "php": "^7.4|^8",
 | 
				
			||||||
        "ext-dom": "*",
 | 
					        "ext-dom": "*",
 | 
				
			||||||
        "ext-json": "*",
 | 
					        "ext-json": "*",
 | 
				
			||||||
        "ext-libxml": "*",
 | 
					        "ext-libxml": "*",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										78
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										78
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@ -4,7 +4,7 @@
 | 
				
			|||||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
					        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
				
			||||||
        "This file is @generated automatically"
 | 
					        "This file is @generated automatically"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "content-hash": "da1e6c59711334fd5dca75d2adb884d8",
 | 
					    "content-hash": "cd912a40faea3a658298daa4b17a7f25",
 | 
				
			||||||
    "packages": [
 | 
					    "packages": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "apimatic/jsonmapper",
 | 
					            "name": "apimatic/jsonmapper",
 | 
				
			||||||
@ -323,16 +323,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "aws/aws-sdk-php",
 | 
					            "name": "aws/aws-sdk-php",
 | 
				
			||||||
            "version": "3.204.5",
 | 
					            "version": "3.204.6",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/aws/aws-sdk-php.git",
 | 
					                "url": "https://github.com/aws/aws-sdk-php.git",
 | 
				
			||||||
                "reference": "1f690db4dfd66d0c729f4f8db12431bb047b4900"
 | 
					                "reference": "59d4d6a58ed7da541aa0ed75cc1944f8d6ca2d1c"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1f690db4dfd66d0c729f4f8db12431bb047b4900",
 | 
					                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/59d4d6a58ed7da541aa0ed75cc1944f8d6ca2d1c",
 | 
				
			||||||
                "reference": "1f690db4dfd66d0c729f4f8db12431bb047b4900",
 | 
					                "reference": "59d4d6a58ed7da541aa0ed75cc1944f8d6ca2d1c",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -408,9 +408,9 @@
 | 
				
			|||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
 | 
					                "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
 | 
				
			||||||
                "issues": "https://github.com/aws/aws-sdk-php/issues",
 | 
					                "issues": "https://github.com/aws/aws-sdk-php/issues",
 | 
				
			||||||
                "source": "https://github.com/aws/aws-sdk-php/tree/3.204.5"
 | 
					                "source": "https://github.com/aws/aws-sdk-php/tree/3.204.6"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2021-11-24T19:13:34+00:00"
 | 
					            "time": "2021-11-26T19:18:52+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "bacon/bacon-qr-code",
 | 
					            "name": "bacon/bacon-qr-code",
 | 
				
			||||||
@ -1735,36 +1735,38 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "doctrine/dbal",
 | 
					            "name": "doctrine/dbal",
 | 
				
			||||||
            "version": "3.1.4",
 | 
					            "version": "3.2.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/doctrine/dbal.git",
 | 
					                "url": "https://github.com/doctrine/dbal.git",
 | 
				
			||||||
                "reference": "821b4f01a36ce63ed36c090ea74767b72db367e9"
 | 
					                "reference": "5d54f63541d7bed1156cb5c9b79274ced61890e4"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/doctrine/dbal/zipball/821b4f01a36ce63ed36c090ea74767b72db367e9",
 | 
					                "url": "https://api.github.com/repos/doctrine/dbal/zipball/5d54f63541d7bed1156cb5c9b79274ced61890e4",
 | 
				
			||||||
                "reference": "821b4f01a36ce63ed36c090ea74767b72db367e9",
 | 
					                "reference": "5d54f63541d7bed1156cb5c9b79274ced61890e4",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
                "composer/package-versions-deprecated": "^1.11.99",
 | 
					                "composer/package-versions-deprecated": "^1.11.99",
 | 
				
			||||||
                "doctrine/cache": "^1.0|^2.0",
 | 
					                "doctrine/cache": "^1.11|^2.0",
 | 
				
			||||||
                "doctrine/deprecations": "^0.5.3",
 | 
					                "doctrine/deprecations": "^0.5.3",
 | 
				
			||||||
                "doctrine/event-manager": "^1.0",
 | 
					                "doctrine/event-manager": "^1.0",
 | 
				
			||||||
                "php": "^7.3 || ^8.0"
 | 
					                "php": "^7.3 || ^8.0",
 | 
				
			||||||
 | 
					                "psr/cache": "^1|^2|^3",
 | 
				
			||||||
 | 
					                "psr/log": "^1|^2|^3"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require-dev": {
 | 
					            "require-dev": {
 | 
				
			||||||
                "doctrine/coding-standard": "9.0.0",
 | 
					                "doctrine/coding-standard": "9.0.0",
 | 
				
			||||||
                "jetbrains/phpstorm-stubs": "2021.1",
 | 
					                "jetbrains/phpstorm-stubs": "2021.1",
 | 
				
			||||||
                "phpstan/phpstan": "1.1.1",
 | 
					                "phpstan/phpstan": "1.2.0",
 | 
				
			||||||
                "phpstan/phpstan-strict-rules": "^1",
 | 
					                "phpstan/phpstan-strict-rules": "^1.1",
 | 
				
			||||||
                "phpunit/phpunit": "9.5.10",
 | 
					                "phpunit/phpunit": "9.5.10",
 | 
				
			||||||
                "psalm/plugin-phpunit": "0.16.1",
 | 
					                "psalm/plugin-phpunit": "0.16.1",
 | 
				
			||||||
                "squizlabs/php_codesniffer": "3.6.1",
 | 
					                "squizlabs/php_codesniffer": "3.6.1",
 | 
				
			||||||
                "symfony/cache": "^5.2|^6.0",
 | 
					                "symfony/cache": "^5.2|^6.0",
 | 
				
			||||||
                "symfony/console": "^2.0.5|^3.0|^4.0|^5.0|^6.0",
 | 
					                "symfony/console": "^2.0.5|^3.0|^4.0|^5.0|^6.0",
 | 
				
			||||||
                "vimeo/psalm": "4.12.0"
 | 
					                "vimeo/psalm": "4.13.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "suggest": {
 | 
					            "suggest": {
 | 
				
			||||||
                "symfony/console": "For helpful console commands such as SQL execution and import of files."
 | 
					                "symfony/console": "For helpful console commands such as SQL execution and import of files."
 | 
				
			||||||
@ -1824,7 +1826,7 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/doctrine/dbal/issues",
 | 
					                "issues": "https://github.com/doctrine/dbal/issues",
 | 
				
			||||||
                "source": "https://github.com/doctrine/dbal/tree/3.1.4"
 | 
					                "source": "https://github.com/doctrine/dbal/tree/3.2.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "funding": [
 | 
					            "funding": [
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -1840,7 +1842,7 @@
 | 
				
			|||||||
                    "type": "tidelift"
 | 
					                    "type": "tidelift"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "time": "2021-11-15T16:44:33+00:00"
 | 
					            "time": "2021-11-26T21:00:12+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "doctrine/deprecations",
 | 
					            "name": "doctrine/deprecations",
 | 
				
			||||||
@ -4589,16 +4591,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "league/flysystem",
 | 
					            "name": "league/flysystem",
 | 
				
			||||||
            "version": "1.1.6",
 | 
					            "version": "1.1.7",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/thephpleague/flysystem.git",
 | 
					                "url": "https://github.com/thephpleague/flysystem.git",
 | 
				
			||||||
                "reference": "627be7fcde84c71aa0f15097fcf48fd5f2be5287"
 | 
					                "reference": "3ca8f158ee21efa4bbd4f74bea5730c9b9261e2d"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/627be7fcde84c71aa0f15097fcf48fd5f2be5287",
 | 
					                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3ca8f158ee21efa4bbd4f74bea5730c9b9261e2d",
 | 
				
			||||||
                "reference": "627be7fcde84c71aa0f15097fcf48fd5f2be5287",
 | 
					                "reference": "3ca8f158ee21efa4bbd4f74bea5730c9b9261e2d",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -4671,7 +4673,7 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/thephpleague/flysystem/issues",
 | 
					                "issues": "https://github.com/thephpleague/flysystem/issues",
 | 
				
			||||||
                "source": "https://github.com/thephpleague/flysystem/tree/1.1.6"
 | 
					                "source": "https://github.com/thephpleague/flysystem/tree/1.1.7"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "funding": [
 | 
					            "funding": [
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -4679,7 +4681,7 @@
 | 
				
			|||||||
                    "type": "other"
 | 
					                    "type": "other"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "time": "2021-11-21T11:04:36+00:00"
 | 
					            "time": "2021-11-25T19:40:58+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "league/flysystem-aws-s3-v3",
 | 
					            "name": "league/flysystem-aws-s3-v3",
 | 
				
			||||||
@ -6427,16 +6429,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "php-http/client-common",
 | 
					            "name": "php-http/client-common",
 | 
				
			||||||
            "version": "2.4.0",
 | 
					            "version": "2.5.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/php-http/client-common.git",
 | 
					                "url": "https://github.com/php-http/client-common.git",
 | 
				
			||||||
                "reference": "29e0c60d982f04017069483e832b92074d0a90b2"
 | 
					                "reference": "d135751167d57e27c74de674d6a30cef2dc8e054"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/php-http/client-common/zipball/29e0c60d982f04017069483e832b92074d0a90b2",
 | 
					                "url": "https://api.github.com/repos/php-http/client-common/zipball/d135751167d57e27c74de674d6a30cef2dc8e054",
 | 
				
			||||||
                "reference": "29e0c60d982f04017069483e832b92074d0a90b2",
 | 
					                "reference": "d135751167d57e27c74de674d6a30cef2dc8e054",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -6447,14 +6449,14 @@
 | 
				
			|||||||
                "psr/http-client": "^1.0",
 | 
					                "psr/http-client": "^1.0",
 | 
				
			||||||
                "psr/http-factory": "^1.0",
 | 
					                "psr/http-factory": "^1.0",
 | 
				
			||||||
                "psr/http-message": "^1.0",
 | 
					                "psr/http-message": "^1.0",
 | 
				
			||||||
                "symfony/options-resolver": "^2.6 || ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0",
 | 
					                "symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0",
 | 
				
			||||||
                "symfony/polyfill-php80": "^1.17"
 | 
					                "symfony/polyfill-php80": "^1.17"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require-dev": {
 | 
					            "require-dev": {
 | 
				
			||||||
                "doctrine/instantiator": "^1.1",
 | 
					                "doctrine/instantiator": "^1.1",
 | 
				
			||||||
                "guzzlehttp/psr7": "^1.4",
 | 
					                "guzzlehttp/psr7": "^1.4",
 | 
				
			||||||
                "nyholm/psr7": "^1.2",
 | 
					                "nyholm/psr7": "^1.2",
 | 
				
			||||||
                "phpspec/phpspec": "^5.1 || ^6.0",
 | 
					                "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
 | 
				
			||||||
                "phpspec/prophecy": "^1.10.2",
 | 
					                "phpspec/prophecy": "^1.10.2",
 | 
				
			||||||
                "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3"
 | 
					                "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
@ -6496,9 +6498,9 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/php-http/client-common/issues",
 | 
					                "issues": "https://github.com/php-http/client-common/issues",
 | 
				
			||||||
                "source": "https://github.com/php-http/client-common/tree/2.4.0"
 | 
					                "source": "https://github.com/php-http/client-common/tree/2.5.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2021-07-05T08:19:25+00:00"
 | 
					            "time": "2021-11-26T15:01:24+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "php-http/discovery",
 | 
					            "name": "php-http/discovery",
 | 
				
			||||||
@ -12585,16 +12587,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "facade/ignition",
 | 
					            "name": "facade/ignition",
 | 
				
			||||||
            "version": "2.17.0",
 | 
					            "version": "2.17.1",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/facade/ignition.git",
 | 
					                "url": "https://github.com/facade/ignition.git",
 | 
				
			||||||
                "reference": "28d12b473ffcbe326959385772fd5125c73bc974"
 | 
					                "reference": "317f6110c1977b50e06365bbb155fbe5079035ec"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/facade/ignition/zipball/28d12b473ffcbe326959385772fd5125c73bc974",
 | 
					                "url": "https://api.github.com/repos/facade/ignition/zipball/317f6110c1977b50e06365bbb155fbe5079035ec",
 | 
				
			||||||
                "reference": "28d12b473ffcbe326959385772fd5125c73bc974",
 | 
					                "reference": "317f6110c1977b50e06365bbb155fbe5079035ec",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -12659,7 +12661,7 @@
 | 
				
			|||||||
                "issues": "https://github.com/facade/ignition/issues",
 | 
					                "issues": "https://github.com/facade/ignition/issues",
 | 
				
			||||||
                "source": "https://github.com/facade/ignition"
 | 
					                "source": "https://github.com/facade/ignition"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2021-11-24T08:47:21+00:00"
 | 
					            "time": "2021-11-25T10:26:30+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "facade/ignition-contracts",
 | 
					            "name": "facade/ignition-contracts",
 | 
				
			||||||
@ -15611,7 +15613,7 @@
 | 
				
			|||||||
    "prefer-stable": true,
 | 
					    "prefer-stable": true,
 | 
				
			||||||
    "prefer-lowest": false,
 | 
					    "prefer-lowest": false,
 | 
				
			||||||
    "platform": {
 | 
					    "platform": {
 | 
				
			||||||
        "php": "^7.4|^8.0",
 | 
					        "php": "^7.4|^8",
 | 
				
			||||||
        "ext-dom": "*",
 | 
					        "ext-dom": "*",
 | 
				
			||||||
        "ext-json": "*",
 | 
					        "ext-json": "*",
 | 
				
			||||||
        "ext-libxml": "*"
 | 
					        "ext-libxml": "*"
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,9 @@ CREATE TABLE `accounts` (
 | 
				
			|||||||
  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
					  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
  `is_scheduler_running` tinyint(1) NOT NULL DEFAULT '0',
 | 
					  `is_scheduler_running` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
  `trial_duration` int(10) unsigned DEFAULT NULL,
 | 
					  `trial_duration` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `is_onboarding` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `onboarding` mediumtext COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
 | 
					  `is_migrated` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  KEY `accounts_payment_id_index` (`payment_id`)
 | 
					  KEY `accounts_payment_id_index` (`payment_id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
 | 
				
			||||||
@ -66,6 +69,8 @@ CREATE TABLE `activities` (
 | 
				
			|||||||
  `quote_id` int(10) unsigned DEFAULT NULL,
 | 
					  `quote_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
  `subscription_id` int(10) unsigned DEFAULT NULL,
 | 
					  `subscription_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
  `recurring_invoice_id` int(10) unsigned DEFAULT NULL,
 | 
					  `recurring_invoice_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `recurring_expense_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `recurring_quote_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  KEY `activities_vendor_id_company_id_index` (`vendor_id`,`company_id`),
 | 
					  KEY `activities_vendor_id_company_id_index` (`vendor_id`,`company_id`),
 | 
				
			||||||
  KEY `activities_project_id_company_id_index` (`project_id`,`company_id`),
 | 
					  KEY `activities_project_id_company_id_index` (`project_id`,`company_id`),
 | 
				
			||||||
@ -93,6 +98,7 @@ CREATE TABLE `backups` (
 | 
				
			|||||||
  `created_at` timestamp(6) NULL DEFAULT NULL,
 | 
					  `created_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
					  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
  `amount` decimal(16,4) NOT NULL,
 | 
					  `amount` decimal(16,4) NOT NULL,
 | 
				
			||||||
 | 
					  `filename` text COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  KEY `backups_activity_id_foreign` (`activity_id`),
 | 
					  KEY `backups_activity_id_foreign` (`activity_id`),
 | 
				
			||||||
  CONSTRAINT `backups_activity_id_foreign` FOREIGN KEY (`activity_id`) REFERENCES `activities` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
					  CONSTRAINT `backups_activity_id_foreign` FOREIGN KEY (`activity_id`) REFERENCES `activities` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
				
			||||||
@ -378,6 +384,7 @@ CREATE TABLE `companies` (
 | 
				
			|||||||
  `markdown_enabled` tinyint(1) NOT NULL DEFAULT '1',
 | 
					  `markdown_enabled` tinyint(1) NOT NULL DEFAULT '1',
 | 
				
			||||||
  `use_comma_as_decimal_place` tinyint(1) NOT NULL DEFAULT '0',
 | 
					  `use_comma_as_decimal_place` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
  `report_include_drafts` tinyint(1) NOT NULL DEFAULT '0',
 | 
					  `report_include_drafts` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `client_registration_fields` mediumtext COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  UNIQUE KEY `companies_company_key_unique` (`company_key`),
 | 
					  UNIQUE KEY `companies_company_key_unique` (`company_key`),
 | 
				
			||||||
  KEY `companies_industry_id_foreign` (`industry_id`),
 | 
					  KEY `companies_industry_id_foreign` (`industry_id`),
 | 
				
			||||||
@ -1371,6 +1378,69 @@ CREATE TABLE `quotes` (
 | 
				
			|||||||
  CONSTRAINT `quotes_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
					  CONSTRAINT `quotes_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
 | 
				
			||||||
/*!40101 SET character_set_client = @saved_cs_client */;
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `recurring_expenses`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `recurring_expenses` (
 | 
				
			||||||
 | 
					  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `created_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `deleted_at` timestamp NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `company_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `vendor_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `user_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `status_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `invoice_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `client_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `bank_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `project_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `payment_type_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `recurring_expense_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `uses_inclusive_taxes` tinyint(1) NOT NULL DEFAULT '1',
 | 
				
			||||||
 | 
					  `tax_name1` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_name2` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_name3` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `date` date DEFAULT NULL,
 | 
				
			||||||
 | 
					  `payment_date` date DEFAULT NULL,
 | 
				
			||||||
 | 
					  `should_be_invoiced` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `invoice_documents` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `transaction_id` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_value1` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_value2` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_value3` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_value4` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `category_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `calculate_tax_by_amount` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `tax_amount1` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_amount2` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_amount3` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_rate1` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_rate2` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `tax_rate3` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `amount` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `foreign_amount` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `exchange_rate` decimal(20,6) NOT NULL DEFAULT '1.000000',
 | 
				
			||||||
 | 
					  `assigned_user_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `number` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `invoice_currency_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `currency_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `private_notes` text COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
 | 
					  `public_notes` text COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
 | 
					  `transaction_reference` text COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
 | 
					  `frequency_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `last_sent_date` datetime DEFAULT NULL,
 | 
				
			||||||
 | 
					  `next_send_date` datetime DEFAULT NULL,
 | 
				
			||||||
 | 
					  `remaining_cycles` int(11) DEFAULT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  UNIQUE KEY `recurring_expenses_company_id_number_unique` (`company_id`,`number`),
 | 
				
			||||||
 | 
					  KEY `recurring_expenses_company_id_deleted_at_index` (`company_id`,`deleted_at`),
 | 
				
			||||||
 | 
					  KEY `recurring_expenses_user_id_foreign` (`user_id`),
 | 
				
			||||||
 | 
					  KEY `recurring_expenses_company_id_index` (`company_id`),
 | 
				
			||||||
 | 
					  CONSTRAINT `recurring_expenses_company_id_foreign` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 | 
				
			||||||
 | 
					  CONSTRAINT `recurring_expenses_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
DROP TABLE IF EXISTS `recurring_invoice_invitations`;
 | 
					DROP TABLE IF EXISTS `recurring_invoice_invitations`;
 | 
				
			||||||
/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
/*!40101 SET character_set_client = utf8 */;
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
@ -1481,6 +1551,41 @@ CREATE TABLE `recurring_invoices` (
 | 
				
			|||||||
  CONSTRAINT `recurring_invoices_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
					  CONSTRAINT `recurring_invoices_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
 | 
				
			||||||
/*!40101 SET character_set_client = @saved_cs_client */;
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `recurring_quote_invitations`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `recurring_quote_invitations` (
 | 
				
			||||||
 | 
					  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `company_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `user_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `client_contact_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `recurring_quote_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
 | 
					  `key` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
 | 
				
			||||||
 | 
					  `transaction_reference` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `message_id` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `email_error` mediumtext COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
 | 
					  `signature_base64` text COLLATE utf8mb4_unicode_ci,
 | 
				
			||||||
 | 
					  `signature_date` datetime DEFAULT NULL,
 | 
				
			||||||
 | 
					  `sent_date` datetime DEFAULT NULL,
 | 
				
			||||||
 | 
					  `viewed_date` datetime DEFAULT NULL,
 | 
				
			||||||
 | 
					  `opened_date` datetime DEFAULT NULL,
 | 
				
			||||||
 | 
					  `email_status` enum('delivered','bounced','spam') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `created_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `deleted_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  UNIQUE KEY `cli_rec_q` (`client_contact_id`,`recurring_quote_id`),
 | 
				
			||||||
 | 
					  KEY `recurring_quote_invitations_user_id_foreign` (`user_id`),
 | 
				
			||||||
 | 
					  KEY `recurring_quote_invitations_company_id_foreign` (`company_id`),
 | 
				
			||||||
 | 
					  KEY `rec_co_del_q` (`deleted_at`,`recurring_quote_id`,`company_id`),
 | 
				
			||||||
 | 
					  KEY `recurring_quote_invitations_recurring_quote_id_index` (`recurring_quote_id`),
 | 
				
			||||||
 | 
					  KEY `recurring_quote_invitations_key_index` (`key`),
 | 
				
			||||||
 | 
					  CONSTRAINT `recurring_quote_invitations_client_contact_id_foreign` FOREIGN KEY (`client_contact_id`) REFERENCES `client_contacts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 | 
				
			||||||
 | 
					  CONSTRAINT `recurring_quote_invitations_company_id_foreign` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 | 
				
			||||||
 | 
					  CONSTRAINT `recurring_quote_invitations_recurring_quote_id_foreign` FOREIGN KEY (`recurring_quote_id`) REFERENCES `recurring_invoices` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 | 
				
			||||||
 | 
					  CONSTRAINT `recurring_quote_invitations_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
DROP TABLE IF EXISTS `recurring_quotes`;
 | 
					DROP TABLE IF EXISTS `recurring_quotes`;
 | 
				
			||||||
/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
/*!40101 SET character_set_client = utf8 */;
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
@ -1521,13 +1626,29 @@ CREATE TABLE `recurring_quotes` (
 | 
				
			|||||||
  `balance` decimal(20,6) NOT NULL DEFAULT '0.000000',
 | 
					  `balance` decimal(20,6) NOT NULL DEFAULT '0.000000',
 | 
				
			||||||
  `last_viewed` datetime DEFAULT NULL,
 | 
					  `last_viewed` datetime DEFAULT NULL,
 | 
				
			||||||
  `frequency_id` int(10) unsigned NOT NULL,
 | 
					  `frequency_id` int(10) unsigned NOT NULL,
 | 
				
			||||||
  `start_date` date DEFAULT NULL,
 | 
					 | 
				
			||||||
  `last_sent_date` datetime DEFAULT NULL,
 | 
					  `last_sent_date` datetime DEFAULT NULL,
 | 
				
			||||||
  `next_send_date` datetime DEFAULT NULL,
 | 
					  `next_send_date` datetime DEFAULT NULL,
 | 
				
			||||||
  `remaining_cycles` int(10) unsigned DEFAULT NULL,
 | 
					  `remaining_cycles` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
  `created_at` timestamp(6) NULL DEFAULT NULL,
 | 
					  `created_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
					  `updated_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
  `deleted_at` timestamp(6) NULL DEFAULT NULL,
 | 
					  `deleted_at` timestamp(6) NULL DEFAULT NULL,
 | 
				
			||||||
 | 
					  `auto_bill` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'off',
 | 
				
			||||||
 | 
					  `auto_bill_enabled` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `paid_to_date` decimal(20,6) NOT NULL DEFAULT '0.000000',
 | 
				
			||||||
 | 
					  `custom_surcharge1` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_surcharge2` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_surcharge3` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_surcharge4` decimal(20,6) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `custom_surcharge_tax1` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `custom_surcharge_tax2` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `custom_surcharge_tax3` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `custom_surcharge_tax4` tinyint(1) NOT NULL DEFAULT '0',
 | 
				
			||||||
 | 
					  `due_date_days` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 | 
				
			||||||
 | 
					  `exchange_rate` decimal(13,6) NOT NULL DEFAULT '1.000000',
 | 
				
			||||||
 | 
					  `partial` decimal(16,4) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `partial_due_date` date DEFAULT NULL,
 | 
				
			||||||
 | 
					  `subscription_id` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `uses_inclusive_taxes` tinyint(1) NOT NULL DEFAULT '1',
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  KEY `recurring_quotes_company_id_deleted_at_index` (`company_id`,`deleted_at`),
 | 
					  KEY `recurring_quotes_company_id_deleted_at_index` (`company_id`,`deleted_at`),
 | 
				
			||||||
  KEY `recurring_quotes_user_id_foreign` (`user_id`),
 | 
					  KEY `recurring_quotes_user_id_foreign` (`user_id`),
 | 
				
			||||||
@ -1973,3 +2094,25 @@ INSERT INTO `migrations` VALUES (91,'2021_08_10_034407_add_more_languages',4);
 | 
				
			|||||||
INSERT INTO `migrations` VALUES (92,'2021_08_18_220124_use_comma_as_decimal_place_companies_table',4);
 | 
					INSERT INTO `migrations` VALUES (92,'2021_08_18_220124_use_comma_as_decimal_place_companies_table',4);
 | 
				
			||||||
INSERT INTO `migrations` VALUES (93,'2021_08_24_115919_update_designs',4);
 | 
					INSERT INTO `migrations` VALUES (93,'2021_08_24_115919_update_designs',4);
 | 
				
			||||||
INSERT INTO `migrations` VALUES (94,'2021_08_25_093105_report_include_drafts_in_companies_table',5);
 | 
					INSERT INTO `migrations` VALUES (94,'2021_08_25_093105_report_include_drafts_in_companies_table',5);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (95,'2021_08_14_054458_square_payment_driver',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (96,'2021_08_23_101529_recurring_expenses_schema',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (97,'2021_09_05_101209_update_braintree_gateway',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (98,'2021_09_20_233053_set_square_test_mode_boolean',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (99,'2021_09_23_100629_add_currencies',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (100,'2021_09_24_201319_add_mollie_bank_transfer_to_payment_types',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (101,'2021_09_24_211504_add_kbc_to_payment_types',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (102,'2021_09_24_213858_add_bancontact_to_payment_types',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (103,'2021_09_28_154647_activate_gocardless_payment_driver',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (104,'2021_09_29_190258_add_required_client_registration_fields',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (105,'2021_10_04_134908_add_ideal_to_payment_types',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (106,'2021_10_06_044800_updated_bold_and_modern_designs',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (107,'2021_10_07_141737_razorpay',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (108,'2021_10_07_155410_add_hosted_page_to_payment_types',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (109,'2021_10_15_00000_stripe_payment_gateways',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (110,'2021_10_16_135200_add_direct_debit_to_payment_types',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (111,'2021_10_19_142200_add_gateway_type_for_direct_debit',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (112,'2021_10_20_005529_add_filename_to_backups_table',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (113,'2021_11_08_131308_onboarding',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (114,'2021_11_09_115919_update_designs',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (115,'2021_11_10_184847_add_is_migrate_column_to_accounts_table',6);
 | 
				
			||||||
 | 
					INSERT INTO `migrations` VALUES (116,'2021_11_11_163121_add_instant_bank_transfer',7);
 | 
				
			||||||
 | 
				
			|||||||
@ -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' => '{"apiKey":"", "publishableKey":""}'],
 | 
					            ['id' => 20, 'name' => 'Stripe', 'provider' => 'Stripe', 'sort_order' => 1, 'key' => 'd14dd26a37cecc30fdd65700bfb55b23', 'fields' => '{"publishableKey":"","apiKey":""}'],
 | 
				
			||||||
            ['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":""}'],
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@
 | 
				
			|||||||
  <php>
 | 
					  <php>
 | 
				
			||||||
    <env name="APP_ENV" value="testing"/>
 | 
					    <env name="APP_ENV" value="testing"/>
 | 
				
			||||||
    <env name="BCRYPT_ROUNDS" value="4"/>
 | 
					    <env name="BCRYPT_ROUNDS" value="4"/>
 | 
				
			||||||
    <env name="CACHE_DRIVER" value="array"/>
 | 
					    <env name="CACHE_DRIVER" value="file"/>
 | 
				
			||||||
    <env name="SESSION_DRIVER" value="array"/>
 | 
					    <env name="SESSION_DRIVER" value="array"/>
 | 
				
			||||||
    <env name="QUEUE_CONNECTION" value="sync"/>
 | 
					    <env name="QUEUE_CONNECTION" value="sync"/>
 | 
				
			||||||
    <env name="MAIL_MAILER" value="array"/>
 | 
					    <env name="MAIL_MAILER" value="array"/>
 | 
				
			||||||
 | 
				
			|||||||
@ -71,7 +71,7 @@ class CreditTest extends TestCase
 | 
				
			|||||||
    public function testCreditRESTEndPoints()
 | 
					    public function testCreditRESTEndPoints()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $response = $this->withHeaders([
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
            'X-API-SECRET' => config('ninja.api_secret'),
 | 
					        'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
            'X-API-TOKEN' => $this->token,
 | 
					            'X-API-TOKEN' => $this->token,
 | 
				
			||||||
        ])->get('/api/v1/credits/'.$this->encodePrimaryKey($this->credit->id));
 | 
					        ])->get('/api/v1/credits/'.$this->encodePrimaryKey($this->credit->id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -104,7 +104,7 @@ class CreditTest extends TestCase
 | 
				
			|||||||
            'number' => 'dfdfd',
 | 
					            'number' => 'dfdfd',
 | 
				
			||||||
            'discount' => 0,
 | 
					            'discount' => 0,
 | 
				
			||||||
            'is_amount_discount' => 1,
 | 
					            'is_amount_discount' => 1,
 | 
				
			||||||
            'number' => '3434343',
 | 
					            'number' => '34343xx43',
 | 
				
			||||||
            'public_notes' => 'notes',
 | 
					            'public_notes' => 'notes',
 | 
				
			||||||
            'is_deleted' => 0,
 | 
					            'is_deleted' => 0,
 | 
				
			||||||
            'custom_value1' => 0,
 | 
					            'custom_value1' => 0,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user