feat(malaysia): 입출고 일자별 낱개 수량 엑셀 다운로드
- '일괄 적용' 버튼명 '입력'으로 변경 - 입력 버튼 우측 '다운로드' 버튼 추가 - GET /malaysia/movements/export: 해당 일자/종류(IN/OUT) 낱개 합계를 엑셀(A=사방넷코드, B=수량, C=이름)로 스트리밍 - db.daily_movement_totals(): 일자/종류별 낱개 합계 집계 - itemcode.sabangnet_code_map(): item_code → 사방넷 코드 매핑 - i18n 사전 '입력'/'다운로드' 추가, malaysia.js 캐시 버전 bump Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -304,6 +304,31 @@ class MalaysiaStockStore:
|
||||
).fetchall()
|
||||
return [self._serialize(r) for r in rows]
|
||||
|
||||
def daily_movement_totals(
|
||||
self, *, warehouse_code: str, movement_date: str, movement_type: str
|
||||
) -> dict[str, int]:
|
||||
"""특정 일자/종류의 낱개 아이템별 합계 수량.
|
||||
|
||||
세트 OUT 은 생성 시 이미 구성품 OUT 으로 분해 저장되므로 그대로 합산된다.
|
||||
반환: { item_code: 합계수량 }
|
||||
"""
|
||||
if movement_type not in store.MOVEMENT_TYPES:
|
||||
raise ValueError(f"허용되지 않는 이동 종류: {movement_type}")
|
||||
with self._pool.connection() as conn:
|
||||
rows = conn.execute(
|
||||
"""
|
||||
SELECT item_code, SUM(qty) AS qty
|
||||
FROM stock_movement
|
||||
WHERE warehouse_code = %s
|
||||
AND movement_date = %s
|
||||
AND movement_type = %s
|
||||
GROUP BY item_code
|
||||
ORDER BY item_code
|
||||
""",
|
||||
(warehouse_code, movement_date, movement_type),
|
||||
).fetchall()
|
||||
return {r["item_code"]: int(r["qty"] or 0) for r in rows}
|
||||
|
||||
def current_stock(self, *, warehouse_code: str) -> dict[str, int]:
|
||||
"""창고별 현재고(낱개 아이템 기준).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user