mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 23:37:33 -05:00 
			
		
		
		
	Merge pull request #4239 from turbo124/v5-develop
Version Bump + linking tasks and expenses to invoices
This commit is contained in:
		
						commit
						959e4936cd
					
				
							
								
								
									
										1
									
								
								.env.ci
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								.env.ci
									
									
									
									
									
								
							@ -19,3 +19,4 @@ DB_HOST=127.0.0.1
 | 
				
			|||||||
NINJA_ENVIRONMENT=hosted
 | 
					NINJA_ENVIRONMENT=hosted
 | 
				
			||||||
COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
 | 
					COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
 | 
				
			||||||
TRAVIS=true
 | 
					TRAVIS=true
 | 
				
			||||||
 | 
					API_SECRET=superdoopersecrethere
 | 
				
			||||||
 | 
				
			|||||||
@ -55,10 +55,5 @@ NINJA_ENVIRONMENT=selfhost
 | 
				
			|||||||
PHANTOMJS_KEY='a-demo-key-with-low-quota-per-ip-address'
 | 
					PHANTOMJS_KEY='a-demo-key-with-low-quota-per-ip-address'
 | 
				
			||||||
PHANTOMJS_SECRET=
 | 
					PHANTOMJS_SECRET=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SELF_UPDATER_REPO_VENDOR = invoiceninja
 | 
					 | 
				
			||||||
SELF_UPDATER_REPO_NAME = invoiceninja
 | 
					 | 
				
			||||||
SELF_UPDATER_USE_BRANCH = v2
 | 
					 | 
				
			||||||
SELF_UPDATER_MAILTO_ADDRESS = user@example.com
 | 
					 | 
				
			||||||
SELF_UPDATER_MAILTO_NAME = "John Doe"
 | 
					 | 
				
			||||||
COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
 | 
					COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
 | 
				
			||||||
SENTRY_LARAVEL_DSN=https://cc7e8e2c678041689e53e409b7dba236@sentry.invoicing.co/5
 | 
					SENTRY_LARAVEL_DSN=https://cc7e8e2c678041689e53e409b7dba236@sentry.invoicing.co/5
 | 
				
			||||||
@ -1 +1 @@
 | 
				
			|||||||
5.0.22
 | 
					5.0.23
 | 
				
			||||||
 | 
				
			|||||||
@ -507,7 +507,7 @@ class CompanySettings extends BaseSettings
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Provides class defaults on init.
 | 
					     * Provides class defaults on init.
 | 
				
			||||||
     * @return object
 | 
					     * @return stdClass
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function defaults(): stdClass
 | 
					    public static function defaults(): stdClass
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -149,7 +149,7 @@ class FreeCompanySettings extends BaseSettings
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Provides class defaults on init.
 | 
					     * Provides class defaults on init.
 | 
				
			||||||
     * @return object
 | 
					     * @return stdClass
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function defaults(): stdClass
 | 
					    public static function defaults(): stdClass
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
namespace App\Exceptions;
 | 
					namespace App\Exceptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Exceptions\GenericPaymentDriverFailure;
 | 
					use App\Exceptions\GenericPaymentDriverFailure;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
use Exception;
 | 
					use Exception;
 | 
				
			||||||
use Illuminate\Auth\Access\AuthorizationException;
 | 
					use Illuminate\Auth\Access\AuthorizationException;
 | 
				
			||||||
use Illuminate\Auth\AuthenticationException;
 | 
					use Illuminate\Auth\AuthenticationException;
 | 
				
			||||||
@ -27,14 +28,14 @@ use Illuminate\Support\Arr;
 | 
				
			|||||||
use Illuminate\Support\Facades\Schema;
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
use Illuminate\Validation\ValidationException;
 | 
					use Illuminate\Validation\ValidationException;
 | 
				
			||||||
use PDOException;
 | 
					use PDOException;
 | 
				
			||||||
 | 
					use Sentry\State\Scope;
 | 
				
			||||||
use Swift_TransportException;
 | 
					use Swift_TransportException;
 | 
				
			||||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
 | 
					use Symfony\Component\Console\Exception\CommandNotFoundException;
 | 
				
			||||||
use function Sentry\configureScope;
 | 
					 | 
				
			||||||
use Sentry\State\Scope;
 | 
					 | 
				
			||||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
 | 
					use Symfony\Component\Debug\Exception\FatalThrowableError;
 | 
				
			||||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
 | 
					use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
 | 
				
			||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 | 
					use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 | 
				
			||||||
use Throwable;
 | 
					use Throwable;
 | 
				
			||||||
 | 
					use function Sentry\configureScope;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Handler extends ExceptionHandler
 | 
					class Handler extends ExceptionHandler
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -71,9 +72,12 @@ class Handler extends ExceptionHandler
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! Schema::hasTable('accounts')) {
 | 
					        if (! Schema::hasTable('accounts')) {
 | 
				
			||||||
            info('account table not found');
 | 
					            info('account table not found');
 | 
				
			||||||
 | 
					 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        // if(Account::count() == 0){
 | 
				
			||||||
 | 
					        //     info("handler - account table not found");
 | 
				
			||||||
 | 
					        //     return;
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (app()->bound('sentry') && $this->shouldReport($exception)) {
 | 
					        if (app()->bound('sentry') && $this->shouldReport($exception)) {
 | 
				
			||||||
            app('sentry')->configureScope(function (Scope $scope): void {
 | 
					            app('sentry')->configureScope(function (Scope $scope): void {
 | 
				
			||||||
 | 
				
			|||||||
@ -87,11 +87,6 @@ class SetupController extends Controller
 | 
				
			|||||||
        $_ENV['MAIL_FROM_ADDRESS'] = $request->input('mail_address');
 | 
					        $_ENV['MAIL_FROM_ADDRESS'] = $request->input('mail_address');
 | 
				
			||||||
        $_ENV['MAIL_PASSWORD'] = $request->input('mail_password');
 | 
					        $_ENV['MAIL_PASSWORD'] = $request->input('mail_password');
 | 
				
			||||||
        $_ENV['NINJA_ENVIRONMENT'] = 'selfhost';
 | 
					        $_ENV['NINJA_ENVIRONMENT'] = 'selfhost';
 | 
				
			||||||
        $_ENV['SELF_UPDATER_REPO_VENDOR'] = 'invoiceninja';
 | 
					 | 
				
			||||||
        $_ENV['SELF_UPDATER_REPO_NAME'] = 'invoiceninja';
 | 
					 | 
				
			||||||
        $_ENV['SELF_UPDATER_USE_BRANCH'] = 'v2';
 | 
					 | 
				
			||||||
        $_ENV['SELF_UPDATER_MAILTO_ADDRESS'] = $request->input('mail_address');
 | 
					 | 
				
			||||||
        $_ENV['SELF_UPDATER_MAILTO_NAME'] = $request->input('mail_name');
 | 
					 | 
				
			||||||
        $_ENV['DB_CONNECTION'] = 'db-ninja-01';
 | 
					        $_ENV['DB_CONNECTION'] = 'db-ninja-01';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $config = '';
 | 
					        $config = '';
 | 
				
			||||||
 | 
				
			|||||||
@ -34,12 +34,14 @@ class SetEmailDb
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($request->input('email') && config('ninja.db.multi_db_enabled')) {
 | 
					        if ($request->input('email') && config('ninja.db.multi_db_enabled')) {
 | 
				
			||||||
 | 
					            info("trying to find db");
 | 
				
			||||||
            if (! MultiDB::userFindAndSetDb($request->input('email'))) {
 | 
					            if (! MultiDB::userFindAndSetDb($request->input('email'))) {
 | 
				
			||||||
                return response()->json($error, 403);
 | 
					                return response()->json($error, 400);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } 
 | 
				
			||||||
            return response()->json($error, 403);
 | 
					        // else {
 | 
				
			||||||
        }
 | 
					        //     return response()->json($error, 403);
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $next($request);
 | 
					        return $next($request);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -112,7 +112,7 @@ class UpdateClientRequest extends Request
 | 
				
			|||||||
     * are saveable
 | 
					     * are saveable
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  object $settings
 | 
					     * @param  object $settings
 | 
				
			||||||
     * @return object $settings
 | 
					     * @return stdClass $settings
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function filterSaveableSettings($settings)
 | 
					    private function filterSaveableSettings($settings)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,7 @@ class UpdateCompanyRequest extends Request
 | 
				
			|||||||
     * are saveable
 | 
					     * are saveable
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  object $settings
 | 
					     * @param  object $settings
 | 
				
			||||||
     * @return object $settings
 | 
					     * @return stdClass $settings
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function filterSaveableSettings($settings)
 | 
					    private function filterSaveableSettings($settings)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ class UpdateGroupSettingRequest extends Request
 | 
				
			|||||||
     * are saveable
 | 
					     * are saveable
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  object $settings
 | 
					     * @param  object $settings
 | 
				
			||||||
     * @return object $settings
 | 
					     * @return stdClass $settings
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function filterSaveableSettings($settings)
 | 
					    private function filterSaveableSettings($settings)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -38,8 +38,8 @@ class StoreTaskRequest extends Request
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $rules = [];
 | 
					        $rules = [];
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        $rules['number'] = Rule::unique('tasks')
 | 
					        if(isset($this->number))
 | 
				
			||||||
                                ->where('company_id', auth()->user()->company()->id);
 | 
					            $rules['number'] = Rule::unique('tasks')->where('company_id', auth()->user()->company()->id);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
       return $this->globalRules($rules);
 | 
					       return $this->globalRules($rules);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -38,9 +38,8 @@ class UpdateTaskRequest extends Request
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $rules = [];
 | 
					        $rules = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules['number'] = Rule::unique('tasks')
 | 
					        if(isset($this->number))
 | 
				
			||||||
                                ->where('company_id', auth()->user()->company()->id)
 | 
					            $rules['number'] = Rule::unique('tasks')->where('company_id', auth()->user()->company()->id)->ignore($this->task->id);
 | 
				
			||||||
                                ->ignore($this->task->id);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->globalRules($rules);
 | 
					        return $this->globalRules($rules);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@ namespace App\Jobs\Cron;
 | 
				
			|||||||
use App\Jobs\RecurringInvoice\SendRecurring;
 | 
					use App\Jobs\RecurringInvoice\SendRecurring;
 | 
				
			||||||
use App\Libraries\MultiDB;
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
use App\Models\RecurringInvoice;
 | 
					use App\Models\RecurringInvoice;
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Builder;
 | 
				
			||||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
use Illuminate\Support\Carbon;
 | 
					use Illuminate\Support\Carbon;
 | 
				
			||||||
@ -46,6 +47,9 @@ class RecurringInvoicesCron
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                $recurring_invoices = RecurringInvoice::whereDate('next_send_date', '=', now())
 | 
					                $recurring_invoices = RecurringInvoice::whereDate('next_send_date', '=', now())
 | 
				
			||||||
                                                        ->where('status_id', RecurringInvoice::STATUS_ACTIVE)
 | 
					                                                        ->where('status_id', RecurringInvoice::STATUS_ACTIVE)
 | 
				
			||||||
 | 
					                                                        ->whereHas('company', function(Builder $query){
 | 
				
			||||||
 | 
					                                                            $query->where('is_disabled', false);
 | 
				
			||||||
 | 
					                                                        })
 | 
				
			||||||
                                                        ->cursor();
 | 
					                                                        ->cursor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Log::info(now()->format('Y-m-d') . ' Sending Recurring Invoices. Count = '.$recurring_invoices->count());
 | 
					                Log::info(now()->format('Y-m-d') . ' Sending Recurring Invoices. Count = '.$recurring_invoices->count());
 | 
				
			||||||
@ -66,6 +70,9 @@ class RecurringInvoicesCron
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                $recurring_invoices = RecurringInvoice::whereDate('next_send_date', '=', now())
 | 
					                $recurring_invoices = RecurringInvoice::whereDate('next_send_date', '=', now())
 | 
				
			||||||
                                                        ->where('status_id', RecurringInvoice::STATUS_ACTIVE)
 | 
					                                                        ->where('status_id', RecurringInvoice::STATUS_ACTIVE)
 | 
				
			||||||
 | 
					                                                        ->whereHas('company', function(Builder $query){
 | 
				
			||||||
 | 
					                                                            $query->where('is_disabled', false);
 | 
				
			||||||
 | 
					                                                        })
 | 
				
			||||||
                                                        ->cursor();
 | 
					                                                        ->cursor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Log::info(now()->format('Y-m-d') . ' Sending Recurring Invoices. Count = '.$recurring_invoices->count().' On Database # '.$db);
 | 
					                Log::info(now()->format('Y-m-d') . ' Sending Recurring Invoices. Count = '.$recurring_invoices->count().' On Database # '.$db);
 | 
				
			||||||
 | 
				
			|||||||
@ -94,7 +94,9 @@ class EmailEntity extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if($this->company->is_disabled)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        MultiDB::setDB($this->company->db);
 | 
					        MultiDB::setDB($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->setMailDriver();
 | 
					        $this->setMailDriver();
 | 
				
			||||||
 | 
				
			|||||||
@ -57,7 +57,7 @@ class BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
         *  Now that our token is refresh and valid we can boot the
 | 
					         *  Now that our token is refreshed and valid we can boot the
 | 
				
			||||||
         *  mail driver at runtime and also set the token which will persist
 | 
					         *  mail driver at runtime and also set the token which will persist
 | 
				
			||||||
         *  just for this request.
 | 
					         *  just for this request.
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
 | 
				
			|||||||
@ -71,14 +71,13 @@ class EntityPaidMailer extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /*If we are migrating data we don't want to fire these notification*/
 | 
				
			||||||
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
        //Set DB
 | 
					        //Set DB
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*If we are migrating data we don't want to fire these notification*/
 | 
					 | 
				
			||||||
        if ($this->company->company_users->first()->is_migrating) {
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //if we need to set an email driver do it now
 | 
					        //if we need to set an email driver do it now
 | 
				
			||||||
        $this->setMailDriver();
 | 
					        $this->setMailDriver();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -75,6 +75,10 @@ class EntitySentMailer extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /*If we are migrating data we don't want to fire these notification*/
 | 
				
			||||||
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        //Set DB
 | 
					        //Set DB
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -75,7 +75,10 @@ class EntityViewedMailer extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /*If we are migrating data we don't want to fire these notification*/
 | 
				
			||||||
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        //Set DB
 | 
					        //Set DB
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -67,6 +67,10 @@ class MailRouter extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /*If we are migrating data we don't want to fire these notification*/
 | 
				
			||||||
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //if we need to set an email driver do it now
 | 
					        //if we need to set an email driver do it now
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,10 @@ class PaymentFailureMailer extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /*If we are migrating data we don't want to fire these notification*/
 | 
				
			||||||
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        //Set DB
 | 
					        //Set DB
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -32,18 +32,21 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private $contact;
 | 
					    private $contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private $company;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new job instance.
 | 
					     * Create a new job instance.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param Payment $payment
 | 
					     * @param Payment $payment
 | 
				
			||||||
     * @param $email_builder
 | 
					     * @param $email_builder
 | 
				
			||||||
     * @param $contact
 | 
					     * @param $contact
 | 
				
			||||||
 | 
					     * @param $company
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function __construct(Payment $payment, $email_builder, $contact)
 | 
					    public function __construct(Payment $payment, $email_builder, $contact, company)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->payment = $payment;
 | 
					        $this->payment = $payment;
 | 
				
			||||||
        $this->email_builder = $email_builder;
 | 
					        $this->email_builder = $email_builder;
 | 
				
			||||||
        $this->contact = $contact;
 | 
					        $this->contact = $contact;
 | 
				
			||||||
 | 
					        $this->company = $company;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -54,6 +57,9 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if($this->company->is_disabled)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if ($this->contact->email) {
 | 
					        if ($this->contact->email) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            MultiDB::setDb($this->payment->company->db); //this may fail if we don't pass the serialized object with the company record
 | 
					            MultiDB::setDb($this->payment->company->db); //this may fail if we don't pass the serialized object with the company record
 | 
				
			||||||
 | 
				
			|||||||
@ -54,6 +54,9 @@ class UserEmailChanged extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if($this->company->is_disabled)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        //Set DB
 | 
					        //Set DB
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -79,7 +79,8 @@ class StartMigration implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        auth()->user()->setCompany($this->company);
 | 
					        auth()->user()->setCompany($this->company);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->company->setMigration(true);
 | 
					        $this->company->is_disabled = true;
 | 
				
			||||||
 | 
					        $this->company->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $zip = new ZipArchive();
 | 
					        $zip = new ZipArchive();
 | 
				
			||||||
        $archive = $zip->open($this->filepath);
 | 
					        $archive = $zip->open($this->filepath);
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ class WebhookHandler implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle() :bool
 | 
					    public function handle() :bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $this->entity->company || $this->entity->company->company_users->first()->is_migrating == true) {
 | 
					        if (! $this->entity->company || $this->entity->company->is_disabled) {
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -48,12 +48,13 @@ class PaymentNotification implements ShouldQueue
 | 
				
			|||||||
        MultiDB::setDb($event->company->db);
 | 
					        MultiDB::setDb($event->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $payment = $event->payment;
 | 
					        $payment = $event->payment;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ($event->company->is_disabled) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*User notifications*/
 | 
					        /*User notifications*/
 | 
				
			||||||
        foreach ($payment->company->company_users as $company_user) {
 | 
					        foreach ($payment->company->company_users as $company_user) {
 | 
				
			||||||
            if ($company_user->is_migrating) {
 | 
					 | 
				
			||||||
                return true;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user = $company_user->user;
 | 
					            $user = $company_user->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -285,7 +285,7 @@ class Client extends BaseModel implements HasLocalePreference
 | 
				
			|||||||
     * of settings which have been merged from
 | 
					     * of settings which have been merged from
 | 
				
			||||||
     * Client > Group > Company levels.
 | 
					     * Client > Group > Company levels.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return object stdClass object of settings
 | 
					     * @return stdClass stdClass object of settings
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getMergedSettings() :object
 | 
					    public function getMergedSettings() :object
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -107,6 +107,7 @@ class Company extends BaseModel
 | 
				
			|||||||
        'enable_shop_api',
 | 
					        'enable_shop_api',
 | 
				
			||||||
        'invoice_task_timelog',
 | 
					        'invoice_task_timelog',
 | 
				
			||||||
        'auto_start_tasks',
 | 
					        'auto_start_tasks',
 | 
				
			||||||
 | 
					        'is_disabled',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $hidden = [
 | 
					    protected $hidden = [
 | 
				
			||||||
@ -443,13 +444,5 @@ class Company extends BaseModel
 | 
				
			|||||||
        return $this->slack_webhook_url;
 | 
					        return $this->slack_webhook_url;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function setMigration($status)
 | 
					   
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $company_users = CompanyUser::where('company_id', $this->id)->get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($company_users as $cu) {
 | 
					 | 
				
			||||||
            $cu->is_migrating = $status;
 | 
					 | 
				
			||||||
            $cu->save();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -324,32 +324,32 @@ class CompanyGateway extends BaseModel
 | 
				
			|||||||
     * @param $invoice_count
 | 
					     * @param $invoice_count
 | 
				
			||||||
     * @return stdClass
 | 
					     * @return stdClass
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function calcGatewayFeeObject($amount, $invoice_count)
 | 
					    // public function calcGatewayFeeObject($amount, $invoice_count)
 | 
				
			||||||
    {
 | 
					    // {
 | 
				
			||||||
        $total_gateway_fee = $this->calcGatewayFee($amount);
 | 
					    //     $total_gateway_fee = $this->calcGatewayFee($amount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $fee_object = new stdClass;
 | 
					    //     $fee_object = new stdClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $fees_and_limits = $this->getFeesAndLimits();
 | 
					    //     $fees_and_limits = $this->getFeesAndLimits();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $fees_and_limits) {
 | 
					    //     if (! $fees_and_limits) {
 | 
				
			||||||
            return $fee_object;
 | 
					    //         return $fee_object;
 | 
				
			||||||
        }
 | 
					    //     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $fee_component_amount = $fees_and_limits->fee_amount ?: 0;
 | 
					    //     $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;
 | 
					    //     $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;
 | 
					    //     $combined_fee_component = $fee_component_amount + $fee_component_percent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $fee_component_tax_name1 = $fees_and_limits->fee_tax_name1 ?: '';
 | 
					    //     $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_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_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_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_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;
 | 
					    //     $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)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -185,7 +185,7 @@ class Credit extends BaseModel
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Access the invoice calculator object.
 | 
					     * Access the invoice calculator object.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return object The invoice calculator object getters
 | 
					     * @return stdClass The invoice calculator object getters
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function calc()
 | 
					    public function calc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -209,6 +209,15 @@ class Invoice extends BaseModel
 | 
				
			|||||||
        return $this->hasMany(Credit::class);
 | 
					        return $this->hasMany(Credit::class);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function tasks()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->hasMany(Task::class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function expenses()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->hasMany(Expense::class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Service entry points.
 | 
					     * Service entry points.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -356,7 +365,7 @@ class Invoice extends BaseModel
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Access the invoice calculator object.
 | 
					     * Access the invoice calculator object.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return object The invoice calculator object getters
 | 
					     * @return stdClass The invoice calculator object getters
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function calc()
 | 
					    public function calc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -159,7 +159,7 @@ class Quote extends BaseModel
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Access the quote calculator object.
 | 
					     * Access the quote calculator object.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return object The quote calculator object getters
 | 
					     * @return stdClass The quote calculator object getters
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function calc()
 | 
					    public function calc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ class BasePaymentDriver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns the Omnipay driver.
 | 
					     * Returns the Omnipay driver.
 | 
				
			||||||
     * @return object Omnipay initialized object
 | 
					     * @return stdClass Omnipay initialized object
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function gateway()
 | 
					    protected function gateway()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -314,6 +314,7 @@ class BaseRepository
 | 
				
			|||||||
            if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
 | 
					            if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
 | 
				
			||||||
                $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']));
 | 
					                $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']));
 | 
				
			||||||
                $model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save();
 | 
					                $model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save();
 | 
				
			||||||
 | 
					                $model->service()->linkEntities()->save();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (! $model->design_id) {
 | 
					            if (! $model->design_id) {
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,10 @@ class PaymentRepository extends BaseRepository
 | 
				
			|||||||
        $this->credit_repo = $credit_repo;
 | 
					        $this->credit_repo = $credit_repo;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** 
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getClassName()
 | 
					    public function getClassName()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Payment::class;
 | 
					        return Payment::class;
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ class RecurringInvoiceRepository extends BaseRepository
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $invoice->save();
 | 
					        $invoice->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invoice_calc = new InvoiceSum($invoice, $invoice->settings);
 | 
					        $invoice_calc = new InvoiceSum($invoice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invoice->service()
 | 
					        $invoice->service()
 | 
				
			||||||
                ->applyNumber()
 | 
					                ->applyNumber()
 | 
				
			||||||
 | 
				
			|||||||
@ -30,9 +30,9 @@ class TaskRepository extends BaseRepository
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Gets the class name.
 | 
					     * Gets the class name.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return     string The class name.
 | 
					     * @return string The class name.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getClassName()
 | 
					    public function getClassName() 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Task::class;
 | 
					        return Task::class;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -40,8 +40,8 @@ class TaskRepository extends BaseRepository
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Saves the task and its contacts.
 | 
					     * Saves the task and its contacts.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param      array                           $data    The data
 | 
					     * @param      array                         $data    The data
 | 
				
			||||||
     * @param      \App\Models\task              $task  The task
 | 
					     * @param      \App\Models\Task              $task  The task
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return     task|null  task Object
 | 
					     * @return     task|null  task Object
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
@ -43,11 +43,10 @@ class UserRepository extends BaseRepository
 | 
				
			|||||||
     * @param array $data The data
 | 
					     * @param array $data The data
 | 
				
			||||||
     * @param \App\Models\user $user The user
 | 
					     * @param \App\Models\user $user The user
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param bool $is_migrating
 | 
					 | 
				
			||||||
     * @param bool $unset_company_user
 | 
					     * @param bool $unset_company_user
 | 
				
			||||||
     * @return     user|\App\Models\user|null  user Object
 | 
					     * @return     user|\App\Models\user|null  user Object
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function save(array $data, User $user, $is_migrating = false, $unset_company_user = false)
 | 
					    public function save(array $data, User $user, $unset_company_user = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $details = $data;
 | 
					        $details = $data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -85,13 +84,11 @@ class UserRepository extends BaseRepository
 | 
				
			|||||||
            if (! $cu) {
 | 
					            if (! $cu) {
 | 
				
			||||||
                $data['company_user']['account_id'] = $account->id;
 | 
					                $data['company_user']['account_id'] = $account->id;
 | 
				
			||||||
                $data['company_user']['notifications'] = CompanySettings::notificationDefaults();
 | 
					                $data['company_user']['notifications'] = CompanySettings::notificationDefaults();
 | 
				
			||||||
                $data['company_user']['is_migrating'] = $is_migrating;
 | 
					 | 
				
			||||||
                $user->companies()->attach($company->id, $data['company_user']);
 | 
					                $user->companies()->attach($company->id, $data['company_user']);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $cu->fill($data['company_user']);
 | 
					                $cu->fill($data['company_user']);
 | 
				
			||||||
                $cu->restore();
 | 
					                $cu->restore();
 | 
				
			||||||
                $cu->tokens()->restore();
 | 
					                $cu->tokens()->restore();
 | 
				
			||||||
                $cu->is_migrating = true;
 | 
					 | 
				
			||||||
                $cu->save();
 | 
					                $cu->save();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -108,8 +105,6 @@ class UserRepository extends BaseRepository
 | 
				
			|||||||
    public function destroy(array $data, User $user)
 | 
					    public function destroy(array $data, User $user)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
info("destroy user");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (array_key_exists('company_user', $data)) {
 | 
					        if (array_key_exists('company_user', $data)) {
 | 
				
			||||||
            $this->forced_includes = 'company_users';
 | 
					            $this->forced_includes = 'company_users';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -136,8 +131,6 @@ info("destroy user");
 | 
				
			|||||||
    public function delete($user)
 | 
					    public function delete($user)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
info("delete user");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $company = auth()->user()->company();
 | 
					        $company = auth()->user()->company();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $cu = CompanyUser::whereUserId($user->id)
 | 
					        $cu = CompanyUser::whereUserId($user->id)
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,10 @@ namespace App\Services\Invoice;
 | 
				
			|||||||
use App\Jobs\Entity\CreateEntityPdf;
 | 
					use App\Jobs\Entity\CreateEntityPdf;
 | 
				
			||||||
use App\Jobs\Util\UnlinkFile;
 | 
					use App\Jobs\Util\UnlinkFile;
 | 
				
			||||||
use App\Models\CompanyGateway;
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use App\Models\Expense;
 | 
				
			||||||
use App\Models\Invoice;
 | 
					use App\Models\Invoice;
 | 
				
			||||||
use App\Models\Payment;
 | 
					use App\Models\Payment;
 | 
				
			||||||
 | 
					use App\Models\Task;
 | 
				
			||||||
use App\Services\Client\ClientService;
 | 
					use App\Services\Client\ClientService;
 | 
				
			||||||
use App\Services\Invoice\ApplyNumber;
 | 
					use App\Services\Invoice\ApplyNumber;
 | 
				
			||||||
use App\Services\Invoice\ApplyPayment;
 | 
					use App\Services\Invoice\ApplyPayment;
 | 
				
			||||||
@ -30,10 +32,13 @@ use App\Services\Invoice\MarkInvoicePaid;
 | 
				
			|||||||
use App\Services\Invoice\MarkSent;
 | 
					use App\Services\Invoice\MarkSent;
 | 
				
			||||||
use App\Services\Invoice\TriggeredActions;
 | 
					use App\Services\Invoice\TriggeredActions;
 | 
				
			||||||
use App\Services\Invoice\UpdateBalance;
 | 
					use App\Services\Invoice\UpdateBalance;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
use Illuminate\Support\Carbon;
 | 
					use Illuminate\Support\Carbon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InvoiceService
 | 
					class InvoiceService
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    use MakesHash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $invoice;
 | 
					    private $invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $client_service;
 | 
					    protected $client_service;
 | 
				
			||||||
@ -328,6 +333,30 @@ class InvoiceService
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function linkEntities()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //set all task.invoice_ids = 0
 | 
				
			||||||
 | 
					        $this->invoice->tasks()->update(['invoice_id' => null]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //set all tasks.invoice_ids = x with the current  line_items
 | 
				
			||||||
 | 
					        $tasks = collect($this->invoice->line_items)->map(function ($item){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(isset($item->task_id))
 | 
				
			||||||
 | 
					                $item->task_id = $this->decodePrimaryKey($item->task_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(isset($item->expense_id))
 | 
				
			||||||
 | 
					                $item->expense_id = $this->decodePrimaryKey($item->expense_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Task::whereIn('id',$tasks->pluck('task_id'))->update(['invoice_id' => $this->invoice->id]);
 | 
				
			||||||
 | 
					        Expense::whereIn('id',$tasks->pluck('expense_id'))->update(['invoice_id' => $this->invoice->id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Saves the invoice.
 | 
					     * Saves the invoice.
 | 
				
			||||||
     * @return Invoice object
 | 
					     * @return Invoice object
 | 
				
			||||||
 | 
				
			|||||||
@ -53,6 +53,10 @@ class MarkInvoiceDeleted extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $this->invoice->number = $number;
 | 
					        $this->invoice->number = $number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //wipe references to invoices from related entities.
 | 
				
			||||||
 | 
					        $this->invoice->tasks()->update(['invoice_id' => null]);
 | 
				
			||||||
 | 
					        $this->invoice->expenses()->update(['invoice_id' => null]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->invoice;
 | 
					        return $this->invoice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -33,11 +33,11 @@ class SendEmail
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function run()
 | 
					    public function run()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $email_builder = (new PaymentEmail())->build($this->payment, $contact);
 | 
					        $email_builder = (new PaymentEmail())->build($this->payment, $this->contact);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->payment->client->contacts->each(function ($contact) use ($email_builder) {
 | 
					        $this->payment->client->contacts->each(function ($contact) use ($email_builder) {
 | 
				
			||||||
            if ($contact->send && $contact->email) {
 | 
					            if ($contact->send && $contact->email) {
 | 
				
			||||||
                EmailPayment::dispatchNow($this->payment, $email_builder, $contact);
 | 
					                EmailPayment::dispatchNow($this->payment, $email_builder, $contact, $this->payment->company);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -148,6 +148,7 @@ class CompanyTransformer extends EntityTransformer
 | 
				
			|||||||
            'enabled_item_tax_rates' => (int) $company->enabled_item_tax_rates,
 | 
					            'enabled_item_tax_rates' => (int) $company->enabled_item_tax_rates,
 | 
				
			||||||
            'client_can_register' => (bool) $company->client_can_register,
 | 
					            'client_can_register' => (bool) $company->client_can_register,
 | 
				
			||||||
            'is_large' => (bool) $company->is_large,
 | 
					            'is_large' => (bool) $company->is_large,
 | 
				
			||||||
 | 
					            'is_disabled' => (bool) $company->is_disabled,
 | 
				
			||||||
            'enable_shop_api' => (bool) $company->enable_shop_api,
 | 
					            'enable_shop_api' => (bool) $company->enable_shop_api,
 | 
				
			||||||
            'mark_expenses_invoiceable'=> (bool) $company->mark_expenses_invoiceable,
 | 
					            'mark_expenses_invoiceable'=> (bool) $company->mark_expenses_invoiceable,
 | 
				
			||||||
            'mark_expenses_paid' => (bool) $company->mark_expenses_paid,
 | 
					            'mark_expenses_paid' => (bool) $company->mark_expenses_paid,
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,6 @@ class UserTransformer extends EntityTransformer
 | 
				
			|||||||
            'created_at' => (int) $user->created_at,
 | 
					            'created_at' => (int) $user->created_at,
 | 
				
			||||||
            'updated_at' => (int) $user->updated_at,
 | 
					            'updated_at' => (int) $user->updated_at,
 | 
				
			||||||
            'archived_at' => (int) $user->deleted_at,
 | 
					            'archived_at' => (int) $user->deleted_at,
 | 
				
			||||||
            'created_at' => (int) $user->created_at,
 | 
					 | 
				
			||||||
            'is_deleted' => (bool) $user->is_deleted,
 | 
					            'is_deleted' => (bool) $user->is_deleted,
 | 
				
			||||||
            'phone' => $user->phone ?: '',
 | 
					            'phone' => $user->phone ?: '',
 | 
				
			||||||
            'email_verified_at' => $user->getEmailVerifiedAt(),
 | 
					            'email_verified_at' => $user->getEmailVerifiedAt(),
 | 
				
			||||||
 | 
				
			|||||||
@ -57,7 +57,7 @@ class EmailStats
 | 
				
			|||||||
     * Iterates through a list of companies
 | 
					     * Iterates through a list of companies
 | 
				
			||||||
     * and flushes the email sent data.
 | 
					     * and flushes the email sent data.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  string $companies The company key
 | 
					     * @param  Collection $companies The company key
 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function clearCompanies($companies)
 | 
					    public static function clearCompanies($companies)
 | 
				
			||||||
 | 
				
			|||||||
@ -251,8 +251,8 @@ class HtmlEngine
 | 
				
			|||||||
        $data['$contact.phone'] = ['value' => $this->contact->phone, 'label' => ctrans('texts.phone')];
 | 
					        $data['$contact.phone'] = ['value' => $this->contact->phone, 'label' => ctrans('texts.phone')];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data['$contact.name'] = ['value' => isset($this->contact) ? $this->contact->present()->name() : 'no contact name on record', 'label' => ctrans('texts.contact_name')];
 | 
					        $data['$contact.name'] = ['value' => isset($this->contact) ? $this->contact->present()->name() : 'no contact name on record', 'label' => ctrans('texts.contact_name')];
 | 
				
			||||||
        $data['$contact.first_name'] = ['value' => isset($contact) ? $contact->first_name : '', 'label' => ctrans('texts.first_name')];
 | 
					        $data['$contact.first_name'] = ['value' => isset($this->contact) ? $this->contact->first_name : '', 'label' => ctrans('texts.first_name')];
 | 
				
			||||||
        $data['$contact.last_name'] = ['value' => isset($contact) ? $contact->last_name : '', 'label' => ctrans('texts.last_name')];
 | 
					        $data['$contact.last_name'] = ['value' => isset($this->contact) ? $this->contact->last_name : '', 'label' => ctrans('texts.last_name')];
 | 
				
			||||||
        $data['$contact.custom1'] = ['value' => isset($this->contact) ? $this->contact->custom_value1 : ' ', 'label' => $this->makeCustomField('contact1')];
 | 
					        $data['$contact.custom1'] = ['value' => isset($this->contact) ? $this->contact->custom_value1 : ' ', 'label' => $this->makeCustomField('contact1')];
 | 
				
			||||||
        $data['$contact.custom2'] = ['value' => isset($this->contact) ? $this->contact->custom_value2 : ' ', 'label' => $this->makeCustomField('contact1')];
 | 
					        $data['$contact.custom2'] = ['value' => isset($this->contact) ? $this->contact->custom_value2 : ' ', 'label' => $this->makeCustomField('contact1')];
 | 
				
			||||||
        $data['$contact.custom3'] = ['value' => isset($this->contact) ? $this->contact->custom_value3 : ' ', 'label' => $this->makeCustomField('contact1')];
 | 
					        $data['$contact.custom3'] = ['value' => isset($this->contact) ? $this->contact->custom_value3 : ' ', 'label' => $this->makeCustomField('contact1')];
 | 
				
			||||||
 | 
				
			|||||||
@ -35,9 +35,8 @@ class Phantom
 | 
				
			|||||||
     * Phantom JS API.
 | 
					     * Phantom JS API.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param $invitation
 | 
					     * @param $invitation
 | 
				
			||||||
     * @return pdf HTML to PDF conversion
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function generate($invitation)
 | 
					    public function generate($invitation) 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $entity = false;
 | 
					        $entity = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -139,7 +139,7 @@ trait ClientGroupSettingsSaver
 | 
				
			|||||||
     * so that it can be saved cleanly
 | 
					     * so that it can be saved cleanly
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  array $settings The settings request() array
 | 
					     * @param  array $settings The settings request() array
 | 
				
			||||||
     * @return object          stdClass object
 | 
					     * @return stdClass          stdClass object
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function checkSettingType($settings) : stdClass
 | 
					    private function checkSettingType($settings) : stdClass
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -214,8 +214,7 @@ trait ClientGroupSettingsSaver
 | 
				
			|||||||
            case 'array':
 | 
					            case 'array':
 | 
				
			||||||
                return is_array($value);
 | 
					                return is_array($value);
 | 
				
			||||||
            case 'json':
 | 
					            case 'json':
 | 
				
			||||||
                json_decode($string);
 | 
					                json_decode($value);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return json_last_error() == JSON_ERROR_NONE;
 | 
					                    return json_last_error() == JSON_ERROR_NONE;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
 | 
				
			|||||||
@ -71,7 +71,7 @@ trait CompanyGatewayFeesAndLimitsSaver
 | 
				
			|||||||
            case 'array':
 | 
					            case 'array':
 | 
				
			||||||
                return is_array($value);
 | 
					                return is_array($value);
 | 
				
			||||||
            case 'json':
 | 
					            case 'json':
 | 
				
			||||||
                json_decode($string);
 | 
					                json_decode($value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return json_last_error() == JSON_ERROR_NONE;
 | 
					                    return json_last_error() == JSON_ERROR_NONE;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
 | 
				
			|||||||
@ -131,7 +131,7 @@ trait CompanySettingsSaver
 | 
				
			|||||||
     * so that it can be saved cleanly
 | 
					     * so that it can be saved cleanly
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  array $settings The settings request() array
 | 
					     * @param  array $settings The settings request() array
 | 
				
			||||||
     * @return object          stdClass object
 | 
					     * @return stdClass       stdClass object
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function checkSettingType($settings) : stdClass
 | 
					    private function checkSettingType($settings) : stdClass
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -224,7 +224,7 @@ trait CompanySettingsSaver
 | 
				
			|||||||
            case 'array':
 | 
					            case 'array':
 | 
				
			||||||
                return is_array($value);
 | 
					                return is_array($value);
 | 
				
			||||||
            case 'json':
 | 
					            case 'json':
 | 
				
			||||||
                json_decode($string);
 | 
					                json_decode($value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return json_last_error() == JSON_ERROR_NONE;
 | 
					                    return json_last_error() == JSON_ERROR_NONE;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
 | 
				
			|||||||
@ -442,7 +442,7 @@ trait GeneratesCounter
 | 
				
			|||||||
     * check if we need to reset here.
 | 
					     * check if we need to reset here.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param Client $client client entity
 | 
					     * @param Client $client client entity
 | 
				
			||||||
     * @return false
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function resetCounters(Client $client)
 | 
					    private function resetCounters(Client $client)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -44,13 +44,9 @@ trait Inviteable
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function getLink() :string
 | 
					    public function getLink() :string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        //$entity_type = strtolower(class_basename($this->entityType()));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $entity_type = Str::snake(class_basename($this->entityType()));
 | 
					        $entity_type = Str::snake(class_basename($this->entityType()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //$this->with('company','contact',$this->entity_type);
 | 
					 | 
				
			||||||
        //$this->with('company');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $domain = isset($this->company->portal_domain) ?: $this->company->domain();
 | 
					        $domain = isset($this->company->portal_domain) ?: $this->company->domain();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch ($this->company->portal_mode) {
 | 
					        switch ($this->company->portal_mode) {
 | 
				
			||||||
@ -65,6 +61,9 @@ trait Inviteable
 | 
				
			|||||||
                return $domain.'client/'.$entity_type.'/'.$this->key;
 | 
					                return $domain.'client/'.$entity_type.'/'.$this->key;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                return '';
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -52,15 +52,17 @@ trait MakesDates
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Formats a date.
 | 
					     * Formats a date.
 | 
				
			||||||
     * @param  Carbon/String $date   Carbon object or date string
 | 
					     * @param  Carbon|string $date   Carbon object or date string
 | 
				
			||||||
     * @param  string $format The date display format
 | 
					     * @param  string $format The date display format
 | 
				
			||||||
     * @return string         The formatted date
 | 
					     * @return string         The formatted date
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function formatDate($date, string $format) :string
 | 
					    public function formatDate($date, string $format) :string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $date || strlen($date) < 1) {
 | 
					        if(!isset($date))
 | 
				
			||||||
            return '';
 | 
					            return '';
 | 
				
			||||||
        }
 | 
					        // if (!$date || strlen($date) < 1) {
 | 
				
			||||||
 | 
					        //     return '';
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_string($date)) {
 | 
					        if (is_string($date)) {
 | 
				
			||||||
            $date = $this->convertToDateObject($date);
 | 
					            $date = $this->convertToDateObject($date);
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ trait MakesHash
 | 
				
			|||||||
            $decoded_array = $hashids->decode($value);
 | 
					            $decoded_array = $hashids->decode($value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (! is_array($decoded_array)) {
 | 
					            if (! is_array($decoded_array)) {
 | 
				
			||||||
                throw new Exception("Invalid Primary Key");
 | 
					                throw new \Exception("Invalid Primary Key");
 | 
				
			||||||
                //response()->json(['error'=>'Invalid primary key'], 400);
 | 
					                //response()->json(['error'=>'Invalid primary key'], 400);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ 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 ($this->migrationRunning($company_user)) {
 | 
					        if ($company_user->company->is_disabled) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,7 +41,7 @@ trait UserNotifies
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function findUserEntityNotificationType($entity, $company_user, $required_permissions) :array
 | 
					    public function findUserEntityNotificationType($entity, $company_user, $required_permissions) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->migrationRunning($company_user)) {
 | 
					        if ($company_user->company->is_disabled) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,7 +65,7 @@ trait UserNotifies
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function findCompanyUserNotificationType($company_user, $required_permissions) :array
 | 
					    public function findCompanyUserNotificationType($company_user, $required_permissions) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->migrationRunning($company_user)) {
 | 
					        if ($company_user->company->is_disabled) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,8 +79,4 @@ trait UserNotifies
 | 
				
			|||||||
        return $notifiable_methods;
 | 
					        return $notifiable_methods;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function migrationRunning($company_user)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $company_user->is_migrating;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										622
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										622
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -12,7 +12,7 @@ return [
 | 
				
			|||||||
    'require_https' => env('REQUIRE_HTTPS', true),
 | 
					    'require_https' => env('REQUIRE_HTTPS', true),
 | 
				
			||||||
    'app_url' => rtrim(env('APP_URL', ''), '/').'/',
 | 
					    'app_url' => rtrim(env('APP_URL', ''), '/').'/',
 | 
				
			||||||
    'app_domain' => env('APP_DOMAIN', ''),
 | 
					    'app_domain' => env('APP_DOMAIN', ''),
 | 
				
			||||||
    'app_version' => '5.0.22',
 | 
					    'app_version' => '5.0.23',
 | 
				
			||||||
    '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', ''),
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,7 @@ class ExpenseFactory extends Factory
 | 
				
			|||||||
            'public_notes' => $this->faker->text(50),
 | 
					            'public_notes' => $this->faker->text(50),
 | 
				
			||||||
            'private_notes' => $this->faker->text(50),
 | 
					            'private_notes' => $this->faker->text(50),
 | 
				
			||||||
            'transaction_reference' => $this->faker->text(5),
 | 
					            'transaction_reference' => $this->faker->text(5),
 | 
				
			||||||
 | 
					            'invoice_id' => null,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ class TaskFactory extends Factory
 | 
				
			|||||||
	    {
 | 
						    {
 | 
				
			||||||
	    return [
 | 
						    return [
 | 
				
			||||||
	        'description' => $this->faker->text(50),
 | 
						        'description' => $this->faker->text(50),
 | 
				
			||||||
 | 
					            'invoice_id' => null,
 | 
				
			||||||
	    ];
 | 
						    ];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Migrations\Migration;
 | 
				
			||||||
 | 
					use Illuminate\Database\Schema\Blueprint;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DropMigratingColumn extends Migration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Run the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function up()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('company_user', function(Blueprint $table){
 | 
				
			||||||
 | 
					            $table->dropColumn('is_migrating');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function down()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								psalm.xml
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								psalm.xml
									
									
									
									
									
								
							@ -51,7 +51,18 @@
 | 
				
			|||||||
      <directory name="app" /> 
 | 
					      <directory name="app" /> 
 | 
				
			||||||
    </errorLevel>
 | 
					    </errorLevel>
 | 
				
			||||||
  </InvalidScalarArgument> 
 | 
					  </InvalidScalarArgument> 
 | 
				
			||||||
 | 
					  <UndefinedMagicPropertyFetch>
 | 
				
			||||||
 | 
					    <errorLevel type="suppress">
 | 
				
			||||||
 | 
					      <directory name="app" /> 
 | 
				
			||||||
 | 
					    </errorLevel>
 | 
				
			||||||
 | 
					  </UndefinedMagicPropertyFetch> 
 | 
				
			||||||
 | 
					  <InvalidNullableReturnType>
 | 
				
			||||||
 | 
					    <errorLevel type="suppress">
 | 
				
			||||||
 | 
					      <directory name="app" /> 
 | 
				
			||||||
 | 
					    </errorLevel>
 | 
				
			||||||
 | 
					  </InvalidNullableReturnType> 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</issueHandlers>
 | 
					</issueHandlers>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,9 @@ Route::group(['middleware' => ['api_secret_check']], function () {
 | 
				
			|||||||
    Route::post('api/v1/oauth_login', 'Auth\LoginController@oauthApiLogin');
 | 
					    Route::post('api/v1/oauth_login', 'Auth\LoginController@oauthApiLogin');
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Route::group(['api_secret_check', 'email_db'], function () {
 | 
					Route::group(['middleware' => ['api_secret_check', 'email_db']], function () {
 | 
				
			||||||
    Route::post('api/v1/login', 'Auth\LoginController@apiLogin')->name('login.submit');
 | 
					    Route::post('api/v1/login', 'Auth\LoginController@apiLogin')->name('login.submit');
 | 
				
			||||||
    Route::post('api/v1/reset_password', 'Auth\ForgotPasswordController@sendResetLinkEmail');
 | 
					    Route::post('api/v1/reset_password', 'Auth\ForgotPasswordController@sendResetLinkEmail');
 | 
				
			||||||
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'api/v1', 'as' => 'api.'], function () {
 | 
					Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'api/v1', 'as' => 'api.'], function () {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										77
									
								
								tests/Feature/InvoiceLinkTasksTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								tests/Feature/InvoiceLinkTasksTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					namespace Tests\Feature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\DataMapper\ClientSettings;
 | 
				
			||||||
 | 
					use App\DataMapper\CompanySettings;
 | 
				
			||||||
 | 
					use App\Factory\InvoiceFactory;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
 | 
					use App\Models\Client;
 | 
				
			||||||
 | 
					use App\Models\ClientContact;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\Task;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Testing\RefreshDatabase;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Testing\WithFaker;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Log;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Session;
 | 
				
			||||||
 | 
					use Tests\MockAccountData;
 | 
				
			||||||
 | 
					use Tests\TestCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @test
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceLinkTasksTest 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 testMapCreation()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $temp_invoice_id = $this->invoice->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $tasks = collect($this->invoice->line_items)->map(function ($item){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(isset($item->task_id))
 | 
				
			||||||
 | 
					                $item->task_id = $this->decodePrimaryKey($item->task_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(isset($item->expense_id))
 | 
				
			||||||
 | 
					                $item->expense_id = $this->decodePrimaryKey($item->expense_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals($tasks->first()->task_id, $this->task->id);
 | 
				
			||||||
 | 
					        $this->assertEquals($tasks->first()->expense_id, $this->expense->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->invoice = $this->invoice->service()->linkEntities()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals($this->task->fresh()->invoice_id, $temp_invoice_id);
 | 
				
			||||||
 | 
					        $this->assertEquals($this->expense->fresh()->invoice_id, $temp_invoice_id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -24,6 +24,7 @@ use Illuminate\Http\Request;
 | 
				
			|||||||
use Illuminate\Support\Facades\Log;
 | 
					use Illuminate\Support\Facades\Log;
 | 
				
			||||||
use Illuminate\Support\Facades\Session;
 | 
					use Illuminate\Support\Facades\Session;
 | 
				
			||||||
use Tests\TestCase;
 | 
					use Tests\TestCase;
 | 
				
			||||||
 | 
					use Illuminate\Validation\ValidationException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @test
 | 
					 * @test
 | 
				
			||||||
@ -141,6 +142,10 @@ class LoginTest extends TestCase
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function testApiLogin()
 | 
					    public function testApiLogin()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        Account::all()->each(function ($account){
 | 
				
			||||||
 | 
					            $account->delete();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = Account::factory()->create();
 | 
					        $account = Account::factory()->create();
 | 
				
			||||||
        $user = User::factory()->create([
 | 
					        $user = User::factory()->create([
 | 
				
			||||||
            'account_id' => $account->id,
 | 
					            'account_id' => $account->id,
 | 
				
			||||||
@ -177,15 +182,28 @@ class LoginTest extends TestCase
 | 
				
			|||||||
        $this->assertTrue($user->company_users->first() !== null);
 | 
					        $this->assertTrue($user->company_users->first() !== null);
 | 
				
			||||||
        $this->assertTrue($user->company_user->account !== null);
 | 
					        $this->assertTrue($user->company_user->account !== null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals($user->email, 'test@example.com');
 | 
				
			||||||
 | 
					        $this->assertTrue(\Hash::check('123456', $user->password));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
            'email' => 'test@example.com',
 | 
					            'email' => 'test@example.com',
 | 
				
			||||||
            'password' => '123456',
 | 
					            'password' => '123456',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try{
 | 
				
			||||||
        $response = $this->withHeaders([
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
                'X-API-SECRET' => config('ninja.api_secret'),
 | 
					            'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
            ])->post('/api/v1/login', $data);
 | 
					            ])->post('/api/v1/login', $data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } catch (ValidationException $e) {
 | 
				
			||||||
 | 
					            $message = json_decode($e->validator->getMessageBag(), 1);
 | 
				
			||||||
 | 
					            info(print_r($message,1));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $response->json();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        info(print_r($arr,1));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        $response->assertStatus(200);
 | 
					        $response->assertStatus(200);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -570,6 +570,8 @@ trait MockAccountData
 | 
				
			|||||||
        $item = InvoiceItemFactory::create();
 | 
					        $item = InvoiceItemFactory::create();
 | 
				
			||||||
        $item->quantity = 1;
 | 
					        $item->quantity = 1;
 | 
				
			||||||
        $item->cost = 10;
 | 
					        $item->cost = 10;
 | 
				
			||||||
 | 
					        $item->task_id = $this->encodePrimaryKey($this->task->id);
 | 
				
			||||||
 | 
					        $item->expense_id = $this->encodePrimaryKey($this->expense->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $line_items[] = $item;
 | 
					        $line_items[] = $item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -61,19 +61,19 @@ class ImportTest extends TestCase
 | 
				
			|||||||
        $this->assertTrue($status);
 | 
					        $this->assertTrue($status);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function testAllImport()
 | 
					    // public function testAllImport()
 | 
				
			||||||
    {
 | 
					    // {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->invoice->forceDelete();
 | 
					    //     $this->invoice->forceDelete();
 | 
				
			||||||
        $this->quote->forceDelete();
 | 
					    //     $this->quote->forceDelete();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->user->setCompany($this->company);
 | 
					    //     $this->user->setCompany($this->company);
 | 
				
			||||||
        auth()->login($this->user, true);
 | 
					    //     auth()->login($this->user, true);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Import::dispatchNow($this->migration_array, $this->company, $this->user);
 | 
					    //     Import::dispatchNow($this->migration_array, $this->company, $this->user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->assertTrue(true);
 | 
					    //     $this->assertTrue(true);
 | 
				
			||||||
    }
 | 
					    // }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
//     public function testExceptionOnUnavailableResource()
 | 
					//     public function testExceptionOnUnavailableResource()
 | 
				
			||||||
//     {
 | 
					//     {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user