belongsTo(Asset::class); } public function types(): HasMany { return $this->hasMany(CompanyType::class); } public function departments(): HasMany { return $this->hasMany(Department::class); } public function members(): HasMany { return $this->hasMany(CompanyMember::class); } public function rootMembers(): HasMany { return $this->members()->whereNull('department_id'); } public function management(): HasMany { return $this->members()->whereIn('status', [CompanyMemberRank::VICE, CompanyMemberRank::CHIEF]); } public function vices(): HasMany { return $this->members()->where(['status' => CompanyMemberRank::VICE]); } public function employees(): HasMany { return $this->members()->where(['status' => CompanyMemberRank::EMPLOYEE]); } public function addresses(): HasMany { return $this->hasMany(Address::class); } public function bankDetails(): HasOne { return $this->hasOne(BankDetails::class); } public function contacts(): HasMany { return $this->hasMany(Contact::class); } public function phones(): HasMany { return $this->contacts()->where(['type' => ContactType::PHONE]); } public function emails(): HasMany { return $this->contacts()->where(['type' => ContactType::EMAIL]); } public function advisoryCompanies(): HasMany { return $this->hasMany(AdvisoryCompany::class); } public function scopeByTypes($query, $types) { return $query->whereHas('types', function($query) use($types) { $query->whereIn('name', is_array($types) ? $types : [$types]); }); } public function getLegalAddressAttribute(): Model { return $this->addresses()->firstOrCreate(['type' => Address::$TYPE_LEGAL]); } public function getActualAddressAttribute(): Model { return $this->addresses()->firstOrCreate(['type' => Address::$TYPE_ACTUAL]); } public function getPhoneAttribute(): Model { return $this->phones()->firstOrCreate(['type' => ContactType::PHONE]); } public function getEmailAttribute(): Model { return $this->emails()->firstOrCreate(['type' => ContactType::EMAIL]); } public function getRootDepartmentAttribute(): Model { $res = $this->departments()->whereNull('parent_id')->firstOrCreate(['name' => 'root']); if (!$res->title) $res->update(['title' => 'Дирекция']); return $res; } public function getRepresentativeMemberAttribute() { return $this->members()->where(['representative' => true])->first(); } public function getResponsibleMemberAttribute() { return $this->members()->orderBy('representative', 'desc')->first(); } public static function getByData($data) { $result = false; if (!empty($data['inn'])) { $result = self::firstOrCreate(['inn' => $data['inn']]); (new DaDataService($data['inn']))->saveToCompany($result); if ($val = $data['name'] ?? null) $result->update(['name' => $val, 'full_name' => $val]); if (($val = $data['address'] ?? null) && $result->legalAddress->full !== $val) $result->setAddress($val); if ($val = $data['phone'] ?? null) $result->setPhone($val); if ($val = $data['email'] ?? null) $result->setEmail($val); if ($val = $data['contacts'] ?? null) $result->setContacts($val); if ($val = $data['types'] ?? null) $result->setTypes($val); if ($val = $data['logo'] ?? null) $result->setLogo($val); if (!$result->name && !is_numeric($result->inn)) $result->update(['name' => $result->inn, 'full_name' => $result->inn]); } return $result; } public function addMember(User $user, $position, $departmentId = null, $rank = null): Model { if ($member = $this->members()->where(['user_id' => $user->id, 'position' => $position])->first()) { if ($departmentId) $member->update(['department_id' => $departmentId]); if (!is_null($rank)) $member->update(['rank' => $rank]); } elseif ($member = $this->members()->create(['user_id' => $user->id, 'position' => $position])) { $member->update(['department_id' => $departmentId ?? $this->rootDepartment->id ?? null, 'rank' => $rank ?? CompanyMemberRank::EMPLOYEE]); } return $member; } public function isMember(CompanyMember $member): bool { return $this->members()->where('id', $member->id)->exists(); } public function findDepartments($search): Collection { return $this->departments()->where('title', 'like', "%{$search}%")->get(); } public function findMembers($search): Collection { return $this->members()->where('position', 'like', "%{$search}%")->orWhereHas('user', function($query) use($search) { $query->where('name', 'like', "%{$search}%"); })->get(); } public function setTypes(array $types) { $exists = collect($types)->map(function($item) { $name = (is_string($item)) ? $item : $item['id'] ?? null; return $name ? $this->types()->firstOrCreate(['name' => $name]) : null; }); $this->types()->whereNotIn('name', $exists->pluck('name')->all())->delete(); } public function setLogo($val) { $asset = Asset::byUuid($val)->first(); $this->update(['logo_id' => $asset->id ?? null]); } public function setAddress($val) { $this->legalAddress->setFullAddress($val); $this->actualAddress->setFullAddress($val); } public function setEmail($val): ?Model { $this->emails()->delete(); return $val ? $this->contacts()->create(['type' => ContactType::EMAIL, 'value' => $val]) : null; } public function setPhone($val): ?Model { $this->phones()->delete(); return $val ? $this->contacts()->create(['type' => ContactType::PHONE, 'value' => $val]) : null; } public function setContacts($val) { $this->contacts()->firstOrCreate(['type' => ContactType::MIXED, 'value' => $val]); collect(explode(';', $val))->each(function($contact) { $type = (Str::contains($contact, '@')) ? ContactType::EMAIL : ContactType::PHONE; $this->contacts()->firstOrCreate(['type' => $type, 'value' => trim($contact)]); }); } public function getPermissions(User $user): array { $result = ['view' => false, 'edit' => false]; if ($user->isAdmin) $result = ['view' => true, 'edit' => true]; elseif ($user->isCompanyMember($this)) { $result['view'] = true; if ($this->members()->where(['user_id' => $user->id, 'representative' => 1])->exists()) $result['edit'] = true; } return $result; } }