feat(dispatch): 주문/패키지/송장 번호로 받는 사람 찾기 검색

배치 목록 상단에 검색 박스 추가. 주문번호·패키지번호·송장번호 일부만
입력하면 전체 출고 배치에서 해당 박스의 받는 사람(이름·전화·주소)과
소속 배치를 찾아준다.

- db.search_parcels: 3개 식별자 ILIKE 부분일치 + 배치 조인(파라미터 바인딩)
- GET /dispatch/api/search: 2글자 이상, dispatch 권한 가드
- batches.html: 디바운스 검색 UI, 매칭 강조, 한/영 토글 연동

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-26 17:06:45 +09:00
parent 26d0753579
commit 6dc14a7350
3 changed files with 159 additions and 0 deletions
+41
View File
@@ -358,6 +358,47 @@ class DispatchStore:
),
)
def search_parcels(self, *, query: str, limit: int = 50) -> list[dict[str, Any]]:
"""주문번호/패키지번호/송장번호(부분 일치)로 박스를 찾는다.
3개 식별자 어디든 query 가 포함되면 매칭. 받는 사람(이름/전화/주소)과
소속 배치(날짜/플랫폼/배치명/id) + 박스 seq 를 함께 돌려준다.
최신 출고일/배치 우선. query 가 비면 빈 리스트.
"""
q = (query or "").strip()
if not q:
return []
like = f"%{q}%"
with self._pool.connection() as conn:
rows = conn.execute(
"""
SELECT p.id AS parcel_id,
p.seq,
p.order_id,
p.package_id,
p.tracking_id,
p.shipping_provider,
p.recipient_name,
p.recipient_phone,
p.recipient_address,
p.label_attached,
p.handed_to_kagayaku,
b.id AS batch_id,
b.dispatch_date,
b.platform,
b.batch_name
FROM dispatch_parcels p
JOIN dispatch_batches b ON b.id = p.batch_id
WHERE p.order_id ILIKE %(like)s
OR p.package_id ILIKE %(like)s
OR p.tracking_id ILIKE %(like)s
ORDER BY b.dispatch_date DESC, b.id DESC, p.seq ASC
LIMIT %(limit)s
""",
{"like": like, "limit": int(limit)},
).fetchall()
return [self._serialize(r) for r in rows]
def parcel_batch_id(self, *, parcel_id: int) -> int | None:
with self._pool.connection() as conn:
row = conn.execute(