f137f2a6a6
- 신규 모듈 app/modules/malaysia (prefix /malaysia, 권한키 malaysia) - malaysia_stock_db: warehouses/malaysia_items/set_bom/stock_movement/ daily_stocktake/daily_stocktake_line (멱등 init SQL) - 낱개(MT/MX/MZ) 입출고·조정 movement, 세트(MY) BOM 관리, 세트 출고 BOM 분해 - 일일 재고조사: 세트→낱개 자동 분해(direct+from_set=total), 확정 시 차이만 STOCKTAKE - prefix 검증 이중화(DB CHECK + store.py 순수함수), MD- 전면 제외 - 상품명은 itemcode_db 읽기 전용 재사용(중복 마스터 없음) - 화면 4종 + JSON API, 순수로직 테스트 14건, README/docs 갱신 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
70 lines
3.2 KiB
HTML
70 lines
3.2 KiB
HTML
{% extends "erp_base.html" %}
|
|
|
|
{% block content %}
|
|
<section class="mys">
|
|
{% set active_tab = 'sets' %}
|
|
{% include "malaysia/_nav.html" %}
|
|
|
|
<div style="display:grid;grid-template-columns:340px 1fr;gap:16px;align-items:start;">
|
|
|
|
<!-- 구성품 추가 -->
|
|
<div class="erp-card">
|
|
<div class="cpg-card-head"><h2>세트 구성 추가/수정</h2></div>
|
|
<span class="erp-muted">같은 세트+구성품은 덮어씁니다.</span>
|
|
<form method="post" action="/malaysia/sets/bom" style="margin-top:10px;display:flex;flex-direction:column;gap:8px;">
|
|
<label class="erp-field"><span>세트 (MY-)</span>
|
|
<select class="erp-select" name="set_code" required>
|
|
<option value="">— 선택 —</option>
|
|
{% for it in set_items %}
|
|
<option value="{{ it.item_code }}">{{ it.item_code }} · {{ it.item_name }}</option>
|
|
{% endfor %}
|
|
</select></label>
|
|
<label class="erp-field"><span>구성품 (MT-/MX-/MZ-)</span>
|
|
<select class="erp-select" name="component_code" required>
|
|
<option value="">— 선택 —</option>
|
|
{% for it in individual_items %}
|
|
<option value="{{ it.item_code }}">{{ it.item_code }} · {{ it.item_name }}</option>
|
|
{% endfor %}
|
|
</select></label>
|
|
<label class="erp-field"><span>구성 수량</span>
|
|
<input class="erp-input" type="number" name="component_qty" min="1" required /></label>
|
|
<div class="erp-page-actions"><button type="submit" class="erp-btn erp-btn-primary">저장</button></div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- 세트별 구성 목록 -->
|
|
<div class="erp-card">
|
|
<div class="cpg-card-head"><h2>세트 구성표 (set_bom)</h2></div>
|
|
{% for it in set_items %}
|
|
<div style="margin-bottom:18px;">
|
|
<h3 style="margin:6px 0;">{{ it.item_code }} · {{ it.item_name }}</h3>
|
|
<div class="erp-table-wrap">
|
|
<table class="erp-table">
|
|
<thead><tr><th>Component</th><th>Name</th><th style="text-align:right">Qty</th><th>Active</th><th></th></tr></thead>
|
|
<tbody>
|
|
{% for b in by_set.get(it.item_code, []) %}
|
|
<tr>
|
|
<td>{{ b.component_code }}</td>
|
|
<td>{{ names.get(b.component_code, '—') }}</td>
|
|
<td style="text-align:right">{{ b.component_qty }}</td>
|
|
<td>{% if b.active %}<span class="erp-badge erp-badge-success">활성</span>{% else %}<span class="erp-badge erp-badge-neutral">비활성</span>{% endif %}</td>
|
|
<td>
|
|
<form method="post" action="/malaysia/sets/bom/{{ b.id }}/delete" onsubmit="return confirm('이 구성품을 삭제합니다. 계속?');">
|
|
<button type="submit" class="erp-btn erp-btn-danger">삭제</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% if not by_set.get(it.item_code) %}
|
|
<tr><td colspan="5" class="erp-muted">구성품이 없습니다. (재고조사에 입력 시 경고)</td></tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{% endblock %}
|