|
|
<?php
namespace App\Models;
use App\Models\File; use App\Models\Model; use App\Models\SoftDeletes; use App\Notifications\SocketNotification; use Illuminate\Support\Facades\Notification; use Illuminate\Validation\Rule; use Illuminate\Http\UploadedFile; use Spatie\MediaLibrary\HasMedia; use App\Models\ReportableRelation; use Illuminate\Support\Facades\Cache; use Spatie\MediaLibrary\InteractsWithMedia; use Spatie\MediaLibrary\MediaCollections\Models\Media;
class Business extends Model implements HasMedia { use SoftDeletes, InteractsWithMedia;
const CONVERSION_NAME = 'avatar';
const COLLECTION_NAME = 'avatars';
public static $permissions = ['level'];
protected $table = 'businesses';
protected $fillable = ['name', 'slug', 'wallet','files_volume','cache', 'color', 'description', 'has_avatar', 'calculated_at', 'suspended_at', 'users'];
protected $fillable_relations = [ 'users' ];
protected $reportable = [ 'name', 'slug', 'wallet', 'files_volume', 'cache', 'calculated_at', // fields
['users' => 'business_user'] // relations [ name => pivot ]
];
public $detach_relation = false;
protected $casts = [ 'has_avatar' => 'boolean', 'calculated_at' => 'datetime', 'suspended_at' => 'datetime', 'wallet' => 'integer', ];
public function getValueOf(?string $key) { $values = [ 'business_id' => $this->id, 'workflow_id' => null, 'project_id' => null, 'sprint_id' => null, 'status_id' => null, 'system_id' => null, 'user_id' => null, 'task_id' => null, 'subject_id' => $this->id, ];
if ($key && isset($values, $key)) { return $values[$key]; }
return $values; }
public function rules() { return [ 'name' => 'bail|required|string|min:2|max:255', 'color' => 'nullable|string|min:2|max:255', 'slug' => ['bail', 'required', 'string', 'min:2', 'max:255', 'regex:/^[a-zA-Z]+[a-zA-Z\d-]*(.*[a-zA-Z\d])+$/', Rule::unique($this->table, 'slug')->ignore($this->id)], 'description' => 'nullable|string|min:2|max:1000', ]; }
public function cost() { return $this->hasMany(Cost::class, 'business_id','id'); }
public function owners() { return $this->users()->wherePivot('level', '=', enum('levels.owner.id')); }
public function members() { return $this->users()->wherePivot('owner', '!=', enum('levels.owner.id')); }
public function users() { return $this->belongsToMany( User::class, 'business_user', 'business_id', 'user_id', 'id', 'id', __FUNCTION__ ) ->using(ReportableRelation::class) ->withPivot(self::$permissions); }
public function tags() { return $this->hasMany(Tag::class, 'business_id', 'id'); }
public function projects() { return $this->hasMany(Project::class, 'business_id', 'id'); }
public function systems() { return $this->hasMany(System::class, 'business_id', 'id'); }
public function workflows() { return $this->hasMany(Workflow::class, 'business_id', 'id'); } public function sprints() { return $this->hasMany(Sprint::class, 'business_id', 'id'); }
public function statuses() { return $this->hasMany(Status::class, 'business_id', 'id'); }
public function files() { return $this->hasMany(File::class, 'user_id', 'id'); }
public function transactions() { return $this->hasMany(Transaction::class, 'business_id', 'id'); }
public function updateRelations() { // users relations
if (!empty($this->filled_relations['users']) || $this->detach_relation) { $this->dirties['users'] = $this->users()->sync($this->filled_relations['users'], $this->detach_relation); } }
public static function info($businessId, $fresh = false) {
$info = [];
$fresh = true; if ($fresh){ Cache::forget('business_info'.$businessId); }
if (Cache::has('business_info'.$businessId)) { return Cache::get('business_info'.$businessId); } else { $business = self::findOrFail($businessId);
$tags = $business->tags()->select('id', 'label', 'color')->get()->keyBy('id'); $info['tags'] = $tags->pluck('id');
$workflows = $business->workflows()->select ('id', 'business_id', 'name','desc')->get()->keyBy('id') ->load(['statuses'=> fn($q) => $q->select('id', 'business_id', 'workflow_id', 'name', 'state', 'order')]) ->map(fn($q) => [ 'id' => $q->id, 'business_id' => $q->business_id, 'name' => $q->name, 'desc' => $q->desc, 'statuses' => $q['statuses']->keyBy('id'), ]);
$info['workflows'] = $workflows->map(fn($q) => ['statuses' => $q['statuses']->pluck('id')]);
$users = $business->users()->select('id', 'name', 'email', 'mobile', 'username')->with('media')->get() ->keyBy('id') ->map(fn($u) => [ 'id' => $u->id, 'name' => $u->name, 'email' => $u->email, 'mobile' => $u->mobile, 'username' => $u->get, 'avatar' => $u->has_avatar, 'level' => $u->pivot['level'], ]);
$info['users'] = $users->map(fn($u) => [ 'level' => $u['level'] ]);
$projects = $business->projects()->get()->keyBy('id')->load([ 'members' => fn($q) => $q->select('id', 'level'), 'systems' => fn($q) => $q->select('id', 'project_id', 'name'), 'sprints' => fn($q) => $q->select('id', 'project_id', 'name', 'description', 'started_at', 'ended_at', 'active'), 'media', ]);
$info['projects'] = $projects->map(function($q) use($users){ return [ 'avatar' => $q->has_avatar, 'systems' => $q->systems->pluck('id'), 'sprints' => $q->sprints->pluck('id'), 'members' => $users->keyBy('id')->map(function($u, $uid) use ($q){ $project_user = $q->members->firstWhere('id', $uid); return $project_user? ['level' => $project_user->pivot->level, 'is_direct' => true]: ['level' => $q->private && $u['level'] != enum('levels.owner.id') ? enum('levels.inactive.id') : $u['level'], 'is_direct'=> $project_user ? true : false]; }) ]; });
$business_info = array_merge( $business->only('id', 'name', 'slug', 'color','wallet', 'files_volume'), ['avatar' => $business->has_avatar], compact( 'info', 'tags', 'workflows', 'users', 'projects' ) );
Cache::put('business_info'.$businessId , $business_info, config('app.cache_ttl'));
Notification::send(auth()->user(), new SocketNotification(['message' => 'business info update','payload'=>$business_info]));
return $business_info; }
}
public static function stats() { return [ 'users' => [ 10 => [ 'statuses' => [ 10 => 20, 30 => 40 ], 'workflows' => [ 10 => 20, 30 => 40 ], 'tags' => [ 10 => 20, 30 => 40 ], 'project' => [ 10 => 20, 30 => 40 ],
'sprints' => [ 10 => 20, 30 => 40 ], 'works' => [ ], '__subsystems' => [ 10 => 20, 30 => 40 ], ] ], 'workflows' => [ 50 => [ 'statuses' => [ 20 => 50 ],
] ], 'statuses' => [ 10 => [ 'users' => [
], 'projects' => [
] ] ], 'sprints' => [ 10 => [ 'statuses' => [ 10 => [ 10 => 1 ] ] ] ] ]; }
public function reportActivity() {
}
public static function nuxtInfo($businessId) { if (empty($businessId)){ return null; }
Cache::forget('business_nuxt_info' . $businessId); return Cache::rememberForever('business_nuxt_info' . $businessId, function () use ($businessId) {
$business = self::with([ 'projects.members' => fn($q) => $q->select('id', 'name'), 'projects', 'tags', 'workflows.statuses', 'workflows', 'statuses', 'users', ])->findOrFail($businessId);
$globals = []; $business->users->each(function ($u) use (&$globals) { $globals[$u->id] = $u->pivot->owner == true ? ['owner' => true] : $u->pivot->only(self::$permissions); });
$projects = []; $business->projects->each(function ($p) use (&$projects, &$globals) {
});
$business->setRelation('projects', collect($projects)); $business->setRelation('users', collect($globals));
return $business; });
}
public static function infoOld($businessId) {
if (empty($businessId)) return null;
Cache::forget('business_info' . $businessId); return Cache::rememberForever('business_info' . $businessId, function () use ($businessId) { $ob = []; $business = self::with([ 'projects.members' => fn($q) => $q->select('id', 'name'), 'projects' => fn($q) => $q->select('id', 'business_id', 'private'), 'tags' => fn($q) => $q->select('id', 'business_id', 'label'), 'sprints' => fn($q) => $q->select('id','business_id','name', 'active'), 'workflows.statuses' => fn($q) => $q->select('id', 'name'), 'workflows' => fn($q) => $q->select('id', 'business_id', 'name'), 'statuses' => fn($q) => $q->select('id', 'business_id', 'name', 'state'), 'users' => fn($q) => $q->select('id', 'name'), ])->findOrFail($businessId);
// permissions in business
$permissions = []; $business->users->each(function ($user) use (&$permissions) { $permissions[$user->id] = $user->pivot->only(['owner']); $permissions[$user->id]['global_PA'] = $permissions[$user->id]['owner'] == true ? enum('roles.manager.id') : $user->pivot->PA; $permissions[$user->id]['global_FA'] = $permissions[$user->id]['owner'] == true ? enum('roles.manager.id') : $user->pivot->FA; $permissions[$user->id]['PA'] = []; $permissions[$user->id]['FA'] = []; });
//projects
$projects = []; $business->projects->each(function ($p) use (&$permissions, $business, &$projects) {
$business->users->each(function ($user) use (&$permissions, $p) { $PA = null; $FA = null;
if ($permissions[$user->id]['owner'] == true) { $PA = enum('roles.manager.id'); $FA = enum('roles.manager.id'); } else if (!empty($project_user = $p->getPermissions($user->id))) { $PA = $project_user->pivot->PA; $FA = $project_user->pivot->FA; } else if (empty($p->getPermissions($user->id))) { $PA = $p->private == false ? $permissions[$user->id]['global_PA'] : enum('roles.hidden.id') ; $FA = $p->private == false ? $permissions[$user->id]['global_FA'] : enum('roles.hidden.id'); }
if ($PA !== null && $FA !== null) { $permissions[$user->id]['PA'][$p->id] = $PA; $permissions[$user->id]['FA'][$p->id] = $FA; } });
$projects[$p->id] =''; });
//workflow
$workflows = []; $business->workflows->each(function ($w) use (&$workflows) { $workflows[$w->id] = $w->statuses->pluck('id'); });
$ob['tags'] = $business->tags->pluck('id'); $ob['statuses'] = $business->statuses; $ob['sprints'] = $business->sprints; $ob['workflows'] = $workflows; $ob['users'] = $permissions; $ob['projects'] = $projects;
return collect($ob); });
}
public function registerMediaCollections(): void { $this->addMediaCollection(static::COLLECTION_NAME) ->acceptsMimeTypes([ 'image/jpeg', 'image/png', 'image/tiff', 'image/gif', ]) ->useDisk('public') ->singleFile(); }
public function registerMediaConversions(Media $media = null): void { $this->addMediaConversion(static::CONVERSION_NAME) ->width(200) ->height(200) ->queued() ->nonOptimized() ->performOnCollections(static::COLLECTION_NAME); }
public function saveAsAvatar(UploadedFile $avatar): void { $this->addMedia($avatar)->toMediaCollection(static::COLLECTION_NAME); $this->update([ 'has_avatar' => true, ]); @unlink($this->getFirstMedia(static::COLLECTION_NAME)->getPath()); }
public function deleteAvatar(): void { $path = $this->getFirstMedia(static::COLLECTION_NAME)->getPath(); $this->getFirstMedia(static::COLLECTION_NAME)->delete(); $this->update([ 'has_avatar' => false, ]); @unlink($path); }
public function getAvatarUrl(): ?string { if ($url = $this->getFirstMediaUrl(static::COLLECTION_NAME, static::CONVERSION_NAME)) { return $url; }
return null; } }
|