first init

This commit is contained in:
ISMAIL MASSERAN
2026-06-08 11:37:14 +08:00
commit 94ecbe5887
1058 changed files with 87732 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
<?php
namespace App\Traits;
use App\Models\Document;
use Illuminate\Http\UploadedFile;
trait HasDocuments
{
/**
* Get all documents for this model.
*/
public function documents()
{
return $this->morphMany(Document::class, 'documentable');
}
/**
* Get documents of a specific type.
*/
public function documentsOfType($type)
{
return $this->documents()->where('document_type', $type);
}
/**
* Upload a document for this model.
*/
public function uploadDocument(UploadedFile $file, $documentType = 'general', $description = null)
{
// Generate unique filename
$fileName = time().'_'.$file->getClientOriginalName();
// Store file in a folder named after the model
$folderName = strtolower(class_basename($this));
$filePath = $file->storeAs("documents/{$folderName}", $fileName);
// Create document record
return $this->documents()->create([
'document_name' => $file->getClientOriginalName(),
'document_path' => $filePath,
'file_size' => $file->getSize(),
'mime_type' => $file->getClientMimeType(),
'document_type' => $documentType,
'description' => $description,
'uploaded_by' => auth()->id(),
]);
}
/**
* Delete a document by ID.
*/
public function deleteDocument($documentId)
{
$document = $this->documents()->findOrFail($documentId);
return $document->delete();
}
/**
* Get documents count.
*/
public function getDocumentsCountAttribute()
{
return $this->documents()->count();
}
/**
* Get documents count by type.
*/
public function getDocumentsCountByType($type)
{
return $this->documentsOfType($type)->count();
}
/**
* Check if model has documents.
*/
public function hasDocuments()
{
return $this->documents()->exists();
}
/**
* Check if model has documents of specific type.
*/
public function hasDocumentsOfType($type)
{
return $this->documentsOfType($type)->exists();
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php
namespace App\Traits;
use App\Services\VisibilityService;
use Illuminate\Database\Eloquent\Builder;
trait HasVisibility
{
/**
* Get the visibility service instance
*/
protected function getVisibilityService(): VisibilityService
{
return app(VisibilityService::class);
}
public function scopeVisibleTo(Builder $query, $user)
{
$includeUnitsWithoutFormation = property_exists($this, 'includeUnitsWithoutFormation')
? (bool) $this->includeUnitsWithoutFormation
: false;
// Check if model has a direct unit column
$unitColumn = property_exists($this, 'unitColumn') ? $this->unitColumn : 'unit_id';
// Check if model has an indirect unit relationship
$unitRelationship = property_exists($this, 'unitRelationship') ? $this->unitRelationship : null;
if ($unitRelationship) {
return $this->getVisibilityService()->applyVisibilityToIndirectQuery(
$query,
$user,
$unitRelationship,
$includeUnitsWithoutFormation
);
}
return $this->getVisibilityService()->applyVisibilityToQuery(
$query,
$user,
$unitColumn,
$includeUnitsWithoutFormation
);
}
/**
* Get all units under the same government as the user's unit
* Handles both direct government relationships and formation-government relationships
* Priority: Direct government_id takes precedence over formation government
*
* @deprecated Use VisibilityService::getUnitsUnderGovernment() instead
*/
protected function getUnitsUnderGovernment($userUnit)
{
return $this->getVisibilityService()->getUnitsUnderGovernment($userUnit);
}
}
+104
View File
@@ -0,0 +1,104 @@
<?php
namespace App\Traits;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
trait HttpClientTrait
{
/**
* Get a configured HTTP client with global settings.
*
* @param array $additionalHeaders Additional headers to add
* @param bool $withoutVerifying Whether to skip SSL verification
* @return \Illuminate\Http\Client\PendingRequest
*/
protected function getHttpClient(array $additionalHeaders = [], bool $withoutVerifying = false)
{
$client = Http::withHeaders($additionalHeaders);
if ($withoutVerifying) {
$client = $client->withoutVerifying();
}
return $client;
}
/**
* Get a configured HTTP client with authentication.
*
* @param string $token Bearer token for authentication
* @param array $additionalHeaders Additional headers to add
* @param bool $withoutVerifying Whether to skip SSL verification
* @return \Illuminate\Http\Client\PendingRequest
*/
protected function getAuthenticatedHttpClient(string $token, array $additionalHeaders = [], bool $withoutVerifying = false)
{
$headers = array_merge([
'Authorization' => 'Bearer '.$token,
'Accept' => 'application/json',
'Content-Type' => 'application/json',
], $additionalHeaders);
return $this->getHttpClient($headers, $withoutVerifying);
}
/**
* Log HTTP request details for debugging.
*
* @param string $method HTTP method
* @param string $url Request URL
* @param array $data Request data
* @param array $headers Request headers
*/
protected function logHttpRequest(string $method, string $url, array $data = [], array $headers = [])
{
Log::debug('HTTP Request', [
'method' => $method,
'url' => $url,
'data' => $data,
'headers' => array_keys($headers), // Don't log sensitive header values
'environment' => config('app.env'),
'proxy_enabled' => $this->isProxyEnabled(),
]);
}
/**
* Log HTTP response details for debugging.
*
* @param \Illuminate\Http\Client\Response $response
* @param string $context Additional context
*/
protected function logHttpResponse($response, string $context = '')
{
Log::debug('HTTP Response'.($context ? " - {$context}" : ''), [
'status' => $response->status(),
'successful' => $response->successful(),
'body_length' => strlen($response->body()),
'headers' => $response->headers(),
]);
}
/**
* Check if proxy is enabled for current environment.
*/
protected function isProxyEnabled(): bool
{
$config = config('http');
$proxyConfig = $config['proxy'] ?? [];
return isset($proxyConfig['enabled']) && $proxyConfig['enabled'] &&
in_array(config('app.env'), $proxyConfig['environments'] ?? []);
}
/**
* Get current proxy configuration.
*/
protected function getProxyConfig(): array
{
$config = config('http');
return $config['proxy'] ?? [];
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace App\Traits;
use Illuminate\Support\Collection;
use Modules\Auth\Entities\User;
trait NotifiesAdmins
{
/**
* Get admin users (PENTADBIR and DEVELOPER) who should receive all notifications
*/
protected function getAdminUsers(): Collection
{
return User::whereHas('roles', function ($query) {
$query->whereIn('name', ['PENTADBIR', 'DEVELOPER']);
})->get();
}
/**
* Merge admin users with specific role users and return unique collection
*/
protected function mergeWithAdmins(Collection $specificUsers): Collection
{
$adminUsers = $this->getAdminUsers();
return $specificUsers->merge($adminUsers)->unique('id');
}
/**
* Get users with specific roles and merge with admins
*/
protected function getUsersWithRolesAndAdmins(array $roles): Collection
{
$specificUsers = User::whereHas('roles', function ($query) use ($roles) {
$query->whereIn('name', $roles);
})->get();
return $this->mergeWithAdmins($specificUsers);
}
/**
* Get user IDs from a collection and merge with admin user IDs
*/
protected function mergeUserIdsWithAdmins($userIds): Collection
{
$adminIds = $this->getAdminUsers()->pluck('id');
if ($userIds instanceof Collection) {
return $userIds->merge($adminIds)->unique()->filter();
}
return collect($userIds)->merge($adminIds)->unique()->filter();
}
}