feat(malaysia): 이동 이력에 낱개/콤보 분리 표시
- set_movement(콤보 출고 원장)을 이동이력에 병합, 구분 컬럼(낱개/콤보) 추가 - db.list_set_movements (동일 필터: 창고/종류/날짜) - 콤보 줄은 set_code 를 Item 으로 표시 → 콤보 몇 개 나갔는지 확인 가능 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -327,6 +327,40 @@ class MalaysiaStockStore:
|
|||||||
).fetchall()
|
).fetchall()
|
||||||
return [self._serialize(r) for r in rows]
|
return [self._serialize(r) for r in rows]
|
||||||
|
|
||||||
|
def list_set_movements(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
warehouse_code: str | None = None,
|
||||||
|
movement_type: str | None = None,
|
||||||
|
date_from: str | None = None,
|
||||||
|
date_to: str | None = None,
|
||||||
|
limit: int = 500,
|
||||||
|
) -> list[dict[str, Any]]:
|
||||||
|
"""콤보(세트) 출고 원장(set_movement) 목록. 이동이력 콤보 줄 표시용."""
|
||||||
|
clauses: list[str] = []
|
||||||
|
params: list[Any] = []
|
||||||
|
if warehouse_code:
|
||||||
|
clauses.append("warehouse_code = %s")
|
||||||
|
params.append(warehouse_code)
|
||||||
|
if movement_type in store.MOVEMENT_TYPES:
|
||||||
|
clauses.append("movement_type = %s")
|
||||||
|
params.append(movement_type)
|
||||||
|
if date_from:
|
||||||
|
clauses.append("movement_date >= %s")
|
||||||
|
params.append(date_from)
|
||||||
|
if date_to:
|
||||||
|
clauses.append("movement_date <= %s")
|
||||||
|
params.append(date_to)
|
||||||
|
where = ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
||||||
|
params.append(int(limit))
|
||||||
|
with self._pool.connection() as conn:
|
||||||
|
rows = conn.execute(
|
||||||
|
f"SELECT * FROM set_movement {where} "
|
||||||
|
"ORDER BY movement_date DESC, id DESC LIMIT %s",
|
||||||
|
params,
|
||||||
|
).fetchall()
|
||||||
|
return [self._serialize(r) for r in rows]
|
||||||
|
|
||||||
def daily_movement_totals(
|
def daily_movement_totals(
|
||||||
self, *, warehouse_code: str, movement_date: str, movement_type: str
|
self, *, warehouse_code: str, movement_date: str, movement_type: str
|
||||||
) -> dict[str, int]:
|
) -> dict[str, int]:
|
||||||
|
|||||||
@@ -268,12 +268,26 @@ async def movements_page(request: Request) -> HTMLResponse:
|
|||||||
wh = _selected_wh(request, st)
|
wh = _selected_wh(request, st)
|
||||||
mtype = (request.query_params.get("type") or "").strip().upper()
|
mtype = (request.query_params.get("type") or "").strip().upper()
|
||||||
fdate = (request.query_params.get("date") or "").strip()
|
fdate = (request.query_params.get("date") or "").strip()
|
||||||
movements = st.list_movements(
|
mt = mtype if mtype in store.MOVEMENT_TYPES else None
|
||||||
warehouse_code=wh,
|
singles = st.list_movements(
|
||||||
movement_type=mtype if mtype in store.MOVEMENT_TYPES else None,
|
warehouse_code=wh, movement_type=mt,
|
||||||
date_from=fdate or None,
|
date_from=fdate or None, date_to=fdate or None, limit=300,
|
||||||
date_to=fdate or None,
|
)
|
||||||
limit=300,
|
for m in singles:
|
||||||
|
m["kind"] = "individual"
|
||||||
|
# 콤보(세트) 출고 원장도 함께 보여준다(낱개/콤보 분리 표시).
|
||||||
|
combos = st.list_set_movements(
|
||||||
|
warehouse_code=wh, movement_type=mt,
|
||||||
|
date_from=fdate or None, date_to=fdate or None, limit=300,
|
||||||
|
)
|
||||||
|
for m in combos:
|
||||||
|
m["kind"] = "set"
|
||||||
|
m["item_code"] = m.get("set_code", "")
|
||||||
|
# 날짜(그다음 id) 내림차순 병합.
|
||||||
|
movements = sorted(
|
||||||
|
singles + combos,
|
||||||
|
key=lambda m: (str(m.get("movement_date") or ""), int(m.get("id") or 0)),
|
||||||
|
reverse=True,
|
||||||
)
|
)
|
||||||
for m in movements:
|
for m in movements:
|
||||||
m["date_label"] = _date_label(m.get("movement_date"))
|
m["date_label"] = _date_label(m.get("movement_date"))
|
||||||
|
|||||||
@@ -144,11 +144,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="erp-table-wrap">
|
<div class="erp-table-wrap">
|
||||||
<table class="erp-table">
|
<table class="erp-table">
|
||||||
<thead><tr><th>Date</th><th>Type</th><th>Item</th><th style="text-align:right">Qty</th><th>Memo</th><th>By</th></tr></thead>
|
<thead><tr><th>Date</th><th>구분</th><th>Type</th><th>Item</th><th style="text-align:right">Qty</th><th>Memo</th><th>By</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for m in movements %}
|
{% for m in movements %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ m.date_label }}</td>
|
<td>{{ m.date_label }}</td>
|
||||||
|
<td>
|
||||||
|
{% if m.kind == 'set' %}
|
||||||
|
<span class="erp-badge" style="background:#fef3c7;color:#92400e;">콤보</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="erp-badge" style="background:#e0e7ff;color:#3730a3;">낱개</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
<td>{{ m.movement_type }}</td>
|
<td>{{ m.movement_type }}</td>
|
||||||
<td>{{ m.item_code }}</td>
|
<td>{{ m.item_code }}</td>
|
||||||
<td style="text-align:right">{{ m.qty }}</td>
|
<td style="text-align:right">{{ m.qty }}</td>
|
||||||
@@ -157,7 +164,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if not movements %}
|
{% if not movements %}
|
||||||
<tr><td colspan="6" class="erp-muted">이동 이력이 없습니다.</td></tr>
|
<tr><td colspan="7" class="erp-muted">이동 이력이 없습니다.</td></tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
Reference in New Issue
Block a user