Files
njts-accounting-core/FRONTEND_INTEGRATION_GUIDE.js
2026-02-20 15:47:27 +09:00

314 lines
11 KiB
JavaScript
Raw Permalink 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.
// ============================================================================
// 【前端集成指南】 - 修正版本追踪系統
// ============================================================================
/**
* 【API 變更概要】
*
* 舊 API
* - POST /journal-entries (parent_entry_id) // 創建逆仕訳
* - 複雜的逆仕訳生成邏輯
*
* 新 API
* - POST /journal-entries (original_entry_id) // 直接創建修正版本
* - GET /journal-entries/{id}/revision-history // 查看修正歷史
*/
// ============================================================================
// 【1】創建新交易無修正- 基本用法
// ============================================================================
async function createJournalEntry(entryData) {
const payload = {
entry_date: entryData.date, // "2025-01-15"
description: entryData.description, // "銷售收入"
lines: entryData.lines, // 交易明細
tax_paid_account_id: entryData.taxPaidId,
tax_received_account_id: entryData.taxReceivedId,
rounding_mode: "round"
// 注意:這裡 original_entry_id 沒有指定,表示這是新交易
};
const response = await fetch("/journal-entries", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
if (response.ok) {
const result = await response.json();
console.log("✓ 交易創建成功:", result.journal_entry_id);
return result;
} else {
alert("❌ 創建失敗");
}
}
// ============================================================================
// 【2】創建修正版本 - 關鍵變更
// ============================================================================
async function createRevisionEntry(originalEntryId, entryData) {
const payload = {
entry_date: entryData.date,
description: `【修正】${entryData.description}`, // 添加【修正】標記
lines: entryData.lines,
tax_paid_account_id: entryData.taxPaidId,
tax_received_account_id: entryData.taxReceivedId,
rounding_mode: "round",
// ✨ 新參數:指向原始交易
original_entry_id: originalEntryId
};
const response = await fetch("/journal-entries", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
if (response.ok) {
const result = await response.json();
console.log("✓ 修正版本創建成功:");
console.log(` 原始交易 ID: ${originalEntryId}`);
console.log(` 新版本 ID: ${result.journal_entry_id}`);
console.log(` 版本: ${result.revision_created ? "新版本" : "覆蓋"}`);
return result;
}
}
// ============================================================================
// 【3】查看修正歷史 - 新功能
// ============================================================================
async function viewRevisionHistory(journalId) {
const response = await fetch(`/journal-entries/${journalId}/revision-history`);
if (response.ok) {
const data = await response.json();
console.log(`修正歷史 (原始交易 ID: ${data.original_entry_id}):`);
console.log(`總版本數: ${data.total_versions}`);
data.versions.forEach(version => {
const status = version.is_latest ? "【最新】" : "【已過時】";
console.log(`
版本 ${version.revision_count}: ${status}
- 交易 ID: ${version.journal_entry_id}
- 摘要: ${version.description}
- 建立時間: ${version.created_at}
`);
});
return data;
}
}
// ============================================================================
// 【4】前端修正流程 - 完整示例
// ============================================================================
async function handleEditTransaction(originalEntryId) {
// 步驟 1: 顯示修正對話框
const originalData = await fetchJournalEntry(originalEntryId); // 現有的 API
const editedData = showEditDialog(originalData); // 用户編緬
if (!editedData) {
console.log("⚠️ 編輯已取消");
return;
}
// 步驟 2: 檢查是否有實際變更
if (areEntriesEqual(originalData, editedData)) {
console.log("⚠️ 沒有任何變更");
return;
}
// 步驟 3: 創建修正版本
const result = await createRevisionEntry(originalEntryId, editedData);
if (result && result.status === "ok") {
// 步驟 4: 更新頁面
refreshJournalList(); // 重新加載列表
alert(`✓ 交易已修正。新版本 ID: ${result.journal_entry_id}`);
// 步驟 5: 可選 - 顯示修正歷史
// await showRevisionHistory(originalEntryId);
}
}
// ============================================================================
// 【5】試算表查詢 - 前端優化
// ============================================================================
/**
* 舊做法(不需要):
* const entries = await fetchAllJournalEntries();
* const latestOnly = entries.filter(e => e.parent_entry_id === null);
*
* 新做法(推薦):
* 後端已經自動過濾, 返回的都是 is_latest = true 的交易
*/
async function fetchTrialBalance(fromDate, toDate) {
// 不需要任何客戶端過濾邏輯
// 後端已確保只返回 is_latest = true 的交易
const response = await fetch(
`/journal-entries?from_date=${fromDate}&to_date=${toDate}`,
{ method: "GET" }
);
if (response.ok) {
const entries = await response.json();
// entries 已經只包含最新版本
// 直接計算試算表
return calculateTrialBalance(entries);
}
}
// ============================================================================
// 【6】修正歷史界面 - UI 示例
// ============================================================================
function displayRevisionHistory(journalId) {
// HTML 結構
const html = `
<div class="revision-history">
<h3>修正歷史</h3>
<div class="revision-timeline" id="timeline">
<!-- 將使用 JavaScript 動態填充 -->
</div>
<button onclick="showRevisionComparison()">
對比版本
</button>
</div>
`;
// 獲取歷史數據
viewRevisionHistory(journalId).then(data => {
const timeline = document.getElementById("timeline");
data.versions.forEach(version => {
const element = document.createElement("div");
element.className = `revision-item ${version.is_latest ? "latest" : "outdated"}`;
element.innerHTML = `
<div class="revision-header">
<span class="version-number">版本 ${version.revision_count}</span>
<span class="status">
${version.is_latest ? "✓ 最新" : "過時"}
</span>
</div>
<div class="revision-details">
<p><strong>摘要:</strong> ${version.description}</p>
<p><strong>日期:</strong> ${version.entry_date}</p>
<p><strong>建立:</strong> ${new Date(version.created_at).toLocaleString()}</p>
<p><strong>操作員:</strong> ${version.created_by}</p>
</div>
`;
timeline.appendChild(element);
});
});
}
// ============================================================================
// 【7】向後兼容性 - 舊 parent_entry_id 支持
// ============================================================================
/**
* 為了向後兼容,後端仍然接受 parent_entry_id 參數
* 但將被忽略,請改用 original_entry_id
*
* 舊代碼仍然有效(會自動轉換):
*/
async function createRevisionParentMethod(parentId, data) {
// ⚠️ 不推薦 - 舊方式
return await fetch("/journal-entries", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
...data,
parent_entry_id: parentId // ← 舊參數(向後兼容)
})
});
}
// ============================================================================
// 【8】錯誤處理
// ============================================================================
async function createRevisionWithErrorHandling(originalEntryId, data) {
try {
const result = await createRevisionEntry(originalEntryId, data);
if (!result.status) {
throw new Error("API 響應格式錯誤");
}
if (result.status === "error") {
throw new Error(result.detail || "未知錯誤");
}
return result;
} catch (error) {
console.error("❌ 修正失敗:", error.message);
alert(`修正失敗: ${error.message}`);
throw error;
}
}
// ============================================================================
// 【9】測試檢查清單
// ============================================================================
/**
* 部署前請確認以下功能正常:
*
* [ ] 創建新交易 (original_entry_id = null)
* [ ] 創建修正版本 (original_entry_id ≠ null)
* [ ] 試算表只顯示最新版本
* [ ] 修正歷史端點返回完整列表
* [ ] 舊的 parent_entry_id 參數仍然可用(向後兼容)
* [ ] 修改同一交易三次,全部版本都能查詢
*/
// ============================================================================
// 【10】遷移檢查表 - 前端
// ============================================================================
const PRE_DEPLOYMENT_CHECKLIST = {
API_Changes: [
"✓ 使用 original_entry_id 創建修正版本",
"✓ 調用 GET .../revision-history 查看歷史",
"✓ 試算表查詢已包含 is_latest = true後端處理"
],
UI_Updates: [
"[ ] 修正的交易不再出現在主列表中",
"[ ] 添加"查看歷史"按鈕",
"[ ] 添加修正時間線顯示",
"[ ] 錯誤提示信息已更新"
],
Testing: [
"[ ] 單元測試已更新",
"[ ] 集成測試已完成",
"[ ] E2E 測試已通過",
"[ ] 性能測試已驗證"
],
Documentation: [
"[ ] 用户文檔已更新",
"[ ] API 文檔已更新",
"[ ] 訓練資料已準備"
]
};
// ============================================================================