Migrate remaining legacy operator workflows
This commit is contained in:
@@ -134,6 +134,8 @@
|
||||
mode: null,
|
||||
manualLocked: false,
|
||||
available: null,
|
||||
unavailableCode: "",
|
||||
unavailableMessage: "",
|
||||
quarantined: false,
|
||||
quarantineMessage: "",
|
||||
audience: "INDIVIDUAL",
|
||||
@@ -150,6 +152,7 @@
|
||||
searchMessage: "",
|
||||
pending: {
|
||||
status: null,
|
||||
legacyImport: null,
|
||||
netRead: null,
|
||||
netSave: null,
|
||||
viRead: null,
|
||||
@@ -167,7 +170,15 @@
|
||||
}
|
||||
|
||||
function canMutate() {
|
||||
return state.available === true && !state.pending.status && !locked() && !state.quarantined;
|
||||
return state.available === true && !state.pending.status && !state.pending.legacyImport &&
|
||||
!locked() && !state.quarantined;
|
||||
}
|
||||
|
||||
function hasPendingManualDataOperation() {
|
||||
return Boolean(
|
||||
state.pending.status || state.pending.legacyImport ||
|
||||
state.pending.netRead || state.pending.netSave ||
|
||||
state.pending.viRead || state.pending.viSave);
|
||||
}
|
||||
|
||||
function notify(message, kind = "info") {
|
||||
@@ -197,6 +208,29 @@
|
||||
send(workflow.createStatusRequest(requestId));
|
||||
}
|
||||
|
||||
function importLegacyManualData() {
|
||||
if (!canMutate() || hasPendingManualDataOperation()) return false;
|
||||
const confirmation =
|
||||
"원본 프로젝트의 개인.dat, 외국인.dat, 기관.dat, VI발동.dat를 " +
|
||||
"앱 전용 폴더로 한 번만 가져옵니다. 기존 대상 파일이 하나라도 있으면 " +
|
||||
"아무것도 덮어쓰지 않고 중단합니다. 계속하시겠습니까?";
|
||||
let confirmed = false;
|
||||
try {
|
||||
confirmed = root && typeof root.confirm === "function" && root.confirm(confirmation) === true;
|
||||
} catch {
|
||||
confirmed = false;
|
||||
}
|
||||
if (!confirmed) return false;
|
||||
|
||||
const request = workflow.createLegacyImportRequest(nextId());
|
||||
state.pending.legacyImport = { requestId: request.payload.requestId };
|
||||
state.netVerified = null;
|
||||
state.viVerified = null;
|
||||
send(request);
|
||||
render();
|
||||
return true;
|
||||
}
|
||||
|
||||
function requestNetRead(audience, verification = null) {
|
||||
state.netVerified = null;
|
||||
const requestId = nextId();
|
||||
@@ -281,7 +315,7 @@
|
||||
const entry = workflow.createNetSellPlaylistEntry(state.audience, {
|
||||
id: nextId(),
|
||||
fadeDuration: DEFAULT_FADE_DURATION
|
||||
});
|
||||
}, verified.freshRead);
|
||||
appendPlaylistEntry(entry);
|
||||
notify("수동 순매도 컷을 playlist에 추가했습니다.", "success");
|
||||
log(`수동 순매도 컷 추가 · ${state.audience}`);
|
||||
@@ -381,7 +415,7 @@
|
||||
const entry = workflow.createViPlaylistEntry(state.viItems, state.viVersion, {
|
||||
id: nextId(),
|
||||
fadeDuration: DEFAULT_FADE_DURATION
|
||||
});
|
||||
}, verified.freshRead);
|
||||
appendPlaylistEntry(entry);
|
||||
notify("VI 발동 컷을 playlist에 추가했습니다.", "success");
|
||||
log(`VI 발동 컷 추가 · ${state.viItems.length}종목 · ${entry.pageCount}페이지`);
|
||||
@@ -399,6 +433,8 @@
|
||||
if (!normalized) return false;
|
||||
state.pending.status = null;
|
||||
state.available = normalized.available;
|
||||
state.unavailableCode = normalized.available ? "" : normalized.code;
|
||||
state.unavailableMessage = normalized.available ? "" : (normalized.message || "");
|
||||
if (normalized.writeQuarantined) {
|
||||
state.quarantined = true;
|
||||
state.quarantineMessage = normalized.message || "수동 저장 결과를 확인할 수 없습니다.";
|
||||
@@ -407,6 +443,24 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLegacyImport(payload) {
|
||||
const pending = state.pending.legacyImport;
|
||||
if (!pending) return false;
|
||||
const normalized = workflow.normalizeLegacyImportResponse(payload, pending.requestId);
|
||||
if (!normalized) return false;
|
||||
state.pending.legacyImport = null;
|
||||
state.netVerified = null;
|
||||
state.viVerified = null;
|
||||
notify(
|
||||
`원본 수동 데이터를 가져왔습니다. 순매도 ${normalized.netSellRowCount}행 · VI ${normalized.viItemCount}종목`,
|
||||
"success");
|
||||
log(`원본 수동 데이터 가져오기 완료 · marker v${normalized.markerVersion}`);
|
||||
if (state.mode === "net") requestNetRead(state.audience);
|
||||
if (state.mode === "vi") requestViRead();
|
||||
render();
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleNetData(payload) {
|
||||
const pending = state.pending.netRead;
|
||||
if (!pending) return false;
|
||||
@@ -420,7 +474,8 @@
|
||||
rowsEqual(pending.verification.rows, normalized.rows)) {
|
||||
state.netVerified = {
|
||||
audience: state.audience,
|
||||
rows: copyRows(normalized.rows)
|
||||
rows: copyRows(normalized.rows),
|
||||
freshRead: normalized
|
||||
};
|
||||
notify("저장 파일 재조회가 입력과 일치합니다.", "success");
|
||||
} else {
|
||||
@@ -465,7 +520,8 @@
|
||||
} else {
|
||||
state.viVerified = {
|
||||
version: normalized.version,
|
||||
items: copyItems(normalized.items)
|
||||
items: copyItems(normalized.items),
|
||||
freshRead: normalized
|
||||
};
|
||||
if (verification) {
|
||||
notify(
|
||||
@@ -501,6 +557,7 @@
|
||||
|
||||
const pendingOperations = Object.freeze({
|
||||
status: "status",
|
||||
legacyImport: "import-legacy-manual-data",
|
||||
netRead: "read-net-sell",
|
||||
netSave: "save-net-sell",
|
||||
viRead: "read-vi",
|
||||
@@ -514,7 +571,11 @@
|
||||
const normalized = workflow.normalizeError(payload, pending.requestId);
|
||||
if (!normalized || normalized.operation !== operation) return false;
|
||||
state.pending[key] = null;
|
||||
if (key === "status") state.available = false;
|
||||
if (key === "status") {
|
||||
state.available = false;
|
||||
state.unavailableCode = normalized.code;
|
||||
state.unavailableMessage = normalized.message;
|
||||
}
|
||||
if (key === "viSave" && normalized.code === "STALE_DATA") {
|
||||
state.viBaseVersion = null;
|
||||
state.viVersion = null;
|
||||
@@ -566,6 +627,7 @@
|
||||
function handleMessage(type, payload) {
|
||||
switch (type) {
|
||||
case workflow.bridgeContract.statusResultType: return handleStatus(payload);
|
||||
case workflow.bridgeContract.legacyImportResultType: return handleLegacyImport(payload);
|
||||
case workflow.bridgeContract.netSellDataType: return handleNetData(payload);
|
||||
case workflow.bridgeContract.netSellSaveResultType: return handleNetSave(payload);
|
||||
case workflow.bridgeContract.viDataType: return handleViData(payload);
|
||||
@@ -603,7 +665,12 @@
|
||||
state.open = false;
|
||||
render();
|
||||
}, { className: "manual-lists-close" });
|
||||
header.append(title, close);
|
||||
const legacyImport = button("원본 데이터 가져오기", importLegacyManualData, {
|
||||
className: "manual-lists-button",
|
||||
disabled: !canMutate() || hasPendingManualDataOperation(),
|
||||
title: "원본 프로젝트의 FSell/VI 파일을 앱 전용 폴더로 한 번만 가져옵니다."
|
||||
});
|
||||
header.append(title, legacyImport, close);
|
||||
panel.append(header);
|
||||
}
|
||||
|
||||
@@ -624,7 +691,7 @@
|
||||
panel.append(element(
|
||||
"div",
|
||||
"manual-lists-banner manual-lists-banner-danger",
|
||||
"수동 데이터 저장소를 사용할 수 없습니다."));
|
||||
state.unavailableMessage || "수동 데이터 저장소를 사용할 수 없습니다."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,6 +873,8 @@
|
||||
mode: state.mode,
|
||||
locked: locked(),
|
||||
available: state.available,
|
||||
unavailableCode: state.unavailableCode,
|
||||
unavailableMessage: state.unavailableMessage,
|
||||
quarantined: state.quarantined,
|
||||
audience: state.audience,
|
||||
netRows: Object.freeze(copyRows(state.netRows)),
|
||||
@@ -896,6 +965,7 @@
|
||||
clearViItems,
|
||||
saveVi,
|
||||
addViCut,
|
||||
importLegacyManualData,
|
||||
requestViRead: () => requestViRead(),
|
||||
close: () => {
|
||||
state.open = false;
|
||||
|
||||
Reference in New Issue
Block a user