221 lines
7.8 KiB
PHP
221 lines
7.8 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Companies;
|
|
|
|
use App\Models\Advisories\AdvisoryCompany;
|
|
use App\Models\Asset;
|
|
use App\Models\User;
|
|
use App\Services\DaDataService;
|
|
use App\Support\RelationValuesTrait;
|
|
use App\Support\UuidScopeTrait;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Str;
|
|
|
|
class Company extends Model {
|
|
use UuidScopeTrait, SoftDeletes, RelationValuesTrait;
|
|
|
|
protected $dates = [
|
|
'tax_registration_date',
|
|
'deleted_at'
|
|
];
|
|
|
|
protected $fillable = [
|
|
'uuid',
|
|
'logo_id',
|
|
'name',
|
|
'full_name',
|
|
'inn',
|
|
'kpp',
|
|
'ogrn',
|
|
'okpo',
|
|
'okved',
|
|
'okato',
|
|
'tax_registration_date',
|
|
'is_main'
|
|
];
|
|
|
|
protected $hidden = [
|
|
'id',
|
|
'deleted_at',
|
|
'updated_at',
|
|
'pivot'
|
|
];
|
|
|
|
public function logo(): BelongsTo {
|
|
return $this->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;
|
|
}
|
|
|
|
|
|
}
|