chore: 年度リストを昇順に変更
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user