Files
dbx-main/app/modules/malaysia/templates/malaysia/movements.html
T
king 2ab38c7dbd feat(malaysia): 이동 이력에 낱개/콤보 분리 표시
- set_movement(콤보 출고 원장)을 이동이력에 병합, 구분 컬럼(낱개/콤보) 추가
- db.list_set_movements (동일 필터: 창고/종류/날짜)
- 콤보 줄은 set_code 를 Item 으로 표시 → 콤보 몇 개 나갔는지 확인 가능

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 18:14:45 +09:00

175 lines
8.1 KiB
HTML

{% extends "erp_base.html" %}
{% block head_extra %}
<style>
.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 th.ccol, .mys-compact td.ccol { white-space:nowrap; width:88px; }
.mys-compact .qcol { width:110px; }
.mys-compact .qcol .erp-input { width:100px; }
.mys-compact .optfields .erp-field { width:100%; }
.mys-compact .optfields .erp-input,
.mys-compact .optfields .erp-select { width:100%; box-sizing:border-box; }
</style>
{% endblock %}
{% block content %}
<section class="mys mys-compact">
{% include "malaysia/_i18n.html" %}
{% set active_tab = 'move' %}
{% include "malaysia/_nav.html" %}
<!-- 3분할: 좌(옵션) · 중(낱개) · 우(세트), 버튼 하나 -->
<form method="post" action="/malaysia/movements/apply" onsubmit="return mysCheckComboIn(this)">
<input type="hidden" name="warehouse_code" value="{{ selected_wh }}" />
<div class="mys-grid" style="display:grid;grid-template-columns:280px 1fr 1fr;gap:16px;align-items:start;">
<!-- 좌: 종류 / 날짜 / 메모 -->
<div class="erp-card">
<div class="cpg-card-head"><h2>등록 옵션</h2></div>
<div class="optfields" style="display:flex;flex-direction:column;gap:10px;margin-top:8px;">
<label class="erp-field"><span>이동 종류 (낱개)</span>
<select class="erp-select" name="movement_type" required>
<option value="IN">IN (입고)</option>
<option value="OUT">OUT (출고)</option>
<option value="ADJUST">ADJUST (조정 ±)</option>
</select></label>
<label class="erp-field"><span>날짜</span>
<input class="erp-input" type="date" name="movement_date" value="{{ today }}" required /></label>
<label class="erp-field"><span>메모</span>
<input class="erp-input" type="text" name="memo" /></label>
</div>
<div class="erp-page-actions" style="margin-top:12px;display:flex;gap:8px;">
<button type="submit" class="erp-btn erp-btn-primary">입력</button>
<button type="button" class="erp-btn erp-btn-outline" onclick="mysDownloadMovements(this)">다운로드</button>
</div>
</div>
<!-- 중: 낱개 -->
<div class="erp-card">
<div class="cpg-card-head"><h2>낱개 상품</h2></div>
<div class="erp-table-wrap" style="margin-top:8px;">
<table class="erp-table">
<thead><tr><th class="ccol">Code</th><th>Name</th><th class="qcol">Qty</th></tr></thead>
<tbody>
{% for it in individual_items %}
<tr>
<td class="ccol">{{ it.item_code }}</td>
<td class="nm" data-en="{{ it.item_name }}" data-ko="{{ ko_names.get(it.item_code, it.item_name) }}">{{ it.item_name }}</td>
<td class="qcol"><input class="erp-input" type="number" name="qty_{{ it.item_code }}" placeholder="—" /></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- 우: 세트 -->
<div class="erp-card">
<div class="cpg-card-head"><h2>콤보 상품</h2></div>
<div class="erp-table-wrap" style="margin-top:8px;">
<table class="erp-table">
<thead><tr><th class="ccol">Set Code</th><th>Set Name</th><th class="qcol">Qty</th></tr></thead>
<tbody>
{% for it in set_items %}
<tr>
<td class="ccol">{{ it.item_code }}</td>
<td class="nm" data-en="{{ it.item_name }}" data-ko="{{ ko_names.get(it.item_code, it.item_name) }}">{{ it.item_name }}</td>
<td class="qcol"><input class="erp-input" type="number" min="0" name="qty_{{ it.item_code }}" placeholder="—" /></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</form>
<script>
// 콤보(MY-)는 입고 불가 — IN 선택 + 콤보 수량 입력 시 안내 후 제출 차단
function mysCheckComboIn(form) {
var type = form.querySelector('[name=movement_type]').value;
if (type !== 'IN') return true;
var keyed = [];
form.querySelectorAll('input[name^="qty_MY-"]').forEach(function (inp) {
var v = (inp.value || '').trim();
if (v !== '' && v !== '0') keyed.push(inp.name.replace('qty_', ''));
});
if (keyed.length) {
var en = localStorage.getItem('mys_lang') === 'en';
alert(en
? 'Combo products cannot be received.\nReceive them as separate single items.\n\nNot allowed: ' + keyed.join(', ')
: '콤보 상품은 입고할 수 없습니다.\n낱개로 분리해서 입고하세요.\n\n입고 불가 콤보: ' + keyed.join(', '));
return false;
}
return true;
}
function mysDownloadMovements(btn) {
var form = btn.closest('form');
var type = form.querySelector('[name=movement_type]').value;
var date = form.querySelector('[name=movement_date]').value;
var wh = form.querySelector('[name=warehouse_code]').value;
if (type !== 'IN' && type !== 'OUT') {
alert('다운로드는 IN(입고) 또는 OUT(출고)만 가능합니다.');
return;
}
if (!date) { alert('날짜를 선택하세요.'); return; }
var url = '/malaysia/movements/export?wh=' + encodeURIComponent(wh)
+ '&type=' + encodeURIComponent(type)
+ '&date=' + encodeURIComponent(date);
window.location.href = url;
}
</script>
<!-- 이동 이력 -->
<div class="erp-card" style="margin-top:16px;">
<div class="cpg-card-head" style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
<h2><span class="i18n">이동 이력</span>{% if filter_date %} · {{ filter_date }}{% endif %}</h2>
<span style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;">
<form method="get" style="display:flex;gap:6px;align-items:center;">
<input type="hidden" name="wh" value="{{ selected_wh }}" />
{% if filter_type %}<input type="hidden" name="type" value="{{ filter_type }}" />{% endif %}
<input class="erp-input" type="date" name="date" value="{{ filter_date }}" onchange="this.form.submit()" />
{% if filter_date %}<a class="erp-btn erp-btn-outline" href="/malaysia/movements?wh={{ selected_wh }}{% if filter_type %}&type={{ filter_type }}{% endif %}">날짜해제</a>{% endif %}
</form>
<a class="erp-btn erp-btn-outline" href="/malaysia/movements?wh={{ selected_wh }}{% if filter_date %}&date={{ filter_date }}{% endif %}">전체</a>
{% for t in ['IN','OUT','ADJUST','STOCKTAKE'] %}
<a class="erp-btn {% if filter_type==t %}erp-btn-primary{% else %}erp-btn-outline{% endif %}" href="/malaysia/movements?wh={{ selected_wh }}&type={{ t }}{% if filter_date %}&date={{ filter_date }}{% endif %}">{{ t }}</a>
{% endfor %}
</span>
</div>
<div class="erp-table-wrap">
<table class="erp-table">
<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>
{% for m in movements %}
<tr>
<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.item_code }}</td>
<td style="text-align:right">{{ m.qty }}</td>
<td>{{ m.memo or '—' }}</td>
<td>{{ m.created_by or '—' }}</td>
</tr>
{% endfor %}
{% if not movements %}
<tr><td colspan="7" class="erp-muted">이동 이력이 없습니다.</td></tr>
{% endif %}
</tbody>
</table>
</div>
</div>
</section>
{% endblock %}