From a65ca65a8b7852a5b91ce92181a08d7a275198b0 Mon Sep 17 00:00:00 2001 From: king Date: Fri, 19 Jun 2026 15:54:23 +0900 Subject: [PATCH] =?UTF-8?q?feat(dispatch):=20=EB=B0=B0=EC=86=A1=EC=82=AC?= =?UTF-8?q?=20=EB=B0=B0=EC=A7=80=EB=A5=BC=20=EB=A1=9C=EA=B3=A0=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=EB=A1=9C=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - store.courier_logo_url: 배송사명(부분 일치) → 로고 SVG URL, 없으면 텍스트 폴백 - Jinja 필터 courier_logo 등록(main.py) - Ninja Van / J&T Express 내장 SVG 로고 추가(static/dispatch/courier/) - 출고 작업 카드 + Kagayaku 전달 요약에 로고 렌더 Co-Authored-By: Claude Opus 4.8 --- app/main.py | 5 +++ app/modules/dispatch/store.py | 43 +++++++++++++++++++ .../dispatch/templates/dispatch/detail.html | 8 +++- .../dispatch/templates/dispatch/handover.html | 2 + app/static/dispatch/courier/jnt.svg | 7 +++ app/static/dispatch/courier/ninjavan.svg | 12 ++++++ 6 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 app/static/dispatch/courier/jnt.svg create mode 100644 app/static/dispatch/courier/ninjavan.svg diff --git a/app/main.py b/app/main.py index ed722de..28c0aa4 100644 --- a/app/main.py +++ b/app/main.py @@ -125,6 +125,11 @@ templates.env.loader = ChoiceLoader( ] ) +# 배송사명 → 로고 URL(dispatch 모듈). 템플릿에서 {{ provider | courier_logo }}. +from .modules.dispatch.store import courier_logo_url as _courier_logo_url # noqa: E402 + +templates.env.filters["courier_logo"] = _courier_logo_url + oauth = build_google_oauth() user_store = UserStore(DATA_DIR / "users.json") diff --git a/app/modules/dispatch/store.py b/app/modules/dispatch/store.py index 9fc8537..77702bf 100644 --- a/app/modules/dispatch/store.py +++ b/app/modules/dispatch/store.py @@ -203,6 +203,49 @@ def normalize_quantity(value: Any) -> int: return n if n > 0 else 1 +# ── 배송사 로고 ── +# 배송사명(부분 일치, 소문자) → 슬러그. 로고 SVG 가 있는 슬러그만 이미지로 +# 렌더하고, 없으면 텍스트 배지로 폴백한다. 새 배송사 로고 추가 절차: +# 1) app/static/dispatch/courier/<슬러그>.svg 추가 +# 2) 아래 _COURIER_KEYWORDS 에 (키워드, 슬러그) 추가 +# 3) _COURIER_LOGO_AVAILABLE 에 슬러그 추가 +_COURIER_KEYWORDS: tuple[tuple[str, str], ...] = ( + ("ninja", "ninjavan"), + ("j&t", "jnt"), + ("jnt", "jnt"), + ("flash", "flash"), + ("city", "citylink"), + ("pos laju", "poslaju"), + ("poslaju", "poslaju"), + ("gdex", "gdex"), + ("gd express", "gdex"), + ("shopee", "spx"), + ("spx", "spx"), +) + +# 실제 SVG 파일이 있는 슬러그만(없는 건 텍스트 폴백 → 깨진 이미지 방지). +_COURIER_LOGO_AVAILABLE: frozenset[str] = frozenset({"ninjavan", "jnt"}) + + +def courier_slug(provider: Any) -> str: + """배송사명 → 로고 슬러그(부분 일치). 매칭 없으면 "".""" + name = clean_text(provider).lower() + if not name: + return "" + for keyword, slug in _COURIER_KEYWORDS: + if keyword in name: + return slug + 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" + return "" + + def sku_summary(parcels: list[dict[str, Any]]) -> list[dict[str, Any]]: """전체 박스 기준 SKU별 총 수량(피킹 요약). seller_sku 오름차순.""" totals: dict[str, dict[str, Any]] = {} diff --git a/app/modules/dispatch/templates/dispatch/detail.html b/app/modules/dispatch/templates/dispatch/detail.html index f6b0a90..196a02f 100644 --- a/app/modules/dispatch/templates/dispatch/detail.html +++ b/app/modules/dispatch/templates/dispatch/detail.html @@ -21,6 +21,7 @@ .dsp-btn-status small { display:block;font-size:10px;font-weight:500;opacity:.8; } .dsp-btn-status.on { background:#16a34a;border-color:#16a34a;color:#fff; } .dsp-btn-status:disabled { opacity:.6;cursor:wait; } + .dsp-courier { height:22px;width:auto;max-width:140px;display:block; } .dsp-hidden { display:none !important; } @media (max-width:480px){ .dsp-cards{grid-template-columns:1fr;} } @@ -62,7 +63,12 @@ data-search="{{ (p.order_id ~ ' ' ~ p.package_id ~ ' ' ~ p.tracking_id ~ ' ' ~ (p['items']|map(attribute='seller_sku')|join(' ')))|lower }}">
No. {{ p.seq }} - {% if p.shipping_provider %}{{ p.shipping_provider }}{% endif %} + {% set logo = p.shipping_provider | courier_logo %} + {% if logo %} + {{ p.shipping_provider }} + {% elif p.shipping_provider %} + {{ p.shipping_provider }} + {% endif %}
Order {{ p.order_id or '—' }}
diff --git a/app/modules/dispatch/templates/dispatch/handover.html b/app/modules/dispatch/templates/dispatch/handover.html index 8b296b4..06f80e0 100644 --- a/app/modules/dispatch/templates/dispatch/handover.html +++ b/app/modules/dispatch/templates/dispatch/handover.html @@ -45,6 +45,8 @@
{% for pv in handover.by_provider %}
+ {% set logo = pv.provider | courier_logo %} + {% if logo %}{{ pv.provider }}{% endif %}
{{ pv.box_count }}
{{ pv.provider }}
diff --git a/app/static/dispatch/courier/jnt.svg b/app/static/dispatch/courier/jnt.svg new file mode 100644 index 0000000..7ca93c0 --- /dev/null +++ b/app/static/dispatch/courier/jnt.svg @@ -0,0 +1,7 @@ + + + J&T + EXPRESS + diff --git a/app/static/dispatch/courier/ninjavan.svg b/app/static/dispatch/courier/ninjavan.svg new file mode 100644 index 0000000..a217557 --- /dev/null +++ b/app/static/dispatch/courier/ninjavan.svg @@ -0,0 +1,12 @@ + + + + + + + + + + Ninja Van +