179 lines
7.0 KiB
PHP
179 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Business\KukaPostingQuotation;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Throwable;
|
|
|
|
class KukaPostingQuotationPageData
|
|
{
|
|
/**
|
|
* @return array<string,mixed>
|
|
*/
|
|
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<array<string,mixed>> $fields
|
|
* @param list<string> $statuses
|
|
* @param array<string,mixed> $import
|
|
* @return array<string,mixed>
|
|
*/
|
|
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,
|
|
];
|
|
}
|
|
}
|