diff --git a/app/modules/malaysia/db.py b/app/modules/malaysia/db.py index 5b162eb..962f997 100644 --- a/app/modules/malaysia/db.py +++ b/app/modules/malaysia/db.py @@ -360,6 +360,40 @@ class MalaysiaStockStore: out.sort(key=lambda x: x["item_code"]) return out + def latest_set_quantities(self, *, warehouse_code: str) -> dict[str, Any]: + """가장 최근(취소 제외) 재고조사에 입력된 콤보(MY-) 수량. + + 반환: {"stocktake_date": str|None, "rows": [{set_code,set_name,qty}]} + 재고현황 우측 패널용 — 세트 단위로 입력된 콤보 재고를 그대로 보여줌. + """ + with self._pool.connection() as conn: + head = conn.execute( + "SELECT id, stocktake_date FROM daily_stocktake " + "WHERE warehouse_code = %s AND status <> 'cancelled' " + "ORDER BY stocktake_date DESC, id DESC LIMIT 1", + (warehouse_code,), + ).fetchone() + if not head: + return {"stocktake_date": None, "rows": []} + lines = conn.execute( + "SELECT sku_code, qty FROM daily_stocktake_line " + "WHERE stocktake_id = %s AND sku_code LIKE 'MY-%%' " + "ORDER BY sku_code ASC", + (head["id"],), + ).fetchall() + names = self.item_name_map() + d = head["stocktake_date"] + date_str = d.isoformat() if isinstance(d, date) else str(d) + rows = [ + { + "set_code": r["sku_code"], + "set_name": names.get(r["sku_code"], r["sku_code"]), + "qty": int(r["qty"]), + } + for r in lines + ] + return {"stocktake_date": date_str, "rows": rows} + def _last_stocktake_dates(self, *, warehouse_code: str) -> dict[str, str]: """아이템별 마지막 STOCKTAKE movement 날짜.""" with self._pool.connection() as conn: diff --git a/app/modules/malaysia/router.py b/app/modules/malaysia/router.py index fd9cc08..fc4cbbd 100644 --- a/app/modules/malaysia/router.py +++ b/app/modules/malaysia/router.py @@ -143,11 +143,14 @@ async def index(request: Request) -> HTMLResponse: st, user = guard wh = _selected_wh(request, st) ctx = _base_ctx(request, user, st, wh=wh) + set_stock = st.latest_set_quantities(warehouse_code=wh) ctx.update( { "page_title": "말레이시아 재고관리", "page_subtitle": f"{wh} · 재고 현황", "rows": st.stock_status(warehouse_code=wh), + "set_rows": set_stock["rows"], + "set_stocktake_date": set_stock["stocktake_date"], } ) return render_template(request, "malaysia/index.html", ctx) diff --git a/app/modules/malaysia/templates/malaysia/index.html b/app/modules/malaysia/templates/malaysia/index.html index 08d08b9..a7a5558 100644 --- a/app/modules/malaysia/templates/malaysia/index.html +++ b/app/modules/malaysia/templates/malaysia/index.html @@ -1,34 +1,71 @@ {% extends "erp_base.html" %} +{% block head_extra %} + +{% endblock %} + {% block content %} -
+
{% set active_tab = 'status' %} {% include "malaysia/_nav.html" %} -
-
-

재고 현황 ({{ rows|length }})

- 현재고 = 입고 − 출고 + 조정 + 재고조사반영 (낱개 아이템 기준) +
+ + +
+
+

재고 현황 — 낱개 기준 ({{ rows|length }})

+ 현재고 = 입고 − 출고 + 조정 + 재고조사반영 (콤보는 낱개로 분해 반영됨) +
+
+ + + + + + {% for r in rows %} + + + + + + + {% endfor %} + {% if not rows %} + + {% endif %} + +
Item CodeProduct NameCurrent QtyLast Stocktake
{{ r.item_code }}{{ r.item_name }}{{ r.current_qty }}{{ r.last_stocktake_date or '—' }}
표시할 재고가 없습니다.
+
-
- - - - - - {% for r in rows %} - - - - - - - {% endfor %} - {% if not rows %} - - {% endif %} - -
Item CodeProduct NameCurrent QtyLast Stocktake
{{ r.item_code }}{{ r.item_name }}{{ r.current_qty }}{{ r.last_stocktake_date or '—' }}
표시할 재고가 없습니다.
+ + +
+

콤보 재고 (세트 단위)

+ + {% if set_stocktake_date %}최근 재고조사 {{ set_stocktake_date }} 기준 입력 수량{% else %}재고조사 입력 없음{% endif %} + +
+ + + + {% for s in set_rows %} + + + + + + {% endfor %} + {% if not set_rows %} + + {% endif %} + +
Set CodeSet NameQty
{{ s.set_code }}{{ s.set_name }}{{ s.qty }}
콤보 재고 입력이 없습니다.
+
diff --git a/app/modules/malaysia/templates/malaysia/movements.html b/app/modules/malaysia/templates/malaysia/movements.html index 8e09311..ec1a79c 100644 --- a/app/modules/malaysia/templates/malaysia/movements.html +++ b/app/modules/malaysia/templates/malaysia/movements.html @@ -5,6 +5,9 @@ .mys-compact .erp-table th, .mys-compact .erp-table td { padding-top:4px; padding-bottom:4px; } .mys-compact .erp-input { padding-top:4px; padding-bottom:4px; } + .mys-compact td.nm { white-space:nowrap; } + .mys-compact .qcol { width:150px; } + .mys-compact .qcol .erp-input { width:140px; } {% endblock %} @@ -44,13 +47,13 @@

낱개 상품

- + {% for it in individual_items %} - - + + {% endfor %} @@ -63,13 +66,13 @@

콤보 상품

CodeNameQty
CodeNameQty
{{ it.item_code }}{{ it.item_name }}{{ it.item_name }}
- + {% for it in set_items %} - - + + {% endfor %} diff --git a/app/modules/malaysia/templates/malaysia/stocktake_detail.html b/app/modules/malaysia/templates/malaysia/stocktake_detail.html index 1cf69af..7a2e169 100644 --- a/app/modules/malaysia/templates/malaysia/stocktake_detail.html +++ b/app/modules/malaysia/templates/malaysia/stocktake_detail.html @@ -1,61 +1,83 @@ {% extends "erp_base.html" %} +{% block head_extra %} + +{% endblock %} + {% block content %} -
+
-
-
-

재고조사 #{{ stocktake.id }} — {{ stocktake.stocktake_date }} · {{ stocktake.warehouse_code }}

- - {% if stocktake.status=='finalized' %}확정 ({{ stocktake.finalized_at }}) - {% elif stocktake.status=='cancelled' %}취소 - {% else %}작성중{% endif %} - -
- {% if missing_bom %} -

⚠ BOM 구성이 없는 세트: {{ missing_bom|join(', ') }} — itemcode_db set_components 확인 필요. 확정 불가.

- {% endif %} -
+
+
- {% if is_draft %} - - -
+
-

① 낱개 아이템

- 세트 안에 든 건 빼고, 낱개 보관분만. 빈칸=미조사, 0 입력 가능. +

재고조사 #{{ stocktake.id }}

+
+
날짜
{{ stocktake.stocktake_date }}
+
창고
{{ stocktake.warehouse_code }}
+
상태
+ {% if stocktake.status=='finalized' %}확정 + {% elif stocktake.status=='cancelled' %}취소 + {% else %}작성중{% endif %} +
+ {% if stocktake.finalized_at %}
확정시각
{{ stocktake.finalized_at }}
{% endif %} +
+ + {% if missing_bom %} +

⚠ BOM 없는 콤보: {{ missing_bom|join(', ') }}

+ {% endif %} + + {% if is_draft %} +
+ +
+ {% endif %} +
+ + +
+

낱개 상품

Set CodeSet NameQty (OUT)
Set CodeSet NameQty
{{ it.item_code }}{{ it.item_name }}{{ it.item_name }}
- + {% for it in individual_items %} - - + + {% endfor %}
CodeNameQty
CodeNameQty
{{ it.item_code }}{{ it.item_name }}{{ it.item_name }}
+ +
-

② 세트 아이템

- 미리 포장된 세트 재고. BOM(itemcode_db)으로 낱개 분해됨. +

콤보 상품

- + {% for it in set_items %} - - + + {% endfor %} @@ -63,14 +85,25 @@ -
+ + + {% if is_draft %} +
+
+ + +
+ + +
{% endif %} - +

최종 계산 (낱개 기준)

- total_qty = direct_qty(낱개 직접) + from_set_qty(세트 분해) + total_qty = direct_qty(낱개 직접) + from_set_qty(콤보 분해)
Set CodeSet NameQty
Set CodeSet NameQty
{{ it.item_code }}{{ it.item_name }}{{ it.item_name }}
@@ -91,17 +124,5 @@
Item CodeProduct NameDirectFrom SetTotal
- - {% if is_draft %} -
-
- -
-
- -
-
- {% endif %}
{% endblock %}