option('date')) ?: now()->toDateString(); if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) !== 1) { $this->error('推送日期格式无效。'); return self::FAILURE; } $failed = false; foreach (Company::enabled()->orderBy('id')->get() as $company) { $company->makeCurrent(); $rows = $pageData->rowsForFilters([]); $periods = array_values(array_unique(array_filter(array_map( static fn (array $row): string => trim((string) ($row['summary_month'] ?? '')), $rows, )))); if ($periods === []) { $this->line("#{$company->id} {$company->name}: 没有负数预警数据"); continue; } rsort($periods); $period = $periods[0]; $latestRows = array_values(array_filter( $rows, static fn (array $row): bool => trim((string) ($row['summary_month'] ?? '')) === $period, )); $handled = array_fill_keys( $workflow->handledSuppliersForPeriod((int) $company->id, $period), true, ); $unhandledRows = array_values(array_filter( $latestRows, static fn (array $row): bool => ! isset($handled[trim((string) ($row['supplier'] ?? ''))]), )); if ($unhandledRows === []) { $this->line("#{$company->id} {$company->name} {$period}: 供应商均已处理"); continue; } $lockKey = sprintf( 'supplier-negative-alert:auto-push:%d:%s:%s', $company->id, $period, $date, ); if (! $this->option('force') && ! Cache::add($lockKey, true, now()->addDays(2))) { $this->line("#{$company->id} {$company->name} {$period}: 今天已经自动推送"); continue; } try { $result = $workflow->sendGrouped( $unhandledRows, ['month' => $period, 'automatic' => true], (int) $company->id, null, ); $this->info(sprintf( '#%d %s %s: 已推送 %d 位采购、%d 家供应商、%d 条未处理预警', $company->id, $company->name, $period, $result['purchaser_count'], $result['supplier_count'], $result['row_count'], )); } catch (Throwable $exception) { Cache::forget($lockKey); report($exception); $this->error("#{$company->id} {$company->name} {$period}: 自动推送失败:" . $exception->getMessage()); $failed = true; } } return $failed ? self::FAILURE : self::SUCCESS; } }