diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php
index 0947acad3685..cdd1ff6c1338 100644
--- a/app/DataMapper/CompanySettings.php
+++ b/app/DataMapper/CompanySettings.php
@@ -93,9 +93,9 @@ class CompanySettings extends BaseSettings
$config = json_decode(config('ninja.settings'));
return (object) [
- 'timezone_id' => config('ninja.i18n.timezone'),
- 'language_id' => config('ninja.i18n.language'),
- 'currency_id' => config('ninja.i18n.currency'),
+ 'timezone_id' => config('ninja.i18n.timezone_id'),
+ 'language_id' => config('ninja.i18n.language_id'),
+ 'currency_id' => config('ninja.i18n.currency_id'),
'payment_terms' => config('ninja.i18n.payment_terms'),
'datetime_format_id' => config('ninja.i18n.datetime_format'),
'military_time' => config('ninja.i18n.military_time'),
diff --git a/app/Models/Client.php b/app/Models/Client.php
index 79ed5da1653f..f8ba50671913 100644
--- a/app/Models/Client.php
+++ b/app/Models/Client.php
@@ -6,6 +6,7 @@ use App\DataMapper\ClientSettings;
use App\Models\Company;
use App\Models\Country;
use App\Models\Filterable;
+use App\Models\Timezone;
use App\Utils\Traits\MakesHash;
use Hashids\Hashids;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -43,8 +44,6 @@ class Client extends BaseModel
'settings' => 'object'
];
- //protected $dates = ['deleted_at'];
-
public function getClientSettingsObjectAttribute()
{
return new ClientSettings($this->settings);
@@ -80,4 +79,16 @@ class Client extends BaseModel
return $this->belongsTo(Country::class, 'shipping_country_id', 'id');
}
+ public function timezone()
+ {
+ return Timezone::find($this->getSettings()->timezone_id);
+ }
+
+ public function getSettings()
+ {
+ return ClientSettings::buildClientSettings($this->company->settings, $this->settings);
+ }
+
+
+
}
diff --git a/app/Models/Invitation.php b/app/Models/Invitation.php
deleted file mode 100644
index 7e0974406a65..000000000000
--- a/app/Models/Invitation.php
+++ /dev/null
@@ -1,22 +0,0 @@
-morphedByMany(Invoice::class, 'inviteable');
- }
-
-
- public function proposals()
- {
- return $this->morphedByMany(Proposal::class, 'inviteable');
- }
-
-}
diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php
index 3bab2c4c3499..2cbf3b9b1219 100644
--- a/app/Models/Invoice.php
+++ b/app/Models/Invoice.php
@@ -42,6 +42,6 @@ class Invoice extends BaseModel
public function invitations()
{
- $this->morphMany(Invitation::class, 'inviteable');
+ return $this->hasMany(InvoiceInvitation::class);
}
}
diff --git a/app/Models/InvoiceInvitation.php b/app/Models/InvoiceInvitation.php
new file mode 100644
index 000000000000..903814dcb5a9
--- /dev/null
+++ b/app/Models/InvoiceInvitation.php
@@ -0,0 +1,54 @@
+belongsTo(Invoice::class)->withTrashed();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function contact()
+ {
+ return $this->belongsTo(ClientContact::class)->withTrashed();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function user()
+ {
+ return $this->belongsTo(User::class)->withTrashed();
+ }
+
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function company()
+ {
+ return $this->belongsTo(Company::class);
+ }
+
+ public function signatureDiv()
+ {
+ if (! $this->signature_base64) {
+ return false;
+ }
+
+ return sprintf('
%s: %s', $this->signature_base64, ctrans('texts.signed'), $this->createClientDate($this->signature_date, $this->contact->client->timezone()->name));
+ }
+
+}
diff --git a/app/Models/Quote.php b/app/Models/Quote.php
index d3df7b803e42..d58997272dca 100644
--- a/app/Models/Quote.php
+++ b/app/Models/Quote.php
@@ -30,6 +30,7 @@ class Quote extends BaseModel
public function invitations()
{
- $this->morphMany(Invitation::class, 'inviteable');
+ return $this->hasMany(QuoteInvitation::class);
}
+
}
diff --git a/app/Models/QuoteInvitation.php b/app/Models/QuoteInvitation.php
new file mode 100644
index 000000000000..3546fa98f933
--- /dev/null
+++ b/app/Models/QuoteInvitation.php
@@ -0,0 +1,54 @@
+belongsTo(Quote::class)->withTrashed();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function contact()
+ {
+ return $this->belongsTo(ClientContact::class)->withTrashed();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function user()
+ {
+ return $this->belongsTo(User::class)->withTrashed();
+ }
+
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function company()
+ {
+ return $this->belongsTo(Company::class);
+ }
+
+ public function signatureDiv()
+ {
+ if (! $this->signature_base64) {
+ return false;
+ }
+
+ return sprintf('
%s: %s', $this->signature_base64, ctrans('texts.signed'), $this->createClientDate($this->signature_date, $this->contact->client->timezone()->name));
+ }
+
+}
diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php
index 698c24b001f0..b84ce24c719b 100644
--- a/app/Models/RecurringInvoice.php
+++ b/app/Models/RecurringInvoice.php
@@ -33,6 +33,6 @@ class RecurringInvoice extends BaseModel
public function invitations()
{
- $this->morphMany(Invitation::class, 'inviteable');
+ $this->morphMany(RecurringInvoiceInvitation::class);
}
}
diff --git a/app/Models/RecurringInvoiceInvitation.php b/app/Models/RecurringInvoiceInvitation.php
new file mode 100644
index 000000000000..29f4b0ae0ef1
--- /dev/null
+++ b/app/Models/RecurringInvoiceInvitation.php
@@ -0,0 +1,54 @@
+belongsTo(RecurringInvoice::class)->withTrashed();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function contact()
+ {
+ return $this->belongsTo(ClientContact::class)->withTrashed();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function user()
+ {
+ return $this->belongsTo(User::class)->withTrashed();
+ }
+
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function company()
+ {
+ return $this->belongsTo(Company::class);
+ }
+
+ public function signatureDiv()
+ {
+ if (! $this->signature_base64) {
+ return false;
+ }
+
+ return sprintf('
%s: %s', $this->signature_base64, ctrans('texts.signed'), $this->createClientDate($this->signature_date, $this->contact->client->timezone()->name));
+ }
+
+}
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
index e5319b7457a1..f5bb53a2f048 100644
--- a/app/Providers/RouteServiceProvider.php
+++ b/app/Providers/RouteServiceProvider.php
@@ -2,6 +2,9 @@
namespace App\Providers;
+use App\Models\InvoiceInvitation;
+use App\Models\QuoteInvitation;
+use App\Models\RecurringInvoiceInvitation;
use App\Utils\Traits\MakesHash;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
@@ -63,8 +66,16 @@ class RouteServiceProvider extends ServiceProvider
return \App\Models\Expense::withTrashed()->where('id', $this->decodePrimaryKey($value))->firstOrFail();
});
- Route::bind('invitation', function ($value) {
- return \App\Models\Invitation::withTrashed()->where('id', $this->decodePrimaryKey($value))->firstOrFail();
+ Route::bind('invoice_invitation', function ($value) {
+ return \App\Models\InvoiceInvitation::withTrashed()->where('id', $this->decodePrimaryKey($value))->firstOrFail();
+ });
+
+ Route::bind('recurring_invoice_invitation', function ($value) {
+ return \App\Models\RecurringInvoiceInvitation::withTrashed()->where('id', $this->decodePrimaryKey($value))->firstOrFail();
+ });
+
+ Route::bind('quote_invitation', function ($value) {
+ return \App\Models\QuoteInvitation::withTrashed()->where('id', $this->decodePrimaryKey($value))->firstOrFail();
});
Route::bind('task', function ($value) {
diff --git a/config/ninja.php b/config/ninja.php
index d5972490a650..b80009de757e 100644
--- a/config/ninja.php
+++ b/config/ninja.php
@@ -33,10 +33,10 @@ return [
],
'i18n' => [
- 'timezone' => env('DEFAULT_TIMEZONE', 15),
- 'country' => env('DEFAULT_COUNTRY', 840), // United Stated
- 'currency' => env('DEFAULT_CURRENCY', 1), //USD
- 'language' => env('DEFAULT_LANGUAGE', 1), //en
+ 'timezone_id' => env('DEFAULT_TIMEZONE', 15),
+ 'country_id' => env('DEFAULT_COUNTRY', 840), // United Stated
+ 'currency_id' => env('DEFAULT_CURRENCY', 1), //USD
+ 'language_id' => env('DEFAULT_LANGUAGE', 1), //en
'date_format' => env('DEFAULT_DATE_FORMAT', 'M j, Y'),
'date_picker_format' => env('DEFAULT_DATE_PICKER_FORMAT', 'M d, yyyy'),
'datetime_format' => env('DEFAULT_DATETIME_FORMAT', 'F j, Y g:i a'),
diff --git a/database/migrations/2014_10_13_000000_create_users_table.php b/database/migrations/2014_10_13_000000_create_users_table.php
index cf3dda5aab5a..b3136af0f0fb 100644
--- a/database/migrations/2014_10_13_000000_create_users_table.php
+++ b/database/migrations/2014_10_13_000000_create_users_table.php
@@ -506,26 +506,33 @@ class CreateUsersTable extends Migration
$t->unique(['company_id', 'quote_number']);
});
- Schema::create('invitations', function ($t) {
+ Schema::create('invoice_invitations', function ($t) {
$t->increments('id');
$t->unsignedInteger('company_id');
- $t->unsignedInteger('inviteable_id');
- $t->string('inviteable_type');
$t->unsignedInteger('user_id');
$t->unsignedInteger('client_contact_id');
$t->unsignedInteger('invoice_id')->index();
- $t->string('invitation_key',100)->index()->unique();
+ $t->string('invitation_key')->index()->unique();
$t->timestamps();
$t->softDeletes();
$t->string('transaction_reference')->nullable();
+ $t->string('message_id')->nullable();
+ $t->text('email_error');
+ $t->text('signature_base64');
+ $t->timestamp('signature_date')->nullable();
+
$t->timestamp('sent_date')->nullable();
$t->timestamp('viewed_date')->nullable();
+ $t->timestamp('opened_date')->nullable();
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$t->foreign('client_contact_id')->references('id')->on('client_contacts')->onDelete('cascade');
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$t->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
+
+ $t->index(['deleted_at', 'invoice_id']);
+
});
diff --git a/tests/Feature/ClientTest.php b/tests/Feature/ClientTest.php
index 937b45c6837b..b3061cdaf32a 100644
--- a/tests/Feature/ClientTest.php
+++ b/tests/Feature/ClientTest.php
@@ -3,6 +3,7 @@
namespace Tests\Feature;
use App\Models\Account;
+use App\Models\Client;
use App\Models\Company;
use App\Models\User;
use App\Utils\Traits\MakesHash;
@@ -179,4 +180,34 @@ class ClientTest extends TestCase
}
+ public function testDefaultTimeZoneFromClientModel()
+ {
+
+ $user = User::all()->first();
+ $company = Company::all()->first();
+
+ factory(\App\Models\Client::class, 3)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){
+
+ factory(\App\Models\ClientContact::class,1)->create([
+ 'user_id' => $user->id,
+ 'client_id' => $c->id,
+ 'company_id' => $company->id,
+ 'is_primary' => 1
+ ]);
+
+ factory(\App\Models\ClientContact::class,2)->create([
+ 'user_id' => $user->id,
+ 'client_id' => $c->id,
+ 'company_id' => $company->id
+ ]);
+
+ });
+
+ $client = Client::all()->first();
+
+ $this->assertEquals($client->getSettings()->timezone_id, 15);
+
+ $this->assertEquals($client->timezone()->name, 'US/Eastern');
+ }
+
}
diff --git a/tests/Feature/LoginTest.php b/tests/Feature/LoginTest.php
index 3d91c9d94123..ab0b305da423 100644
--- a/tests/Feature/LoginTest.php
+++ b/tests/Feature/LoginTest.php
@@ -20,9 +20,9 @@ use Tests\TestCase;
class LoginTest extends TestCase
{
- //use DatabaseTransactions;
- use UserSessionAttributes;
- use RefreshDatabase;
+ use DatabaseTransactions;
+ //use UserSessionAttributes;
+ //use RefreshDatabase;
public function setUp()
{