Client Portal conditionals (#3039)

* Fixes for tests

* add additional fields for company settings

* fixes for travis

* update company settings schema

* Disable client portal

* Client Portal middleware

* Working on client portal

* hide portal

* Implement notification channgels for User and ClientContact models

* Push notifications onto queue

* Force authentication if client portal is password protected
This commit is contained in:
David Bomba 2019-11-04 11:22:59 +11:00 committed by GitHub
parent ea2f15d1a9
commit b7d3f4e7aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 375 additions and 44 deletions

View File

@ -26,6 +26,13 @@ class CompanySettings extends BaseSettings
public $auto_archive_invoice = false;
public $lock_sent_invoices = false;
public $enable_client_portal_tasks = false;
public $enable_client_portal_password = false;
public $enable_client_portal = true; //implemented
public $enable_client_portal_dashboard = true; //implemented
public $signature_on_pdf = false;
public $document_email_attachment = false;
public $send_portal_password = false;
public $timezone_id = '';
public $date_format_id = '';
@ -52,7 +59,6 @@ class CompanySettings extends BaseSettings
public $payment_terms = 1;
public $send_reminders = false;
public $show_tasks_in_portal = false;
public $custom_message_dashboard = '';
public $custom_message_unpaid_invoice = '';
@ -62,6 +68,7 @@ class CompanySettings extends BaseSettings
public $auto_convert_quote = false;
public $inclusive_taxes = false;
public $quote_footer = '';
public $translations;
@ -104,7 +111,7 @@ class CompanySettings extends BaseSettings
public $shared_invoice_quote_counter = false;
public $recurring_invoice_number_prefix = 'R';
public $recurring_number_prefix = 'R';
public $reset_counter_frequency_id = '0';
public $reset_counter_date = '';
public $counter_padding = 4;
@ -130,7 +137,6 @@ class CompanySettings extends BaseSettings
public $custom_fields = '';
public $invoice_fields = '';
public $enable_portal_password = false;
public $show_accept_invoice_terms = false;
public $show_accept_quote_terms = false;
public $require_invoice_signature = false;
@ -147,9 +153,11 @@ class CompanySettings extends BaseSettings
public $email_subject_invoice = '';
public $email_subject_quote = '';
public $email_subject_payment = '';
public $email_subject_statement = '';
public $email_template_invoice = '';
public $email_template_quote = '';
public $email_template_payment = '';
public $email_template_statement = '';
public $email_subject_reminder1 = '';
public $email_subject_reminder2 = '';
public $email_subject_reminder3 = '';
@ -158,7 +166,8 @@ class CompanySettings extends BaseSettings
public $email_template_reminder2 = '';
public $email_template_reminder3 = '';
public $email_template_reminder_endless = '';
public $email_footer = '';
public $email_signature = '';
public $enable_email_markup = true;
/* Company Meta data that we can use to build sub companies*/
@ -187,6 +196,16 @@ class CompanySettings extends BaseSettings
public static $casts = [
'document_email_attachment' => 'bool',
'enable_client_portal_password' => 'bool',
'enable_email_markup' => 'bool',
'enable_client_portal_dashboard' => 'bool',
'enable_client_portal' => 'bool',
'email_template_statement' => 'string',
'email_subject_statement' => 'string',
'signature_on_pdf' => 'bool',
'send_portal_password' => 'bool',
'quote_footer' => 'string',
'page_size' => 'string',
'font_size' => 'int',
'primary_font' => 'string',
@ -243,7 +262,7 @@ class CompanySettings extends BaseSettings
'custom_message_unapproved_quote' => 'string',
'custom_fields' => 'string',
'default_task_rate' => 'float',
'email_footer' => 'string',
'email_signature' => 'string',
'email_subject_invoice' => 'string',
'email_subject_quote' => 'string',
'email_subject_payment' => 'string',
@ -258,7 +277,7 @@ class CompanySettings extends BaseSettings
'email_template_reminder2' => 'string',
'email_template_reminder3' => 'string',
'email_template_reminder_endless' => 'string',
'enable_portal_password' => 'bool',
'enable_client_portal_password' => 'bool',
'inclusive_taxes' => 'bool',
'invoice_number_prefix' => 'string',
'invoice_number_pattern' => 'string',
@ -280,7 +299,7 @@ class CompanySettings extends BaseSettings
'quote_number_pattern' => 'string',
'quote_number_counter' => 'integer',
'quote_terms' => 'string',
'recurring_invoice_number_prefix' => 'string',
'recurring_number_prefix' => 'string',
'reset_counter_frequency_id' => 'integer',
'reset_counter_date' => 'string',
'require_invoice_signature' => 'bool',
@ -304,7 +323,7 @@ class CompanySettings extends BaseSettings
'language_id' => 'string',
'show_currency_code' => 'bool',
'send_reminders' => 'bool',
'show_tasks_in_portal' => 'bool',
'enable_client_portal_tasks' => 'bool',
'lock_sent_invoices' => 'bool',
'auto_archive_invoice' => 'bool',
'auto_archive_quote' => 'bool',

View File

@ -12,6 +12,7 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\ClientContact;
use Auth;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
@ -26,7 +27,7 @@ class ContactLoginController extends Controller
public function __construct()
{
$this->middleware('guest:contact', ['except' => ['logout']]);
$this->middleware('guest:contact', ['except' => ['logout']]);
}
public function showLoginForm()
@ -60,7 +61,16 @@ class ContactLoginController extends Controller
return $this->sendFailedLoginResponse($request);
}
public function authenticated(Request $request, ClientContact $client)
{
Auth::guard('contact')->login($client, true);
if(session()->get('url.intended'))
return redirect(session()->get('url.intended'));
return redirect()->intended();
}
public function logout()
{

View File

@ -32,13 +32,19 @@ class InvitationController extends Controller
public function invoiceRouter(string $invitation_key)
{
// $invitation = InvoiceInvitation::whereInvitationKey($invitation_key)->first();
$invitation = InvoiceInvitation::whereRaw("BINARY `invitation_key`= ?", [$invitation_key])->first();
if($invitation){
$invitation->markViewed();
Auth::guard('contact')->loginUsingId($invitation->client_contact_id, true);
return redirect()->route('client.invoice.show', ['invoice' => $this->encodePrimaryKey($invitation->invoice_id)]);
\Log::error("bool val = ".boolval($invitation->contact->client->getSetting('enable_client_portal_password')));
if((bool)$invitation->contact->client->getSetting('enable_client_portal_password') !== false)
$this->middleware('auth:contact');
$invitation->markViewed();
return redirect()->route('client.invoice.show', ['invoice' => $this->encodePrimaryKey($invitation->invoice_id)]);
}
else
abort(404);

View File

@ -17,6 +17,7 @@ use App\Models\RecurringInvoice;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Yajra\DataTables\Facades\DataTables;
use Yajra\DataTables\Html\Builder;
@ -80,8 +81,24 @@ class RecurringInvoiceController extends Controller
];
return view('portal.default.recurring_invoices.show', $data);
}
public function requestCancellation(Request $request, RecurringInvoice $recurring_invoice)
{
$data = [
'invoice' => $recurring_invoice
];
//todo double check the user is able to request a cancellation
Mail::to(config('ninja.contact.ninja_official_contact'))
->send(new RecurringCancellationRequest($invoice));
return view('portal.default.recurring_invoices.request_cancellation', $data);
}
}

View File

@ -21,7 +21,7 @@
* @OA\Property(property="custom_invoice_taxes4", type="boolean", example=true, description="____________"),
* @OA\Property(property="default_task_rate", type="number", format="float", example="10.00", description="____________"),
* @OA\Property(property="send_reminders", type="boolean", example=true, description="____________"),
* @OA\Property(property="show_tasks_in_portal", type="boolean", example=true, description="____________"),
* @OA\Property(property="enable_client_portal_tasks", type="boolean", example=true, description="____________"),
* @OA\Property(property="email_style", type="string", example="light", description="options include plain,light,dark,custom"),
* @OA\Property(property="reply_to_email", type="string", example="email@gmail.com", description="The reply to email address"),
* @OA\Property(property="bcc_email", type="string", example="email@gmail.com, contact@gmail.com", description="A comma separate list of BCC emails"),
@ -134,6 +134,16 @@
* @OA\Property(property="embed_documents", type="boolean", example=false, description="____________"),
* @OA\Property(property="all_pages_header", type="boolean", example=false, description="____________"),
* @OA\Property(property="all_pages_footer", type="boolean", example=false, description="____________"),
* @OA\Property(property="document_email_attachment", type="boolean", example=false, description="____________"),
* @OA\Property(property="enable_client_portal_password", type="boolean", example=false, description="____________"),
* @OA\Property(property="enable_email_markup", type="boolean", example=false, description="____________"),
* @OA\Property(property="enable_client_portal_dashboard", type="boolean", example=false, description="____________"),
* @OA\Property(property="enable_client_portal", type="boolean", example=false, description="____________"),
* @OA\Property(property="email_template_statement", type="string", example='template matter', description="____________"),
* @OA\Property(property="email_subject_statement", type="string", example='subject matter', description="____________"),
* @OA\Property(property="signature_on_pdf", type="boolean", example=false, description="____________"),
* @OA\Property(property="send_portal_password", type="boolean", example=false, description="____________"),
* @OA\Property(property="quote_footer", type="string", example='the quote footer', description="____________"),
* )
*/

View File

@ -107,5 +107,6 @@ class Kernel extends HttpKernel
'domain_db' => \App\Http\Middleware\SetDomainNameDb::class,
'password_protected' => \App\Http\Middleware\PasswordProtection::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'portal_enabled' => \App\Http\Middleware\ClientPortalEnabled::class,
];
}

View File

@ -0,0 +1,36 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Middleware;
use App\Models\User;
use Closure;
class ClientPortalEnabled
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if(auth()->user()->client->getSetting('enable_client_portal') === false)
return redirect()->to('client/dashboard');
return $next($request);
}
}

View File

@ -29,7 +29,7 @@ class RedirectIfAuthenticated
switch ($guard) {
case 'contact':
if (Auth::guard($guard)->check()) {
return redirect()->route('client.dashboard');
return redirect()->route('client.dashboard');
}
break;
case 'user':

View File

@ -49,6 +49,9 @@ class PortalComposer
$data['countries'] = TranslationHelper::getCountries();
$data['company'] = auth()->user()->company;
$data['client'] = auth()->user()->client;
$data['settings'] = auth()->user()->client->getMergedSettings();
//\Log::error(print_r($data['settings'],1));
return $data;

View File

@ -17,11 +17,13 @@ use App\Jobs\Company\CreateCompanyToken;
use App\Jobs\User\CreateUser;
use App\Models\Account;
use App\Models\User;
use App\Notifications\NewAccountCreated;
use App\Utils\Traits\UserSessionAttributes;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
class CreateAccount
{
@ -89,6 +91,9 @@ class CreateAccount
if($user)
event(new AccountCreated($user));
Notification::route('slack', config('ninja.notification.slack'))
->notify(new NewAccountCreated($user, $company));
return $account;
}
}

View File

@ -62,6 +62,7 @@ class CreateUser
$user->fill($this->request);
$user->email = $this->request['email'];//todo need to remove this in production
$user->last_login = now();
$user->ip = request()->ip();
$user->save();
$user->companies()->attach($this->company->id, [

View File

@ -0,0 +1,35 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class RecurringCancellationRequest extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public $recurring_invoice
public function __construct(RecurringInvoice $recurring_invoice)
{
$this->recurring_invoice = $recurring_invoice
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('view.name');
}
}

View File

@ -47,7 +47,7 @@ class SupportMessageSent extends Mailable
$log_lines = iterator_to_array($lines);
}
return $this->from(config('mail.from.address'))
return $this->from(config('mail.from.address')) //todo this needs to be fixed to handle the hosted version
->subject(ctrans('texts.new_support_message'))
->markdown('email.support.message', [
'message' => $this->message,

View File

@ -12,20 +12,22 @@
namespace App\Models;
use App\Models\Company;
use App\Models\Language;
use App\Models\User;
use App\Notifications\ClientContactResetPassword as ResetPasswordNotification;
use App\Notifications\ClientContactResetPassword;
use App\Utils\Traits\MakesHash;
use Hashids\Hashids;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laracasts\Presenter\PresentableTrait;
use Illuminate\Support\Facades\Log;
use Laracasts\Presenter\PresentableTrait;
class ClientContact extends Authenticatable
class ClientContact extends Authenticatable implements HasLocalePreference
{
use Notifiable;
use MakesHash;
@ -133,4 +135,11 @@ class ClientContact extends Authenticatable
{
$this->notify(new ClientContactResetPassword($token));
}
public function preferredLocale()
{
$lang = Language::find($this->client->getSetting('language_id'));
return $lang->locale;
}
}

View File

@ -43,7 +43,7 @@ class InvoiceInvitation extends BaseModel
*/
public function contact()
{
return $this->belongsTo(ClientContact::class)->withTrashed();
return $this->belongsTo(ClientContact::class,'client_contact_id','id')->withTrashed();
}
/**

View File

@ -15,11 +15,13 @@ use App\Models\Company;
use App\Models\CompanyToken;
use App\Models\CompanyUser;
use App\Models\Filterable;
use App\Models\Language;
use App\Models\Traits\UserTrait;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\UserSessionAttributes;
use App\Utils\Traits\UserSettings;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
@ -28,7 +30,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Laracasts\Presenter\PresentableTrait;
class User extends Authenticatable implements MustVerifyEmail
class User extends Authenticatable implements MustVerifyEmail,HasLocalePreference
{
use Notifiable;
use SoftDeletes;
@ -62,8 +64,8 @@ class User extends Authenticatable implements MustVerifyEmail
protected $fillable = [
'first_name',
'last_name',
// 'email',
// 'phone',
'email',
'phone',
'signature',
'avatar',
'accepted_terms_version',
@ -323,4 +325,19 @@ class User extends Authenticatable implements MustVerifyEmail
return null;
}
public function routeNotificationForSlack($notification)
{
//todo need to return the company channel here for hosted users
//else the env variable for selfhosted
return config('ninja.notification.slack');
}
public function preferredLocale()
{
$lang = Language::find($this->company()->settings->language_id);
return $lang->locale;
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
class NewAccountCreated extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
protected $user;
protected $company;
public function __construct($user, $company)
{
$this->user = $user;
$this->company = $company;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['slack'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
public function toSlack($notifiable)
{
$user_name = $this->user->first_name . " " . $this->user->last_name;
$email = $this->user->email;
$ip = $this->user->ip;
return (new SlackMessage)
->success()
->to("#devv2")
->from("System")
->image('https://app.invoiceninja.com/favicon.png')
->content("A new account has been created by {$user_name} - {$email} - from IP: {$ip}");
}
}

View File

@ -27,6 +27,7 @@
"intervention/image": "^2.4",
"laracasts/presenter": "^0.2.1",
"laravel/framework": "6.0.*",
"laravel/slack-notification-channel": "^2.0",
"laravel/socialite": "^4.0",
"laravel/tinker": "^1.0",
"laravelcollective/html": "6.0.*",

View File

@ -84,6 +84,9 @@ return [
//'frequencies' => 'App\Models\Frequency',
//'fonts' => 'App\Models\Font',
],
'notification' => [
'slack' => env('SLACK_WEBHOOK_URL',''),
],
'payment_terms' => [
[
'num_days' => 0,

View File

@ -230,6 +230,8 @@ class CreateUsersTable extends Migration
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('phone')->nullable();
$table->string('ip')->nullable();
$table->string('device_token')->nullable();
$table->string('email',100)->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('confirmation_code')->nullable();

View File

@ -3,6 +3,7 @@
@section('body')
<main class="main">
<div class="container-fluid">
@if($settings->enable_client_portal_dashboard == 'true')
<div class="row" style="margin-top: 30px;">
<div class="col-6 col-lg-4">
<div class="card">
@ -40,6 +41,7 @@
</div>
</div>
</div>
@endif
<!-- client and supplier information -->
<div class="row">
<div class="col-sm-6 col-md-6">

View File

@ -56,4 +56,12 @@
@yield('body')
@include('portal.default.footer')
@yield('footer')
</html>
</html>
<script type="text/javascript">
@if($settings->enable_client_portal === false)
$('.navbar-toggler-icon').hide();
$('.app').removeClass("sidebar-lg-show");
$('.app').addClass("sidebar-hidden");
@endif
</script>

View File

@ -0,0 +1,40 @@
@extends('portal.default.layouts.master')
@section('header')
@stop
@section('body')
<main class="main">
<div class="container-fluid">
<div class="row" style="padding-top: 30px;">
<div class="col d-flex justify-content-center">
<div class="card w-50 p-10">
<div class="card-header">
Request Cancellation
</div>
<div class="card-body">
<table class="table table-responsive-sm table-bordered">
<tr><td style="text-align: right;">{{ctrans('texts.start_date')}}</td><td>{!! $invoice->start_date !!}</td></tr>
<tr><td style="text-align: right;">{{ctrans('texts.next_send_date')}}</td><td>{!! $invoice->next_send_date !!}</td></tr>
<tr><td style="text-align: right;">{{ctrans('texts.frequency')}}</td><td>{!! App\Models\RecurringInvoice::frequencyForKey($invoice->frequency_id) !!}</td></tr>
<tr><td style="text-align: right;">{{ctrans('texts.cycles_remaining')}}</td><td>{!! $invoice->remaining_cycles !!}</td></tr>
<tr><td style="text-align: right;">{{ctrans('texts.amount')}}</td><td>{!! $invoice->amount !!}</td></tr>
</table>
<div class="alert alert-primary" role="alert">Cancellation pending, we'll be in touch!</div>
</div>
</div>
</div>
</div>
</div>
</main>
</body>
@endsection
@push('css')
@endpush
@push('scripts')
@endpush
@section('footer')
@endsection

View File

@ -28,7 +28,7 @@
@if($invoice->remaining_cycles >=1)
<div class="pull-right">
<button class="btn btn-primary">Cancel</button>
<button class="btn btn-danger mb-1" type="button" data-toggle="modal" data-target="#cancel_recurring">Request Cancellation</button>
</div>
@endif
</div>
@ -38,6 +38,27 @@
</div>
</main>
<div class="modal fade show" id="cancel_recurring" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" style="display: none;" aria-hidden="true">
<div class="modal-dialog modal-danger" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Request Cancellation</h4>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Warning! You are requesting a cancellation of this service.</p>
<p>Your service may be cancelled with no further notification to you.</p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Close</button>
<a href="{{ route('client.recurring_invoices.request_cancellation',['recurring_invoice' => $invoice->hashed_id]) }}" class="btn btn-danger">Confirm Cancellation</a>
</div>
</div>
</div>
</div>
</body>
@endsection
@push('css')

View File

@ -16,15 +16,16 @@ Route::group(['middleware' => ['auth:contact'], 'prefix' => 'client', 'as' => 'c
Route::get('dashboard', 'ClientPortal\DashboardController@index')->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit
Route::get('invoices', 'ClientPortal\InvoiceController@index')->name('invoices.index');
Route::get('invoices', 'ClientPortal\InvoiceController@index')->name('invoices.index')->middleware('portal_enabled');
Route::post('invoices/payment', 'ClientPortal\InvoiceController@bulk')->name('invoices.bulk');
Route::get('invoices/{invoice}', 'ClientPortal\InvoiceController@show')->name('invoice.show');
Route::get('invoices/{invoice_invitation}', 'ClientPortal\InvoiceController@show')->name('invoice.show_invitation');
Route::get('recurring_invoices', 'ClientPortal\RecurringInvoiceController@index')->name('recurring_invoices.index');
Route::get('recurring_invoices', 'ClientPortal\RecurringInvoiceController@index')->name('recurring_invoices.index')->middleware('portal_enabled');
Route::get('recurring_invoices/{recurring_invoice}', 'ClientPortal\RecurringInvoiceController@show')->name('recurring_invoices.show');
Route::get('recurring_invoices/{recurring_invoice}/request_cancellation', 'ClientPortal\RecurringInvoiceController@requestCancellation')->name('recurring_invoices.request_cancellation');
Route::get('payments', 'ClientPortal\PaymentController@index')->name('payments.index');
Route::get('payments', 'ClientPortal\PaymentController@index')->name('payments.index')->middleware('portal_enabled');
Route::get('payments/{payment}', 'ClientPortal\PaymentController@show')->name('payments.show');
Route::post('payments/process', 'ClientPortal\PaymentController@process')->name('payments.process');
Route::post('payments/process/response', 'ClientPortal\PaymentController@response')->name('payments.response');

View File

@ -72,7 +72,7 @@ class AccountTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$response->assertStatus(200);

View File

@ -57,7 +57,7 @@ class ClientTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$response->assertStatus(200);
@ -98,7 +98,7 @@ class ClientTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();

View File

@ -128,7 +128,7 @@ class CompanySettingsTest extends TestCase
$settings->require_quote_signature = true;
$settings->show_accept_quote_terms = false;
$settings->show_accept_invoice_terms = "TRUE";
$settings->show_tasks_in_portal = "FALSE";
$settings->enable_client_portal_tasks = "FALSE";
$this->company->settings = $settings;

View File

@ -58,7 +58,7 @@ class CompanyTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$response->assertStatus(200);
@ -80,7 +80,7 @@ class CompanyTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $token,
])->post('/api/v1/companies/',
])->post('/api/v1/companies?include=company',
[
'name' => 'A New Company',
'logo' => UploadedFile::fake()->image('avatar.jpg')

View File

@ -61,7 +61,7 @@ class InvoiceTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();

View File

@ -58,7 +58,7 @@ class PaymentTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();
@ -122,7 +122,7 @@ class PaymentTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();

View File

@ -55,7 +55,7 @@ class ProductTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$response->assertStatus(200);

View File

@ -57,7 +57,7 @@ class QuoteTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();
@ -121,7 +121,7 @@ class QuoteTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();

View File

@ -57,7 +57,7 @@ class RecurringInvoiceTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();
@ -121,7 +121,7 @@ class RecurringInvoiceTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();
$account = Account::find($this->decodePrimaryKey($acc['data'][0]['account']['id']));

View File

@ -57,7 +57,7 @@ class RecurringQuoteTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();
@ -121,7 +121,7 @@ class RecurringQuoteTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$acc = $response->json();

View File

@ -56,7 +56,7 @@ class UserTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
])->post('/api/v1/signup?include=account', $data);
$response->assertStatus(200);