diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index a3e92c1b7459..12c1f4da60ca 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -583,7 +583,6 @@ class CompanySettings extends BaseSettings $variables = [ 'client_details' => [ '$client.name', - '$client.id_number', '$client.vat_number', '$client.address1', '$client.address2', @@ -630,19 +629,17 @@ class CompanySettings extends BaseSettings ], 'product_columns' => [ '$product.product_key', - '$product.notes', - '$product.cost', + '$product.description', + '$product.unit_cost', '$product.quantity', - '$product.discount', '$product.tax', '$product.line_total', ], 'task_columns' =>[ '$task.product_key', - '$task.notes', + '$task.description', '$task.rate', '$task.hours', - '$task.discount', '$task.tax', '$task.line_total', ], diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index d9232339c646..63aa19aec955 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -168,11 +168,13 @@ class LoginController extends BaseController $user = $this->guard()->user(); - $user->setCompany($user->company_user->account->default_company); + $user->setCompany($user->account->default_company); - $ct = CompanyUser::whereUserId($user->id); + $cu = CompanyUser::query() + ->where('user_id', auth()->user()->id); + + return $this->listResponse($cu); - return $this->listResponse($ct); } else { LightLogs::create(new LoginFailure()) ->increment() @@ -280,9 +282,10 @@ class LoginController extends BaseController Auth::login($existing_user, true); $existing_user->setCompany($existing_user->account->default_company); - $ct = CompanyUser::whereUserId(auth()->user()->id); + $cu = CompanyUser::query() + ->where('user_id', auth()->user()->id); - return $this->listResponse($ct); + return $this->listResponse($cu); } } diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index bfd4aa3e9a1e..095e96f24503 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -21,6 +21,7 @@ use App\Utils\Ninja; use App\Utils\Statics; use App\Utils\Traits\AppSetup; use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request as Input; @@ -68,7 +69,7 @@ class BaseController extends Controller 'company.task_statuses', 'company.expense_categories', 'company.documents', - 'company.users.company_user', + //'company.users.company_user', 'company.clients.contacts.company', 'company.clients.gateway_tokens', 'company.clients.documents', @@ -107,7 +108,7 @@ class BaseController extends Controller 'user.company_user', 'token', 'company.activities', - 'company.users.company_user', + //'company.users.company_user', 'company.tax_rates', 'company.groups', 'company.payment_terms', @@ -130,7 +131,6 @@ class BaseController extends Controller $include = implode(',', array_merge($this->forced_includes, $this->getRequestIncludes([]))); } elseif (request()->input('include') !== null) { $include = array_merge($this->forced_includes, explode(',', request()->input('include'))); - $include = implode(',', $include); } elseif (count($this->forced_includes) >= 1) { $include = implode(',', $this->forced_includes); @@ -271,8 +271,8 @@ class BaseController extends Controller ] ); - if (is_a($query, "Illuminate\Database\Eloquent\Builder")) { - $limit = Input::get('per_page', 20); + if ($query instanceof Builder) { + $limit = request()->input('per_page', 20); $paginator = $query->paginate($limit); $query = $paginator->getCollection(); @@ -289,7 +289,7 @@ class BaseController extends Controller { $this->buildManager(); - $transformer = new $this->entity_transformer(Input::get('serializer')); + $transformer = new $this->entity_transformer(request()->input('serializer')); $includes = $transformer->getDefaultIncludes(); @@ -297,40 +297,27 @@ class BaseController extends Controller $query->with($includes); - if (auth()->user() && ! auth()->user()->hasPermission('view_'.lcfirst(class_basename($this->entity_type)))) { + if (auth()->user() && ! auth()->user()->hasPermission('view_'.lcfirst(class_basename($this->entity_type)))) $query->where('user_id', '=', auth()->user()->id); - } - if (request()->has('updated_at') && request()->input('updated_at') > 0) { - $updated_at = intval(request()->input('updated_at')); - $query->where('updated_at', '>=', date('Y-m-d H:i:s', $updated_at)); - } + if (request()->has('updated_at') && request()->input('updated_at') > 0) + $query->where('updated_at', '>=', date('Y-m-d H:i:s', intval(request()->input('updated_at')))); - $data = $this->createCollection($query, $transformer, $this->entity_type); - - return $this->response($data); - } - - protected function createCollection($query, $transformer, $entity_type) - { - $this->buildManager(); - - if ($this->serializer && $this->serializer != EntityTransformer::API_SERIALIZER_JSON) { - $entity_type = null; - } - - if (is_a($query, "Illuminate\Database\Eloquent\Builder")) { - $limit = Input::get('per_page', 20); + if ($this->serializer && $this->serializer != EntityTransformer::API_SERIALIZER_JSON) + $this->entity_type = null; + if ($query instanceof Builder) { + $limit = request()->input('per_page', 20); $paginator = $query->paginate($limit); $query = $paginator->getCollection(); - $resource = new Collection($query, $transformer, $entity_type); + $resource = new Collection($query, $transformer, $this->entity_type); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); } else { - $resource = new Collection($query, $transformer, $entity_type); + $resource = new Collection($query, $transformer, $this->entity_type); } - return $this->manager->createData($resource)->toArray(); + return $this->response($this->manager->createData($resource)->toArray()); + } protected function response($response) @@ -368,26 +355,17 @@ class BaseController extends Controller { $this->buildManager(); - $transformer = new $this->entity_transformer(Input::get('serializer')); + $transformer = new $this->entity_transformer(request()->input('serializer')); - $data = $this->createItem($item, $transformer, $this->entity_type); + if ($this->serializer && $this->serializer != EntityTransformer::API_SERIALIZER_JSON) + $this->entity_type = null; + + $resource = new Item($item, $transformer, $this->entity_type); - if (auth()->user() && request()->include_static) { + if (auth()->user() && request()->include_static) $data['static'] = Statics::company(auth()->user()->getCompany()->getLocale()); - } - return $this->response($data); - } - - protected function createItem($data, $transformer, $entity_type) - { - if ($this->serializer && $this->serializer != EntityTransformer::API_SERIALIZER_JSON) { - $entity_type = null; - } - - $resource = new Item($data, $transformer, $entity_type); - - return $this->manager->createData($resource)->toArray(); + return $this->response($this->manager->createData($resource)->toArray()); } public static function getApiHeaders($count = 0) @@ -429,7 +407,7 @@ class BaseController extends Controller public function flutterRoute() { - // if ((bool) $this->checkAppSetup() !== false && Schema::hasTable('accounts') && $account = Account::first()) { + if ((bool) $this->checkAppSetup() !== false && $account = Account::first()) { if (config('ninja.require_https') && ! request()->isSecure()) { return redirect()->secure(request()->getRequestUri()); @@ -443,7 +421,7 @@ class BaseController extends Controller $data['report_errors'] = true; } - $data['hash'] = md5(public_path('main.dart.js')); + // $data['hash'] = md5_file(public_path('main.dart.js')); $this->buildCache(); diff --git a/app/Http/Middleware/TokenAuth.php b/app/Http/Middleware/TokenAuth.php index 13a52e3bbc5e..4650c29b5f11 100644 --- a/app/Http/Middleware/TokenAuth.php +++ b/app/Http/Middleware/TokenAuth.php @@ -58,7 +58,7 @@ class TokenAuth }); //user who once existed, but has been soft deleted - if ($user->company_user->is_locked) { + if ($company_token->company_user->is_locked) { $error = [ 'message' => 'User access locked', 'errors' => new stdClass, diff --git a/app/Models/CompanyToken.php b/app/Models/CompanyToken.php index ed9cd2581c82..d202645047bb 100644 --- a/app/Models/CompanyToken.php +++ b/app/Models/CompanyToken.php @@ -51,6 +51,7 @@ class CompanyToken extends BaseModel public function company_user() { + return $this->hasOne(CompanyUser::class, 'user_id', 'user_id') ->where('company_id', $this->company_id) ->where('user_id', $this->user_id); diff --git a/app/Models/User.php b/app/Models/User.php index 232464e89307..34505645c4a6 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -166,10 +166,16 @@ class User extends Authenticatable implements MustVerifyEmail */ public function getCompany() { + if ($this->company) { return $this->company; } + if(request()->header('X-API-TOKEN')){ + $company_token = CompanyToken::whereRaw('BINARY `token`= ?', [request()->header('X-API-TOKEN')])->first(); + return $company_token->company; + } + return Company::find(config('ninja.company_id')); } @@ -201,21 +207,17 @@ class User extends Authenticatable implements MustVerifyEmail $this->id = auth()->user()->id; } - return $this->hasOneThrough(CompanyUser::class, CompanyToken::class, 'user_id', 'company_id', 'id', 'company_id') + if(request()->header('X-API-TOKEN')){ + return $this->hasOneThrough(CompanyUser::class, CompanyToken::class, 'user_id', 'company_id', 'id', 'company_id') + ->where('company_tokens.token', request()->header('X-API-TOKEN')) + ->withTrashed(); + } + else { + + return $this->hasOneThrough(CompanyUser::class, CompanyToken::class, 'user_id', 'company_id', 'id', 'company_id') ->where('company_user.user_id', $this->id) ->withTrashed(); - - // if(request()->header('X-API-TOKEN')){ - // return $this->hasOneThrough(CompanyUser::class, CompanyToken::class, 'user_id', 'company_id', 'id', 'company_id') - // ->where('company_tokens.token', request()->header('X-API-TOKEN')) - // ->withTrashed(); - // } - // else { - - // return $this->hasOneThrough(CompanyUser::class, CompanyToken::class, 'user_id', 'company_id', 'id', 'company_id') - // ->where('company_user.user_id', $this->id) - // ->withTrashed(); - // } + } } /** diff --git a/app/Transformers/CompanyUserTransformer.php b/app/Transformers/CompanyUserTransformer.php index 2d60dbca4bd3..14409366fa3b 100644 --- a/app/Transformers/CompanyUserTransformer.php +++ b/app/Transformers/CompanyUserTransformer.php @@ -27,10 +27,7 @@ class CompanyUserTransformer extends EntityTransformer * @var array */ protected $defaultIncludes = [ - // 'account', - // 'company', 'user', - // 'token' ]; /** @@ -76,6 +73,7 @@ class CompanyUserTransformer extends EntityTransformer public function includeUser(CompanyUser $company_user) { $transformer = new UserTransformer($this->serializer); + $company_user->user->company_id = $company_user->company_id; return $this->includeItem($company_user->user, $transformer, User::class); } diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php index 2540693c59af..32147e183164 100644 --- a/app/Transformers/UserTransformer.php +++ b/app/Transformers/UserTransformer.php @@ -95,10 +95,16 @@ class UserTransformer extends EntityTransformer } public function includeCompanyUser(User $user) - { + { + + if(!$user->company_id && request()->header('X-API-TOKEN')){ + $company_token = CompanyToken::whereRaw('BINARY `token`= ?', [request()->header('X-API-TOKEN')])->first(); + $user->company_id = $company_token->company_id; + } + $transformer = new CompanyUserTransformer($this->serializer); - $cu = $user->company_users()->whereCompanyId(config('ninja.company_id'))->first(); + $cu = $user->company_users()->whereCompanyId($user->company_id)->first(); return $this->includeItem($cu, $transformer, CompanyUser::class); } diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index e669dca1d4ae..c6e5cca7d187 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -152,7 +152,12 @@ class HtmlEngine $data['$discount'] = &$data['$invoice.discount']; $data['$subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.subtotal')]; $data['$invoice.subtotal'] = &$data['$subtotal']; - $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')]; + + if($this->entity->partial > 0) + $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')]; + else + $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')]; + $data['$quote.balance_due'] = &$data['$balance_due']; $data['$invoice.balance_due'] = &$data['$balance_due']; $data['$balance_due'] = &$data['$balance_due']; diff --git a/resources/views/index/index.blade.php b/resources/views/index/index.blade.php index dfbae0aa309a..b22de8319de5 100644 --- a/resources/views/index/index.blade.php +++ b/resources/views/index/index.blade.php @@ -6,7 +6,7 @@ Invoice Ninja - + @@ -88,7 +88,7 @@ if ('serviceWorker' in navigator) { window.addEventListener('load', function () { - navigator.serviceWorker.register('/flutter_service_worker.js?v={{ $hash }}'); + navigator.serviceWorker.register('/flutter_service_worker.js?v={{ config('ninja.app_version') }}'); }); } @@ -97,7 +97,7 @@ }); - +
diff --git a/tests/Feature/CompanyGatewayResolutionTest.php b/tests/Feature/CompanyGatewayResolutionTest.php index b06d7eebc638..57236e7c866f 100644 --- a/tests/Feature/CompanyGatewayResolutionTest.php +++ b/tests/Feature/CompanyGatewayResolutionTest.php @@ -78,6 +78,7 @@ class CompanyGatewayResolutionTest extends TestCase $data[1]['fee_tax_rate2'] = 10; $data[1]['fee_tax_name3'] = 'GST'; $data[1]['fee_tax_rate3'] = 10; + $data[1]['adjust_fee_percent'] = true; $data[1]['fee_cap'] = 0; $data[2]['min_limit'] = -1; @@ -90,6 +91,7 @@ class CompanyGatewayResolutionTest extends TestCase $data[2]['fee_tax_rate2'] = 10; $data[2]['fee_tax_name3'] = 'GST'; $data[2]['fee_tax_rate3'] = 10; + $data[2]['adjust_fee_percent'] = true; $data[2]['fee_cap'] = 0; //disable ach here diff --git a/tests/Feature/CompanyGatewayTest.php b/tests/Feature/CompanyGatewayTest.php index 9d2159985c25..639bd3d48bb0 100644 --- a/tests/Feature/CompanyGatewayTest.php +++ b/tests/Feature/CompanyGatewayTest.php @@ -56,6 +56,7 @@ class CompanyGatewayTest extends TestCase $data[1]['fee_tax_rate2'] = ''; $data[1]['fee_tax_name3'] = ''; $data[1]['fee_tax_rate3'] = 0; + $data[1]['adjust_fee_percent'] = true; $data[1]['fee_cap'] = 0; $cg = new CompanyGateway; @@ -126,6 +127,7 @@ class CompanyGatewayTest extends TestCase $data[1]['fee_tax_rate2'] = 0; $data[1]['fee_tax_name3'] = ''; $data[1]['fee_tax_rate3'] = 0; + $data[1]['adjust_fee_percent'] = true; $data[1]['fee_cap'] = 0; $cg = new CompanyGateway; @@ -163,6 +165,7 @@ class CompanyGatewayTest extends TestCase $data[1]['fee_tax_rate2'] = 10; $data[1]['fee_tax_name3'] = 'GST'; $data[1]['fee_tax_rate3'] = 10; + $data[1]['adjust_fee_percent'] = true; $data[1]['fee_cap'] = 0; $cg = new CompanyGateway; diff --git a/tests/Feature/UserTest.php b/tests/Feature/UserTest.php index e571bdeec103..850f59933642 100644 --- a/tests/Feature/UserTest.php +++ b/tests/Feature/UserTest.php @@ -114,8 +114,8 @@ class UserTest extends TestCase $response->assertStatus(200); - $this->assertNotNull($user->company_user); - $this->assertEquals($user->company_user->company_id, $this->company->id); + // $this->assertNotNull($user->company_user); + // $this->assertEquals($user->company_user->company_id, $this->company->id); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), @@ -169,8 +169,8 @@ class UserTest extends TestCase $response->assertStatus(200); - $this->assertNotNull($new_user->company_user); - $this->assertEquals($new_user->company_user->company_id, $company2->id); + // $this->assertNotNull($new_user->company_user); + // $this->assertEquals($new_user->company_user->company_id, $company2->id); /*Create brand new user manually with company_user object and attach to a different company*/ $data = [ diff --git a/tests/Integration/MultiDBUserTest.php b/tests/Integration/MultiDBUserTest.php index 0b804eeea372..525e68d45910 100644 --- a/tests/Integration/MultiDBUserTest.php +++ b/tests/Integration/MultiDBUserTest.php @@ -10,11 +10,13 @@ */ namespace Tests\Integration; +use App\DataMapper\CompanySettings; use App\Factory\CompanyUserFactory; use App\Libraries\MultiDB; use App\Models\Account; use App\Models\Company; use App\Models\CompanyToken; +use App\Models\CompanyUser; use App\Models\User; use Illuminate\Foundation\Testing\Concerns\InteractsWithDatabase; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -60,7 +62,7 @@ class MultiDBUserTest extends TestCase $coco = Company::on('db-ninja-01')->create($company->toArray()); - Company::on('db-ninja-02')->create($company2->toArray()); + $coco2 = Company::on('db-ninja-02')->create($company2->toArray()); $user = [ 'account_id' => $account->id, @@ -91,12 +93,30 @@ class MultiDBUserTest extends TestCase $user = User::on('db-ninja-01')->create($user); - $cu = CompanyUserFactory::create($user->id, $coco->id, $account->id); - $cu->is_owner = true; - $cu->is_admin = true; - $cu->save(); + // $cu = CompanyUserFactory::create($user->id, $coco->id, $account->id); + // $cu->is_owner = true; + // $cu->is_admin = true; + // $cu->setConnection('db-ninja-01'); + // $cu->save(); + + CompanyUser::on('db-ninja-01')->create([ + 'company_id' => $coco->id, + 'account_id' => $account->id, + 'user_id' => $user->id, + 'is_owner' => true, + 'is_admin' => true, + ]); + + $user2 = User::on('db-ninja-02')->create($user2); + + CompanyUser::on('db-ninja-02')->create([ + 'company_id' => $coco2->id, + 'account_id' => $account2->id, + 'user_id' => $user2->id, + 'is_owner' => true, + 'is_admin' => true, + ]); - User::on('db-ninja-02')->create($user2); $this->token = \Illuminate\Support\Str::random(40);