Files
dbx-main/app/static/malaysia.js
T
king 1e0e69fcbe feat(malaysia): 창고 랙 보기 페이지
최근(취소 제외) 재고조사의 랙 입력을 칸별로 한눈에 보는 읽기전용 메뉴.
각 칸에 상품명·박스수×입수량=총개수, 칸 합계(∑) 표시.

- nav: '창고 랙 보기' 탭 추가(active_tab='rack')
- router: GET /malaysia/rack — latest_stocktake → list_rack_entries 칸별 그룹
- 템플릿 rack_view.html — Side A/B 세로 적층, 칸별 아이템 목록
- i18n 키 추가(Rack View 등)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 16:48:07 +09:00

172 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 말레이시아 재고관리 — 화면 한글/영문 실시간 토글.
*
* - UI 고정 문구: 아래 KO_EN 사전으로 치환(요소 텍스트 = 한글 키).
* 대상 셀렉터는 UI 크롬(제목/헤더/버튼/라벨/배지/옵션/안내문)으로 한정 →
* 데이터 셀(상품코드/수량)은 건드리지 않음.
* - 상품명: 서버가 data-ko / data-en 을 함께 렌더 → 언어에 맞게 textContent 교체.
* - 선택값은 localStorage('mys_lang') 에 저장, 모든 화면 공통 적용.
*/
(function () {
"use strict";
var KO_EN = {
// 사이드바 메뉴 / 페이지 제목
"말레이시아 재고관리": "Malaysia Stock",
"입고/출고/조정 일괄 등록": "IN/OUT/ADJUST bulk",
// 탭 / 공통
"재고 현황": "Stock Status",
"입출고": "In / Out",
"일일 재고조사": "Daily Stocktake",
"창고 랙 보기": "Rack View",
"기준 재고조사": "Based on stocktake",
"표시할 재고조사가 없습니다.": "No stocktake to display.",
"박스": "box",
"창고": "Warehouse",
"날짜": "Date",
"메모": "Memo",
"상태": "Status",
// 재고현황
"전산 재고 현황 — 낱개 기준": "System Stock — by Single",
"현재고 = 입고 − 출고 + 조정 + 재고조사반영 (콤보는 낱개로 분해 반영됨)":
"Current = IN OUT + ADJUST + Stocktake (combos exploded to singles)",
"전산재고": "System Qty",
"조사수량": "Stocktake Qty",
"차이": "Diff",
"콤보 재고 (세트 단위)": "Combo Stock (by set)",
"재고조사 입력 없음": "No stocktake input",
"표시할 재고가 없습니다.": "No stock to display.",
"콤보 재고 입력이 없습니다.": "No combo stock input.",
"위험 구역 (슈퍼관리자)": "Danger Zone (Super Admin)",
"재고 초기화": "Reset Stock",
// 입출고
"등록 옵션": "Options",
"이동 종류 (낱개)": "Type (single)",
"IN (입고)": "IN (In)",
"OUT (출고)": "OUT (Out)",
"ADJUST (조정 ±)": "ADJUST (±)",
"입력": "Input",
"다운로드": "Download",
"낱개 상품": "Single Products",
"콤보 상품": "Combo Products",
"이동 이력": "Movement History",
"전체": "All",
"날짜해제": "Clear date",
"이동 이력이 없습니다.": "No movements.",
// 재고조사 목록
"재고조사 생성": "New Stocktake",
"조사 날짜": "Date",
"생성": "Create",
"생성 후 상세에서 낱개/세트 수량을 입력하고 확정하세요.":
"After creating, enter single/set qty in detail and finalize.",
"조사 목록": "Stocktake List",
"열기": "Open",
"삭제": "Delete",
"재고조사가 없습니다.": "No stocktakes.",
"확정": "Final",
"취소": "Cancel",
"작성중": "Draft",
// 재고조사 상세
"재고조사": "Stocktake",
"◀◀ 조사 목록": "◀◀ List",
"확정시각": "Finalized at",
"입력 저장": "Save",
"확정 (전산 반영)": "Finalize (apply)",
"삭제 (슈퍼관리자)": "Delete (super)",
"랙 입력 (박스 단위)": "Rack Input (by box)",
"랙 칸에 아이템·입수량(박스당 개수)·박스 수를 입력하면 낱개/콤보 수량이 자동 집계됩니다. 한 칸에 여러 아이템은 + 로 추가하세요.":
"Enter item · units-per-box · box count in each rack cell; single/combo qty is auto-summed. Use + to add more items in one cell.",
"최종 계산 (낱개 기준)": "Final Calc (by single)",
"total_qty = direct_qty(낱개 직접) + from_set_qty(콤보 분해)":
"total_qty = direct_qty (single) + from_set_qty (combo)",
"입력된 수량이 없습니다.": "No quantities entered.",
// 표 헤더(한글만)
"이동일": "Date",
};
var EN_KO = {};
Object.keys(KO_EN).forEach(function (k) { EN_KO[KO_EN[k]] = k; });
// 부분치환용 키 — 긴 키부터(부분 매칭 충돌 방지)
var RICH_KEYS = Object.keys(KO_EN).sort(function (a, b) { return b.length - a.length; });
// 헤더/사이드바처럼 .mys 밖이면서 KO 문구가 다른 텍스트와 섞인 요소.
// 사이드바는 현재 활성(말레이시아) 항목만 번역 → 다른 메뉴는 그대로 유지.
var RICH_SEL = [
".erp-topbar-title h1",
".erp-topbar-title p",
".erp-sidebar-item.is-active .erp-sidebar-label",
].join(",");
function applyRich(lang) {
document.querySelectorAll(RICH_SEL).forEach(function (el) {
if (el.getAttribute("data-o") === null) {
el.setAttribute("data-o", (el.textContent || "").trim());
}
var ko = el.getAttribute("data-o");
if (lang !== "en") { el.textContent = ko; return; }
var s = ko;
RICH_KEYS.forEach(function (k) {
if (s.indexOf(k) !== -1) s = s.split(k).join(KO_EN[k]);
});
el.textContent = s;
});
}
var SEL = [
".mys h1", ".mys h2", ".mys h3",
".mys th",
".mys label > span",
".mys button",
".mys a.erp-btn",
".mys .erp-muted",
".mys option",
".mys .erp-badge",
".mys .i18n",
].join(",");
function applyLang(lang) {
// 1) 상품명(한/영 동시 보유)
document.querySelectorAll(".mys [data-ko][data-en]").forEach(function (el) {
el.textContent = (lang === "en") ? el.getAttribute("data-en")
: el.getAttribute("data-ko");
});
// 2) UI 고정 문구
document.querySelectorAll(SEL).forEach(function (el) {
// 자식 요소가 있는 컨테이너는 건너뜀(.i18n 로 명시한 경우만 허용)
if (el.children.length && !el.classList.contains("i18n")) return;
if (el.hasAttribute("data-ko") && el.hasAttribute("data-en")) return; // 이미 처리됨
if (el.getAttribute("data-o") === null) {
el.setAttribute("data-o", (el.textContent || "").trim());
}
var ko = el.getAttribute("data-o");
if (lang === "en") {
if (KO_EN[ko] !== undefined) el.textContent = KO_EN[ko];
} else {
el.textContent = ko;
}
});
// 3) 헤더/사이드바(부분 치환)
applyRich(lang);
// 4) 토글 버튼 라벨
var btn = document.getElementById("mys-lang-toggle");
if (btn) btn.textContent = (lang === "en") ? "한글" : "ENG";
document.documentElement.setAttribute("data-mys-lang", lang);
}
function current() {
return localStorage.getItem("mys_lang") === "en" ? "en" : "ko";
}
function toggle() {
var next = current() === "en" ? "ko" : "en";
localStorage.setItem("mys_lang", next);
applyLang(next);
}
document.addEventListener("DOMContentLoaded", function () {
var btn = document.getElementById("mys-lang-toggle");
if (btn) btn.addEventListener("click", toggle);
applyLang(current());
});
})();