merge: develop + kkk 브랜치 병합 (code/lot_no 분리 + origin 신규 기능 통합)

This commit is contained in:
2026-03-21 17:35:26 +09:00
30 changed files with 911 additions and 80 deletions

View File

@@ -3,7 +3,6 @@
namespace App\Services;
use App\Models\BendingItem;
use App\Models\Orders\Order;
class BendingCodeService extends Service
{
@@ -128,9 +127,9 @@ public function getCodeMap(): array
}
/**
* 드롭다운 선택 조합 → bending_items 품목 매핑 조회
* 드롭다운 선택 조합 → 품목(items) 매핑 조회
*
* legacy_code 패턴: BD-{prod}{spec}-{length} (예: BD-CP-30)
* 품목코드 패턴: BD-{prod}{spec}-{length} (예: BD-RC-24)
*/
public function resolveItem(string $prodCode, string $specCode, string $lengthCode): ?array
{
@@ -202,4 +201,87 @@ public static function getMaterial(string $prodCode, string $specCode): ?string
{
return self::MATERIAL_MAP["{$prodCode}:{$specCode}"] ?? null;
}
/**
* 품목 코드(BD-XX-YY) → 매칭되는 bending_item의 전개 폭(width_sum) 반환
*
* 매칭 로직:
* BD-{prod}{spec}-{length} 파싱
* → PRODUCTS/SPECS에서 item_bending, item_sep, 키워드 추출
* → bending_items 검색 → bending_data 마지막 sum = 전개 폭
*/
public function getBendingWidthByItemCode(string $itemCode): ?float
{
if (! preg_match('/^BD-([A-Z])([A-Z])-(\d+)$/', $itemCode, $m)) {
return null;
}
$prodCode = $m[1];
$specCode = $m[2];
// 제품명 → item_bending 추출 (가이드레일(벽면형) → 가이드레일)
$productName = null;
foreach (self::PRODUCTS as $p) {
if ($p['code'] === $prodCode) {
$productName = $p['name'];
break;
}
}
if (! $productName) {
return null;
}
// 종류명 추출
$specName = null;
foreach (self::SPECS as $s) {
if ($s['code'] === $specCode && in_array($prodCode, $s['products'])) {
$specName = $s['name'];
break;
}
}
if (! $specName) {
return null;
}
// item_bending: 괄호 제거 (가이드레일(벽면형) → 가이드레일)
$itemBending = preg_replace('/\(.*\)/', '', $productName);
// item_sep 판단: 종류명 또는 제품명에 '철재' → 철재, 아니면 스크린
$itemSep = (str_contains($specName, '철재') || str_contains($productName, '철재'))
? '철재' : '스크린';
// bending_items 검색
$query = \App\Models\BendingItem::query()
->where('tenant_id', $this->tenantId())
->where('item_bending', $itemBending)
->where('item_sep', $itemSep)
->whereNotNull('bending_data');
// 가이드레일: 벽면형/측면형 구분 (item_name 키워드 매칭)
if (str_contains($productName, '벽면형')) {
$query->where('item_name', 'LIKE', '%벽면형%');
} elseif (str_contains($productName, '측면형')) {
$query->where('item_name', 'LIKE', '%측면형%');
}
// 종류 키워드 매칭 (본체, C형, D형, 전면, 점검구, 린텔 등)
$specKeyword = preg_replace('/\(.*\)/', '', $specName); // 본체(철재) → 본체
$query->where('item_name', 'LIKE', "%{$specKeyword}%");
// 최신 코드 우선
$bendingItem = $query->orderByDesc('code')->first();
if (! $bendingItem) {
return null;
}
// bending_data 마지막 항목의 sum = 전개 폭
$data = $bendingItem->bending_data;
if (empty($data)) {
return null;
}
$last = end($data);
return isset($last['sum']) ? (float) $last['sum'] : null;
}
}