chore: 年度リストを昇順に変更

This commit is contained in:
admin
2026-06-07 21:58:20 +09:00
parent 91632ea5b6
commit 4a500ff5e9
25 changed files with 1531 additions and 67 deletions

View File

@@ -405,6 +405,29 @@
cursor: default;
}
/* ── 印刷ヘッダー ── */
.print-header {
display: none;
}
@media print {
.print-header {
display: block;
margin-bottom: 12px;
border-bottom: 2px solid #000;
padding-bottom: 8px;
}
.print-header .ph-company {
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
.print-header .ph-sub {
font-size: 12px;
display: flex;
gap: 24px;
}
}
/* ── 印刷スタイル ── */
@media print {
.no-print {
@@ -434,50 +457,133 @@
</style>
</head>
<body>
<!-- 印刷時のみ表示されるヘッダー -->
<div class="print-header">
<div class="ph-company" id="printCompany"></div>
<div class="ph-sub">
<span id="printBank"></span>
<span id="printDate"></span>
</div>
</div>
<div class="page-header no-print">
<h2>🏦 銀行明細照会</h2>
<div class="header-btns">
<button class="btn btn-orange" onclick="openImportModal()">
CSV取込
</button>
<button class="btn btn-blue" onclick="window.print()">印刷</button>
<button class="btn btn-blue" onclick="doPrint()">印刷</button>
<a class="btn btn-gray" href="index.html">← メニューへ戻る</a>
</div>
</div>
<!-- 印刷設定(画面のみ) -->
<div
class="search-form no-print"
style="padding: 10px 18px; background: #fff8e1; border-color: #ffe082"
>
<label style="font-weight: bold; white-space: nowrap">印刷設定:</label>
<label style="white-space: nowrap">会社名:</label>
<input
type="text"
id="printCompanyInput"
style="
width: 220px;
padding: 4px 8px;
border: 1px solid #999;
border-radius: 3px;
font-size: 13px;
"
placeholder="例:株式会社〇〇"
/>
</div>
<div id="msgBar" class="msg-bar no-print"></div>
<!-- 検索フォーム -->
<div class="search-form no-print">
<label>年:</label>
<input
type="number"
id="filterYear"
min="2000"
max="2099"
style="width: 80px"
/>
<label>月:</label>
<select id="filterMonth">
<option value="">全月</option>
<option value="1">1月</option>
<option value="2">2月</option>
<option value="3">3月</option>
<option value="4">4月</option>
<option value="5">5月</option>
<option value="6">6月</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
<label>銀行:</label>
<select id="filterBank">
<option value="">全銀行</option>
</select>
<button class="btn btn-primary" onclick="loadData()">検索</button>
<div
class="search-form no-print"
style="flex-direction: column; align-items: flex-start; gap: 10px"
>
<div
style="display: flex; align-items: center; flex-wrap: wrap; gap: 8px"
>
<label style="min-width: 3em">開始:</label>
<input
type="number"
id="startYear"
min="2000"
max="2099"
style="width: 72px"
placeholder="年"
/><span></span>
<select id="startMonth" style="width: 60px">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7月</option>
<option value="8">8月</option>
<option value="9">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
<input
type="number"
id="startDay"
min="1"
max="31"
style="width: 48px"
placeholder="日"
/><span></span>
<span style="margin: 0 6px; color: #999"></span>
<label style="min-width: 3em">終了:</label>
<input
type="number"
id="endYear"
min="2000"
max="2099"
style="width: 72px"
placeholder="年"
/><span></span>
<select id="endMonth" style="width: 60px">
<option value=""></option>
<option value="1">1月</option>
<option value="2">2月</option>
<option value="3">3月</option>
<option value="4">4月</option>
<option value="5">5月</option>
<option value="6">6月</option>
<option value="7">7月</option>
<option value="8">8月</option>
<option value="9">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
<input
type="number"
id="endDay"
min="1"
max="31"
style="width: 48px"
placeholder="日"
/><span></span>
</div>
<div
style="display: flex; align-items: center; flex-wrap: wrap; gap: 8px"
>
<label>銀行:</label>
<select id="filterBank">
<option value="">全銀行</option>
</select>
<button class="btn btn-primary" onclick="loadData()">検索</button>
<button class="btn btn-gray" onclick="clearDateFilter()">クリア</button>
</div>
</div>
<!-- 月別チップ -->
@@ -638,16 +744,114 @@
}
// ── 明細データ読み込み ──────────────────────────────────
function _lastDayOfMonth(year, month) {
return new Date(parseInt(year), parseInt(month), 0).getDate();
}
// 会社名をlocalStorageに保存・復元
const COMPANY_KEY = "bankPrintCompanyName";
document.addEventListener("DOMContentLoaded", function () {
const saved = localStorage.getItem(COMPANY_KEY) || "";
const input = document.getElementById("printCompanyInput");
if (input && saved) input.value = saved;
input &&
input.addEventListener("input", function () {
localStorage.setItem(COMPANY_KEY, this.value);
});
});
function doPrint() {
const company = (
document.getElementById("printCompanyInput").value || ""
).trim();
const bankVal = document.getElementById("filterBank").value;
// 期間ラベル生成
const sy = document.getElementById("startYear").value;
const sm = document.getElementById("startMonth").value;
const sd = document.getElementById("startDay").value;
const ey = document.getElementById("endYear").value;
const em = document.getElementById("endMonth").value;
const ed = document.getElementById("endDay").value;
let periodLabel = "";
if (sy || ey) {
const from = sy
? sy +
(sm ? "/" + String(sm).padStart(2, "0") : "") +
(sd ? "/" + String(sd).padStart(2, "0") : "")
: "";
const to = ey
? ey +
(em ? "/" + String(em).padStart(2, "0") : "") +
(ed ? "/" + String(ed).padStart(2, "0") : "")
: "";
if (from && to) periodLabel = " (" + from + " 〜 " + to + ")";
else if (from) periodLabel = " (" + from + " 〜)";
else if (to) periodLabel = " (〜 " + to + ")";
}
// 印刷ヘッダーを設定
document.getElementById("printCompany").textContent = company;
document.getElementById("printBank").textContent = bankVal
? "銀行:" + bankVal + periodLabel
: "期間:全期間" + periodLabel || "全期間";
const today = new Date();
const dateStr =
today.getFullYear() +
"年" +
(today.getMonth() + 1) +
"月" +
today.getDate() +
"日";
document.getElementById("printDate").textContent = "印刷日:" + dateStr;
window.print();
}
function clearDateFilter() {
[
"startYear",
"startMonth",
"startDay",
"endYear",
"endMonth",
"endDay",
].forEach((id) => {
const el = document.getElementById(id);
if (el) el.value = "";
});
loadData();
}
async function loadData() {
const year = document.getElementById("filterYear").value;
const month = document.getElementById("filterMonth").value;
const sy = document.getElementById("startYear").value.trim();
const sm = document.getElementById("startMonth").value;
const sd = document.getElementById("startDay").value.trim();
const ey = document.getElementById("endYear").value.trim();
const em = document.getElementById("endMonth").value;
const ed = document.getElementById("endDay").value.trim();
const bank = document.getElementById("filterBank").value;
hideMsg("msgBar");
const qp = [];
if (year) qp.push(`year=${year}`);
if (month) qp.push(`month=${month}`);
if (sy) {
const m = sm ? String(sm).padStart(2, "0") : "01";
const d = sd ? String(sd).padStart(2, "0") : "01";
qp.push(`date_from=${sy}-${m}-${d}`);
}
if (ey) {
const m = em ? String(em).padStart(2, "0") : "12";
let d;
if (ed) {
d = String(ed).padStart(2, "0");
} else if (em) {
d = String(_lastDayOfMonth(ey, em)).padStart(2, "0");
} else {
d = "31";
}
qp.push(`date_to=${ey}-${m}-${d}`);
}
if (bank) qp.push(`bank_name=${encodeURIComponent(bank)}`);
const url = "/bank-statements" + (qp.length ? "?" + qp.join("&") : "");
@@ -658,7 +862,7 @@
_allRows = data.rows;
_currentPage = 1;
renderMonthlyChips(data.monthly, year, month);
renderMonthlyChips(data.monthly, { sy, sm, sd, ey, em, ed });
renderStats();
renderTable();
updateBankFilter(data.banks);
@@ -682,18 +886,23 @@
}
// ── 月別チップ ──────────────────────────────────────────
function renderMonthlyChips(monthly, selYear, selMonth) {
function renderMonthlyChips(monthly, filter) {
const { sy, sm, sd, ey, em, ed } = filter || {};
const wrap = document.getElementById("monthlyChips");
wrap.innerHTML = "";
if (!monthly.length) return;
// 「全月」チップ
// 「全月」チップ:開始・終了が同じ年で月未指定の場合にアクティブ
const noMonthSelected = !sm && !em && !sd && !ed;
const allChip = document.createElement("span");
allChip.className =
"month-chip no-print" + (!selMonth ? " active" : "");
"month-chip no-print" + (noMonthSelected ? " active" : "");
allChip.textContent = "全月";
allChip.onclick = () => {
document.getElementById("filterMonth").value = "";
document.getElementById("startMonth").value = "";
document.getElementById("startDay").value = "";
document.getElementById("endMonth").value = "";
document.getElementById("endDay").value = "";
loadData();
};
wrap.appendChild(allChip);
@@ -702,15 +911,22 @@
const [y, mo] = m.ym.split("-");
const chip = document.createElement("span");
const isActive =
String(selYear) === y && String(selMonth) === String(parseInt(mo));
sy === y &&
ey === y &&
String(parseInt(sm || "0")) === String(parseInt(mo)) &&
String(parseInt(em || "0")) === String(parseInt(mo)) &&
!sd &&
!ed;
chip.className = "month-chip no-print" + (isActive ? " active" : "");
chip.innerHTML = `${parseInt(mo)}月 <small style="color:inherit;opacity:.8">${
m.count
}件</small>`;
chip.innerHTML = `${parseInt(mo)}月 <small style="color:inherit;opacity:.8">${m.count}件</small>`;
chip.title = `出金 ${fmt(m.total_debit)} / 入金 ${fmt(m.total_credit)}`;
chip.onclick = () => {
document.getElementById("filterYear").value = y;
document.getElementById("filterMonth").value = parseInt(mo);
document.getElementById("startYear").value = y;
document.getElementById("startMonth").value = parseInt(mo);
document.getElementById("startDay").value = "";
document.getElementById("endYear").value = y;
document.getElementById("endMonth").value = parseInt(mo);
document.getElementById("endDay").value = "";
loadData();
};
wrap.appendChild(chip);