Merge pull request #4803 from turbo124/v5-develop

Fixes for displaying recurring invoices with Phantom Cloud JS
This commit is contained in:
David Bomba 2021-01-31 17:43:37 +11:00 committed by GitHub
commit 3ed247aa7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 292 additions and 765 deletions

View File

@ -35,10 +35,10 @@ function nlog($output, $context = []): void
} }
if (!function_exists('ray')) { // if (!function_exists('ray')) {
function ray($payload) // function ray($payload)
{ // {
return true; // return true;
} // }
} // }

View File

@ -32,7 +32,9 @@ class InvitationController extends Controller
use MakesDates; use MakesDates;
public function router(string $entity, string $invitation_key) public function router(string $entity, string $invitation_key)
{ {
Auth::logout();
return $this->genericRouter($entity, $invitation_key); return $this->genericRouter($entity, $invitation_key);
} }
@ -43,6 +45,7 @@ class InvitationController extends Controller
private function genericRouter(string $entity, string $invitation_key) private function genericRouter(string $entity, string $invitation_key)
{ {
$key = $entity.'_id'; $key = $entity.'_id';
$entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation'; $entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation';
@ -51,17 +54,24 @@ class InvitationController extends Controller
->with('contact.client') ->with('contact.client')
->firstOrFail(); ->firstOrFail();
nlog($invitation->contact->client->id);
nlog($invitation->invoice->client_id);
/* Return early if we have the correct client_hash embedded */ /* Return early if we have the correct client_hash embedded */
if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) { if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) {
auth()->guard('contact')->login($invitation->contact, true); auth()->guard('contact')->login($invitation->contact, true);
} elseif ((bool) $invitation->contact->client->getSetting('enable_client_portal_password') !== false) { } elseif ((bool) $invitation->contact->client->getSetting('enable_client_portal_password') !== false) {
//If no contact password is set - this will cause a 401 error - instead redirect to the client.login route
$this->middleware('auth:contact'); $this->middleware('auth:contact');
return redirect()->route('client.login');
} else { } else {
auth()->guard('contact')->login($invitation->contact, true); auth()->guard('contact')->login($invitation->contact, true);
} }
if (auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) { if (auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
$invitation->markViewed(); $invitation->markViewed();

View File

@ -206,7 +206,7 @@ class Import implements ShouldQueue
$this->setInitialCompanyLedgerBalances(); $this->setInitialCompanyLedgerBalances();
Mail::to($this->user) Mail::to($this->user)
->send(new MigrationCompleted()); ->send(new MigrationCompleted($this->company));
/*After a migration first some basic jobs to ensure the system is up to date*/ /*After a migration first some basic jobs to ensure the system is up to date*/
VersionCheck::dispatch(); VersionCheck::dispatch();

View File

@ -2,6 +2,7 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Company;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -10,14 +11,16 @@ class MigrationCompleted extends Mailable
{ {
use Queueable, SerializesModels; use Queueable, SerializesModels;
public $company;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @return void * @return void
*/ */
public function __construct() public function __construct(Company $company)
{ {
// $this->company = $company;
} }
/** /**
@ -27,9 +30,11 @@ class MigrationCompleted extends Mailable
*/ */
public function build() public function build()
{ {
$data['settings'] = auth()->user()->company()->settings; $data['settings'] = $this->company->settings;
$data['company'] = $this->company;
return $this->from(config('mail.from.address'), config('mail.from.name')) return $this->from(config('mail.from.address'), config('mail.from.name'))
->view('email.migration.completed', $data); ->view('email.import.completed', $data)
->attach($this->company->invoices->first()->pdf_file_path());
} }
} }

View File

@ -373,6 +373,11 @@ class Company extends BaseModel
return $this->hasMany(CompanyToken::class); return $this->hasMany(CompanyToken::class);
} }
public function client_gateway_tokens()
{
return $this->hasMany(ClientGatewayToken::class);
}
public function system_logs() public function system_logs()
{ {
return $this->hasMany(SystemLog::class)->orderBy('id', 'DESC')->take(50); return $this->hasMany(SystemLog::class)->orderBy('id', 'DESC')->take(50);

View File

@ -16,6 +16,7 @@ use App\Models\CreditInvitation;
use App\Models\Design; use App\Models\Design;
use App\Models\InvoiceInvitation; use App\Models\InvoiceInvitation;
use App\Models\QuoteInvitation; use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\Design as PdfMakerDesign;
@ -52,6 +53,9 @@ class Phantom
} elseif ($invitation instanceof QuoteInvitation) { } elseif ($invitation instanceof QuoteInvitation) {
$entity = 'quote'; $entity = 'quote';
$entity_design_id = 'quote_design_id'; $entity_design_id = 'quote_design_id';
} elseif ($invitation instanceof RecurringInvoiceInvitation) {
$entity = 'recurring_invoice';
$entity_design_id = 'invoice_design_id';
} }
$entity_obj = $invitation->{$entity}; $entity_obj = $invitation->{$entity};
@ -68,6 +72,10 @@ class Phantom
$path = $entity_obj->client->credit_filepath(); $path = $entity_obj->client->credit_filepath();
} }
if ($entity == 'recurring_invoice') {
$path = $entity_obj->client->recurring_invoice_filepath();
}
$file_path = $path.$entity_obj->number.'.pdf'; $file_path = $path.$entity_obj->number.'.pdf';
$url = config('ninja.app_url').'/phantom/'.$entity.'/'.$invitation->key.'?phantomjs_secret='.config('ninja.phantomjs_secret'); $url = config('ninja.app_url').'/phantom/'.$entity.'/'.$invitation->key.'?phantomjs_secret='.config('ninja.phantomjs_secret');
@ -147,6 +155,10 @@ class Phantom
App::setLocale($invitation->contact->preferredLocale()); App::setLocale($invitation->contact->preferredLocale());
$entity_design_id = $entity . '_design_id'; $entity_design_id = $entity . '_design_id';
if($entity == 'recurring_invoice')
$entity_design_id = 'invoice_design_id';
$design_id = $entity_obj->design_id ? $entity_obj->design_id : $this->decodePrimaryKey($entity_obj->client->getSetting($entity_design_id)); $design_id = $entity_obj->design_id ? $entity_obj->design_id : $this->decodePrimaryKey($entity_obj->client->getSetting($entity_design_id));
$design = Design::find($design_id); $design = Design::find($design_id);

View File

@ -79,7 +79,6 @@
"mockery/mockery": "^1.3.1", "mockery/mockery": "^1.3.1",
"nunomaduro/collision": "^5.0", "nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.0", "phpunit/phpunit": "^9.0",
"spatie/laravel-ray": "^1.3",
"vimeo/psalm": "^4.0", "vimeo/psalm": "^4.0",
"wildbit/postmark-php": "^4.0" "wildbit/postmark-php": "^4.0"
}, },

909
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,51 +6,74 @@
<h1>Import completed</h1> <h1>Import completed</h1>
<p>Hello, here is the output of your recent import job.</p> <p>Hello, here is the output of your recent import job.</p>
@if(isset($clients) && count($clients) >=1) <p><b>If your logo imported correctly it will display below. If it didn't import, you'll need to reupload your logo</b></p>
<h3>Clients Imported: {{ count($clients) }} </h3>
<p><img src="{{ $company->present()->logo() }}"></p>
@if(isset($company) && count($company->clients) >=1)
<p><b>Clients Imported:</b> {{ count($company->clients) }} </p>
@endif @endif
@if(isset($errors['clients']) && count($errors['clients']) >=1) @if(isset($company) && count($company->products) >=1)
<h3>Client Errors</h3> <p><b>Products Imported:</b> {{ count($company->products) }} </p>
<ul>
@foreach($errors['clients'] as $error)
<li>{{ $error['client'] }} - {{ $error['error'] }}</li>
@endforeach
</ul>
@endif @endif
@if(isset($invoices) && count($invoices) >=1) @if(isset($company) && count($company->invoices) >=1)
<p><b>Invoices Imported:</b> {{ count($company->invoices) }} </p>
<h3>Invoices Imported: {{ count($invoices) }} </h3> <p>To test your PDF generation is working correctly, click <a href="{{$company->invoices->first()->invitations->first()->getLink() }}">here</a>. We've also attempted to attach the PDF to this email.
@endif @endif
@if(isset($errors['invoices']) && count($errors['invoices']) >=1) @if(isset($company) && count($company->payments) >=1)
<h3>Invoices Errors</h3> <p><b>Payments Imported:</b> {{ count($company->payments) }} </p>
<ul>
@foreach($errors['invoices'] as $error)
<li>{{ $error['invoice'] }} - {{ $error['error'] }}</li>
@endforeach
</ul>
@endif @endif
@if(isset($products) && count($products) >=1) @if(isset($company) && count($company->recurring_invoices) >=1)
<h3>Products Imported: {{ count($products) }} </h3> <p><b>Recurring Invoices Imported:</b> {{ count($company->recurring_invoices) }} </p>
@endif @endif
@if(isset($errors['products']) && count($errors['products']) >=1) @if(isset($company) && count($company->quotes) >=1)
<h3>Client Errors</h3> <p><b>Quotes Imported:</b> {{ count($company->quotes) }} </p>
<ul>
@foreach($errors['products'] as $error)
<li>{{ $error['product'] }} - {{ $error['error'] }}</li>
@endforeach
</ul>
@endif @endif
<a href="{{ url('/') }}" target="_blank" class="button">Visit portal</a> @if(isset($company) && count($company->credits) >=1)
<p><b>Credits Imported:</b> {{ count($company->credits) }} </p>
@endif
<p>Thank you, <br/> Invoice Ninja.</p> @if(isset($company) && count($company->projects) >=1)
<p><b>Projects Imported:</b> {{ count($company->projects) }} </p>
@endif
@if(isset($company) && count($company->tasks) >=1)
<p><b>Tasks Imported:</b> {{ count($company->tasks) }} </p>
@endif
@if(isset($company) && count($company->vendors) >=1)
<p><b>Vendors Imported:</b> {{ count($company->vendors) }} </p>
@endif
@if(isset($company) && count($company->expenses) >=1)
<p><b>Expenses Imported:</b> {{ count($company->expenses) }} </p>
@endif
@if(isset($company) && count($company->company_gateways) >=1)
<p><b>Gateways Imported:</b> {{ count($company->company_gateways) }} </p>
@endif
@if(isset($company) && count($company->client_gateway_tokens) >=1)
<p><b>Client Gateway Tokens Imported:</b> {{ count($company->client_gateway_tokens) }} </p>
@endif
@if(isset($company) && count($company->tax_rates) >=1)
<p><b>Tax Rates Imported:</b> {{ count($company->tax_rates) }} </p>
@endif
@if(isset($company) && count($company->documents) >=1)
<p><b>Documents Imported:</b> {{ count($company->documents) }} </p>
@endif
<a href="{{ url('/') }}" target="_blank" class="button">{{ ctrans('texts.account_login')}}</a>
<p>{{ ctrans('texts.email_signature')}}<br/> {{ ctrans('texts.email_from') }}</p>
@endcomponent @endcomponent

View File

@ -128,7 +128,7 @@ class CompanyGatewayResolutionTest extends TestCase
$payment_methods = $this->client->service()->getPaymentMethods($amount); $payment_methods = $this->client->service()->getPaymentMethods($amount);
$this->assertEquals(3, count($payment_methods)); $this->assertEquals(2, count($payment_methods));
} }
public function testRemoveMethods() public function testRemoveMethods()