resolveCsvUrl(); $csv = $this->downloadCsv($url); $rows = $this->parse($csv); if ($rows === []) { throw new RuntimeException('BEIS CSV parsed empty — check delimiter / encoding'); } DB::table('weekly_pump_prices')->upsert( $rows, ['date'], ['ulsp_pence', 'ulsd_pence', 'ulsp_duty_pence', 'ulsd_duty_pence', 'ulsp_vat_pct', 'ulsd_vat_pct'], ); Cache::flush(); $latest = (string) collect($rows)->pluck('date')->sortDesc()->first(); return [ 'csv_url' => $url, 'parsed' => count($rows), 'upserted' => count($rows), 'latest_date' => $latest, ]; } private function resolveCsvUrl(): string { $response = Http::timeout(15)->acceptJson()->get(self::API_URL); $response->throw(); $attachments = $response->json('details.attachments', []); foreach ($attachments as $a) { if (($a['title'] ?? null) === self::ATTACHMENT_TITLE) { $url = $a['url'] ?? null; if (! is_string($url) || $url === '') { throw new RuntimeException('BEIS attachment had empty URL'); } return $url; } } throw new RuntimeException(sprintf( 'gov.uk content API did not return an attachment titled %s', self::ATTACHMENT_TITLE, )); } private function downloadCsv(string $url): string { $response = Http::timeout(60)->get($url); $response->throw(); return $response->body(); } /** * @return array> */ private function parse(string $csv): array { $rows = []; $lines = preg_split('/\r\n|\r|\n/', $csv); if ($lines === false || count($lines) < 2) { return []; } // Skip header. array_shift($lines); foreach ($lines as $line) { $line = trim($line); if ($line === '') { continue; } $cols = str_getcsv($line, escape: '\\'); if (count($cols) < 7) { continue; } $date = DateTime::createFromFormat('d/m/Y', trim($cols[0])); if ($date === false) { continue; } $rows[] = [ 'date' => $date->format('Y-m-d'), 'ulsp_pence' => (int) round(((float) $cols[1]) * 100), 'ulsd_pence' => (int) round(((float) $cols[2]) * 100), 'ulsp_duty_pence' => (int) round(((float) $cols[3]) * 100), 'ulsd_duty_pence' => (int) round(((float) $cols[4]) * 100), 'ulsp_vat_pct' => (int) $cols[5], 'ulsd_vat_pct' => (int) $cols[6], ]; } return $rows; } }