option('fix'); $since = $this->option('since'); $chunk = max(50, (int) $this->option('chunk')); $query = ShoppingOrder::query() ->whereIn('shipped', ShoppingOrder::SHIPPED_STATES) ->whereNull('shipped_at') ->when($since, fn ($q) => $q->where('created_at', '>=', $since)) ->orderBy('id'); $total = (clone $query)->count(); if ($total === 0) { $this->info('Keine Bestellungen ohne Versanddatum gefunden.'); return self::SUCCESS; } $this->info("Bestellungen ohne Versanddatum: {$total}"); $counts = [ShoppingOrder::SHIPPED_AT_SOURCE_DHL => 0, ShoppingOrder::SHIPPED_AT_SOURCE_ESTIMATED => 0]; $byMonth = []; $bar = $this->output->createProgressBar($total); $query->chunkById($chunk, function ($orders) use ($fix, &$counts, &$byMonth, $bar) { $labels = $this->getLabelDates($orders->pluck('id')->all()); foreach ($orders as $order) { $shippedAt = $labels[$order->id] ?? null; $source = ShoppingOrder::SHIPPED_AT_SOURCE_DHL; if ($shippedAt === null) { $shippedAt = $order->updated_at ?: $order->created_at; $source = ShoppingOrder::SHIPPED_AT_SOURCE_ESTIMATED; } if ($shippedAt === null) { continue; } $counts[$source]++; $month = $shippedAt->format('Y-m'); $byMonth[$month][$source] = ($byMonth[$month][$source] ?? 0) + 1; if ($fix) { ShoppingOrder::withoutTimestamps(fn () => ShoppingOrder::query() ->whereKey($order->id) ->update(['shipped_at' => $shippedAt, 'shipped_at_source' => $source])); } $bar->advance(); } }); $bar->finish(); $this->newLine(2); ksort($byMonth); $rows = []; foreach ($byMonth as $month => $sources) { $dhl = $sources[ShoppingOrder::SHIPPED_AT_SOURCE_DHL] ?? 0; $estimated = $sources[ShoppingOrder::SHIPPED_AT_SOURCE_ESTIMATED] ?? 0; $sum = $dhl + $estimated; $rows[] = [$month, $dhl, $estimated, $sum > 0 ? round($estimated / $sum * 100, 1).' %' : '-']; } $this->table(['Versandmonat', 'aus DHL-Label', 'geschaetzt', 'Anteil geschaetzt'], $rows); $this->info('Exakt aus DHL-Label: '.$counts[ShoppingOrder::SHIPPED_AT_SOURCE_DHL]); $this->info('Geschaetzt aus updated_at: '.$counts[ShoppingOrder::SHIPPED_AT_SOURCE_ESTIMATED]); if (! $fix) { $this->warn('Trockenlauf! Nutze --fix um die Werte zu schreiben.'); } return self::SUCCESS; } /** * Datum des ersten ausgehenden DHL-Labels je Bestellung. * * @param array $orderIds * @return array */ private function getLabelDates(array $orderIds): array { return DhlShipment::query() ->whereIn('order_id', $orderIds) ->where('type', 'outbound') ->orderBy('created_at') ->get(['order_id', 'created_at']) ->groupBy('order_id') ->map(fn ($shipments) => $shipments->first()->created_at) ->all(); } }