*/ public function build(Request $request, int $companyId): array { $fields = array_values((array) config('kuka_posting.quotation_fields', [])); $perPage = (int) $request->integer('per_page', 50); if (! in_array($perPage, [50, 100, 200], true)) { $perPage = 50; } $page = max(1, (int) $request->integer('page', 1)); $keyword = mb_substr(trim((string) $request->query('keyword', '')), 0, 120); $status = mb_substr(trim((string) $request->query('status', '')), 0, 64); $empty = new LengthAwarePaginator([], 0, $perPage, $page, [ 'path' => $request->url(), 'query' => $request->query(), ]); if ($fields === []) { return $this->result($empty, [], $keyword, $status, $perPage, '顾家报价单字段配置不完整。'); } $connectionName = (string) config('upstream_mirrors.connection', 'business_mirror'); $schema = Schema::connection($connectionName); if (! $schema->hasTable('kuka_posting_quotation_rows') || ! $schema->hasTable('kuka_posting_quotation_imports')) { return $this->result($empty, $fields, $keyword, $status, $perPage, '顾家报价单镜像尚未建立,请先执行数据库迁移和报价单导入。'); } try { $connection = DB::connection($connectionName); $import = $connection->table('kuka_posting_quotation_imports') ->where('company_id', $companyId) ->first(); $statuses = $connection->table('kuka_posting_quotation_rows') ->where('company_id', $companyId) ->whereNotNull('record_status') ->where('record_status', '!=', '') ->distinct() ->orderBy('record_status') ->pluck('record_status') ->map(static fn (mixed $value): string => (string) $value) ->all(); if ($status !== '' && ! in_array($status, $statuses, true)) { $status = ''; } $query = $connection->table('kuka_posting_quotation_rows') ->where('company_id', $companyId); if ($keyword !== '') { $like = '%' . addcslashes($keyword, '\\%_') . '%'; $query->where(static function ($nested) use ($like): void { $nested->where('material_number', 'like', $like) ->orWhere('material_desc', 'like', $like) ->orWhere('supplier_account', 'like', $like) ->orWhere('supplier_name', 'like', $like); }); } if ($status !== '') { $query->where('record_status', $status); } $rows = $query ->orderBy('material_number') ->paginate($perPage, ['*'], 'page', $page) ->withQueryString(); $rows->setCollection($rows->getCollection()->map(static function (object $row): object { $values = json_decode((string) $row->source_values, true); return (object) (is_array($values) ? $values : []); })); $range = $connection->table('kuka_posting_quotation_rows') ->where('company_id', $companyId) ->selectRaw('MIN(price_valid_date) as min_valid, MAX(price_expiry_date) as max_expiry') ->first(); $statusCounts = json_decode((string) ($import->status_counts ?? ''), true); return $this->result( $rows, $fields, $keyword, $status, $perPage, null, [ 'rows' => (int) ($import->row_count ?? 0), 'materials' => (int) ($import->material_count ?? 0), 'statuses' => is_array($statusCounts) ? $statusCounts : [], 'valid_from' => $range->min_valid ?? null, 'valid_to' => $range->max_expiry ?? null, 'file_name' => (string) ($import->file_name ?? ''), 'file_sha256' => (string) ($import->file_sha256 ?? ''), 'source_sheet' => (string) ($import->source_sheet ?? ''), 'completed_at' => (string) ($import->completed_at ?? ''), ], $statuses, ); } catch (Throwable $exception) { report($exception); return $this->result( $empty, $fields, $keyword, $status, $perPage, '顾家报价单暂时无法读取,请稍后重试;这不代表报价数据为 0。', ); } } /** * @param list> $fields * @param list $statuses * @param array $import * @return array */ private function result( LengthAwarePaginator $rows, array $fields, string $keyword, string $status, int $perPage, ?string $error, array $import = [], array $statuses = [], ): array { $directoryFields = array_map(static fn (array $field): array => [ 'name' => (string) $field['name'], 'source' => (string) $field['name'], 'label' => (string) $field['label'], 'kind' => (string) ($field['kind'] ?? 'text'), 'tones' => (array) ($field['tones'] ?? []), ], $fields); return [ 'directory' => [ 'title' => '顾家报价单 · 价格明细', 'icon' => 'request_quote', 'status' => '顾家报价单', 'description' => '顾家 SRM 报价数据原始字段;当前数据集共 ' . number_format((int) ($import['rows'] ?? 0)) . ' 条,物料编码唯一。', 'empty' => '顾家报价单尚未导入。', 'fields' => $directoryFields, ], 'rows' => $rows, 'filters' => [ 'keyword' => $keyword, 'status' => $status, 'per_page' => $perPage, ], 'statuses' => $statuses, 'import' => $import, 'summary' => [ 'filtered_rows' => $rows->total(), 'rows' => (int) ($import['rows'] ?? 0), 'materials' => (int) ($import['materials'] ?? 0), 'valid_from' => $import['valid_from'] ?? null, 'valid_to' => $import['valid_to'] ?? null, 'completed_at' => $import['completed_at'] ?? null, ], 'error' => $error, ]; } }