This commit is contained in:
admin
2026-01-16 09:50:21 +09:00
parent 24c04e0d29
commit d8ec60629e
18 changed files with 941 additions and 22 deletions

View File

@@ -44,7 +44,7 @@
<h2>修正仕訳入力</h2>
<label>仕訳日</label>
<input type="date" id="entryDate" />
<input type="date" id="entryDate" min="1900-01-01" max="9999-12-31" />
<label>摘要</label>
<input type="text" id="description" style="width: 60%" />
@@ -143,6 +143,12 @@
tr.querySelectorAll("input")[0].value = line.debit || "";
tr.querySelectorAll("input")[1].value = line.credit || "";
}
// 入力時に合計を自動更新
tr.querySelectorAll("input").forEach((input) => {
input.addEventListener("input", recalc);
input.addEventListener("change", recalc);
});
}
function removeRow(btn) {
@@ -197,6 +203,12 @@
if (lines.length < 2) return showError("仕訳行は2行以上必要です");
if (d !== c) return showError("借方合計と貸方合計が一致していません");
// 逆仕訳IDを親IDとして取得逆仕訳が存在する場合
const src = localStorage.getItem("editSource");
const srcData = src ? JSON.parse(src) : null;
// 【修正後】仕訳のparent_entry_idは、直前に作成された逆仕訳のID
const parentEntryId = srcData?.reversed_journal_entry_id || null;
const payload = {
entry_date: entryDate,
description: desc,
@@ -204,6 +216,7 @@
tax_paid_account_id: null,
tax_received_account_id: null,
rounding_mode: "floor",
parent_entry_id: parentEntryId,
};
try {

View File

@@ -103,6 +103,33 @@
<tbody></tbody>
</table>
<div
style="
margin-top: 10px;
padding: 10px;
background: #f9f9f9;
border: 1px solid #ddd;
display: flex;
gap: 40px;
font-weight: bold;
"
>
<div>
<label>借方合計:</label>
<span id="totalDebit" style="color: #0066cc; font-size: 16px">0</span>
</div>
<div>
<label>貸方合計:</label>
<span id="totalCredit" style="color: #cc0000; font-size: 16px">0</span>
</div>
<div
id="balanceStatus"
style="margin-left: auto; padding: 4px 12px; border-radius: 4px"
></div>
</div>
<div style="margin-top: 10px; display: flex; gap: 8px">
<button onclick="addRow()"> 行追加</button>
<button onclick="submitJournal()">登録</button>
@@ -199,6 +226,7 @@
<th>摘要</th>
<th>借方合計</th>
<th>貸方合計</th>
<th>税率</th>
<th>操作</th>
</tr>
</thead>
@@ -301,6 +329,29 @@
// 摘要履歴を読み込み
loadDescriptionHistory();
// 各フィールドの変更時に合計を更新
document
.getElementById("entryDate")
.addEventListener("change", updateTotals);
document
.getElementById("description")
.addEventListener("input", updateTotals);
document
.getElementById("taxPaidSelect")
.addEventListener("change", updateTotals);
document
.getElementById("taxReceivedSelect")
.addEventListener("change", updateTotals);
document
.getElementById("roundingMode")
.addEventListener("change", () => {
// 端数処理変更時は全ての税行を再計算
const rows = document.querySelectorAll(
"#linesTable tbody tr:not(.tax-row)"
);
rows.forEach((row) => handleTax(row));
});
}
init();
@@ -451,8 +502,16 @@
// 普通行:绑定事件
if (!isTaxRow) {
const recalc = () => handleTax(tr);
tr.querySelector(".debit").addEventListener("input", recalc);
tr.querySelector(".credit").addEventListener("input", recalc);
const debitInput = tr.querySelector(".debit");
const creditInput = tr.querySelector(".credit");
debitInput.addEventListener("input", recalc);
creditInput.addEventListener("input", recalc);
// blurフォーカス離脱時に合計を更新
debitInput.addEventListener("blur", updateTotals);
creditInput.addEventListener("blur", updateTotals);
tr.querySelector(".taxType").addEventListener("change", recalc);
tr.querySelector(".taxDirection").addEventListener("change", recalc);
}
@@ -473,6 +532,49 @@
const row = btn.closest("tr");
removeTaxRowsOf(row);
row.remove();
updateTotals(); // 削除後に合計を更新
}
// -----------------------------
// 借方・貸方合計を計算して表示
// -----------------------------
function updateTotals() {
let totalDebit = 0;
let totalCredit = 0;
const rows = document.querySelectorAll("#linesTable tbody tr");
rows.forEach((row) => {
const debitValue =
row.querySelector(".debit")?.value.replace(/,/g, "") || "0";
const creditValue =
row.querySelector(".credit")?.value.replace(/,/g, "") || "0";
totalDebit += Number(debitValue) || 0;
totalCredit += Number(creditValue) || 0;
});
// 表示を更新
document.getElementById("totalDebit").textContent =
totalDebit.toLocaleString();
document.getElementById("totalCredit").textContent =
totalCredit.toLocaleString();
// 貸借一致チェック
const balanceStatus = document.getElementById("balanceStatus");
if (totalDebit === totalCredit && totalDebit > 0) {
balanceStatus.textContent = "✓ 貸借一致";
balanceStatus.style.background = "#d4edda";
balanceStatus.style.color = "#155724";
} else if (totalDebit === 0 && totalCredit === 0) {
balanceStatus.textContent = "";
balanceStatus.style.background = "";
} else {
balanceStatus.textContent = `✗ 差額: ${Math.abs(
totalDebit - totalCredit
).toLocaleString()}`;
balanceStatus.style.background = "#f8d7da";
balanceStatus.style.color = "#721c24";
}
}
// -----------------------------
@@ -491,10 +593,16 @@
row.querySelector(".credit").value.replace(/,/g, "") || 0
);
if (taxType === "none" || taxDir === "none") return;
if (taxType === "none" || taxDir === "none") {
updateTotals(); // 税なしでも合計更新
return;
}
const totalAmount = debit || credit;
if (!totalAmount) return;
if (!totalAmount) {
updateTotals();
return;
}
const rate = taxType === "8" ? 0.08 : 0.1;
const roundingMode = document.getElementById("roundingMode").value;
@@ -517,7 +625,10 @@
if (taxDir === "paid") {
const taxAcc = document.getElementById("taxPaidSelect").value;
if (!taxAcc) return alert("仮払消費税等 勘定を選択してください");
if (!taxAcc) {
updateTotals();
return alert("仮払消費税等 勘定を選択してください");
}
addRow(
true,
{ accountId: taxAcc, amount: taxAmount, side: "debit" },
@@ -526,13 +637,18 @@
}
if (taxDir === "received") {
const taxAcc = document.getElementById("taxReceivedSelect").value;
if (!taxAcc) return alert("仮受消費税等 勘定を選択してください");
if (!taxAcc) {
updateTotals();
return alert("仮受消費税等 勘定を選択してください");
}
addRow(
true,
{ accountId: taxAcc, amount: taxAmount, side: "credit" },
parentId
);
}
updateTotals(); // 税行追加後に合計更新
}
// 税行は常に「直後の1行」を使う
@@ -686,6 +802,12 @@
rowSeq = 0;
addRow();
// 借方合計・貸方合計を0にリセット
document.getElementById("totalDebit").textContent = "0";
document.getElementById("totalCredit").textContent = "0";
document.getElementById("balanceStatus").textContent = "";
document.getElementById("balanceStatus").style.background = "";
// 仕訳検索を自動実行して最新の登録状況を表示
searchJournals();
} catch (error) {
@@ -911,9 +1033,12 @@
includeHistory && e.version > 1 ? ` (v${e.version})` : "";
tr.innerHTML = `
<td>${e.entry_date}</td>
<td>${e.description}${versionInfo}</td>
<td style="text-align:left">${e.description}${versionInfo}</td>
<td style="text-align:right">${e.debit_total.toLocaleString()}</td>
<td style="text-align:right">${e.credit_total.toLocaleString()}</td>
<td style="text-align:center">${
e.tax_rates ? e.tax_rates + "%" : ""
}</td>
<td>
<button onclick="viewJournal(${
e.journal_entry_id
@@ -1050,6 +1175,8 @@
}
const srcData = await srcRes.json();
// 逆仕訳IDを追加して保存【修正後】仕訳のparent_entry_idとして使用
srcData.reversed_journal_entry_id = data.reversed_journal_entry_id;
localStorage.setItem("editSource", JSON.stringify(srcData));
// 修正画面を開く

View File

@@ -138,6 +138,8 @@
}
const srcData = await srcRes.json();
// 逆仕訳IDを追加して保存【修正後】仕訳のparent_entry_idとして使用
srcData.reversed_journal_entry_id = data.reversed_journal_entry_id;
localStorage.setItem("editSource", JSON.stringify(srcData));
// 修正画面を開く

View File

@@ -99,10 +99,10 @@
<div class="search-form">
<label for="dateFrom">開始年月日:</label>
<input type="date" id="dateFrom" />
<input type="date" id="dateFrom" min="1900-01-01" max="9999-12-31" />
<label for="dateTo">終了年月日:</label>
<input type="date" id="dateTo" />
<input type="date" id="dateTo" min="1900-01-01" max="9999-12-31" />
<button id="btnSearch">検索</button>
<button id="btnFullYear" class="secondary">全年度表示</button>