feat(cupang): 상자 목록을 번호·제품명·제품코드·수량 표로, 엑셀 다운로드 추가
- ② 상자 목록: 카드 대신 표. 한 상자에 여러 제품이면 상자번호 칸 rowspan 병합
- GET /cupang/{id}/boxes.xlsx — 같은 표를 xlsx 로 (export.build_box_list_workbook)
- box_list 항목에 product_code 포함
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -188,3 +188,66 @@ def build_workbook(ship_date: str, shipments: list[dict[str, Any]]) -> Any:
|
||||
ws.row_dimensions[TITLE_ROW].height = 28
|
||||
|
||||
return wb
|
||||
|
||||
|
||||
# ── 상자 목록(상자 번호별 내용물) ──────────────────────────────
|
||||
BOX_HEADERS = ["상자번호", "제품명", "제품코드", "수량"]
|
||||
BOX_WIDTHS_PX = {1: 70, 2: 240, 3: 110, 4: 70}
|
||||
|
||||
|
||||
def build_box_list_workbook(shipment: dict[str, Any], box_list: list[dict[str, Any]]) -> Any:
|
||||
"""상자 번호 · 제품명 · 제품코드 · 수량 한 줄씩. 시트명 = YYYYMMDD(요일)."""
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
|
||||
from openpyxl.utils import get_column_letter
|
||||
|
||||
ship_date = str(shipment.get("ship_date") or "")
|
||||
center = str(shipment.get("center_name_snapshot") or "")
|
||||
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = sheet_title(ship_date) if ship_date else "상자목록"
|
||||
|
||||
thin = Side(style="thin", color="000000")
|
||||
box = Border(left=thin, right=thin, top=thin, bottom=thin)
|
||||
center_align = Alignment(horizontal="center", vertical="center")
|
||||
left_align = Alignment(horizontal="left", vertical="center")
|
||||
|
||||
ws.cell(row=1, column=1, value=f"{with_dow(ship_date)} {center} 상자 목록")
|
||||
ws.cell(row=1, column=1).font = Font(size=14, bold=True)
|
||||
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(BOX_HEADERS))
|
||||
|
||||
header_fill = PatternFill("solid", fgColor=HEADER_BG)
|
||||
for idx, name in enumerate(BOX_HEADERS, start=1):
|
||||
cell = ws.cell(row=2, column=idx, value=name)
|
||||
cell.font = Font(bold=True)
|
||||
cell.alignment = center_align
|
||||
cell.border = box
|
||||
cell.fill = header_fill
|
||||
|
||||
row = 3
|
||||
for entry in box_list:
|
||||
contents = entry.get("items") or []
|
||||
first = row
|
||||
for it in contents:
|
||||
ws.cell(row=row, column=1, value=entry.get("no"))
|
||||
ws.cell(row=row, column=2, value=it.get("product_name") or "")
|
||||
ws.cell(row=row, column=3, value=it.get("product_code") or "")
|
||||
ws.cell(row=row, column=4, value=int(it.get("quantity") or 0))
|
||||
row += 1
|
||||
# 한 상자에 여러 제품이면 상자번호 칸을 세로로 합친다.
|
||||
if row - first > 1:
|
||||
ws.merge_cells(start_row=first, start_column=1, end_row=row - 1, end_column=1)
|
||||
|
||||
last = row - 1
|
||||
for r in range(3, last + 1):
|
||||
for col in range(1, len(BOX_HEADERS) + 1):
|
||||
cell = ws.cell(row=r, column=col)
|
||||
cell.border = box
|
||||
cell.alignment = left_align if col == 2 else center_align
|
||||
|
||||
for col, px in BOX_WIDTHS_PX.items():
|
||||
ws.column_dimensions[get_column_letter(col)].width = round(px / PX_PER_CHAR, 2)
|
||||
ws.row_dimensions[1].height = 24
|
||||
|
||||
return wb
|
||||
|
||||
Reference in New Issue
Block a user