ultimatepos/Modules/Tms/Services/TmsMissionSyncService.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);
}
}