feat(cupang): 제품명 카탈로그 설정 + 달력 공휴일 색상 + 폼 UI 개선
- 설정 화면 추가: /cupang/products — itemcode_db 검색 등록 + 수동 등록. 제품명 드롭다운 소스. cupang_products 테이블 신규(init.sql 멱등 재실행 필요) - 폼 품목라인: 제품명 드롭다운 선택 → 제품코드 자동 입력 - 라인 컬럼 순서 제품명·제품코드·수량·입수량·박스계산·메모 - 제품코드 140px, 수량·입수량 60px 폭 고정 - 공통 헤더 입력란 겹침 수정(min-width:0, width:100%, box-sizing) - 달력: 일/공휴일 빨강, 토 파랑, 글자 크기 확대. 한국 공휴일 모듈(holidays.py) - document_no null → "None" 출력 버그 수정 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ from fastapi.responses import (
|
||||
StreamingResponse,
|
||||
)
|
||||
|
||||
from .holidays import is_holiday
|
||||
from .store import DEFAULT_CENTERS, SHEET_COLUMNS, SHIP_METHODS, STATUSES, compute_boxes
|
||||
|
||||
router = APIRouter(prefix="/cupang", tags=["cupang"])
|
||||
@@ -153,6 +154,9 @@ async def index(request: Request) -> HTMLResponse:
|
||||
"in_month": d.month == month,
|
||||
"is_today": d == today,
|
||||
"is_selected": d.isoformat() == sel,
|
||||
"is_sunday": d.weekday() == 6,
|
||||
"is_saturday": d.weekday() == 5,
|
||||
"is_holiday": is_holiday(d),
|
||||
"counts": counts.get(d.isoformat(), {}),
|
||||
}
|
||||
for d in week
|
||||
@@ -212,6 +216,7 @@ def _form_context(request: Request, store: Any, user: dict[str, Any]) -> dict[st
|
||||
"nav_items": build_erp_nav(user, active="cupang"),
|
||||
"centers": store.list_centers(),
|
||||
"box_rules": store.list_box_rules(),
|
||||
"products": store.list_products(),
|
||||
"ship_methods": list(SHIP_METHODS),
|
||||
"statuses": list(STATUSES),
|
||||
"search_enabled": bool(reader and reader.enabled),
|
||||
@@ -583,6 +588,71 @@ async def box_rule_delete(
|
||||
return RedirectResponse(url="/cupang/box-rules", status_code=303)
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════
|
||||
# 설정 — 제품명 카탈로그 관리 (itemcode_db 에서 등록)
|
||||
# ════════════════════════════════════════════════════════════
|
||||
@router.get("/products", response_class=HTMLResponse)
|
||||
async def products_page(request: Request) -> HTMLResponse:
|
||||
from app.main import build_erp_nav, render_template # noqa: WPS433
|
||||
from app.store import is_admin # noqa: WPS433
|
||||
|
||||
guard = _guard(request)
|
||||
if not isinstance(guard, tuple):
|
||||
return guard
|
||||
store, user = guard
|
||||
reader = _itemcode(request)
|
||||
return render_template(
|
||||
request,
|
||||
"cupang/products.html",
|
||||
{
|
||||
"user": user,
|
||||
"is_admin": is_admin(user),
|
||||
"nav_items": build_erp_nav(user, active="cupang"),
|
||||
"page_title": "쿠팡 밀크런 — 설정 (제품명)",
|
||||
"page_subtitle": "제품명 리스트 관리. itemcode_db 에서 검색해 등록하면 폼 드롭다운에 노출됩니다.",
|
||||
"products": store.list_products(include_inactive=True),
|
||||
"search_enabled": bool(reader and reader.enabled),
|
||||
"search_reason": (reader.reason if reader else ""),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/products")
|
||||
async def product_upsert(
|
||||
request: Request,
|
||||
product_code: str = Form(...),
|
||||
product_name: str = Form(...),
|
||||
sort_order: int = Form(0),
|
||||
user: dict[str, Any] = Depends(_require_user),
|
||||
) -> RedirectResponse:
|
||||
store = _store(request)
|
||||
if store is None:
|
||||
raise HTTPException(status_code=503, detail="cupang_db 미설정")
|
||||
try:
|
||||
store.upsert_product(
|
||||
product_code=product_code, product_name=product_name, sort_order=sort_order
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc))
|
||||
return RedirectResponse(url="/cupang/products", status_code=303)
|
||||
|
||||
|
||||
@router.post("/products/{product_id:int}/delete")
|
||||
async def product_delete(
|
||||
request: Request,
|
||||
product_id: int,
|
||||
user: dict[str, Any] = Depends(_require_user),
|
||||
) -> RedirectResponse:
|
||||
store = _store(request)
|
||||
if store is None:
|
||||
raise HTTPException(status_code=503, detail="cupang_db 미설정")
|
||||
try:
|
||||
store.deactivate_product(product_id=product_id)
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=404, detail="제품을 찾을 수 없습니다.")
|
||||
return RedirectResponse(url="/cupang/products", status_code=303)
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════
|
||||
# 상품 검색 (itemcode_db 읽기 전용) + 박스 계산 미리보기
|
||||
# ════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user