사방넷 코드가 없는 항목은 결과 엑셀에서 제외
itemcode_db 의 single_items.sabangnet_code 가 비어 있거나 마스터에 등록되지 않은 상품(미등록 코드 / 세트 구성 단품 미등록)은 결과 엑셀의 상품코드[필수] 컬럼에 들어갈 값이 없으므로 제외한다. - 폴백 시 sabangnet_code 자리에 내부 코드 채우던 동작 제거 - 엑셀 빌드 단계에서 사방넷 코드가 빈 행을 스킵하고 warning 로그 - success 로그에 excel_row_count / skipped_no_sabang_count 노출 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+25
-7
@@ -766,14 +766,16 @@ def upload_file(
|
|||||||
s_code = comp["single_code"]
|
s_code = comp["single_code"]
|
||||||
comp_qty = safe_int_quantity(comp["quantity"], default=1)
|
comp_qty = safe_int_quantity(comp["quantity"], default=1)
|
||||||
single_qty_sums[s_code] = single_qty_sums.get(s_code, 0) + (qty * comp_qty)
|
single_qty_sums[s_code] = single_qty_sums.get(s_code, 0) + (qty * comp_qty)
|
||||||
# 세트 구성 단품 정보가 single_items 에 없을 수도 있으므로 보강
|
# 세트 구성 단품 정보가 single_items 에 없을 수도 있으므로 placeholder 만 보강.
|
||||||
|
# 사방넷 코드는 비워서, 결과 엑셀 빌드 단계에서 제외 대상으로 인식되게 둔다.
|
||||||
if s_code not in single_items:
|
if s_code not in single_items:
|
||||||
single_items[s_code] = {"sabangnet_code": s_code, "name": ""}
|
single_items[s_code] = {"sabangnet_code": "", "name": ""}
|
||||||
else:
|
else:
|
||||||
# 마스터 미등록 코드: 단품으로 간주, 이름은 주문서의 상품명으로 채움
|
# 마스터 미등록 코드: 사방넷 코드를 알 수 없으므로 placeholder 로만 추적.
|
||||||
|
# 결과 엑셀에서는 제외된다.
|
||||||
unknown_codes.add(prod_code)
|
unknown_codes.add(prod_code)
|
||||||
single_items[prod_code] = {
|
single_items[prod_code] = {
|
||||||
"sabangnet_code": prod_code,
|
"sabangnet_code": "",
|
||||||
"name": order.product_name or ""
|
"name": order.product_name or ""
|
||||||
}
|
}
|
||||||
single_qty_sums[prod_code] = single_qty_sums.get(prod_code, 0) + qty
|
single_qty_sums[prod_code] = single_qty_sums.get(prod_code, 0) + qty
|
||||||
@@ -788,15 +790,29 @@ def upload_file(
|
|||||||
|
|
||||||
# 5. 결과 엑셀 데이터 빌드
|
# 5. 결과 엑셀 데이터 빌드
|
||||||
# A열=사방넷코드, B열=합계수량, C열=이름. 헤더는 요청 사양(상품코드[필수]/가용수량/불용수량).
|
# A열=사방넷코드, B열=합계수량, C열=이름. 헤더는 요청 사양(상품코드[필수]/가용수량/불용수량).
|
||||||
|
# 사방넷 코드가 없는(마스터 미등록·구성품 미등록) 단품은 결과에서 제외한다.
|
||||||
excel_rows = []
|
excel_rows = []
|
||||||
|
skipped_no_sabang: list[str] = []
|
||||||
for s_code, total_qty in single_qty_sums.items():
|
for s_code, total_qty in single_qty_sums.items():
|
||||||
s_info = single_items.get(s_code, {"sabangnet_code": s_code, "name": ""})
|
s_info = single_items.get(s_code, {"sabangnet_code": "", "name": ""})
|
||||||
|
sabang_code = (s_info.get("sabangnet_code") or "").strip()
|
||||||
|
if not sabang_code:
|
||||||
|
skipped_no_sabang.append(s_code)
|
||||||
|
continue
|
||||||
excel_rows.append({
|
excel_rows.append({
|
||||||
"상품코드[필수]": s_info["sabangnet_code"] or s_code,
|
"상품코드[필수]": sabang_code,
|
||||||
"가용수량": total_qty,
|
"가용수량": total_qty,
|
||||||
"불용수량": s_info["name"] or ""
|
"불용수량": s_info.get("name") or ""
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if skipped_no_sabang:
|
||||||
|
log_event(
|
||||||
|
current_user,
|
||||||
|
"낱개 출고 분석 — 사방넷 코드 없는 항목 제외",
|
||||||
|
"warning",
|
||||||
|
{"skipped_count": len(skipped_no_sabang), "sample": skipped_no_sabang[:20]},
|
||||||
|
)
|
||||||
|
|
||||||
df_out = pd.DataFrame(excel_rows, columns=["상품코드[필수]", "가용수량", "불용수량"])
|
df_out = pd.DataFrame(excel_rows, columns=["상품코드[필수]", "가용수량", "불용수량"])
|
||||||
|
|
||||||
# 엑셀 파일 쓰기 (1행 헤더, 2행부터 데이터 — pandas to_excel 기본 동작)
|
# 엑셀 파일 쓰기 (1행 헤더, 2행부터 데이터 — pandas to_excel 기본 동작)
|
||||||
@@ -824,7 +840,9 @@ def upload_file(
|
|||||||
"filenames": filenames_str,
|
"filenames": filenames_str,
|
||||||
"uploaded_count": len(db_records),
|
"uploaded_count": len(db_records),
|
||||||
"single_code_count": len(single_qty_sums),
|
"single_code_count": len(single_qty_sums),
|
||||||
|
"excel_row_count": len(excel_rows),
|
||||||
"unknown_code_count": len(unknown_codes),
|
"unknown_code_count": len(unknown_codes),
|
||||||
|
"skipped_no_sabang_count": len(skipped_no_sabang),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user