ultimatepos/Modules/Portal/Services/CustomerMaintenanceScopeService.php

276 lines
8.7 KiB
PHP

<?php
namespace Modules\Portal\Services;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Schema;
use Modules\Maintenance\Models\Equipment;
use Modules\Maintenance\Models\FieldMission;
use Modules\Maintenance\Models\PreventiveSchedule;
use Modules\Maintenance\Models\ProductionLine;
use Modules\Maintenance\Models\WorkOrder;
use Modules\Project\Entities\Project;
class CustomerMaintenanceScopeService
{
public function __construct(
protected int $businessId,
protected int $contactId
) {
}
public static function make(int $businessId, int $contactId): self
{
return new self($businessId, $contactId);
}
public static function forCurrentUser(): self
{
return new self(
(int) request()->session()->get('user.business_id'),
(int) auth()->user()->crm_contact_id
);
}
public function maintenanceEnabled(): bool
{
return Schema::hasTable('maintenance_equipment');
}
public function preventiveSchedulesAvailable(): bool
{
return Schema::hasTable('maintenance_preventive_schedules');
}
public function workOrdersAvailable(): bool
{
return Schema::hasTable('maintenance_work_orders');
}
public function fieldMissionsAvailable(): bool
{
return Schema::hasTable('maintenance_field_missions');
}
public function failureReportsAvailable(): bool
{
return Schema::hasTable('maintenance_failure_reports');
}
public function productionLinesAvailable(): bool
{
return Schema::hasTable('maintenance_production_lines');
}
public function projectIds(): Collection
{
if (! Schema::hasTable('pjt_projects')) {
return collect();
}
return Project::where('business_id', $this->businessId)
->where('contact_id', $this->contactId)
->pluck('id');
}
public function equipmentIds(): Collection
{
if (! $this->maintenanceEnabled()) {
return collect();
}
return Equipment::where('business_id', $this->businessId)
->where('customer_id', $this->contactId)
->pluck('id');
}
public function productionLineIds(): Collection
{
if (! $this->productionLinesAvailable()) {
return collect();
}
$projectIds = $this->projectIds();
if ($projectIds->isEmpty()) {
return collect();
}
return ProductionLine::where('business_id', $this->businessId)
->whereIn('project_id', $projectIds)
->pluck('id');
}
public function equipmentQuery(): Builder
{
return Equipment::where('business_id', $this->businessId)
->where('customer_id', $this->contactId);
}
public function projectQuery(): Builder
{
return Project::where('business_id', $this->businessId)
->where('contact_id', $this->contactId);
}
public function productionLineQuery(): Builder
{
if (! $this->productionLinesAvailable()) {
return ProductionLine::query()->whereRaw('0 = 1');
}
return ProductionLine::where('business_id', $this->businessId)
->whereIn('project_id', $this->projectIds());
}
public function preventiveScheduleQuery(): Builder
{
if (! $this->preventiveSchedulesAvailable()) {
return PreventiveSchedule::query()->whereRaw('0 = 1');
}
$equipmentIds = $this->equipmentIds();
$projectIds = $this->projectIds();
$lineIds = $this->productionLineIds();
$query = PreventiveSchedule::where('business_id', $this->businessId);
return $query->where(function ($q) use ($equipmentIds, $projectIds, $lineIds) {
$added = false;
if ($equipmentIds->isNotEmpty()) {
$q->whereIn('equipment_id', $equipmentIds);
$added = true;
}
if ($projectIds->isNotEmpty()) {
$added ? $q->orWhereIn('project_id', $projectIds) : $q->whereIn('project_id', $projectIds);
$added = true;
}
if ($lineIds->isNotEmpty()) {
$added ? $q->orWhereIn('production_line_id', $lineIds) : $q->whereIn('production_line_id', $lineIds);
$added = true;
}
if (! $added) {
$q->whereRaw('0 = 1');
}
});
}
public function workOrderQuery(): Builder
{
if (! $this->workOrdersAvailable()) {
return WorkOrder::query()->whereRaw('0 = 1');
}
$equipmentIds = $this->equipmentIds();
$projectIds = $this->projectIds();
$lineIds = $this->productionLineIds();
return WorkOrder::where('business_id', $this->businessId)
->where(function ($q) use ($equipmentIds, $projectIds, $lineIds) {
$added = false;
if ($equipmentIds->isNotEmpty()) {
$q->whereIn('equipment_id', $equipmentIds);
$added = true;
}
if ($projectIds->isNotEmpty()) {
$added ? $q->orWhereIn('project_id', $projectIds) : $q->whereIn('project_id', $projectIds);
$added = true;
}
if ($lineIds->isNotEmpty()) {
$added ? $q->orWhereIn('production_line_id', $lineIds) : $q->whereIn('production_line_id', $lineIds);
$added = true;
}
if (! $added) {
$q->whereRaw('0 = 1');
}
});
}
public function fieldMissionQuery(): Builder
{
if (! $this->fieldMissionsAvailable()) {
return FieldMission::query()->whereRaw('0 = 1');
}
$equipmentIds = $this->equipmentIds();
$projectIds = $this->projectIds();
return FieldMission::where('business_id', $this->businessId)
->where(function ($q) use ($equipmentIds, $projectIds) {
$added = false;
if ($equipmentIds->isNotEmpty()) {
$q->whereIn('equipment_id', $equipmentIds);
$added = true;
}
if ($projectIds->isNotEmpty()) {
$method = $added ? 'orWhere' : 'where';
$q->{$method}(function ($sq) use ($projectIds) {
$sq->where('source_type', 'project')
->whereIn('source_id', $projectIds);
});
}
if (! $added && $projectIds->isEmpty()) {
$q->whereRaw('0 = 1');
}
});
}
public function ownsEquipment(int $equipmentId): bool
{
return $this->equipmentIds()->contains($equipmentId);
}
public function ownsProject(int $projectId): bool
{
return $this->projectIds()->contains($projectId);
}
public function ownsProductionLine(int $lineId): bool
{
return $this->productionLineIds()->contains($lineId);
}
public function ownsPreventiveSchedule(int $scheduleId): bool
{
return $this->preventiveScheduleQuery()->where('id', $scheduleId)->exists();
}
public function ownsWorkOrder(int $workOrderId): bool
{
return $this->workOrderQuery()->where('id', $workOrderId)->exists();
}
public function ownsFieldMission(int $missionId): bool
{
return $this->fieldMissionQuery()->where('id', $missionId)->exists();
}
public function dashboardStats(): array
{
if (! $this->maintenanceEnabled()) {
return [];
}
$openStatuses = ['open', 'pending', 'in_progress', 'assigned', 'scheduled'];
return [
'projects' => $this->projectIds()->count(),
'equipment' => $this->equipmentIds()->count(),
'production_lines' => $this->productionLineIds()->count(),
'open_work_orders' => $this->workOrdersAvailable()
? $this->workOrderQuery()->whereIn('status', $openStatuses)->count()
: 0,
'upcoming_services' => $this->preventiveSchedulesAvailable()
? $this->preventiveScheduleQuery()
->where('is_active', true)
->whereNotNull('next_due_at')
->where('next_due_at', '<=', now()->addDays(30))
->count()
: 0,
'active_missions' => $this->fieldMissionsAvailable()
? $this->fieldMissionQuery()
->whereIn('status', ['planned', 'in_progress', 'scheduled'])
->count()
: 0,
];
}
}