diff --git a/VERSION.txt b/VERSION.txt index 83e2d80cab..230cac8f9b 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.6.29 \ No newline at end of file +5.6.30 \ No newline at end of file diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 91871e2ae6..5a957a8f8f 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -812,14 +812,14 @@ class CompanySettings extends BaseSettings * need to provide a fallback catch on old settings objects which will * set new properties to the object prior to being returned. * - * @param $settings + * @param \stdClass $settings * * @return stdClass */ public static function setProperties($settings): stdClass { $company_settings = (object) get_class_vars(self::class); - + foreach ($company_settings as $key => $value) { if (! property_exists($settings, $key)) { $settings->{$key} = self::castAttribute($key, $company_settings->{$key}); diff --git a/app/Filters/PaymentFilters.php b/app/Filters/PaymentFilters.php index 92c1a78278..38381ed786 100644 --- a/app/Filters/PaymentFilters.php +++ b/app/Filters/PaymentFilters.php @@ -12,6 +12,7 @@ namespace App\Filters; use App\Models\Payment; +use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder; /** @@ -117,6 +118,8 @@ class PaymentFilters extends QueryFilters /** * Returns a list of payments that can be matched to bank transactions + * @param ?string $value + * @return Builder */ public function match_transactions($value = 'true'): Builder { @@ -124,7 +127,7 @@ class PaymentFilters extends QueryFilters if ($value == 'true') { return $this->builder ->where('is_deleted', 0) - ->where(function ($query) { + ->where(function (Builder $query) { $query->whereNull('transaction_id') ->orWhere("transaction_id", "") ->company(); diff --git a/app/Http/Controllers/MigrationController.php b/app/Http/Controllers/MigrationController.php index 55f8979d87..217d29ed5e 100644 --- a/app/Http/Controllers/MigrationController.php +++ b/app/Http/Controllers/MigrationController.php @@ -301,6 +301,7 @@ class MigrationController extends BaseController $user = auth()->user(); $company_count = $user->account->companies()->count(); + $fresh_company = false; // Look for possible existing company (based on company keys). $existing_company = Company::whereRaw('BINARY `company_key` = ?', [$company['company_key']])->first(); diff --git a/app/Http/Controllers/OneTimeTokenController.php b/app/Http/Controllers/OneTimeTokenController.php index 2d387a0fc9..b065a50529 100644 --- a/app/Http/Controllers/OneTimeTokenController.php +++ b/app/Http/Controllers/OneTimeTokenController.php @@ -74,6 +74,7 @@ class OneTimeTokenController extends BaseController 'user_id' => $user->id, 'company_key'=> $user->company()->company_key, 'context' => $request->input('context'), + 'is_react' => $request->has('react') && $request->query('react') == 'true' ? true : false, ]; Cache::put($hash, $data, 3600); diff --git a/app/Http/Controllers/PreviewPurchaseOrderController.php b/app/Http/Controllers/PreviewPurchaseOrderController.php index 8ef2da0d51..81d823cf25 100644 --- a/app/Http/Controllers/PreviewPurchaseOrderController.php +++ b/app/Http/Controllers/PreviewPurchaseOrderController.php @@ -181,8 +181,8 @@ class PreviewPurchaseOrderController extends BaseController DB::connection(config('database.default'))->beginTransaction(); if ($request->has('entity_id')) { - /** @var \App\Models\PurchaseOrder|\Illuminate\Database\Eloquent\Builder $entity_obj **/ - $entity_obj = $class::on(config('database.default')) + /** @var \App\Models\PurchaseOrder|\Illuminate\Contracts\Database\Eloquent\Builder $entity_obj **/ + $entity_obj = \App\Models\PurchaseOrder::on(config('database.default')) ->with('vendor.company') ->where('id', $this->decodePrimaryKey($request->input('entity_id'))) ->where('company_id', $company->id) diff --git a/app/Http/Controllers/StripeConnectController.php b/app/Http/Controllers/StripeConnectController.php index 691d8602fd..b2e2bf70d4 100644 --- a/app/Http/Controllers/StripeConnectController.php +++ b/app/Http/Controllers/StripeConnectController.php @@ -32,7 +32,6 @@ class StripeConnectController extends BaseController */ public function initialize(InitializeStripeConnectRequest $request, string $token) { - // Should we check if company has set country in the ap? Otherwise this will fail. if (! is_array($request->getTokenContent())) { abort(400, 'Invalid token'); @@ -40,8 +39,6 @@ class StripeConnectController extends BaseController MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); - $company = Company::where('company_key', $request->getTokenContent()['company_key'])->first(); - $company_gateway = CompanyGateway::query() ->where('gateway_key', 'd14dd26a47cecc30fdd65700bfb67b34') ->where('company_id', $request->getCompany()->id) @@ -71,6 +68,20 @@ class StripeConnectController extends BaseController } try { + /** @class \stdClass $response + * @property string $scope + * @property string $stripe_user_id + * @property string $stripe_publishable_key + * @property string $refresh_token + * @property string $livemode + * @property string $access_token + * @property string $token_type + * @property string $stripe_user + * @property string $stripe_account + * @property string $error + */ + + /** @var \stdClass $response */ $response = \Stripe\OAuth::token([ 'grant_type' => 'authorization_code', 'code' => $request->input('code'), @@ -81,8 +92,7 @@ class StripeConnectController extends BaseController MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); - /** @var \App\Models\Company $company */ - $company = Company::where('company_key', $request->getTokenContent()['company_key'])->first(); + $company = Company::query()->where('company_key', $request->getTokenContent()['company_key'])->first(); $company_gateway = CompanyGateway::query() ->where('gateway_key', 'd14dd26a47cecc30fdd65700bfb67b34') @@ -97,7 +107,6 @@ class StripeConnectController extends BaseController $company_gateway->fees_and_limits = $fees_and_limits; $company_gateway->setConfig([]); $company_gateway->token_billing = 'always'; - // $company_gateway->save(); } $payload = [ @@ -116,39 +125,14 @@ class StripeConnectController extends BaseController $company_gateway->save(); // StripeWebhook::dispatch($company->company_key, $company_gateway->id); - - //response here - return view('auth.connect.completed'); - } - - private function checkAccountAlreadyLinkToEmail($company_gateway, $email) - { - $client = Client::first() ? Client::first() : new Client; - - //Pull the list of Stripe Accounts and see if we match - $accounts = $company_gateway->driver($client)->getAllConnectedAccounts()->data; - - foreach ($accounts as $account) { - if ($account['email'] == $email) { - return $account['id']; - } + if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) { + $redirect_uri = 'https://app.invoicing.co/#/settings/online_payments'; + } else { + $redirect_uri = 'https://invoicing.co/stripe/completed'; } - return false; + //response here + return view('auth.connect.completed', ['url' => $redirect_uri]); } - /********************************* - * Stripe OAuth - */ - - // public function initialize(InitializeStripeConnectRequest $request, string $token) - // { - - // $stripe_key = config('ninja.ninja_stripe_key'); - - // $endpoint = "https://connect.stripe.com/oauth/authorize?response_type=code&client_id={$stripe_key}&scope=read_write"; - - // return redirect($endpoint); - - // } } diff --git a/app/Http/Controllers/TwilioController.php b/app/Http/Controllers/TwilioController.php index 1f26720773..d6bf7488d9 100644 --- a/app/Http/Controllers/TwilioController.php +++ b/app/Http/Controllers/TwilioController.php @@ -123,6 +123,10 @@ class TwilioController extends BaseController return response()->json(['message' => 'Unable to retrieve user.'], 400); } + if (!$user->phone || $user->phone == '') { + return response()->json(['message' => 'User found, but no valid phone number on file, please contact support.'], 400); + } + $sid = config('ninja.twilio_account_sid'); $token = config('ninja.twilio_auth_token'); diff --git a/app/Http/Middleware/VendorContactKeyLogin.php b/app/Http/Middleware/VendorContactKeyLogin.php index 5b569bbded..e73a325546 100644 --- a/app/Http/Middleware/VendorContactKeyLogin.php +++ b/app/Http/Middleware/VendorContactKeyLogin.php @@ -13,14 +13,12 @@ namespace App\Http\Middleware; use Auth; use Closure; -use App\Utils\Ninja; use App\Models\Vendor; use App\Libraries\MultiDB; use Illuminate\Support\Str; use Illuminate\Http\Request; use App\Models\VendorContact; use Illuminate\Support\Facades\Cache; -use App\Events\Vednor\VendorContactLoggedIn; class VendorContactKeyLogin { @@ -59,8 +57,6 @@ class VendorContactKeyLogin auth()->guard('vendor')->loginUsingId($vendor_contact->id, true); - event(new VendorContactLoggedIn($vendor_contact, $vendor_contact->company, Ninja::eventVars())); - if ($request->query('redirect') && ! empty($request->query('redirect'))) { return redirect()->to($request->query('redirect')); } @@ -76,7 +72,6 @@ class VendorContactKeyLogin $vendor_contact->save(); auth()->guard('vendor')->loginUsingId($vendor_contact->id, true); - event(new VendorContactLoggedIn($vendor_contact, $vendor_contact->company, Ninja::eventVars())); if ($request->query('next')) { return redirect()->to($request->query('next')); } diff --git a/app/Http/Requests/Report/GenericReportRequest.php b/app/Http/Requests/Report/GenericReportRequest.php index d18bb516c2..4f941b5802 100644 --- a/app/Http/Requests/Report/GenericReportRequest.php +++ b/app/Http/Requests/Report/GenericReportRequest.php @@ -22,7 +22,11 @@ class GenericReportRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin() || $user->hasPermission('view_reports'); + } public function rules() diff --git a/app/Http/Requests/Yodlee/YodleeAuthRequest.php b/app/Http/Requests/Yodlee/YodleeAuthRequest.php index 942139a2e2..071ac46483 100644 --- a/app/Http/Requests/Yodlee/YodleeAuthRequest.php +++ b/app/Http/Requests/Yodlee/YodleeAuthRequest.php @@ -17,6 +17,11 @@ use App\Models\Company; use App\Models\User; use Illuminate\Support\Facades\Cache; +/** + * @class \App\Http\Requests\Yodlee\YodleeAuthRequest + * @property string $token + * @property string $state + */ class YodleeAuthRequest extends Request { /** @@ -39,7 +44,6 @@ class YodleeAuthRequest extends Request return []; } - /** @var $token */ public function getTokenContent() { if ($this->state) { diff --git a/app/Jobs/Document/ZipDocuments.php b/app/Jobs/Document/ZipDocuments.php index 393aeec3bb..d255c10640 100644 --- a/app/Jobs/Document/ZipDocuments.php +++ b/app/Jobs/Document/ZipDocuments.php @@ -66,9 +66,6 @@ class ZipDocuments implements ShouldQueue * Execute the job. * * @return void - * @throws \ZipStream\Exception\FileNotFoundException - * @throws \ZipStream\Exception\FileNotReadableException - * @throws \ZipStream\Exception\OverflowException */ public function handle() { diff --git a/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php b/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php index 8d9a14a760..ae545c6662 100644 --- a/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php +++ b/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php @@ -62,9 +62,6 @@ class ZipPurchaseOrders implements ShouldQueue * Execute the job. * * @return void - * @throws \ZipStream\Exception\FileNotFoundException - * @throws \ZipStream\Exception\FileNotReadableException - * @throws \ZipStream\Exception\OverflowException */ public function handle() { diff --git a/app/Jobs/Quote/ZipQuotes.php b/app/Jobs/Quote/ZipQuotes.php index 3dd1b7f896..14693ac3fc 100644 --- a/app/Jobs/Quote/ZipQuotes.php +++ b/app/Jobs/Quote/ZipQuotes.php @@ -62,9 +62,6 @@ class ZipQuotes implements ShouldQueue * Execute the job. * * @return void - * @throws \ZipStream\Exception\FileNotFoundException - * @throws \ZipStream\Exception\FileNotReadableException - * @throws \ZipStream\Exception\OverflowException */ public function handle() { diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 09f5571565..7f8c0d4bca 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -37,7 +37,6 @@ use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundExceptio * @property int $assigned_user_id * @method BaseModel service() * @property \App\Models\Company $company - * @property \App\Models\Vendor $vendor * @method static BaseModel find($value) * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel|Illuminate\Database\Eloquent\Relations\BelongsTo|\Awobaz\Compoships\Database\Eloquent\Relations\BelongsTo|\App\Models\Company company() @@ -63,11 +62,15 @@ use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundExceptio * @method int companyId() * @method createInvitations() * @method Builder scopeCompany(Builder $builder) + * @method static \Illuminate\Database\Eloquent\Builder company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel|\Illuminate\Database\Query\Builder withTrashed(bool $withTrashed = true) * @method static \Illuminate\Database\Eloquent\Builder|BaseModel|\Illuminate\Database\Query\Builder onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel|\Illuminate\Database\Query\Builder withoutTrashed() * @mixin \Eloquent * @mixin \Illuminate\Database\Eloquent\Builder + * + * @property \Illuminate\Support\Collection $tax_map + * @property array $total_tax_map */ class BaseModel extends Model { @@ -119,7 +122,10 @@ class BaseModel extends Model return parent::__call($method, $params); } - + /** + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ public function scopeCompany($query): \Illuminate\Database\Eloquent\Builder { /** @var \App\Models\User $user */ diff --git a/app/Models/Client.php b/app/Models/Client.php index 9f69bfc0d1..2087a27186 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -238,7 +238,10 @@ class Client extends BaseModel implements HasLocalePreference return $this->hasMany(CompanyLedger::class)->orderBy('id', 'desc'); } - public function company_ledger() + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function company_ledger(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(CompanyLedger::class, 'company_ledgerable'); } @@ -516,7 +519,10 @@ class Client extends BaseModel implements HasLocalePreference throw new \Exception('Could not find a settings object', 1); } - public function documents() :MorphMany + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function documents() :\Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(Document::class, 'documentable'); } diff --git a/app/Models/Company.php b/app/Models/Company.php index 0c8ac30a59..9b9f12c118 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -395,6 +395,9 @@ class Company extends BaseModel return $this->calculate_taxes && in_array($this->getSetting('country_id'), $this->tax_coverage_countries); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function documents() { return $this->morphMany(Document::class, 'documentable'); diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index ba3306808f..347365a63d 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -13,6 +13,8 @@ namespace App\Models; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\Pivot; +use Awobaz\Compoships\Exceptions\InvalidUsageException; +use Awobaz\Compoships\Database\Eloquent\Relations\HasMany; /** * App\Models\CompanyUser @@ -129,50 +131,62 @@ class CompanyUser extends Pivot } /** - * * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function user_pivot() + public function user_pivot(): \Illuminate\Database\Eloquent\Relations\HasOne { return $this->hasOne(User::class)->withPivot('permissions', 'settings', 'react_settings', 'is_admin', 'is_owner', 'is_locked', 'slack_webhook_url', 'migrating'); } /** - * * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function company_pivot() + public function company_pivot(): \Illuminate\Database\Eloquent\Relations\HasOne { return $this->hasOne(Company::class)->withPivot('permissions', 'settings', 'react_settings', 'is_admin', 'is_owner', 'is_locked', 'slack_webhook_url', 'migrating'); } - public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function user() { return $this->belongsTo(User::class)->withTrashed(); } - public function company(): \Illuminate\Database\Eloquent\Relations\BelongsTo + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function company() { return $this->belongsTo(Company::class); } - public function users(): \Illuminate\Database\Eloquent\Relations\HasMany + /** + * @return HasMany + */ + public function users() { return $this->hasMany(User::class)->withTrashed(); } - /*todo monitor this function - may fail under certain conditions*/ + /** + * @return HasMany + */ public function token() { return $this->hasMany(CompanyToken::class, 'user_id', 'user_id'); } - public function tokens(): \Illuminate\Database\Eloquent\Relations\HasMany + /** + * @return HasMany + */ + public function tokens() { return $this->hasMany(CompanyToken::class, 'user_id', 'user_id'); } - public function scopeAuthCompany($query) + public function scopeAuthCompany($query): \Illuminate\Database\Eloquent\Builder { /** @var \App\Models\User $user */ $user = auth()->user(); @@ -187,7 +201,7 @@ class CompanyUser extends Pivot * * @return bool */ - public function portalType():bool + public function portalType(): bool { return isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link; } diff --git a/app/Models/Credit.php b/app/Models/Credit.php index 8a4dc2ea64..d7d5e91d86 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -93,29 +93,30 @@ use Illuminate\Database\Eloquent\Relations\MorphMany; * @property string|null $reminder_last_sent * @property float $paid_to_date * @property int|null $subscription_id - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read int|null $activities_count - * @property-read \App\Models\User|null $assigned_user - * @property-read \App\Models\Client $client - * @property-read \App\Models\Company $company - * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger - * @property-read int|null $company_ledger_count - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read int|null $documents_count - * @property-read mixed $hashed_id - * @property-read \Illuminate\Database\Eloquent\Collection $history - * @property-read int|null $history_count - * @property-read \Illuminate\Database\Eloquent\Collection $invitations - * @property-read int|null $invitations_count - * @property-read \App\Models\Invoice|null $invoice - * @property-read \Illuminate\Database\Eloquent\Collection $invoices - * @property-read int|null $invoices_count - * @property-read \Illuminate\Database\Eloquent\Collection $payments - * @property-read int|null $payments_count - * @property-read \App\Models\Project|null $project - * @property-read \App\Models\User $user - * @property-read \App\Models\Client $client - * @property-read \App\Models\Vendor|null $vendor + * @property \Illuminate\Database\Eloquent\Collection $activities + * @property int|null $activities_count + * @property \App\Models\User|null $assigned_user + * @property \App\Models\Client $client + * @property \App\Models\Company $company + * @property \App\Models\CreditInvitation $invitation + * @property \Illuminate\Database\Eloquent\Collection $company_ledger + * @property int|null $company_ledger_count + * @property \Illuminate\Database\Eloquent\Collection $documents + * @property int|null $documents_count + * @property mixed $hashed_id + * @property \Illuminate\Database\Eloquent\Collection $history + * @property int|null $history_count + * @property \Illuminate\Database\Eloquent\Collection $invitations + * @property int|null $invitations_count + * @property \App\Models\Invoice|null $invoice + * @property \Illuminate\Database\Eloquent\Collection $invoices + * @property int|null $invoices_count + * @property \Illuminate\Database\Eloquent\Collection $payments + * @property int|null $payments_count + * @property \App\Models\Project|null $project + * @property \App\Models\User $user + * @property \App\Models\Client $client + * @property \App\Models\Vendor|null $vendor * @property-read mixed $pivot * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger @@ -269,6 +270,9 @@ class Credit extends BaseModel return $this->belongsTo(Invoice::class); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function company_ledger(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(CompanyLedger::class, 'company_ledgerable'); @@ -288,11 +292,17 @@ class Credit extends BaseModel return $this->belongsToMany(Invoice::class)->using(Paymentable::class); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphToMany + */ public function payments(): \Illuminate\Database\Eloquent\Relations\MorphToMany { return $this->morphToMany(Payment::class, 'paymentable'); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function documents(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(Document::class, 'documentable'); diff --git a/app/Models/CreditInvitation.php b/app/Models/CreditInvitation.php index 1c29cd73b7..ca5d8a2fb2 100644 --- a/app/Models/CreditInvitation.php +++ b/app/Models/CreditInvitation.php @@ -41,11 +41,11 @@ use Illuminate\Support\Facades\Storage; * @property int|null $deleted_at * @property string|null $signature_ip * @property string|null $email_status - * @property-read \App\Models\Company $company - * @property-read \App\Models\ClientContact $contact - * @property-read \App\Models\Credit $credit - * @property-read mixed $hashed_id - * @property-read \App\Models\User $user + * @property \App\Models\Company $company + * @property \App\Models\ClientContact $contact + * @property \App\Models\Credit $credit + * @property mixed $hashed_id + * @property \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\CreditInvitationFactory factory($count = null, $state = []) diff --git a/app/Models/Expense.php b/app/Models/Expense.php index d60802bc23..3ebe98b30c 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -150,7 +150,10 @@ class Expense extends BaseModel return self::class; } - public function documents() + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function documents(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(Document::class, 'documentable'); } diff --git a/app/Models/GroupSetting.php b/app/Models/GroupSetting.php index fb6b52b651..1a8bd5f093 100644 --- a/app/Models/GroupSetting.php +++ b/app/Models/GroupSetting.php @@ -102,7 +102,10 @@ class GroupSetting extends StaticModel return $this->hasMany(Client::class, 'id', 'group_settings_id'); } - public function documents() + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function documents(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(Document::class, 'documentable'); } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index f9903591b1..687cde690e 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -31,6 +31,7 @@ use App\Helpers\Invoice\InvoiceSumInclusive; use App\Utils\Traits\Invoice\ActionsInvoice; use Illuminate\Database\Eloquent\SoftDeletes; use App\Events\Invoice\InvoiceReminderWasEmailed; +use Illuminate\Database\Eloquent\Relations\HasManyThrough; /** * App\Models\Invoice @@ -99,12 +100,13 @@ use App\Events\Invoice\InvoiceReminderWasEmailed; * @property int $auto_bill_tries * @property bool $is_proforma * @property-read int|null $activities_count - * @property-read \App\Models\User|null $assigned_user + * @property \App\Models\User|null $assigned_user * @property \App\Models\Client $client - * @property-read \App\Models\Company $company + * @property \App\Models\InvoiceInvitation $invitation + * @property \App\Models\Company $company * @property-read int|null $company_ledger_count * @property-read int|null $credits_count - * @property-read \App\Models\Design|null $design + * @property \App\Models\Design|null $design * @property-read int|null $documents_count * @property-read \App\Models\Expense|null $expense * @property-read int|null $expenses_count @@ -301,16 +303,25 @@ class Invoice extends BaseModel return $this->belongsTo(Subscription::class)->withTrashed(); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function documents(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(Document::class, 'documentable'); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphToMany + */ public function payments(): \Illuminate\Database\Eloquent\Relations\MorphToMany { return $this->morphToMany(Payment::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded')->withTimestamps(); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function company_ledger(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(CompanyLedger::class, 'company_ledgerable'); @@ -321,32 +332,41 @@ class Invoice extends BaseModel return $this->hasMany(Activity::class)->orderBy('id', 'DESC')->take(50); } - public function history() + /** + * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough + */ + public function history(): \Illuminate\Database\Eloquent\Relations\HasManyThrough { return $this->hasManyThrough(Backup::class, Activity::class); } - public function credits() + public function credits(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(Credit::class); } - public function tasks() + public function tasks(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(Task::class); } - public function task() + /** + * @return \Illuminate\Database\Eloquent\Relations\HasOne + */ + public function task(): \Illuminate\Database\Eloquent\Relations\HasOne { return $this->hasOne(Task::class); } - public function expenses() + public function expenses(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(Expense::class); } - public function expense() + /** + * @return \Illuminate\Database\Eloquent\Relations\HasOne + */ + public function expense(): \Illuminate\Database\Eloquent\Relations\HasOne { return $this->hasOne(Expense::class); } @@ -745,4 +765,55 @@ class Invoice extends BaseModel return $type; } + + public function reminderSchedule(): string + { + $reminder_schedule = ''; + $settings = $this->client->getMergedSettings(); + + $send_email_enabled = ctrans('texts.send_email') . " " .ctrans('texts.enabled'); + $send_email_disabled = ctrans('texts.send_email') . " " .ctrans('texts.disabled'); + + $sends_email_1 = $settings->enable_reminder2 ? $send_email_enabled : $send_email_disabled; + $days_1 = $settings->num_days_reminder1 . " " . ctrans('texts.days'); + $schedule_1 = ctrans("texts.{$settings->schedule_reminder1}"); //after due date etc or disabled + $label_1 = ctrans('texts.reminder1'); + + $sends_email_2 = $settings->enable_reminder2 ? $send_email_enabled : $send_email_disabled; + $days_2 = $settings->num_days_reminder2 . " " . ctrans('texts.days'); + $schedule_2 = ctrans("texts.{$settings->schedule_reminder2}"); //after due date etc or disabled + $label_2 = ctrans('texts.reminder2'); + + $sends_email_3 = $settings->enable_reminder2 ? $send_email_enabled : $send_email_disabled; + $days_3 = $settings->num_days_reminder3 . " " . ctrans('texts.days'); + $schedule_3 = ctrans("texts.{$settings->schedule_reminder3}"); //after due date etc or disabled + $label_3 = ctrans('texts.reminder3'); + + $sends_email_endless = $settings->enable_reminder_endless ? $send_email_enabled : $send_email_disabled; + $days_endless = \App\Models\RecurringInvoice::frequencyForKey($settings->endless_reminder_frequency_id); + $label_endless = ctrans('texts.reminder_endless'); + + if($schedule_1 == ctrans('texts.disabled') || $settings->schedule_reminder1 == 'disabled' || $settings->schedule_reminder1 == '') + $reminder_schedule .= "{$label_1}: " . ctrans('texts.disabled') ."
"; + else + $reminder_schedule .= "{$label_1}: {$days_1} {$schedule_1} [{$sends_email_1}]
"; + + if($schedule_2 == ctrans('texts.disabled') || $settings->schedule_reminder2 == 'disabled' || $settings->schedule_reminder2 == '') + $reminder_schedule .= "{$label_2}: " . ctrans('texts.disabled') ."
"; + else + $reminder_schedule .= "{$label_2}: {$days_2} {$schedule_2} [{$sends_email_2}]
"; + + if($schedule_3 == ctrans('texts.disabled') || $settings->schedule_reminder3 == 'disabled' || $settings->schedule_reminder3 == '') + $reminder_schedule .= "{$label_3}: " . ctrans('texts.disabled') ."
"; + else + $reminder_schedule .= "{$label_3}: {$days_3} {$schedule_3} [{$sends_email_3}]
"; + + if($sends_email_endless == ctrans('texts.disabled') || $settings->endless_reminder_frequency_id == '0' || $settings->endless_reminder_frequency_id == '') + $reminder_schedule .= "{$label_endless}: " . ctrans('texts.disabled') ."
"; + else + $reminder_schedule .= "{$label_endless}: {$days_endless} [{$sends_email_endless}]
"; + + + return $reminder_schedule; + } } diff --git a/app/Models/InvoiceInvitation.php b/app/Models/InvoiceInvitation.php index bd4e24f75d..08513619b0 100644 --- a/app/Models/InvoiceInvitation.php +++ b/app/Models/InvoiceInvitation.php @@ -43,11 +43,11 @@ use Illuminate\Support\Facades\Storage; * @property int|null $deleted_at * @property string|null $signature_ip * @property string|null $email_status - * @property-read \App\Models\Company $company - * @property-read \App\Models\ClientContact $contact - * @property-read mixed $hashed_id - * @property-read \App\Models\Invoice $invoice - * @property-read \App\Models\User $user + * @property \App\Models\Company $company + * @property \App\Models\ClientContact $contact + * @property mixed $hashed_id + * @property \App\Models\Invoice $invoice + * @property \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\InvoiceInvitationFactory factory($count = null, $state = []) diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 79f4cfa5a8..3773e8237d 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -216,21 +216,24 @@ class Payment extends BaseModel } /** - * @return MorphedByMany + * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function invoices() + public function invoices(): \Illuminate\Database\Eloquent\Relations\MorphToMany { return $this->morphedByMany(Invoice::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded')->withTimestamps(); } /** - * @return MorphedByMany + * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function credits() + public function credits(): \Illuminate\Database\Eloquent\Relations\MorphToMany { return $this->morphedByMany(Credit::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded')->withTimestamps(); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function company_ledger(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(CompanyLedger::class, 'company_ledgerable'); @@ -266,7 +269,7 @@ class Payment extends BaseModel return $this->belongsTo(Project::class); } - public function translatedType() + public function translatedType(): string { if (! $this->type_id) { return ''; diff --git a/app/Models/PurchaseOrder.php b/app/Models/PurchaseOrder.php index 932d2ba9b9..cf4841147e 100644 --- a/app/Models/PurchaseOrder.php +++ b/app/Models/PurchaseOrder.php @@ -87,17 +87,17 @@ use Illuminate\Support\Facades\Storage; * @property int|null $expense_id * @property int|null $currency_id * @property-read int|null $activities_count - * @property-read \App\Models\User|null $assigned_user - * @property-read \App\Models\Client|null $client - * @property-read \App\Models\Company $company + * @property \App\Models\User|null $assigned_user + * @property \App\Models\Client|null $client + * @property \App\Models\Company $company * @property-read int|null $documents_count - * @property-read \App\Models\Expense|null $expense - * @property-read mixed $hashed_id - * @property-read \App\Models\Invoice|null $invoice - * @property-read \App\Models\Project|null $project - * @property-read \App\Models\User $user - * @property \App\Models\Vendor|null $vendor - * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder company() + * @property \App\Models\Expense|null $expense + * @property string $hashed_id + * @property \App\Models\Invoice|null $invoice + * @property \App\Models\Project|null $project + * @property \App\Models\User $user + * @property \App\Models\Vendor $vendor + * @property \App\Models\PurchaseOrderInvitation $invitation * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder exclude($columns) * @method static \Database\Factories\PurchaseOrderFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder filter(\App\Filters\QueryFilters $filters) @@ -110,10 +110,8 @@ use Illuminate\Support\Facades\Storage; * @property-read \Illuminate\Database\Eloquent\Collection $documents * @property-read \Illuminate\Database\Eloquent\Collection $history * @property-read \Illuminate\Database\Eloquent\Collection $invitations - * @property-read \Illuminate\Database\Eloquent\Collection $invoices - * @property-read \Illuminate\Database\Eloquent\Collection $payments - * @method static \Illuminate\Database\Eloquent\Builder|Task withTrashed() - * @method static \Illuminate\Database\Eloquent\Builder|Task withoutTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder withoutTrashed() * @mixin \Eloquent */ class PurchaseOrder extends BaseModel @@ -236,6 +234,9 @@ class PurchaseOrder extends BaseModel return $this->belongsTo(User::class, 'assigned_user_id', 'id')->withTrashed(); } + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ public function vendor(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Vendor::class)->withTrashed(); diff --git a/app/Models/PurchaseOrderInvitation.php b/app/Models/PurchaseOrderInvitation.php index be8e8f4dee..8599090ed2 100644 --- a/app/Models/PurchaseOrderInvitation.php +++ b/app/Models/PurchaseOrderInvitation.php @@ -40,11 +40,11 @@ use Illuminate\Support\Str; * @property int|null $updated_at * @property int|null $deleted_at * @property string|null $email_status - * @property-read \App\Models\Company $company - * @property-read \App\Models\VendorContact $contact - * @property-read mixed $hashed_id - * @property-read \App\Models\PurchaseOrder $purchase_order - * @property-read \App\Models\User $user + * @property \App\Models\Company $company + * @property \App\Models\VendorContact $contact + * @property string $hashed_id + * @property \App\Models\PurchaseOrder $purchase_order + * @property \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\PurchaseOrderInvitationFactory factory($count = null, $state = []) diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 38a3443460..3ab63980e7 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -91,9 +91,10 @@ use Laracasts\Presenter\PresentableTrait; * @property string|null $reminder_last_sent * @property string $paid_to_date * @property int|null $subscription_id - * @property-read \App\Models\User|null $assigned_user - * @property-read \App\Models\Client $client - * @property-read \App\Models\Company $company + * @property \App\Models\User|null $assigned_user + * @property \App\Models\Client $client + * @property \App\Models\Company $company + * @property \App\Models\QuoteInvitation $invitation * @property-read mixed $balance_due * @property-read mixed $hashed_id * @property-read mixed $total @@ -226,6 +227,9 @@ class Quote extends BaseModel return $this->belongsTo(Vendor::class); } + /** + * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough + */ public function history(): \Illuminate\Database\Eloquent\Relations\HasManyThrough { return $this->hasManyThrough(Backup::class, Activity::class); @@ -266,6 +270,9 @@ class Quote extends BaseModel return $this->hasMany(QuoteInvitation::class); } + /** + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ public function documents(): \Illuminate\Database\Eloquent\Relations\MorphMany { return $this->morphMany(Document::class, 'documentable'); diff --git a/app/Models/QuoteInvitation.php b/app/Models/QuoteInvitation.php index fcd20852f7..a183d3d5b6 100644 --- a/app/Models/QuoteInvitation.php +++ b/app/Models/QuoteInvitation.php @@ -41,11 +41,11 @@ use Illuminate\Support\Facades\Storage; * @property int|null $deleted_at * @property string|null $signature_ip * @property string|null $email_status - * @property-read \App\Models\Company $company - * @property-read \App\Models\ClientContact $contact - * @property-read mixed $hashed_id - * @property-read \App\Models\Quote $quote - * @property-read \App\Models\User $user + * @property \App\Models\Company $company + * @property \App\Models\ClientContact $contact + * @property mixed $hashed_id + * @property \App\Models\Quote $quote + * @property \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\QuoteInvitationFactory factory($count = null, $state = []) diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index 248f946fe9..44e8c61265 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -91,6 +91,7 @@ use Laracasts\Presenter\PresentableTrait; * @property-read \App\Models\User|null $assigned_user * @property-read \App\Models\Client $client * @property-read \App\Models\Company $company + * @property \App\Models\RecurringInvoiceInvitation $invitation * @property-read \Illuminate\Database\Eloquent\Collection $documents * @property-read int|null $documents_count * @property-read mixed $hashed_id diff --git a/app/Models/RecurringInvoiceInvitation.php b/app/Models/RecurringInvoiceInvitation.php index 01e2c088ce..34928a155c 100644 --- a/app/Models/RecurringInvoiceInvitation.php +++ b/app/Models/RecurringInvoiceInvitation.php @@ -37,11 +37,11 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string|null $viewed_date * @property string|null $opened_date * @property string|null $email_status - * @property-read \App\Models\Company $company - * @property-read \App\Models\ClientContact $contact - * @property-read mixed $hashed_id - * @property-read \App\Models\RecurringInvoice $recurring_invoice - * @property-read \App\Models\User $user + * @property \App\Models\Company $company + * @property \App\Models\ClientContact $contact + * @property string $hashed_id + * @property \App\Models\RecurringInvoice $recurring_invoice + * @property \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoiceInvitation newModelQuery() diff --git a/app/Models/User.php b/app/Models/User.php index 4e9a2864d6..98a1108904 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -95,6 +95,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable; * @property-read \Illuminate\Database\Eloquent\Collection $company_users * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications * @property-read \Illuminate\Database\Eloquent\Collection $tokens + * @property-read \Illuminate\Database\Eloquent\Collection $companies * @method bool hasPermissionTo(string $permission) * @method \App\Models\Company getCompany() * @method \App\Models\Company company() diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index d72061bad7..a055ed7992 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -66,7 +66,6 @@ use Laracasts\Presenter\PresentableTrait; * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact * @property-read int|null $primary_contact_count * @property-read \App\Models\User $user - * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns) * @method static \Database\Factories\VendorFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Vendor filter(\App\Filters\QueryFilters $filters) @@ -75,35 +74,6 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Vendor onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Vendor query() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope() - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereAddress1($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereAddress2($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereAssignedUserId($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCity($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCompanyId($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCountryId($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCreatedAt($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCurrencyId($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCustomValue1($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCustomValue2($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCustomValue3($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereCustomValue4($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereDeletedAt($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereId($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereIdNumber($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereIsDeleted($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereName($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereNumber($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor wherePhone($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor wherePostalCode($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor wherePrivateNotes($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor wherePublicNotes($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereState($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereTransactionName($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereUpdatedAt($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereUserId($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereVatNumber($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereVendorHash($value) - * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereWebsite($value) * @method static \Illuminate\Database\Eloquent\Builder|Vendor withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Vendor withoutTrashed() * @property-read \Illuminate\Database\Eloquent\Collection $activities @@ -215,6 +185,9 @@ class Vendor extends BaseModel return $this->company->timezone(); } + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ public function company(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Company::class); @@ -225,7 +198,7 @@ class Vendor extends BaseModel return $this->belongsTo(User::class)->withTrashed(); } - public function translate_entity() + public function translate_entity(): string { return ctrans('texts.vendor'); } @@ -253,7 +226,13 @@ class Vendor extends BaseModel return $defaults; } - public function getSetting($setting) + /** + * Returns a vendor settings proxying company setting + * + * @param string $setting + * @return string + */ + public function getSetting($setting): string { if ((property_exists($this->company->settings, $setting) != false) && (isset($this->company->settings->{$setting}) !== false)) { return $this->company->settings->{$setting}; diff --git a/app/PaymentDrivers/Stripe/ImportCustomers.php b/app/PaymentDrivers/Stripe/ImportCustomers.php index 387544bdb2..9d80b3b3a5 100644 --- a/app/PaymentDrivers/Stripe/ImportCustomers.php +++ b/app/PaymentDrivers/Stripe/ImportCustomers.php @@ -80,7 +80,7 @@ class ImportCustomers { $account = $this->stripe->company_gateway->company->account; - if (Ninja::isHosted() && ! $account->isPaidHostedClient() && Client::where('company_id', $this->stripe->company_gateway->company_id)->count() > config('ninja.quotas.free.clients')) { + if (Ninja::isHosted() && ! $account->isPaidHostedClient() && Client::query()->where('company_id', $this->stripe->company_gateway->company_id)->count() > config('ninja.quotas.free.clients')) { return; } @@ -115,7 +115,7 @@ class ImportCustomers $client->phone = $customer->address->phone ? $customer->phone : ''; if ($customer->address->country) { - $country = Country::where('iso_3166_2', $customer->address->country)->first(); + $country = Country::query()->where('iso_3166_2', $customer->address->country)->first(); if ($country) { $client->country_id = $country->id; @@ -124,7 +124,7 @@ class ImportCustomers } if ($customer->currency) { - $currency = Currency::where('code', $customer->currency)->first(); + $currency = Currency::query()->where('code', $customer->currency)->first(); if ($currency) { $settings = $client->settings; @@ -209,7 +209,7 @@ class ImportCustomers // nlog(count($searchResults)); if (count($searchResults) == 1) { - $cgt = ClientGatewayToken::where('gateway_customer_reference', $searchResults->data[0]->id)->where('company_id', $this->stripe->company_gateway->company->id)->exists(); + $cgt = ClientGatewayToken::query()->where('gateway_customer_reference', $searchResults->data[0]->id)->where('company_id', $this->stripe->company_gateway->company->id)->exists(); if (! $cgt) { nlog('customer '.$searchResults->data[0]->id.' does not exist.'); diff --git a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentFailureWebhook.php b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentFailureWebhook.php index 466c0c49db..38e9da662e 100644 --- a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentFailureWebhook.php +++ b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentFailureWebhook.php @@ -50,7 +50,7 @@ class PaymentIntentFailureWebhook implements ShouldQueue { MultiDB::findAndSetDbByCompanyKey($this->company_key); - $company = Company::where('company_key', $this->company_key)->first(); + $company = Company::query()->where('company_key', $this->company_key)->first(); foreach ($this->stripe_request as $transaction) { if (array_key_exists('payment_intent', $transaction)) { @@ -78,7 +78,7 @@ class PaymentIntentFailureWebhook implements ShouldQueue $payment->status_id = Payment::STATUS_FAILED; $payment->save(); - $payment_hash = PaymentHash::where('payment_id', $payment->id)->first(); + $payment_hash = PaymentHash::query()->where('payment_id', $payment->id)->first(); if ($payment_hash) { $error = ctrans('texts.client_payment_failure_body', [ diff --git a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php index 8cbaaf9575..58ff84400f 100644 --- a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php +++ b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php @@ -208,17 +208,24 @@ class UpdatePaymentMethods switch ($type_id) { case GatewayType::CREDIT_CARD: - $payment_meta = new \stdClass; - $payment_meta->exp_month = (string) $method->card->exp_month; - $payment_meta->exp_year = (string) $method->card->exp_year; - $payment_meta->brand = (string) $method->card->brand; - $payment_meta->last4 = (string) $method->card->last4; - $payment_meta->type = GatewayType::CREDIT_CARD; - - return $payment_meta; - - break; + /** + * @class \Stripe\PaymentMethod $method + * @property \Stripe\StripeObject $card + * @class \Stripe\StripeObject $card + * @property string $exp_year + * @property string $exp_month + * @property string $brand + * @property string $last4 + */ + + $payment_meta = new \stdClass; + $payment_meta->exp_month = (string) $method->card->exp_month; + $payment_meta->exp_year = (string) $method->card->exp_year; + $payment_meta->brand = (string) $method->card->brand; + $payment_meta->last4 = (string) $method->card->last4; + $payment_meta->type = GatewayType::CREDIT_CARD; + return $payment_meta; case GatewayType::ALIPAY: case GatewayType::SOFORT: diff --git a/app/Services/Client/ClientService.php b/app/Services/Client/ClientService.php index 81cd527c61..66ec70ed13 100644 --- a/app/Services/Client/ClientService.php +++ b/app/Services/Client/ClientService.php @@ -155,7 +155,8 @@ class ClientService return false; } - return $this->emailStatement($pdf, $statement->options); + $this->emailStatement($pdf, $statement->options); + return; } return $pdf; diff --git a/app/Services/Pdf/PdfMock.php b/app/Services/Pdf/PdfMock.php index 67ceaa42d8..3ee76fbaed 100644 --- a/app/Services/Pdf/PdfMock.php +++ b/app/Services/Pdf/PdfMock.php @@ -133,7 +133,7 @@ class PdfMock $entity->vendor = Vendor::factory()->make(); break; default: - # code... + $entity = false; break; } @@ -152,11 +152,12 @@ class PdfMock */ public function getMergedSettings() :object { + $settings = $this->company->settings; + match ($this->request['settings_type']) { 'group' => $settings = ClientSettings::buildClientSettings($this->company->settings, $this->request['settings']), 'client' => $settings = ClientSettings::buildClientSettings($this->company->settings, $this->request['settings']), - 'company' => $settings = (object)$this->request['settings'], - default => $settings = $this->company->settings, + 'company' => $settings = (object)$this->request['settings'] }; $settings = CompanySettings::setProperties($settings); @@ -168,9 +169,9 @@ class PdfMock /** * getTaxMap * - * @return void + * @return \Illuminate\Support\Collection */ - private function getTaxMap() + private function getTaxMap(): \Illuminate\Support\Collection { return collect([['name' => 'GST', 'total' => 10]]); } @@ -178,9 +179,9 @@ class PdfMock /** * getTotalTaxMap * - * @return void + * @return array */ - private function getTotalTaxMap() + private function getTotalTaxMap(): array { return [['name' => 'GST', 'total' => 10]]; } @@ -188,8 +189,9 @@ class PdfMock /** * getStubVariables * + * @return array */ - public function getStubVariables() + public function getStubVariables(): array { return ['values' => [ diff --git a/app/Services/Preview/StubBuilder.php b/app/Services/Preview/StubBuilder.php index 4bf2eafcca..8d3cce3076 100644 --- a/app/Services/Preview/StubBuilder.php +++ b/app/Services/Preview/StubBuilder.php @@ -227,10 +227,13 @@ class StubBuilder private function createClient(): self { - $this->recipient = Client::factory()->create([ + /** @var \App\Models\Client $client */ + $client = Client::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, ]); + + $this->recipient = $client; $this->contact = ClientContact::factory()->create([ 'user_id' => $this->user->id, @@ -245,10 +248,13 @@ class StubBuilder private function createVendor(): self { - $this->recipient = Vendor::factory()->create([ + /** @var \App\Models\Vendor $vendor */ + $vendor = Vendor::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->user->company()->id, ]); + + $this->recipient = $vendor; $this->contact = VendorContact::factory()->create([ 'user_id' => $this->user->id, @@ -276,7 +282,8 @@ class StubBuilder private function createInvoice() { - $this->entity = Invoice::factory()->create([ + /** @var \App\Models\Invoice $invoice */ + $invoice = Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->recipient->id, @@ -285,6 +292,8 @@ class StubBuilder 'status_id' => Invoice::STATUS_PAID, ]); + $this->entity = $invoice; + $this->invitation = InvoiceInvitation::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, diff --git a/app/Transformers/BankIntegrationTransformer.php b/app/Transformers/BankIntegrationTransformer.php index 0f296e19ad..c0a983ced7 100644 --- a/app/Transformers/BankIntegrationTransformer.php +++ b/app/Transformers/BankIntegrationTransformer.php @@ -12,6 +12,7 @@ namespace App\Transformers; use App\Models\Account; +use App\Models\Company; use App\Models\BankIntegration; use App\Models\BankTransaction; use App\Utils\Traits\MakesHash; diff --git a/app/Transformers/CompanyGatewayTransformer.php b/app/Transformers/CompanyGatewayTransformer.php index d1f2140865..2c79a442a5 100644 --- a/app/Transformers/CompanyGatewayTransformer.php +++ b/app/Transformers/CompanyGatewayTransformer.php @@ -11,11 +11,12 @@ namespace App\Transformers; -use App\Models\CompanyGateway; +use stdClass; +use App\Models\Gateway; use App\Models\SystemLog; +use App\Models\CompanyGateway; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\SoftDeletes; -use stdClass; /** * Class CompanyGatewayTransformer. diff --git a/app/Transformers/InvoiceTransformer.php b/app/Transformers/InvoiceTransformer.php index c12ae1361b..d30ef214be 100644 --- a/app/Transformers/InvoiceTransformer.php +++ b/app/Transformers/InvoiceTransformer.php @@ -87,7 +87,7 @@ class InvoiceTransformer extends EntityTransformer public function transform(Invoice $invoice) { - return [ + $data = [ 'id' => $this->encodePrimaryKey($invoice->id), 'user_id' => $this->encodePrimaryKey($invoice->user_id), 'project_id' => $this->encodePrimaryKey($invoice->project_id), @@ -151,5 +151,12 @@ class InvoiceTransformer extends EntityTransformer 'auto_bill_enabled' => (bool) $invoice->auto_bill_enabled, 'tax_info' => $invoice->tax_data ?: new \stdClass, ]; + + if (request()->has('reminder_schedule') && request()->query('reminder_schedule') == 'true') { + $data['reminder_schedule'] = (string) $invoice->reminderSchedule(); + } + + return $data; + } } diff --git a/app/Transformers/VendorContactTransformer.php b/app/Transformers/VendorContactTransformer.php index 39f4d60d0e..ca344634ce 100644 --- a/app/Transformers/VendorContactTransformer.php +++ b/app/Transformers/VendorContactTransformer.php @@ -44,7 +44,7 @@ class VendorContactTransformer extends EntityTransformer 'custom_value3' => $vendor->custom_value3 ?: '', 'custom_value4' => $vendor->custom_value4 ?: '', 'link' => $vendor->getLoginLink(), - 'last_login' => 'timestamp', + 'last_login' => (int)$vendor->last_login, ]; } } diff --git a/app/Utils/TemplateEngine.php b/app/Utils/TemplateEngine.php index 3cd5221d5d..2e531daf94 100644 --- a/app/Utils/TemplateEngine.php +++ b/app/Utils/TemplateEngine.php @@ -52,8 +52,8 @@ class TemplateEngine public $template; - /** @var Invoice | Quote | Credit | PurchaseOrder | RecurringInvoice | null $entity_obj **/ - private $entity_obj; + /** @var \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder | \App\Models\RecurringInvoice $entity_obj **/ + private \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder | \App\Models\RecurringInvoice $entity_obj; /** @var \App\Models\Company | \App\Models\Client | null $settings_entity **/ private $settings_entity; @@ -81,7 +81,7 @@ class TemplateEngine $this->template = $template; - $this->entity_obj = null; + // $this->entity_obj = null; $this->settings_entity = null; } @@ -99,7 +99,7 @@ class TemplateEngine { if (strlen($this->entity) > 1 && strlen($this->entity_id) > 1) { $class = 'App\Models\\' . ucfirst(Str::camel($this->entity)); - $this->entity_obj = $class::withTrashed()->where('id', $this->decodePrimaryKey($this->entity_id))->company()->first(); + $this->entity_obj = $class::query()->withTrashed()->where('id', $this->decodePrimaryKey($this->entity_id))->company()->first(); } elseif (stripos($this->template, 'quote') !== false && $quote = Quote::query()->whereHas('invitations')->withTrashed()->company()->first()) { $this->entity = 'quote'; $this->entity_obj = $quote; @@ -111,6 +111,7 @@ class TemplateEngine $this->entity_obj = $payment; } elseif ($invoice = Invoice::query()->whereHas('invitations')->withTrashed()->company()->first()) { + /** @var \App\Models\Invoice $invoice */ $this->entity_obj = $invoice; } else { $this->mockEntity(); @@ -286,6 +287,8 @@ class TemplateEngine private function mockEntity() { + $invitation = false; + if (!$this->entity && $this->template && str_contains($this->template, 'purchase_order')) { $this->entity = 'purchaseOrder'; } elseif (str_contains($this->template, 'payment')) { @@ -304,7 +307,6 @@ class TemplateEngine 'company_id' => $user->company()->id, ]); - /** @var \App\Models\ClientContact $contact */ $contact = ClientContact::factory()->create([ 'user_id' => $user->id, @@ -315,7 +317,8 @@ class TemplateEngine ]); if ($this->entity == 'payment') { - $this->entity_obj = Payment::factory()->create([ + /** @var \App\Models\Payment $payment */ + $payment = Payment::factory()->create([ 'user_id' => $user->id, 'company_id' => $user->company()->id, 'client_id' => $client->id, @@ -324,6 +327,8 @@ class TemplateEngine 'refunded' => 5, ]); + $this->entity_obj = $payment; + /** @var \App\Models\Invoice $invoice */ $invoice = Invoice::factory()->create([ 'user_id' => $user->id, @@ -349,7 +354,8 @@ class TemplateEngine } if (!$this->entity || $this->entity == 'invoice') { - $this->entity_obj = Invoice::factory()->create([ + /** @var \App\Models\Invoice $invoice */ + $invoice = Invoice::factory()->create([ 'user_id' => $user->id, 'company_id' => $user->company()->id, 'client_id' => $client->id, @@ -357,6 +363,8 @@ class TemplateEngine 'balance' => '10', ]); + $this->entity_obj = $invoice; + $invitation = InvoiceInvitation::factory()->create([ 'user_id' => $user->id, 'company_id' => $user->company()->id, @@ -366,11 +374,14 @@ class TemplateEngine } if ($this->entity == 'quote') { - $this->entity_obj = Quote::factory()->create([ + /** @var \App\Models\Quote $quote */ + $quote = Quote::factory()->create([ 'user_id' => $user->id, 'company_id' => $user->company()->id, 'client_id' => $client->id, ]); + + $this->entity_obj = $quote; $invitation = QuoteInvitation::factory()->create([ 'user_id' => $user->id, @@ -395,12 +406,15 @@ class TemplateEngine 'is_primary' => 1, 'send_email' => true, ]); - - $this->entity_obj = PurchaseOrder::factory()->create([ + + /** @var \App\Models\PurchaseOrder $purchase_order **/ + $purchase_order = PurchaseOrder::factory()->create([ 'user_id' => $user->id, 'company_id' => $user->company()->id, 'vendor_id' => $vendor->id, ]); + + $this->entity_obj = $purchase_order; /** @var \App\Models\PurchaseOrderInvitation $invitation **/ $invitation = PurchaseOrderInvitation::factory()->create([ diff --git a/composer.json b/composer.json index 7e1bf4f4ba..0d071ca1da 100644 --- a/composer.json +++ b/composer.json @@ -113,6 +113,7 @@ "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^9.5.10", "spatie/laravel-ignition": "^1.0", + "spaze/phpstan-stripe": "^3.0", "vimeo/psalm": "^4.24" }, "autoload": { diff --git a/composer.lock b/composer.lock index 4afddc900c..6bf16dd7b2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "be16996524279f340c44e2f6c9a0ba53", + "content-hash": "9d7348352c913eb82fcca2e67670e1f8", "packages": [ { "name": "adrienrn/php-mimetyper", @@ -17898,6 +17898,68 @@ ], "time": "2023-01-03T19:28:04+00:00" }, + { + "name": "spaze/phpstan-stripe", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/spaze/phpstan-stripe.git", + "reference": "6e5debe4f65b15192a28bd01f01670ced8250443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spaze/phpstan-stripe/zipball/6e5debe4f65b15192a28bd01f01670ced8250443", + "reference": "6e5debe4f65b15192a28bd01f01670ced8250443", + "shasum": "" + }, + "require": { + "php": "^8.0", + "phpstan/phpstan": "^1.7" + }, + "require-dev": { + "nikic/php-parser": "^4.13", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "spaze/coding-standard": "^1.1", + "stripe/stripe-php": "^8.7|^9.9|^10.8" + }, + "suggest": { + "phpstan/extension-installer": "Allows automatic requirement of extension.neon" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Spaze\\PHPStan\\Stripe\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michal Špaček", + "email": "mail@michalspacek.cz", + "homepage": "https://www.michalspacek.cz" + } + ], + "description": "Stripe SDK extension for PHPStan", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/spaze/phpstan-stripe/issues", + "source": "https://github.com/spaze/phpstan-stripe/tree/v3.0.0" + }, + "time": "2023-03-06T00:39:29+00:00" + }, { "name": "symfony/polyfill-php81", "version": "v1.27.0", diff --git a/config/ninja.php b/config/ninja.php index eb9345acba..a3d19b473f 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -15,8 +15,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION','5.6.29'), - 'app_tag' => env('APP_TAG','5.6.29'), + 'app_version' => env('APP_VERSION','5.6.30'), + 'app_tag' => env('APP_TAG','5.6.30'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), diff --git a/phpstan.neon b/phpstan.neon index 7aec499ed7..92bb544440 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ includes: - ./vendor/nunomaduro/larastan/extension.neon + - ./vendor/spaze/phpstan-stripe/extension.neon parameters: level: 2 paths: diff --git a/resources/views/auth/connect/completed.blade.php b/resources/views/auth/connect/completed.blade.php index 3d9999add5..05ea6a8cd4 100644 --- a/resources/views/auth/connect/completed.blade.php +++ b/resources/views/auth/connect/completed.blade.php @@ -8,6 +8,6 @@

Connecting your account using Stripe has been successfully completed.

- Click here to continue. + Click here to continue. @endsection