177 lines
5.3 KiB
PHP
177 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace Modules\Tms\Services;
|
|
|
|
use Modules\Maintenance\Models\Equipment;
|
|
use Modules\Maintenance\Models\FieldMission;
|
|
use Modules\Maintenance\Models\InspectionVisit;
|
|
use Modules\Maintenance\Models\MissionCrewMember;
|
|
use Modules\Maintenance\Models\Overhaul;
|
|
use Modules\Maintenance\Models\RebuildProject;
|
|
use Modules\Maintenance\Models\WorkOrder;
|
|
use Modules\Tms\Models\Driver;
|
|
use Modules\Tms\Models\Shipment;
|
|
use Modules\Tms\Utils\TmsUtil;
|
|
|
|
class TmsMissionSyncService
|
|
{
|
|
public function __construct(protected TmsUtil $tmsUtil) {}
|
|
|
|
public function resolveProjectIdFromMission(FieldMission $mission): ?int
|
|
{
|
|
if ($mission->source_id && $mission->source_type !== 'standalone') {
|
|
$projectId = match ($mission->source_type) {
|
|
'overhaul' => Overhaul::where('business_id', $mission->business_id)->find($mission->source_id)?->project_id,
|
|
'rebuild' => RebuildProject::where('business_id', $mission->business_id)->find($mission->source_id)?->project_id,
|
|
'work_order' => WorkOrder::where('business_id', $mission->business_id)->find($mission->source_id)?->project_id,
|
|
'inspection_visit' => InspectionVisit::where('business_id', $mission->business_id)->find($mission->source_id)?->project_id,
|
|
default => null,
|
|
};
|
|
|
|
if ($projectId) {
|
|
return (int) $projectId;
|
|
}
|
|
}
|
|
|
|
if ($mission->equipment_id) {
|
|
return Equipment::where('business_id', $mission->business_id)
|
|
->find($mission->equipment_id)?->project_id;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function findShipmentForMission(FieldMission $mission): ?Shipment
|
|
{
|
|
return Shipment::where('business_id', $mission->business_id)
|
|
->where('source_type', 'field_mission')
|
|
->where('source_id', $mission->id)
|
|
->where('status', '!=', 'cancelled')
|
|
->orderByDesc('id')
|
|
->first();
|
|
}
|
|
|
|
public function resolveDriverId(FieldMission $mission): ?int
|
|
{
|
|
$mission->loadMissing('crewMembers');
|
|
|
|
$driverCrew = $mission->crewMembers->first(fn (MissionCrewMember $m) => $m->role === 'driver' && $m->user_id);
|
|
|
|
if ($driverCrew?->user_id) {
|
|
$driver = Driver::where('business_id', $mission->business_id)
|
|
->where('user_id', $driverCrew->user_id)
|
|
->where('is_active', true)
|
|
->first();
|
|
|
|
if ($driver) {
|
|
return (int) $driver->id;
|
|
}
|
|
}
|
|
|
|
if ($mission->lead_user_id) {
|
|
$driver = Driver::where('business_id', $mission->business_id)
|
|
->where('user_id', $mission->lead_user_id)
|
|
->where('is_active', true)
|
|
->first();
|
|
|
|
return $driver ? (int) $driver->id : null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function resolveMissionDestination(FieldMission $mission): ?string
|
|
{
|
|
if (! empty($mission->destination_site)) {
|
|
return $mission->destination_site;
|
|
}
|
|
|
|
$mission->loadMissing('destinationLocation');
|
|
$loc = $mission->destinationLocation;
|
|
|
|
if (! $loc) {
|
|
return null;
|
|
}
|
|
|
|
return trim(implode(' ', array_filter([
|
|
$loc->name,
|
|
$loc->landmark ?? null,
|
|
$loc->city ?? null,
|
|
]))) ?: null;
|
|
}
|
|
|
|
public function buildCargoDescription(FieldMission $mission): string
|
|
{
|
|
$mission->loadMissing(['items.sparePart']);
|
|
|
|
$parts = $mission->items
|
|
->map(fn ($item) => $item->part_name ?: $item->sparePart?->name)
|
|
->filter()
|
|
->take(5)
|
|
->values()
|
|
->all();
|
|
|
|
if (empty($parts)) {
|
|
return $mission->title;
|
|
}
|
|
|
|
return $mission->title.' — '.implode(', ', $parts);
|
|
}
|
|
|
|
public function syncMissionFromShipment(Shipment $shipment): void
|
|
{
|
|
if ($shipment->source_type !== 'field_mission' || ! $shipment->source_id) {
|
|
return;
|
|
}
|
|
|
|
$settings = $this->tmsUtil->getTmsSettings((int) $shipment->business_id);
|
|
if (empty($settings['sync_mission_status'])) {
|
|
return;
|
|
}
|
|
|
|
if (! class_exists(FieldMission::class)) {
|
|
return;
|
|
}
|
|
|
|
$mission = FieldMission::where('business_id', $shipment->business_id)
|
|
->find($shipment->source_id);
|
|
|
|
if (! $mission || in_array($mission->status, ['closed', 'cancelled'], true)) {
|
|
return;
|
|
}
|
|
|
|
$missionStatus = match ($shipment->status) {
|
|
'in_transit' => 'dispatched',
|
|
'delivered' => 'on_site',
|
|
'cancelled' => 'cancelled',
|
|
default => null,
|
|
};
|
|
|
|
if (! $missionStatus) {
|
|
return;
|
|
}
|
|
|
|
$order = [
|
|
'draft' => 0,
|
|
'planned' => 1,
|
|
'dispatched' => 2,
|
|
'on_site' => 3,
|
|
'returning' => 4,
|
|
'closed' => 5,
|
|
'cancelled' => 6,
|
|
];
|
|
|
|
if (($order[$missionStatus] ?? 0) <= ($order[$mission->status] ?? 0)) {
|
|
return;
|
|
}
|
|
|
|
$updates = ['status' => $missionStatus];
|
|
|
|
if ($missionStatus === 'dispatched' && ! $mission->actual_departure_at) {
|
|
$updates['actual_departure_at'] = $shipment->pickup_at ?? now();
|
|
}
|
|
|
|
$mission->update($updates);
|
|
}
|
|
}
|