$rows->count()]); if ($rows->count() === 0) { Log::warning('No rows found'); return; } $firstRow = $rows->first(); Log::info('First row keys', ['keys' => $firstRow->keys()->toArray()]); Log::info('First row awb', ['awb' => $firstRow['awb'] ?? 'N/A']); foreach ($rows as $index => $row) { try { $awbNo = $this->normalizeAwb($row['awb'] ?? null); $eventDate = $this->normalizeDate($row['date'] ?? null); $eventTime = $this->normalizeTime($row['time'] ?? null); $eventDescription = $this->normalizeDescription($row['state'] ?? null); $location = $this->normalizeLocation($row['country'] ?? null); $deliveryStatus = $this->normalizeDeliveryStatus($row['last_state'] ?? null); if (!$awbNo || !$eventDate || !$eventDescription) { $this->skippedEvents++; continue; } $shipment = Shipment::where('awb_no', $awbNo)->first(); if (!$shipment) { $shipment = $this->createShipmentFromTrackingRow($row, $awbNo, $location); $this->createdShipments++; } ShipmentTrackingEvent::create([ 'shipment_id' => $shipment->id, 'event_date' => $eventDate, 'event_time' => $eventTime, 'location' => $location, 'event_description' => $eventDescription, 'delivery_status' => $deliveryStatus, 'source' => 'manual', ]); $this->importedEvents++; } catch (\Throwable $e) { $this->skippedEvents++; $this->errors[] = "Row {$index}: " . $e->getMessage(); Log::error('Tracking import error', ['row' => $index, 'error' => $e->getMessage()]); } } Log::info('Tracking import completed', [ 'imported' => $this->importedEvents, 'skipped' => $this->skippedEvents, 'created' => $this->createdShipments, 'errors' => count($this->errors), ]); } protected function createShipmentFromTrackingRow(array $row, string $awbNo, ?string $location): Shipment { $countryName = $location ? explode(' - ', $location)[0] : null; $country = Country::where('name', 'like', "%{$countryName}%")->first(); $lastState = strtolower($row['last_state'] ?? ''); $status = 'processed'; if (str_contains($lastState, 'delivered')) $status = 'delivered'; elseif (str_contains($lastState, 'in transit')) $status = 'in_transit'; elseif (str_contains($lastState, 'picked')) $status = 'picked_up'; elseif (str_contains($lastState, 'out for delivery')) $status = 'out_for_delivery'; elseif (str_contains($lastState, 'failed')) $status = 'failed'; $shipment = Shipment::create([ 'awb_no' => $awbNo, 'direction' => 'export', 'type' => 'PARCEL', 'status' => $status, 'weight' => 0, 'volumetric_weight' => 0, 'chargeable_weight' => 0, 'shipping_price' => 0, 'extra_service' => 0, 'packing_cost' => 0, 'domestic_pickup' => 0, 'domestic_delivery' => 0, 'warehousing_cost' => 0, 'vat_amount' => 0, 'discount' => 0, 'total_fee' => 0, 'net_dirham' => 0, 'net_rial' => 0, 'from_country_id' => Country::where('name', 'Iran')->first()?->id, 'to_country_id' => $country?->id, 'sender_name' => 'Unknown', 'receiver_name' => 'Unknown', ]); return $shipment; } public function getImportedEvents(): int { return $this->importedEvents; } public function getSkippedEvents(): int { return $this->skippedEvents; } public function getErrors(): array { return $this->errors; } public function getCreatedShipments(): int { return $this->createdShipments; } protected function normalizeAwb($value): ?string { if (!$value) return null; $value = trim($value); return $value === '' || $value === '0' ? null : $value; } protected function normalizeDate($value): ?string { if (!$value) return null; if ($value instanceof \DateTime) { return $value->format('Y-m-d'); } $value = trim($value); if ($value === '' || $value === '1899-12-31') return null; try { return date('Y-m-d', strtotime($value)); } catch (\Throwable $e) { return null; } } protected function normalizeTime($value): ?string { if (!$value) return null; if ($value instanceof \DateTime) { return $value->format('H:i:s'); } $value = trim($value); if ($value === '' || $value === '1899-12-31') return null; try { return date('H:i:s', strtotime($value)); } catch (\Throwable $e) { return null; } } protected function normalizeDescription($value): ?string { if (!$value) return null; $value = trim($value); return $value === '' ? null : $value; } protected function normalizeLocation($value): ?string { if (!$value) return null; $value = trim($value); return $value === '' || $value === '.' ? null : $value; } protected function normalizeDeliveryStatus($value): ?string { if (!$value) return null; $value = trim($value); if ($value === '') return null; $statuses = [ 'processed' => 'processed', 'picked up' => 'picked_up', 'in transit' => 'in_transit', 'out for delivery' => 'out_for_delivery', 'failed' => 'failed', 'delivered' => 'delivered', 'returned' => 'returned', ]; $lower = strtolower($value); foreach ($statuses as $key => $status) { if (str_contains($lower, $key)) { return $status; } } return null; } }