From fd4ef9180c9b9a1ddbccbb787ec499aea1dbce7f Mon Sep 17 00:00:00 2001 From: king Date: Fri, 19 Jun 2026 16:08:45 +0900 Subject: [PATCH] =?UTF-8?q?feat(dispatch):=20=EB=B0=B0=EC=86=A1=EC=82=AC?= =?UTF-8?q?=20=EB=A1=9C=EA=B3=A0=20=ED=8C=8C=EC=9D=BC=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9E=90=20=EC=9E=90=EB=8F=99=20=EA=B0=90=EC=A7=80(png=20?= =?UTF-8?q?=EC=9A=B0=EC=84=A0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 디스크에 있는 <슬러그>.png 또는 .svg 를 탐지해 URL 반환(png 우선), 없으면 텍스트 폴백. 새 로고는 파일 1개 + 키워드 1줄로 추가 가능. lru_cache 로 페이지당 반복 stat 최소화. Co-Authored-By: Claude Opus 4.8 --- app/modules/dispatch/store.py | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/app/modules/dispatch/store.py b/app/modules/dispatch/store.py index 77702bf..e88586d 100644 --- a/app/modules/dispatch/store.py +++ b/app/modules/dispatch/store.py @@ -14,6 +14,8 @@ from __future__ import annotations +from functools import lru_cache +from pathlib import Path from typing import Any, Iterable # ── 작업 상태 필드(토글 대상) ── @@ -204,11 +206,11 @@ def normalize_quantity(value: Any) -> int: # ── 배송사 로고 ── -# 배송사명(부분 일치, 소문자) → 슬러그. 로고 SVG 가 있는 슬러그만 이미지로 -# 렌더하고, 없으면 텍스트 배지로 폴백한다. 새 배송사 로고 추가 절차: -# 1) app/static/dispatch/courier/<슬러그>.svg 추가 -# 2) 아래 _COURIER_KEYWORDS 에 (키워드, 슬러그) 추가 -# 3) _COURIER_LOGO_AVAILABLE 에 슬러그 추가 +# 배송사명(부분 일치, 소문자) → 슬러그. 슬러그 이름의 이미지 파일이 실제로 +# 있으면 이미지로 렌더하고, 없으면 텍스트 배지로 폴백한다(깨진 이미지 방지). +# 새 배송사 로고 추가: 파일 1개 + 키워드 1줄. +# 1) app/static/dispatch/courier/<슬러그>.png (또는 .svg) 추가 +# 2) 아래 _COURIER_KEYWORDS 에 (배송사명키워드, 슬러그) 추가 _COURIER_KEYWORDS: tuple[tuple[str, str], ...] = ( ("ninja", "ninjavan"), ("j&t", "jnt"), @@ -223,8 +225,9 @@ _COURIER_KEYWORDS: tuple[tuple[str, str], ...] = ( ("spx", "spx"), ) -# 실제 SVG 파일이 있는 슬러그만(없는 건 텍스트 폴백 → 깨진 이미지 방지). -_COURIER_LOGO_AVAILABLE: frozenset[str] = frozenset({"ninjavan", "jnt"}) +# 로고 파일 디렉토리(app/static/dispatch/courier). png 를 svg 보다 우선한다. +_COURIER_DIR = Path(__file__).resolve().parents[2] / "static" / "dispatch" / "courier" +_COURIER_EXTS: tuple[str, ...] = (".png", ".svg") def courier_slug(provider: Any) -> str: @@ -238,14 +241,22 @@ def courier_slug(provider: Any) -> str: return "" -def courier_logo_url(provider: Any) -> str: - """배송사명 → 로고 SVG URL. SVG 없는 배송사는 ""(템플릿이 텍스트로 폴백).""" - slug = courier_slug(provider) - if slug in _COURIER_LOGO_AVAILABLE: - return f"/static/dispatch/courier/{slug}.svg" +@lru_cache(maxsize=128) +def _logo_url_for_slug(slug: str) -> str: + """슬러그에 해당하는 실제 로고 파일 URL(png 우선). 없으면 "".""" + if not slug: + return "" + for ext in _COURIER_EXTS: + if (_COURIER_DIR / f"{slug}{ext}").exists(): + return f"/static/dispatch/courier/{slug}{ext}" return "" +def courier_logo_url(provider: Any) -> str: + """배송사명 → 로고 이미지 URL. 파일 없으면 ""(템플릿이 텍스트로 폴백).""" + return _logo_url_for_slug(courier_slug(provider)) + + def sku_summary(parcels: list[dict[str, Any]]) -> list[dict[str, Any]]: """전체 박스 기준 SKU별 총 수량(피킹 요약). seller_sku 오름차순.""" totals: dict[str, dict[str, Any]] = {}