feat: [수주서] 절곡품 이미지 연동 — bending_items files 기반
- groupBendingParts에서 item_code prefix → bending_items 이미지 매칭 - getBendingItemImages: BD prefix 기반 files 테이블 사전 조회 - 각 bending_parts item에 image_url 포함하여 응답
This commit is contained in:
@@ -573,6 +573,8 @@ private function getOrderDetail(int $id): array
|
||||
*/
|
||||
private function groupBendingParts($steelItems, int $shutterCount = 0): array
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$groups = [
|
||||
'가이드레일' => [],
|
||||
'케이스' => [],
|
||||
@@ -581,6 +583,10 @@ private function groupBendingParts($steelItems, int $shutterCount = 0): array
|
||||
'기타' => [],
|
||||
];
|
||||
|
||||
// item_code별 bending_item 이미지 사전 조회
|
||||
$itemCodes = $steelItems->pluck('item_code')->filter()->unique()->values()->toArray();
|
||||
$imageMap = $this->getBendingItemImages($itemCodes, $tenantId);
|
||||
|
||||
foreach ($steelItems->groupBy('item_name') as $name => $group) {
|
||||
$item = $group->first();
|
||||
$totalQty = $group->sum('quantity');
|
||||
@@ -591,16 +597,31 @@ private function groupBendingParts($steelItems, int $shutterCount = 0): array
|
||||
$isCase = str_contains($name, '케이스') && ! $isMaguri;
|
||||
|
||||
if ($shutterCount > 0 && ($isGuideRail || $isCase || $isMaguri)) {
|
||||
// 가이드레일, 마구리: 2 × 셔터수량 / 케이스: 셔터수량
|
||||
$qty = ($isGuideRail || $isMaguri) ? 2 * $shutterCount : $shutterCount;
|
||||
} else {
|
||||
$qty = $totalQty;
|
||||
}
|
||||
|
||||
// 이미지 URL: item_code(BD-XX-NN) 기반 → bending_item prefix 매칭
|
||||
$itemCode = $item['item_code'] ?? null;
|
||||
$imageUrl = $itemCode ? ($imageMap[$itemCode] ?? null) : null;
|
||||
|
||||
// item_code로 직접 매칭 안 되면 prefix(BD-XX)로 매칭 시도
|
||||
if (! $imageUrl && $itemCode && preg_match('/^(BD-[A-Z]{2})/', $itemCode, $m)) {
|
||||
$prefix = $m[1];
|
||||
foreach ($imageMap as $code => $url) {
|
||||
if (str_starts_with($code, $prefix)) {
|
||||
$imageUrl = $url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$row = [
|
||||
'name' => $item['item_name'],
|
||||
'spec' => $item['specification'] ?? '-',
|
||||
'qty' => (int) $qty,
|
||||
'image_url' => $imageUrl,
|
||||
];
|
||||
|
||||
if (str_contains($name, '연기차단재')) {
|
||||
@@ -629,6 +650,70 @@ private function groupBendingParts($steelItems, int $shutterCount = 0): array
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* bending_items의 이미지 URL 사전 조회
|
||||
*
|
||||
* item_code(BD-XX-NN) → bending_items.code(BD-XX.NNN) prefix 매칭 → files 테이블에서 이미지 조회
|
||||
*
|
||||
* @return array<string, string> item_code → image_url 매핑
|
||||
*/
|
||||
private function getBendingItemImages(array $itemCodes, int $tenantId): array
|
||||
{
|
||||
if (empty($itemCodes)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// item_code에서 prefix 추출 (BD-RM-24 → BD-RM)
|
||||
$prefixes = [];
|
||||
foreach ($itemCodes as $code) {
|
||||
if (preg_match('/^(BD-[A-Z]{2})/', $code, $m)) {
|
||||
$prefixes[$m[1]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($prefixes)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// bending_items에서 해당 prefix 매칭 + files 조인
|
||||
$bendingItems = \App\Models\BendingItem::where('tenant_id', $tenantId)
|
||||
->where(function ($q) use ($prefixes) {
|
||||
foreach (array_keys($prefixes) as $prefix) {
|
||||
$q->orWhere('code', 'LIKE', "{$prefix}%");
|
||||
}
|
||||
})
|
||||
->whereHas('files')
|
||||
->with(['files' => fn ($q) => $q->orderBy('id', 'desc')->limit(1)])
|
||||
->get();
|
||||
|
||||
// prefix → file_id 매핑 (첫 번째 매칭만)
|
||||
$prefixImageMap = [];
|
||||
foreach ($bendingItems as $bi) {
|
||||
$file = $bi->files->first();
|
||||
if (! $file) {
|
||||
continue;
|
||||
}
|
||||
// BD-RM.001 → BD-RM prefix 추출
|
||||
$biPrefix = substr($bi->code, 0, 5); // "BD-RM"
|
||||
if (! isset($prefixImageMap[$biPrefix])) {
|
||||
$prefixImageMap[$biPrefix] = url("/api/v1/files/{$file->id}/view");
|
||||
}
|
||||
}
|
||||
|
||||
// item_code → image_url 매핑
|
||||
$result = [];
|
||||
foreach ($itemCodes as $code) {
|
||||
if (preg_match('/^(BD-[A-Z]{2})/', $code, $m)) {
|
||||
$prefix = $m[1];
|
||||
if (isset($prefixImageMap[$prefix])) {
|
||||
$result[$code] = $prefixImageMap[$prefix];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getWorkOrderLogDetail(int $id): array
|
||||
{
|
||||
$workOrder = WorkOrder::with('process')->findOrFail($id);
|
||||
@@ -797,27 +882,27 @@ private function formatFqcTemplate($template): ?array
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $s->id,
|
||||
'name' => $s->name,
|
||||
'title' => $s->title,
|
||||
'description' => $s->description,
|
||||
'image_path' => $s->image_path,
|
||||
'file_id' => $s->file_id,
|
||||
'image_url' => $imageUrl,
|
||||
'sort_order' => $s->sort_order,
|
||||
'items' => $s->items->map(fn ($i) => [
|
||||
'id' => $i->id,
|
||||
'section_id' => $i->section_id,
|
||||
'item_name' => $i->item ?? '',
|
||||
'standard' => $i->standard,
|
||||
'tolerance' => $i->tolerance,
|
||||
'measurement_type' => $i->measurement_type,
|
||||
'frequency' => $i->frequency,
|
||||
'sort_order' => $i->sort_order,
|
||||
'category' => $i->category,
|
||||
'method' => $i->method,
|
||||
])->all(),
|
||||
];
|
||||
'id' => $s->id,
|
||||
'name' => $s->name,
|
||||
'title' => $s->title,
|
||||
'description' => $s->description,
|
||||
'image_path' => $s->image_path,
|
||||
'file_id' => $s->file_id,
|
||||
'image_url' => $imageUrl,
|
||||
'sort_order' => $s->sort_order,
|
||||
'items' => $s->items->map(fn ($i) => [
|
||||
'id' => $i->id,
|
||||
'section_id' => $i->section_id,
|
||||
'item_name' => $i->item ?? '',
|
||||
'standard' => $i->standard,
|
||||
'tolerance' => $i->tolerance,
|
||||
'measurement_type' => $i->measurement_type,
|
||||
'frequency' => $i->frequency,
|
||||
'sort_order' => $i->sort_order,
|
||||
'category' => $i->category,
|
||||
'method' => $i->method,
|
||||
])->all(),
|
||||
];
|
||||
})->all(),
|
||||
'columns' => $template->columns->map(fn ($c) => [
|
||||
'id' => $c->id,
|
||||
|
||||
Reference in New Issue
Block a user