mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 23:17:32 -05:00 
			
		
		
		
	Merge branch 'v5-develop' into v5-stable
This commit is contained in:
		
						commit
						5ea0440ad0
					
				@ -1 +1 @@
 | 
				
			|||||||
5.2.15
 | 
					5.2.16
 | 
				
			||||||
@ -76,7 +76,6 @@ class ContactForgotPasswordController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function sendResetLinkEmail(ContactPasswordResetRequest $request)
 | 
					    public function sendResetLinkEmail(ContactPasswordResetRequest $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        $user = MultiDB::hasContact($request->input('email'));
 | 
					        $user = MultiDB::hasContact($request->input('email'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->validateEmail($request);
 | 
					        $this->validateEmail($request);
 | 
				
			||||||
 | 
				
			|||||||
@ -71,6 +71,31 @@ class ContactResetPasswordController extends Controller
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function reset(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $request->validate($this->rules(), $this->validationErrorMessages());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Here we will attempt to reset the user's password. If it is successful we
 | 
				
			||||||
 | 
					        // will update the password on an actual user model and persist it to the
 | 
				
			||||||
 | 
					        // database. Otherwise we will parse the error and return the response.
 | 
				
			||||||
 | 
					        $response = $this->broker()->reset(
 | 
				
			||||||
 | 
					            $this->credentials($request), function ($user, $password) {
 | 
				
			||||||
 | 
					                $this->resetPassword($user, $password);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Added this because it collides the session between
 | 
				
			||||||
 | 
					        // client & main portal giving unlimited redirects.
 | 
				
			||||||
 | 
					        auth()->logout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If the password was successfully reset, we will redirect the user back to
 | 
				
			||||||
 | 
					        // the application's home authenticated view. If there is an error we can
 | 
				
			||||||
 | 
					        // redirect them back to where they came from with their error message.
 | 
				
			||||||
 | 
					        return $response == Password::PASSWORD_RESET
 | 
				
			||||||
 | 
					                    ? $this->sendResetResponse($request, $response)
 | 
				
			||||||
 | 
					                    : $this->sendResetFailedResponse($request, $response);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function guard()
 | 
					    protected function guard()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Auth::guard('contact');
 | 
					        return Auth::guard('contact');
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
namespace App\Http\Controllers\ClientPortal;
 | 
					namespace App\Http\Controllers\ClientPortal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Http\Controllers\Controller;
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
 | 
					use App\Models\RecurringInvoice;
 | 
				
			||||||
use Auth;
 | 
					use Auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ContactHashLoginController extends Controller
 | 
					class ContactHashLoginController extends Controller
 | 
				
			||||||
@ -24,6 +25,17 @@ class ContactHashLoginController extends Controller
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function login(string $contact_key)
 | 
					    public function login(string $contact_key)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if(request()->has('subscription') && $request->subscription == 'true') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $recurring_invoice = RecurringInvoice::where('client_id', auth()->guard('contact')->client->id)
 | 
				
			||||||
 | 
					                                                 ->whereNotNull('subscription_id')
 | 
				
			||||||
 | 
					                                                 ->whereNull('deleted_at')
 | 
				
			||||||
 | 
					                                                 ->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return redirect()->route('client.recurring_invoice.show', $recurring_invoice->hashed_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return redirect('/client/invoices');
 | 
					        return redirect('/client/invoices');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -185,7 +185,10 @@ class InvoiceController extends Controller
 | 
				
			|||||||
        $zip = new ZipStream(date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip', $options);
 | 
					        $zip = new ZipStream(date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip', $options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($invoices as $invoice) {
 | 
					        foreach ($invoices as $invoice) {
 | 
				
			||||||
            $zip->addFileFromPath(basename($invoice->pdf_file_path()), TempFile::path($invoice->pdf_file_path()));
 | 
					
 | 
				
			||||||
 | 
					            #add it to the zip
 | 
				
			||||||
 | 
					            $zip->addFile(basename($invoice->pdf_file_path()), file_get_contents($invoice->pdf_file_path(null, 'url', true)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // finish the zip stream
 | 
					        // finish the zip stream
 | 
				
			||||||
 | 
				
			|||||||
@ -107,7 +107,9 @@ class QuoteController extends Controller
 | 
				
			|||||||
        $zip = new ZipStream(date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip', $options);
 | 
					        $zip = new ZipStream(date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip', $options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($quotes as $quote) {
 | 
					        foreach ($quotes as $quote) {
 | 
				
			||||||
            $zip->addFileFromPath(basename($quote->pdf_file_path()), TempFile::path($quote->pdf_file_path()));
 | 
					            $zip->addFile(basename($quote->pdf_file_path()), file_get_contents($quote->pdf_file_path(null, 'url', true)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // $zip->addFileFromPath(basename($quote->pdf_file_path()), TempFile::path($quote->pdf_file_path()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // finish the zip stream
 | 
					        // finish the zip stream
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,7 @@ use App\Repositories\InvoiceRepository;
 | 
				
			|||||||
use App\Repositories\QuoteRepository;
 | 
					use App\Repositories\QuoteRepository;
 | 
				
			||||||
use App\Repositories\RecurringInvoiceRepository;
 | 
					use App\Repositories\RecurringInvoiceRepository;
 | 
				
			||||||
use App\Services\PdfMaker\Design as PdfMakerDesign;
 | 
					use App\Services\PdfMaker\Design as PdfMakerDesign;
 | 
				
			||||||
 | 
					use App\Services\PdfMaker\Design as PdfDesignModel;
 | 
				
			||||||
use App\Services\PdfMaker\Design;
 | 
					use App\Services\PdfMaker\Design;
 | 
				
			||||||
use App\Services\PdfMaker\PdfMaker;
 | 
					use App\Services\PdfMaker\PdfMaker;
 | 
				
			||||||
use App\Utils\HostedPDF\NinjaPdf;
 | 
					use App\Utils\HostedPDF\NinjaPdf;
 | 
				
			||||||
 | 
				
			|||||||
@ -192,19 +192,17 @@ class Import implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        nlog("Starting Migration");
 | 
					        nlog("Starting Migration");
 | 
				
			||||||
        nlog($this->user->email);
 | 
					        nlog($this->user->email);
 | 
				
			||||||
        info("Starting Migration");
 | 
					        nlog("Company ID = ");
 | 
				
			||||||
        info($this->user->email);
 | 
					        nlog($this->company->id);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        auth()->login($this->user, false);
 | 
					        auth()->login($this->user, false);
 | 
				
			||||||
        auth()->user()->setCompany($this->company);
 | 
					        auth()->user()->setCompany($this->company);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //   $jsonStream = \JsonMachine\JsonMachine::fromFile($this->file_path, "/data");
 | 
					 | 
				
			||||||
        $array = json_decode(file_get_contents($this->file_path), 1);
 | 
					        $array = json_decode(file_get_contents($this->file_path), 1);
 | 
				
			||||||
        $data = $array['data'];
 | 
					        $data = $array['data'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($this->available_imports as $import) {
 | 
					        foreach ($this->available_imports as $import) {
 | 
				
			||||||
            if (! array_key_exists($import, $data)) {
 | 
					            if (! array_key_exists($import, $data)) {
 | 
				
			||||||
                //throw new ResourceNotAvailableForMigration("Resource {$key} is not available for migration.");
 | 
					 | 
				
			||||||
                info("Resource {$import} is not available for migration.");
 | 
					                info("Resource {$import} is not available for migration.");
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -249,7 +247,17 @@ class Import implements ShouldQueue
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // CreateCompanyPaymentTerms::dispatchNow($sp035a66, $spaa9f78);
 | 
					        // CreateCompanyPaymentTerms::dispatchNow($sp035a66, $spaa9f78);
 | 
				
			||||||
        CreateCompanyTaskStatuses::dispatchNow($this->company, $this->user);
 | 
					        // CreateCompanyTaskStatuses::dispatchNow($this->company, $this->user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $task_statuses = [
 | 
				
			||||||
 | 
					            ['name' => ctrans('texts.backlog'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now(), 'status_order' => 1],
 | 
				
			||||||
 | 
					            ['name' => ctrans('texts.ready_to_do'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now(), 'status_order' => 2],
 | 
				
			||||||
 | 
					            ['name' => ctrans('texts.in_progress'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now(), 'status_order' => 3],
 | 
				
			||||||
 | 
					            ['name' => ctrans('texts.done'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now(), 'status_order' => 4],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TaskStatus::insert($task_statuses);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        info('Completed🚀🚀🚀🚀🚀 at '.now());
 | 
					        info('Completed🚀🚀🚀🚀🚀 at '.now());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -293,7 +301,7 @@ class Import implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function setInitialCompanyLedgerBalances()
 | 
					    private function setInitialCompanyLedgerBalances()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Client::cursor()->each(function ($client) {
 | 
					        Client::where('company_id', $this->company->id)->cursor()->each(function ($client) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $invoice_balances = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance');
 | 
					            $invoice_balances = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -198,6 +198,10 @@ class ClientContact extends Authenticatable implements HasLocalePreference
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function sendPasswordResetNotification($token)
 | 
					    public function sendPasswordResetNotification($token)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->token = $token;
 | 
				
			||||||
 | 
					        $this->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nmo = new NinjaMailerObject;
 | 
					        $nmo = new NinjaMailerObject;
 | 
				
			||||||
        $nmo->mailable = new NinjaMailer((new ClientContactResetPasswordObject($token, $this))->build());
 | 
					        $nmo->mailable = new NinjaMailer((new ClientContactResetPasswordObject($token, $this))->build());
 | 
				
			||||||
        $nmo->to_user = $this;
 | 
					        $nmo->to_user = $this;
 | 
				
			||||||
 | 
				
			|||||||
@ -54,12 +54,22 @@ class CompanyPresenter extends EntityPresenter
 | 
				
			|||||||
            $settings = $this->entity->settings;
 | 
					            $settings = $this->entity->settings;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(config('ninja.is_docker'))
 | 
				
			||||||
 | 
					            return $this->logo($settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $context_options =array(
 | 
				
			||||||
 | 
					            "ssl"=>array(
 | 
				
			||||||
 | 
					               "verify_peer"=>false,
 | 
				
			||||||
 | 
					               "verify_peer_name"=>false,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(strlen($settings->company_logo) >= 1 && (strpos($settings->company_logo, 'http') !== false))
 | 
					        if(strlen($settings->company_logo) >= 1 && (strpos($settings->company_logo, 'http') !== false))
 | 
				
			||||||
            return "data:image/png;base64, ". base64_encode(file_get_contents($settings->company_logo));
 | 
					            return "data:image/png;base64, ". base64_encode(file_get_contents($settings->company_logo, false, stream_context_create($context_options)));
 | 
				
			||||||
        else if(strlen($settings->company_logo) >= 1)
 | 
					        else if(strlen($settings->company_logo) >= 1)
 | 
				
			||||||
            return "data:image/png;base64, ". base64_encode(file_get_contents(url('') . $settings->company_logo));
 | 
					            return "data:image/png;base64, ". base64_encode(file_get_contents(url('') . $settings->company_logo, false, stream_context_create($context_options)));
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            return "data:image/png;base64, ". base64_encode(file_get_contents(asset('images/new_logo.png')));
 | 
					            return "data:image/png;base64, ". base64_encode(file_get_contents(asset('images/new_logo.png'), false, stream_context_create($context_options)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -174,8 +174,8 @@ class BaseRepository
 | 
				
			|||||||
            $model->client_id = $data['client_id'];
 | 
					            $model->client_id = $data['client_id'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //pickup changes here to recalculate reminders
 | 
					        //pickup changes here to recalculate reminders
 | 
				
			||||||
        if($model instanceof Invoice && ($model->isDirty('date') || $model->isDirty('due_date')))
 | 
					        //if($model instanceof Invoice && ($model->isDirty('date') || $model->isDirty('due_date')))
 | 
				
			||||||
            $model->service()->setReminder()->save();
 | 
					           // $model->service()->setReminder()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $client = Client::where('id', $model->client_id)->withTrashed()->first();    
 | 
					        $client = Client::where('id', $model->client_id)->withTrashed()->first();    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -213,6 +213,9 @@ class BaseRepository
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* Model now persisted, now lets do some child tasks */
 | 
					        /* Model now persisted, now lets do some child tasks */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($model instanceof Invoice)
 | 
				
			||||||
 | 
					            $model->service()->setReminder()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Save any documents */
 | 
					        /* Save any documents */
 | 
				
			||||||
        if (array_key_exists('documents', $data)) 
 | 
					        if (array_key_exists('documents', $data)) 
 | 
				
			||||||
            $this->saveDocuments($data['documents'], $model);
 | 
					            $this->saveDocuments($data['documents'], $model);
 | 
				
			||||||
@ -299,8 +302,8 @@ class BaseRepository
 | 
				
			|||||||
        if((int)$model->balance != 0 && $model->partial > $model->amount)
 | 
					        if((int)$model->balance != 0 && $model->partial > $model->amount)
 | 
				
			||||||
            $model->partial = min($model->amount, $model->balance);
 | 
					            $model->partial = min($model->amount, $model->balance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Update product details if necessary */
 | 
					        /* Update product details if necessary - if we are inside a transaction - do nothing */
 | 
				
			||||||
        if ($model->company->update_products && $model->id) 
 | 
					        if ($model->company->update_products && $model->id && \DB::transactionLevel() == 0) 
 | 
				
			||||||
            UpdateOrCreateProduct::dispatch($model->line_items, $model, $model->company);
 | 
					            UpdateOrCreateProduct::dispatch($model->line_items, $model, $model->company);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Perform model specific tasks */
 | 
					        /* Perform model specific tasks */
 | 
				
			||||||
 | 
				
			|||||||
@ -100,6 +100,11 @@ class PaymentMigrationRepository extends BaseRepository
 | 
				
			|||||||
        $payment->deleted_at = $data['deleted_at'] ?: null;
 | 
					        $payment->deleted_at = $data['deleted_at'] ?: null;
 | 
				
			||||||
        $payment->save();
 | 
					        $payment->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(array_key_exists('currency_id', $data) && $data['currency_id'] == 0){
 | 
				
			||||||
 | 
					            $payment->currency_id = $payment->company->settings->currency_id;
 | 
				
			||||||
 | 
					            $payment->save();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*Ensure payment number generated*/
 | 
					        /*Ensure payment number generated*/
 | 
				
			||||||
        if (! $payment->number || strlen($payment->number) == 0) {
 | 
					        if (! $payment->number || strlen($payment->number) == 0) {
 | 
				
			||||||
            $payment->number = $payment->client->getNextPaymentNumber($payment->client);
 | 
					            $payment->number = $payment->client->getNextPaymentNumber($payment->client);
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,15 @@ class HandleRestore extends AbstractService
 | 
				
			|||||||
                                     ->where('paymentable_type', '=', 'invoices')
 | 
					                                     ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
                                     ->sum(\DB::raw('amount'));
 | 
					                                     ->sum(\DB::raw('amount'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nlog("first pre restore amount = {$pre_restore_amount}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $pre_restore_amount -=  $payment->paymentables()
 | 
				
			||||||
 | 
					                                     ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
 | 
					                                     ->sum(\DB::raw('refunded'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nlog("second pre restore amount = {$pre_restore_amount}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //restore the paymentables
 | 
					            //restore the paymentables
 | 
				
			||||||
            $payment->paymentables()
 | 
					            $payment->paymentables()
 | 
				
			||||||
                    ->where('paymentable_type', '=', 'invoices')
 | 
					                    ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
@ -57,7 +66,15 @@ class HandleRestore extends AbstractService
 | 
				
			|||||||
                                     ->where('paymentable_type', '=', 'invoices')
 | 
					                                     ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
                                     ->sum(\DB::raw('amount'));
 | 
					                                     ->sum(\DB::raw('amount'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            info($payment->amount . " == " . $payment_amount);
 | 
					nlog("first payment_amount = {$payment_amount}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $payment_amount -= $payment->paymentables()
 | 
				
			||||||
 | 
					                                     ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
 | 
					                                     ->sum(\DB::raw('refunded'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nlog("second payment_amount = {$payment_amount}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nlog($payment->amount . " == " . $payment_amount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($payment->amount == $payment_amount) {
 | 
					            if ($payment->amount == $payment_amount) {
 | 
				
			||||||
                $payment->is_deleted = false;
 | 
					                $payment->is_deleted = false;
 | 
				
			||||||
 | 
				
			|||||||
@ -90,7 +90,7 @@ class HandleReversal extends AbstractService
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*If there is a payment linked, then the credit needs to be linked back to that payment in case of refund*/
 | 
					        /*If there is a payment linked, then the credit needs to be linked back to that payment in case of refund*/
 | 
				
			||||||
        if ($paymentables->count() > 0) {
 | 
					        if ($paymentables->count() > 0 && $credit) {
 | 
				
			||||||
            $payment = $paymentables->first()->payment;
 | 
					            $payment = $paymentables->first()->payment;
 | 
				
			||||||
            $payment->credits()->save($credit);
 | 
					            $payment->credits()->save($credit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -86,6 +86,11 @@ class MarkInvoiceDeleted extends AbstractService
 | 
				
			|||||||
                                                ->where('paymentable_id', $this->invoice->id)
 | 
					                                                ->where('paymentable_id', $this->invoice->id)
 | 
				
			||||||
                                                ->sum(DB::raw('amount'));
 | 
					                                                ->sum(DB::raw('amount'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $payment_adjustment -= $payment->paymentables
 | 
				
			||||||
 | 
					                                                ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
 | 
					                                                ->where('paymentable_id', $this->invoice->id)
 | 
				
			||||||
 | 
					                                                ->sum(DB::raw('refunded'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $payment->amount -= $payment_adjustment;
 | 
					                $payment->amount -= $payment_adjustment;
 | 
				
			||||||
                $payment->applied -= $payment_adjustment;
 | 
					                $payment->applied -= $payment_adjustment;
 | 
				
			||||||
                $payment->save();
 | 
					                $payment->save();
 | 
				
			||||||
@ -108,10 +113,19 @@ class MarkInvoiceDeleted extends AbstractService
 | 
				
			|||||||
                                                ->where('paymentable_type', '=', 'invoices')
 | 
					                                                ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
                                                ->where('paymentable_id', $this->invoice->id)
 | 
					                                                ->where('paymentable_id', $this->invoice->id)
 | 
				
			||||||
                                                ->sum(DB::raw('amount'));
 | 
					                                                ->sum(DB::raw('amount'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $this->adjustment_amount -= $payment->paymentables
 | 
				
			||||||
 | 
					                                                ->where('paymentable_type', '=', 'invoices')
 | 
				
			||||||
 | 
					                                                ->where('paymentable_id', $this->invoice->id)
 | 
				
			||||||
 | 
					                                                ->sum(DB::raw('refunded'));                                                
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->total_payments = $this->invoice->payments->sum('amount');
 | 
					        $this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded');;
 | 
				
			||||||
 | 
					        //$this->total_payments = $this->invoice->payments->sum('amount - refunded');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nlog("adjustment amount = {$this->adjustment_amount}");
 | 
				
			||||||
 | 
					nlog("total payments = {$this->total_payments}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,9 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            return $this->invoice; //exit early
 | 
					            return $this->invoice; //exit early
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($this->invoice->next_send_date)
 | 
				
			||||||
 | 
					            $this->invoice->next_send_date = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $offset = $this->invoice->client->timezone_offset();
 | 
					        $offset = $this->invoice->client->timezone_offset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $date_collection = collect();
 | 
					        $date_collection = collect();
 | 
				
			||||||
@ -52,7 +55,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 1 after due date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder1_sent) &&
 | 
					        if (is_null($this->invoice->reminder1_sent) &&
 | 
				
			||||||
@ -61,7 +64,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder1)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder1)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 1 before_due_date"); 
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder1_sent) &&
 | 
					        if (is_null($this->invoice->reminder1_sent) &&
 | 
				
			||||||
@ -70,7 +73,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date);
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 1 after_due_date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder2_sent) &&
 | 
					        if (is_null($this->invoice->reminder2_sent) &&
 | 
				
			||||||
@ -79,7 +82,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 2 after_invoice_date = ".$reminder_date->format('Y-m-d'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder2_sent) &&
 | 
					        if (is_null($this->invoice->reminder2_sent) &&
 | 
				
			||||||
@ -88,7 +91,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder2)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder2)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 2 before_due_date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder2_sent) &&
 | 
					        if (is_null($this->invoice->reminder2_sent) &&
 | 
				
			||||||
@ -97,7 +100,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 2 after_due_date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder3_sent) &&
 | 
					        if (is_null($this->invoice->reminder3_sent) &&
 | 
				
			||||||
@ -106,7 +109,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 3 after_invoice_date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder3_sent) &&
 | 
					        if (is_null($this->invoice->reminder3_sent) &&
 | 
				
			||||||
@ -115,7 +118,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder3)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder3)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 3 before_due_date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($this->invoice->reminder3_sent) &&
 | 
					        if (is_null($this->invoice->reminder3_sent) &&
 | 
				
			||||||
@ -124,7 +127,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset);
 | 
					            $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					            if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                $date_collection->push($reminder_date); 
 | 
					                $date_collection->push($reminder_date); nlog("settings reminder 3 after_due_date");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->invoice->last_sent_date &&
 | 
					        if ($this->invoice->last_sent_date &&
 | 
				
			||||||
@ -137,7 +140,7 @@ class UpdateReminder extends AbstractService
 | 
				
			|||||||
                $reminder_date->addSeconds($offset);
 | 
					                $reminder_date->addSeconds($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
					                if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date)))
 | 
				
			||||||
                    $date_collection->push($reminder_date); 
 | 
					                    $date_collection->push($reminder_date); nlog("settings endless reminder");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -347,7 +347,7 @@ class Design extends BaseDesign
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $items = $this->transformLineItems($this->entity->line_items, $type);
 | 
					        $items = $this->transformLineItems($this->entity->line_items, $type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //        $this->processMarkdownOnLineItems($items);
 | 
					        $this->processMarkdownOnLineItems($items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($items) == 0) {
 | 
					        if (count($items) == 0) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
@ -456,6 +456,13 @@ class Design extends BaseDesign
 | 
				
			|||||||
            return $elements;
 | 
					            return $elements;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->entity instanceof Quote) {
 | 
				
			||||||
 | 
					            // We don't want to show Balanace due on the quotes.
 | 
				
			||||||
 | 
					            if (in_array('$outstanding', $variables)) {
 | 
				
			||||||
 | 
					                $variables = \array_diff($variables, ['$outstanding']);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach (['discount'] as $property) {
 | 
					        foreach (['discount'] as $property) {
 | 
				
			||||||
            $variable = sprintf('%s%s', '$', $property);
 | 
					            $variable = sprintf('%s%s', '$', $property);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -333,9 +333,6 @@ document.addEventListener('DOMContentLoaded', function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function processMarkdownOnLineItems(array &$items)
 | 
					    public function processMarkdownOnLineItems(array &$items)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Use setting to determinate if parsing should be done.
 | 
					 | 
				
			||||||
        // 'parse_markdown_on_pdfs'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($items as $key => $item) {
 | 
					        foreach ($items as $key => $item) {
 | 
				
			||||||
            foreach ($item as $variable => $value) {
 | 
					            foreach ($item as $variable => $value) {
 | 
				
			||||||
                $item[$variable] = DesignHelpers::parseMarkdownToHtml($value ?? '');
 | 
					                $item[$variable] = DesignHelpers::parseMarkdownToHtml($value ?? '');
 | 
				
			||||||
 | 
				
			|||||||
@ -91,31 +91,19 @@ trait PdfMakerUtilities
 | 
				
			|||||||
        foreach ($children as $child) {
 | 
					        foreach ($children as $child) {
 | 
				
			||||||
            $contains_html = false;
 | 
					            $contains_html = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (isset($child['content'])) {
 | 
					 | 
				
			||||||
                // Commented cause it keeps adding <br> at the end, if markdown parsing is turned on.
 | 
					 | 
				
			||||||
                // Should update with 'parse_markdown_on_pdfs' setting.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                 $child['content'] = nl2br($child['content']);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // "/\/[a-z]*>/i" -> checks for HTML-like tags:
 | 
					 | 
				
			||||||
            // <my-tag></my-tag> => true
 | 
					 | 
				
			||||||
            // <my-tag /> => true
 | 
					 | 
				
			||||||
            // <my-tag> => false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (isset($child['content'])) {
 | 
					            if (isset($child['content'])) {
 | 
				
			||||||
                if (isset($child['is_empty']) && $child['is_empty'] === true) {
 | 
					                if (isset($child['is_empty']) && $child['is_empty'] === true) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $contains_html = preg_match("/\/[a-z]*>/i", $child['content'], $m) != 0;
 | 
					                $contains_html = preg_match('#(?<=<)\w+(?=[^<]*?>)#', $child['content'], $m) != 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($contains_html) {
 | 
					            if ($contains_html) {
 | 
				
			||||||
                // If the element contains the HTML, we gonna display it as is. DOMDocument, is going to
 | 
					                // If the element contains the HTML, we gonna display it as is. Backend is going to
 | 
				
			||||||
                // encode it for us, preventing any errors on the backend due processing stage.
 | 
					                // encode it for us, preventing any errors on the processing stage.
 | 
				
			||||||
                // Later, we decode this using Javascript so it looks like it's normal HTML being injected.
 | 
					                // Later, we decode this using Javascript so it looks like it's normal HTML being injected.
 | 
				
			||||||
                // To get all elements that need frontend decoding, we use 'data-ref' property.
 | 
					                // To get all elements that need frontend decoding, we use 'data-state' property.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $_child = $this->document->createElement($child['element'], '');
 | 
					                $_child = $this->document->createElement($child['element'], '');
 | 
				
			||||||
                $_child->setAttribute('data-state', 'encoded-html');
 | 
					                $_child->setAttribute('data-state', 'encoded-html');
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,8 @@ return [
 | 
				
			|||||||
    'require_https' => env('REQUIRE_HTTPS', true),
 | 
					    'require_https' => env('REQUIRE_HTTPS', true),
 | 
				
			||||||
    'app_url' => rtrim(env('APP_URL', ''), '/'),
 | 
					    'app_url' => rtrim(env('APP_URL', ''), '/'),
 | 
				
			||||||
    'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
 | 
					    'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
 | 
				
			||||||
    'app_version' => '5.2.15',
 | 
					    'app_version' => '5.2.16',
 | 
				
			||||||
    'app_tag' => '5.2.15',
 | 
					    'app_tag' => '5.2.16',
 | 
				
			||||||
    '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', ''),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										54
									
								
								public/flutter_service_worker.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								public/flutter_service_worker.js
									
									
									
									
										vendored
									
									
								
							@ -3,37 +3,37 @@ const MANIFEST = 'flutter-app-manifest';
 | 
				
			|||||||
const TEMP = 'flutter-temp-cache';
 | 
					const TEMP = 'flutter-temp-cache';
 | 
				
			||||||
const CACHE_NAME = 'flutter-app-cache';
 | 
					const CACHE_NAME = 'flutter-app-cache';
 | 
				
			||||||
const RESOURCES = {
 | 
					const RESOURCES = {
 | 
				
			||||||
  "favicon.png": "dca91c54388f52eded692718d5a98b8b",
 | 
					  "assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
 | 
				
			||||||
"main.dart.js": "c3ca362d549201394b5c4301af639ddb",
 | 
					"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
 | 
				
			||||||
"/": "23224b5e03519aaa87594403d54412cf",
 | 
					"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
 | 
				
			||||||
"manifest.json": "ce1b79950eb917ea619a0a30da27c6a3",
 | 
					"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
 | 
				
			||||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
 | 
					"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
 | 
				
			||||||
"assets/NOTICES": "687b68d41e137cfbdee105c0b9be3e9d",
 | 
					"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
 | 
				
			||||||
 | 
					"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
 | 
				
			||||||
 | 
					"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
 | 
				
			||||||
 | 
					"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
 | 
				
			||||||
 | 
					"assets/assets/images/logo.png": "e5f46d5a78e226e7a9553d4ca6f69219",
 | 
				
			||||||
 | 
					"assets/AssetManifest.json": "753bba1dee0531d5fad970b5ce1d296d",
 | 
				
			||||||
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
 | 
					"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
 | 
				
			||||||
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
 | 
					"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
 | 
				
			||||||
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
 | 
					"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
 | 
				
			||||||
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
 | 
					"assets/NOTICES": "687b68d41e137cfbdee105c0b9be3e9d",
 | 
				
			||||||
"assets/assets/images/logo.png": "e5f46d5a78e226e7a9553d4ca6f69219",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
 | 
					 | 
				
			||||||
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
 | 
					 | 
				
			||||||
"assets/AssetManifest.json": "753bba1dee0531d5fad970b5ce1d296d",
 | 
					 | 
				
			||||||
"version.json": "3f9e03374a3e78d2cab3afd8723d0993",
 | 
					 | 
				
			||||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
 | 
					"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
 | 
				
			||||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
 | 
					"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
 | 
				
			||||||
"favicon.ico": "51636d3a390451561744c42188ccd628"
 | 
					"favicon.png": "dca91c54388f52eded692718d5a98b8b",
 | 
				
			||||||
 | 
					"manifest.json": "ce1b79950eb917ea619a0a30da27c6a3",
 | 
				
			||||||
 | 
					"version.json": "3f9e03374a3e78d2cab3afd8723d0993",
 | 
				
			||||||
 | 
					"favicon.ico": "51636d3a390451561744c42188ccd628",
 | 
				
			||||||
 | 
					"main.dart.js": "2791c77ee5c4768ffdc2ef8aea29967c",
 | 
				
			||||||
 | 
					"/": "d389ab59423a76b2aaaa683ed382c78e"
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The application shell files that are downloaded before a service worker can
 | 
					// The application shell files that are downloaded before a service worker can
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										22
									
								
								public/js/pdf.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								public/js/pdf.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										22
									
								
								public/js/pdf.worker.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								public/js/pdf.worker.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										257254
									
								
								public/main.dart.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										257254
									
								
								public/main.dart.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										256522
									
								
								public/main.foss.dart.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										256522
									
								
								public/main.foss.dart.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -237,7 +237,7 @@ $LANG = array(
 | 
				
			|||||||
    'archived_vendors' => 'Successfully archived :count vendors',
 | 
					    'archived_vendors' => 'Successfully archived :count vendors',
 | 
				
			||||||
    'deleted_vendor' => 'Successfully deleted vendor',
 | 
					    'deleted_vendor' => 'Successfully deleted vendor',
 | 
				
			||||||
    'deleted_vendors' => 'Successfully deleted :count vendors',
 | 
					    'deleted_vendors' => 'Successfully deleted :count vendors',
 | 
				
			||||||
    'confirmation_subject' => 'Invoice Ninja Account Confirmation',
 | 
					    'confirmation_subject' => 'Account Confirmation',
 | 
				
			||||||
    'confirmation_header' => 'Account Confirmation',
 | 
					    'confirmation_header' => 'Account Confirmation',
 | 
				
			||||||
    'confirmation_message' => 'Please access the link below to confirm your account.',
 | 
					    'confirmation_message' => 'Please access the link below to confirm your account.',
 | 
				
			||||||
    'invoice_subject' => 'New invoice :number from :account',
 | 
					    'invoice_subject' => 'New invoice :number from :account',
 | 
				
			||||||
@ -888,7 +888,7 @@ $LANG = array(
 | 
				
			|||||||
    'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.',
 | 
					    'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.',
 | 
				
			||||||
    'token_expired' => 'Validation token was expired. Please try again.',
 | 
					    'token_expired' => 'Validation token was expired. Please try again.',
 | 
				
			||||||
    'invoice_link' => 'Invoice Link',
 | 
					    'invoice_link' => 'Invoice Link',
 | 
				
			||||||
    'button_confirmation_message' => 'Click to confirm your email address.',
 | 
					    'button_confirmation_message' => 'Click to confirm your email.',
 | 
				
			||||||
    'confirm' => 'Confirm',
 | 
					    'confirm' => 'Confirm',
 | 
				
			||||||
    'email_preferences' => 'Email Preferences',
 | 
					    'email_preferences' => 'Email Preferences',
 | 
				
			||||||
    'created_invoices' => 'Successfully created :count invoice(s)',
 | 
					    'created_invoices' => 'Successfully created :count invoice(s)',
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,10 @@
 | 
				
			|||||||
  <title>Invoice Ninja</title>
 | 
					  <title>Invoice Ninja</title>
 | 
				
			||||||
  <meta name="google-signin-client_id" content="{{ config('services.google.client_id') }}">
 | 
					  <meta name="google-signin-client_id" content="{{ config('services.google.client_id') }}">
 | 
				
			||||||
  <link rel="manifest" href="manifest.json?v={{ config('ninja.app_version') }}">
 | 
					  <link rel="manifest" href="manifest.json?v={{ config('ninja.app_version') }}">
 | 
				
			||||||
 | 
					  <script src="{{ asset('js/pdf.min.js') }}"></script>
 | 
				
			||||||
 | 
					  <script type="text/javascript">
 | 
				
			||||||
 | 
					    pdfjsLib.GlobalWorkerOptions.workerSrc = "{{ asset('js/pdf.worker.min.js') }}";
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body style="background-color:#888888;">
 | 
					<body style="background-color:#888888;">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@
 | 
				
			|||||||
    p {
 | 
					    p {
 | 
				
			||||||
        margin: 0;
 | 
					        margin: 0;
 | 
				
			||||||
        padding: 0;
 | 
					        padding: 0;
 | 
				
			||||||
        page-break-after: always;
 | 
					        /* page-break-after: always; */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .header-wrapper {
 | 
					    .header-wrapper {
 | 
				
			||||||
@ -242,6 +242,14 @@
 | 
				
			|||||||
            display: none
 | 
					            display: none
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<table>
 | 
					<table>
 | 
				
			||||||
 | 
				
			|||||||
@ -235,6 +235,14 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 30px;
 | 
					        margin-top: 30px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -193,6 +193,14 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 30px;
 | 
					        margin-top: 30px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -195,6 +195,14 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 30px;
 | 
					        margin-top: 30px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -193,6 +193,14 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 30px;
 | 
					        margin-top: 30px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -204,6 +204,14 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 30px;
 | 
					        margin-top: 30px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@
 | 
				
			|||||||
    p {
 | 
					    p {
 | 
				
			||||||
        margin: 0;
 | 
					        margin: 0;
 | 
				
			||||||
        padding: 0;
 | 
					        padding: 0;
 | 
				
			||||||
        page-break-after: always;
 | 
					        /* page-break-after: always; */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .header-container {
 | 
					    .header-container {
 | 
				
			||||||
@ -261,6 +261,14 @@
 | 
				
			|||||||
            display: none
 | 
					            display: none
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<table>
 | 
					<table>
 | 
				
			||||||
 | 
				
			|||||||
@ -171,6 +171,14 @@
 | 
				
			|||||||
    [data-ref="totals_table-outstanding"] {
 | 
					    [data-ref="totals_table-outstanding"] {
 | 
				
			||||||
        color: var(--primary-color)
 | 
					        color: var(--primary-color)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -240,8 +240,15 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 1rem;
 | 
					        margin-top: 1rem;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="header">
 | 
					<div id="header">
 | 
				
			||||||
    <div style="background-color: #00968B"><!-- 1 --></div>
 | 
					    <div style="background-color: #00968B"><!-- 1 --></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -226,6 +226,14 @@
 | 
				
			|||||||
    #footer {
 | 
					    #footer {
 | 
				
			||||||
        margin-top: 30px;
 | 
					        margin-top: 30px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Markdown-specific styles. **/
 | 
				
			||||||
 | 
					    #product-table h3,
 | 
				
			||||||
 | 
					    #task-table h3,
 | 
				
			||||||
 | 
					    #delivery-note-table h3 {
 | 
				
			||||||
 | 
					        font-size: 1rem;
 | 
				
			||||||
 | 
					        margin-bottom: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="header"></div>
 | 
					<div id="header"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -30,15 +30,14 @@
 | 
				
			|||||||
            </script>
 | 
					            </script>
 | 
				
			||||||
        @endif
 | 
					        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        <!-- Title -->
 | 
					        <!-- Title -->
 | 
				
			||||||
        @auth()
 | 
					        @if(isset($account) && !$account->isPaid())
 | 
				
			||||||
            <title>@yield('meta_title', '') — {{ auth('contact')->user()->user->account->isPaid() ? auth('contact')->user()->company->present()->name() : 'Invoice Ninja' }}</title>
 | 
					            <title>@yield('meta_title', '') — Invoice Ninja</title>
 | 
				
			||||||
        @endauth
 | 
					        @elseif(isset($company) && !is_null($company))
 | 
				
			||||||
 | 
					            <title>@yield('meta_title', '') — {{ $company->present()->name() }}</title>
 | 
				
			||||||
        @guest
 | 
					        @else
 | 
				
			||||||
            <title>@yield('meta_title', '') — {{ config('app.name') }}</title>
 | 
					            <title>@yield('meta_title', '')</title>
 | 
				
			||||||
        @endguest
 | 
					        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <meta charset="utf-8">
 | 
					        <meta charset="utf-8">
 | 
				
			||||||
        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
					        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
				
			|||||||
@ -31,13 +31,13 @@
 | 
				
			|||||||
        @endif
 | 
					        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Title -->
 | 
					        <!-- Title -->
 | 
				
			||||||
        @auth()
 | 
					        @if(isset($account) && !$account->isPaid())
 | 
				
			||||||
            <title>@yield('meta_title', '') — {{ auth('contact')->user()->user->account->isPaid() ? auth('contact')->user()->company->present()->name() : 'Invoice Ninja' }}</title>
 | 
					            <title>@yield('meta_title', '') — Invoice Ninja</title>
 | 
				
			||||||
        @endauth
 | 
					        @elseif(isset($company) && !is_null($company))
 | 
				
			||||||
 | 
					            <title>@yield('meta_title', '') — {{ $company->present()->name() }}</title>
 | 
				
			||||||
        @guest
 | 
					        @else
 | 
				
			||||||
            <title>@yield('meta_title', '') — {{ config('app.name') }}</title>
 | 
					            <title>@yield('meta_title', '')</title>
 | 
				
			||||||
        @endguest
 | 
					        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <meta charset="utf-8">
 | 
					        <meta charset="utf-8">
 | 
				
			||||||
        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
					        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
				
			|||||||
@ -57,5 +57,13 @@
 | 
				
			|||||||
                .querySelector('div[data-ref="gateway-container"]')
 | 
					                .querySelector('div[data-ref="gateway-container"]')
 | 
				
			||||||
                .scrollIntoView({behavior: "smooth"});
 | 
					                .scrollIntoView({behavior: "smooth"});
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        document.addEventListener('DOMContentLoaded', function() {
 | 
				
			||||||
 | 
					            let toggleWithToken = document.querySelector('.toggle-payment-with-token');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (toggleWithToken) {
 | 
				
			||||||
 | 
					                toggleWithToken.click();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
@endpush
 | 
					@endpush
 | 
				
			||||||
 | 
				
			|||||||
@ -40,6 +40,124 @@ class DeleteInvoiceTest extends TestCase
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testInvoiceDeletionAfterCancellation()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'name' => 'A Nice Client',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
 | 
					                'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					                'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					            ])->post('/api/v1/clients', $data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $response->json();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client_hash_id = $arr['data']['id'];
 | 
				
			||||||
 | 
					        $client = Client::find($this->decodePrimaryKey($client_hash_id));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->assertEquals($client->balance, 0);
 | 
				
			||||||
 | 
					        $this->assertEquals($client->paid_to_date, 0);
 | 
				
			||||||
 | 
					        //create new invoice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $line_items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $item = InvoiceItemFactory::create();
 | 
				
			||||||
 | 
					        $item->quantity = 1;
 | 
				
			||||||
 | 
					        $item->cost = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $line_items[] = (array)$item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $item = InvoiceItemFactory::create();
 | 
				
			||||||
 | 
					        $item->quantity = 1;
 | 
				
			||||||
 | 
					        $item->cost = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $line_items[] = (array)$item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $invoice = [
 | 
				
			||||||
 | 
					            'status_id' => 1,
 | 
				
			||||||
 | 
					            'number' => '',
 | 
				
			||||||
 | 
					            'discount' => 0,
 | 
				
			||||||
 | 
					            'is_amount_discount' => 1,
 | 
				
			||||||
 | 
					            'po_number' => '3434343',
 | 
				
			||||||
 | 
					            'public_notes' => 'notes',
 | 
				
			||||||
 | 
					            'is_deleted' => 0,
 | 
				
			||||||
 | 
					            'custom_value1' => 0,
 | 
				
			||||||
 | 
					            'custom_value2' => 0,
 | 
				
			||||||
 | 
					            'custom_value3' => 0,
 | 
				
			||||||
 | 
					            'custom_value4' => 0,
 | 
				
			||||||
 | 
					            'client_id' => $client_hash_id,
 | 
				
			||||||
 | 
					            'line_items' => (array)$line_items,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response = $this->withHeaders([
 | 
				
			||||||
 | 
					                'X-API-SECRET' => config('ninja.api_secret'),
 | 
				
			||||||
 | 
					                'X-API-TOKEN' => $this->token,
 | 
				
			||||||
 | 
					            ])->post('/api/v1/invoices/', $invoice)
 | 
				
			||||||
 | 
					            ->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $response->json();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        $invoice_one_hashed_id = $arr['data']['id'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $invoice = Invoice::find($this->decodePrimaryKey($invoice_one_hashed_id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $invoice = $invoice->service()->markSent()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals(20, $invoice->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(20, $invoice->client->balance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $invoice = $invoice->service()->markPaid()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->client->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(20, $invoice->client->paid_to_date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //partially refund payment
 | 
				
			||||||
 | 
					        $payment = $invoice->fresh()->payments()->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'id' => $payment->id,
 | 
				
			||||||
 | 
					            'amount' => 10,
 | 
				
			||||||
 | 
					            'invoices' => [
 | 
				
			||||||
 | 
					                [
 | 
				
			||||||
 | 
					                'invoice_id' => $invoice->id,
 | 
				
			||||||
 | 
					                'amount' => 10,
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'date' => '2020/12/12',
 | 
				
			||||||
 | 
					            'gateway_refund' => false
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $payment->refund($data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //test balances
 | 
				
			||||||
 | 
					        $this->assertEquals(10, $payment->fresh()->refunded);
 | 
				
			||||||
 | 
					        $this->assertEquals(10, $invoice->client->fresh()->paid_to_date);
 | 
				
			||||||
 | 
					        $this->assertEquals(10, $invoice->fresh()->balance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //cancel invoice and paid_to_date
 | 
				
			||||||
 | 
					        $invoice->fresh()->service()->handleCancellation()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //test balances and paid_to_date
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->fresh()->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->client->fresh()->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(10, $invoice->client->fresh()->paid_to_date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //delete invoice
 | 
				
			||||||
 | 
					        $invoice->fresh()->service()->markDeleted()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //test balances and paid_to_date
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->fresh()->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->client->fresh()->balance);
 | 
				
			||||||
 | 
					        $this->assertEquals(0, $invoice->client->fresh()->paid_to_date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @covers App\Services\Invoice\MarkInvoiceDeleted
 | 
					     * @covers App\Services\Invoice\MarkInvoiceDeleted
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -172,10 +290,11 @@ class DeleteInvoiceTest extends TestCase
 | 
				
			|||||||
        $client_hash_id = $arr['data']['id'];
 | 
					        $client_hash_id = $arr['data']['id'];
 | 
				
			||||||
        $client = Client::find($this->decodePrimaryKey($client_hash_id));
 | 
					        $client = Client::find($this->decodePrimaryKey($client_hash_id));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        //new client
 | 
				
			||||||
        $this->assertEquals($client->balance, 0);
 | 
					        $this->assertEquals($client->balance, 0);
 | 
				
			||||||
        $this->assertEquals($client->paid_to_date, 0);
 | 
					        $this->assertEquals($client->paid_to_date, 0);
 | 
				
			||||||
        //create new invoice.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //create new invoice.
 | 
				
			||||||
        $line_items = [];
 | 
					        $line_items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $item = InvoiceItemFactory::create();
 | 
					        $item = InvoiceItemFactory::create();
 | 
				
			||||||
@ -323,4 +442,16 @@ class DeleteInvoiceTest extends TestCase
 | 
				
			|||||||
        $this->assertEquals(40, $payment->fresh()->amount);
 | 
					        $this->assertEquals(40, $payment->fresh()->amount);
 | 
				
			||||||
        $this->assertEquals(40, $client->fresh()->paid_to_date);
 | 
					        $this->assertEquals(40, $client->fresh()->paid_to_date);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -82,11 +82,36 @@ class ReminderTest extends TestCase
 | 
				
			|||||||
     //   ReminderJob::dispatchNow();
 | 
					     //   ReminderJob::dispatchNow();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testReminderHitsScenarioH1()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->invoice->date = now()->format('Y-m-d');
 | 
				
			||||||
 | 
					        $this->invoice->due_date = Carbon::now()->addDays(30)->format('Y-m-d');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $settings = $this->company->settings;
 | 
				
			||||||
 | 
					        $settings->enable_reminder1 = true;
 | 
				
			||||||
 | 
					        $settings->schedule_reminder1 = 'before_due_date';
 | 
				
			||||||
 | 
					        $settings->num_days_reminder1 = 2;
 | 
				
			||||||
 | 
					        $settings->enable_reminder2 = true;
 | 
				
			||||||
 | 
					        $settings->schedule_reminder2 = 'after_due_date';
 | 
				
			||||||
 | 
					        $settings->num_days_reminder2 = 14;
 | 
				
			||||||
 | 
					        $settings->enable_reminder3 = true;
 | 
				
			||||||
 | 
					        $settings->schedule_reminder3 = 'after_due_date';
 | 
				
			||||||
 | 
					        $settings->num_days_reminder3 = 30;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->company->settings = $settings;
 | 
				
			||||||
 | 
					        $this->invoice->service()->markSent();
 | 
				
			||||||
 | 
					        $this->invoice->service()->setReminder($settings)->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertEquals(Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'), Carbon::now()->addDays(30)->subDays(2)->format('Y-m-d'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     //   ReminderJob::dispatchNow();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Cant set a reminder in the past so need to skip reminder 2 and go straigh to reminder 3*/
 | 
				
			||||||
    public function testReminderNextSendRecalculation()
 | 
					    public function testReminderNextSendRecalculation()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->invoice->date = now()->subDays(2)->format('Y-m-d');
 | 
					        $this->invoice->date = now()->subDays(2)->format('Y-m-d');
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->invoice->due_date = now()->addDays(30)->format('Y-m-d');
 | 
					        $this->invoice->due_date = now()->addDays(30)->format('Y-m-d');
 | 
				
			||||||
        $this->invoice->reminder1_sent = now()->subDays(1)->format('Y-m-d');
 | 
					        $this->invoice->reminder1_sent = now()->subDays(1)->format('Y-m-d');
 | 
				
			||||||
        $this->invoice->last_sent_date = now()->subDays(1)->format('Y-m-d');
 | 
					        $this->invoice->last_sent_date = now()->subDays(1)->format('Y-m-d');
 | 
				
			||||||
@ -110,7 +135,7 @@ class ReminderTest extends TestCase
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $this->invoice->fresh();
 | 
					        $this->invoice->fresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->assertEquals(Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'), now()->format('Y-m-d'));
 | 
					        $this->assertEquals(Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'), now()->addDay()->format('Y-m-d'));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user