1049 lines
35 KiB
HTML
1049 lines
35 KiB
HTML
<!doctype html>
|
||
<html lang="ja">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta
|
||
http-equiv="Cache-Control"
|
||
content="no-cache, no-store, must-revalidate"
|
||
/>
|
||
<meta http-equiv="Pragma" content="no-cache" />
|
||
<meta http-equiv="Expires" content="0" />
|
||
<script src="js/auth.js"></script>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>給与所得の源泉徴収票</title>
|
||
<link rel="stylesheet" href="/css/style.css" />
|
||
<link rel="stylesheet" href="/css/mobile.css" />
|
||
<style>
|
||
/* ===== 画面UI ===== */
|
||
body {
|
||
font-family: "MS Gothic", "Meiryo", sans-serif;
|
||
}
|
||
.container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 0 20px;
|
||
}
|
||
.form-panel {
|
||
background: #f9f9f9;
|
||
border: 1px solid #ddd;
|
||
border-radius: 6px;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
.form-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16px;
|
||
align-items: flex-end;
|
||
}
|
||
.form-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
.form-group label {
|
||
font-size: 13px;
|
||
font-weight: bold;
|
||
}
|
||
.form-group input,
|
||
.form-group select {
|
||
padding: 6px 8px;
|
||
border: 1px solid #ccc;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
}
|
||
.btn {
|
||
padding: 8px 18px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
}
|
||
.btn-primary {
|
||
background: #007bff;
|
||
color: white;
|
||
}
|
||
.btn-primary:hover {
|
||
background: #0056b3;
|
||
}
|
||
.btn-success {
|
||
background: #28a745;
|
||
color: white;
|
||
}
|
||
.btn-success:hover {
|
||
background: #1e7e34;
|
||
}
|
||
.btn-secondary {
|
||
background: #6c757d;
|
||
color: white;
|
||
}
|
||
.employee-list {
|
||
margin: 8px 0;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
.employee-chip {
|
||
padding: 4px 10px;
|
||
background: #e9ecef;
|
||
border-radius: 16px;
|
||
font-size: 13px;
|
||
cursor: pointer;
|
||
border: 2px solid transparent;
|
||
}
|
||
.employee-chip.selected {
|
||
background: #007bff;
|
||
color: white;
|
||
border-color: #0056b3;
|
||
}
|
||
.alert {
|
||
padding: 12px 16px;
|
||
border-radius: 4px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.alert-info {
|
||
background: #d1ecf1;
|
||
color: #0c5460;
|
||
border: 1px solid #bee5eb;
|
||
}
|
||
.alert-warning {
|
||
background: #fff3cd;
|
||
color: #856404;
|
||
border: 1px solid #ffeeba;
|
||
}
|
||
.no-print {
|
||
}
|
||
|
||
/* ===== 印刷プレビューエリア ===== */
|
||
.slip-page {
|
||
background: white;
|
||
margin: 20px auto;
|
||
padding: 6px;
|
||
max-width: 900px;
|
||
}
|
||
.slip-divider {
|
||
border: none;
|
||
border-top: 2px dashed #aaa;
|
||
margin: 4px 0;
|
||
}
|
||
|
||
/* ===== 源泉徴収票 票面 ===== */
|
||
.withholding-slip {
|
||
font-family: "MS Gothic", "MS Mincho", "Meiryo", monospace;
|
||
background: white;
|
||
page-break-inside: avoid;
|
||
margin-bottom: 4px;
|
||
}
|
||
.st {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
table-layout: fixed;
|
||
font-size: 7pt;
|
||
}
|
||
.st td {
|
||
border: 0.6px solid #333;
|
||
padding: 1px 2px;
|
||
vertical-align: middle;
|
||
word-break: break-all;
|
||
}
|
||
/* セルクラス */
|
||
.sl {
|
||
background: #e8e8e8;
|
||
text-align: center;
|
||
font-size: 6pt;
|
||
font-weight: bold;
|
||
vertical-align: middle;
|
||
}
|
||
.sh {
|
||
background: #e8e8e8;
|
||
font-size: 6pt;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
}
|
||
.sv {
|
||
background: white;
|
||
font-size: 7.5pt;
|
||
}
|
||
.sv-r {
|
||
background: white;
|
||
text-align: right;
|
||
font-size: 8pt;
|
||
}
|
||
.sv-c {
|
||
background: white;
|
||
text-align: center;
|
||
font-size: 8pt;
|
||
}
|
||
.sv-s {
|
||
background: white;
|
||
text-align: center;
|
||
font-size: 6.5pt;
|
||
}
|
||
.sh-r {
|
||
background: #e8e8e8;
|
||
text-align: right;
|
||
font-size: 6pt;
|
||
}
|
||
.sh-s {
|
||
background: #e8e8e8;
|
||
text-align: center;
|
||
font-size: 6pt;
|
||
}
|
||
.sv-payer {
|
||
background: white;
|
||
font-size: 7.5pt;
|
||
}
|
||
.st-title {
|
||
text-align: center;
|
||
font-size: 11pt;
|
||
font-weight: bold;
|
||
letter-spacing: 2px;
|
||
padding: 3px 0;
|
||
border: none;
|
||
border-bottom: 0.6px solid #333;
|
||
}
|
||
.sf-name {
|
||
font-size: 10pt;
|
||
font-weight: bold;
|
||
}
|
||
.sf-dep {
|
||
font-size: 8pt;
|
||
}
|
||
.remarks-cell {
|
||
min-height: 16px;
|
||
font-size: 7.5pt;
|
||
}
|
||
.copy-label-cell {
|
||
text-align: center;
|
||
font-weight: bold;
|
||
font-size: 8pt;
|
||
background: #e8e8e8;
|
||
padding: 2px;
|
||
}
|
||
|
||
/* ===== 印刷時 ===== */
|
||
@media print {
|
||
@page {
|
||
size: A4 portrait;
|
||
margin: 6mm 5mm;
|
||
}
|
||
body {
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
.no-print {
|
||
display: none !important;
|
||
}
|
||
.slip-page {
|
||
border: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
max-width: 100%;
|
||
}
|
||
.withholding-slip {
|
||
margin-bottom: 1px;
|
||
}
|
||
.slip-divider {
|
||
margin: 3px 0;
|
||
}
|
||
.page-break {
|
||
page-break-before: always;
|
||
}
|
||
.st {
|
||
font-size: 6.5pt;
|
||
}
|
||
.sh {
|
||
font-size: 5.5pt;
|
||
}
|
||
.sl {
|
||
font-size: 5.5pt;
|
||
}
|
||
.st-title {
|
||
font-size: 10pt;
|
||
}
|
||
.sf-name {
|
||
font-size: 9pt;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container no-print">
|
||
<button
|
||
onclick="location.href = 'payroll.html'"
|
||
class="btn btn-secondary"
|
||
style="margin: 12px 0"
|
||
>
|
||
← 給与管理メニューに戻る
|
||
</button>
|
||
<h1>給与所得の源泉徴収票</h1>
|
||
|
||
<div class="form-panel">
|
||
<h3 style="margin-top: 0">① 発行条件の設定</h3>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>対象年(令和換算)</label>
|
||
<select id="tax-year" style="width: 190px"></select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>従業員を選択(複数可)</label>
|
||
<button
|
||
class="btn btn-secondary"
|
||
onclick="toggleAllEmployees()"
|
||
style="font-size: 12px; padding: 4px 10px"
|
||
>
|
||
全選択 / 全解除
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="employee-list" class="employee-list" style="margin-top: 10px">
|
||
<span style="color: #999">読み込み中...</span>
|
||
</div>
|
||
|
||
<hr style="margin: 16px 0" />
|
||
<h3 style="margin-top: 0">② 支払者情報(源泉徴収票下部に印刷)</h3>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>会社名(氏名又は名称)</label>
|
||
<input
|
||
type="text"
|
||
id="company-name"
|
||
style="width: 320px"
|
||
value="新日本テクノソリューションズ株式会社"
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>住所・所在地</label>
|
||
<input
|
||
type="text"
|
||
id="company-address"
|
||
style="width: 400px"
|
||
value="〒130-0022 東京都墨田区江東橋4丁目31-10-401号室"
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>電話番号</label>
|
||
<input
|
||
type="text"
|
||
id="company-phone"
|
||
style="width: 150px"
|
||
value="03-6388-6465"
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>法人番号(任意)</label>
|
||
<input
|
||
type="text"
|
||
id="company-mynumber"
|
||
style="width: 160px"
|
||
maxlength="13"
|
||
value="3010601055736"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div
|
||
style="
|
||
margin-top: 16px;
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: center;
|
||
"
|
||
>
|
||
<button class="btn btn-primary" onclick="generateSlips()">
|
||
📋 源泉徴収票を作成
|
||
</button>
|
||
<button
|
||
class="btn btn-success"
|
||
onclick="printSlips()"
|
||
id="print-btn"
|
||
style="display: none"
|
||
>
|
||
🖨️ 印刷(3部)
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="alert-area"></div>
|
||
</div>
|
||
|
||
<div id="slip-area"></div>
|
||
|
||
<script>
|
||
const API_BASE = "";
|
||
|
||
function initYearSelect() {
|
||
const sel = document.getElementById("tax-year");
|
||
const currentYear = new Date().getFullYear();
|
||
for (let y = currentYear; y >= currentYear - 5; y--) {
|
||
const reiwa = y - 2018;
|
||
const opt = document.createElement("option");
|
||
opt.value = y;
|
||
opt.textContent = "令和" + reiwa + "年(" + y + "年)";
|
||
if (y === currentYear - 1) opt.selected = true;
|
||
sel.appendChild(opt);
|
||
}
|
||
}
|
||
|
||
async function loadEmployees() {
|
||
try {
|
||
const resp = await fetch(
|
||
API_BASE + "/payroll/withholding-slip/employees",
|
||
{
|
||
headers: {
|
||
Authorization:
|
||
"Bearer " + (localStorage.getItem("token") || ""),
|
||
},
|
||
},
|
||
);
|
||
if (!resp.ok) throw new Error("Failed");
|
||
const data = await resp.json();
|
||
renderEmployeeChips(data.employees || []);
|
||
} catch (e) {
|
||
document.getElementById("employee-list").innerHTML =
|
||
'<span style="color:red">従業員リストの取得に失敗しました</span>';
|
||
}
|
||
}
|
||
|
||
let allEmployees = [];
|
||
function renderEmployeeChips(employees) {
|
||
allEmployees = employees;
|
||
const container = document.getElementById("employee-list");
|
||
if (!employees.length) {
|
||
container.innerHTML =
|
||
'<span style="color:#999">従業員が登録されていません</span>';
|
||
return;
|
||
}
|
||
container.innerHTML = "";
|
||
employees.forEach(function (emp) {
|
||
const chip = document.createElement("div");
|
||
chip.className = "employee-chip selected";
|
||
chip.dataset.id = emp.id;
|
||
chip.textContent = emp.code + "\u3000" + emp.name;
|
||
chip.title = emp.name_kana || "";
|
||
chip.onclick = function () {
|
||
chip.classList.toggle("selected");
|
||
};
|
||
container.appendChild(chip);
|
||
});
|
||
}
|
||
|
||
function toggleAllEmployees() {
|
||
const chips = document.querySelectorAll(".employee-chip");
|
||
const allSelected = Array.from(chips).every(function (c) {
|
||
return c.classList.contains("selected");
|
||
});
|
||
chips.forEach(function (c) {
|
||
if (allSelected) c.classList.remove("selected");
|
||
else c.classList.add("selected");
|
||
});
|
||
}
|
||
|
||
function getSelectedEmployeeIds() {
|
||
return Array.from(
|
||
document.querySelectorAll(".employee-chip.selected"),
|
||
).map(function (c) {
|
||
return parseInt(c.dataset.id);
|
||
});
|
||
}
|
||
|
||
function showAlert(msg, type) {
|
||
type = type || "info";
|
||
document.getElementById("alert-area").innerHTML =
|
||
'<div class="alert alert-' + type + '">' + msg + "</div>";
|
||
}
|
||
|
||
async function generateSlips() {
|
||
const taxYear = parseInt(document.getElementById("tax-year").value);
|
||
const empIds = getSelectedEmployeeIds();
|
||
if (!empIds.length) {
|
||
showAlert("従業員を1名以上選択してください", "warning");
|
||
return;
|
||
}
|
||
const companyName =
|
||
document.getElementById("company-name").value || "(未設定)";
|
||
const companyAddress =
|
||
document.getElementById("company-address").value || "";
|
||
const companyPhone =
|
||
document.getElementById("company-phone").value || "";
|
||
const companyMyNumber =
|
||
document.getElementById("company-mynumber").value || "";
|
||
showAlert("生成中...", "info");
|
||
document.getElementById("slip-area").innerHTML = "";
|
||
try {
|
||
const resp = await fetch(
|
||
API_BASE + "/payroll/withholding-slip/generate",
|
||
{
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
Authorization:
|
||
"Bearer " + (localStorage.getItem("token") || ""),
|
||
},
|
||
body: JSON.stringify({
|
||
tax_year: taxYear,
|
||
employee_ids: empIds,
|
||
company_name: companyName,
|
||
company_address: companyAddress,
|
||
company_phone: companyPhone,
|
||
company_my_number: companyMyNumber,
|
||
}),
|
||
},
|
||
);
|
||
if (!resp.ok) {
|
||
const err = await resp.json();
|
||
throw new Error(err.detail || "取得エラー");
|
||
}
|
||
const data = await resp.json();
|
||
if (!data.slips || data.slips.length === 0) {
|
||
showAlert(
|
||
"令和" +
|
||
(taxYear - 2018) +
|
||
"年(" +
|
||
taxYear +
|
||
"年)の給与データがありません",
|
||
"warning",
|
||
);
|
||
return;
|
||
}
|
||
showAlert(
|
||
data.total_count + "名分の源泉徴収票を生成しました(各3部)",
|
||
"info",
|
||
);
|
||
renderAllSlips(data.slips, taxYear, {
|
||
companyName: companyName,
|
||
companyAddress: companyAddress,
|
||
companyPhone: companyPhone,
|
||
companyMyNumber: companyMyNumber,
|
||
});
|
||
document.getElementById("print-btn").style.display = "";
|
||
} catch (e) {
|
||
showAlert("エラー: " + e.message, "warning");
|
||
}
|
||
}
|
||
|
||
function renderAllSlips(slips, taxYear, payer) {
|
||
const area = document.getElementById("slip-area");
|
||
area.innerHTML = "";
|
||
slips.forEach(function (slip, idx) {
|
||
const page = document.createElement("div");
|
||
page.className = "slip-page" + (idx > 0 ? " page-break" : "");
|
||
// 受給者交付用のみ個人番号を記載しない(法令上の要件)
|
||
const copies = [
|
||
{ label: "市区町村提出用", showMyNumber: true },
|
||
{ label: "受給者交付用", showMyNumber: false },
|
||
{ label: "税務署提出用", showMyNumber: true },
|
||
];
|
||
copies.forEach(function (copy, ci) {
|
||
if (ci > 0) {
|
||
const hr = document.createElement("hr");
|
||
hr.className = "slip-divider";
|
||
page.appendChild(hr);
|
||
}
|
||
const wrapper = document.createElement("div");
|
||
wrapper.innerHTML = buildSlipHTML(
|
||
slip,
|
||
taxYear,
|
||
payer,
|
||
copy.label,
|
||
copy.showMyNumber,
|
||
);
|
||
page.appendChild(wrapper.firstElementChild);
|
||
});
|
||
area.appendChild(page);
|
||
});
|
||
}
|
||
|
||
/* 元号変換 */
|
||
function toGengou(dateStr) {
|
||
if (!dateStr) return "";
|
||
const d = new Date(dateStr);
|
||
const y = d.getFullYear(),
|
||
m = d.getMonth() + 1,
|
||
day = d.getDate();
|
||
const mm = String(m).padStart("0", 2) || ("0" + m).slice(-2);
|
||
const dd = String(day).padStart("0", 2) || ("0" + day).slice(-2);
|
||
const mStr = (m < 10 ? "0" : "") + m;
|
||
const dStr = (day < 10 ? "0" : "") + day;
|
||
if (y >= 2019)
|
||
return "令和" + (y - 2018) + "年" + mStr + "月" + dStr + "日";
|
||
if (y >= 1989)
|
||
return "平成" + (y - 1988) + "年" + mStr + "月" + dStr + "日";
|
||
if (y >= 1926)
|
||
return "昭和" + (y - 1925) + "年" + mStr + "月" + dStr + "日";
|
||
return y + "年" + mStr + "月" + dStr + "日";
|
||
}
|
||
|
||
/* escHtml */
|
||
function escHtml(str) {
|
||
return String(str)
|
||
.replace(/&/g, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """);
|
||
}
|
||
|
||
/* 数値フォーマット */
|
||
function fmt(n) {
|
||
return parseInt(n || 0).toLocaleString("ja-JP");
|
||
}
|
||
function fmtZ(n) {
|
||
return !n || parseInt(n) === 0
|
||
? ""
|
||
: parseInt(n).toLocaleString("ja-JP");
|
||
}
|
||
|
||
/* ====================================================
|
||
扶養親族詳細行 HTML
|
||
─ 16列テーブルの行を生成
|
||
─ 各扶養親族 3行: フリガナ行/氏名行/個人番号行
|
||
==================================================== */
|
||
function buildDependentRowsHTML(slip, showMyNumber) {
|
||
const deps16 = (slip.dependents_over16 || []).slice(0, 4);
|
||
const deps0 = (slip.dependents_under16 || []).slice(0, 2);
|
||
var html = "";
|
||
|
||
for (var i = 0; i < 4; i++) {
|
||
var d = deps16[i] || null;
|
||
var numLabel = i + 1;
|
||
var kana = d ? escHtml(d.name_kana || "") : "";
|
||
var name = d ? escHtml(d.name || "") : "";
|
||
var myNum =
|
||
d && showMyNumber && d.my_number ? escHtml(d.my_number) : "";
|
||
var kubun = d ? escHtml(d.deduction_type || "") : "";
|
||
html +=
|
||
"<tr>" +
|
||
'<td class="sl" rowspan="3" style="font-size:5.5pt">控除対象<br>扶養親族<br>' +
|
||
numLabel +
|
||
"</td>" +
|
||
'<td class="sh">(フリガナ)</td>' +
|
||
'<td class="sv" colspan="10">' +
|
||
kana +
|
||
"</td>" +
|
||
'<td class="sh" colspan="4">区分</td>' +
|
||
"</tr>" +
|
||
"<tr>" +
|
||
'<td class="sh">氏名</td>' +
|
||
'<td class="sv sf-dep" colspan="10">' +
|
||
name +
|
||
"</td>" +
|
||
'<td class="sv-c" colspan="4">' +
|
||
kubun +
|
||
"</td>" +
|
||
"</tr>" +
|
||
"<tr>" +
|
||
'<td class="sh">個人番号</td>' +
|
||
'<td class="sv" colspan="14">' +
|
||
myNum +
|
||
"</td>" +
|
||
"</tr>";
|
||
}
|
||
|
||
for (var j = 0; j < 2; j++) {
|
||
var d2 = deps0[j] || null;
|
||
var numLabel2 = j + 1;
|
||
var kana2 = d2 ? escHtml(d2.name_kana || "") : "";
|
||
var name2 = d2 ? escHtml(d2.name || "") : "";
|
||
var myNum2 =
|
||
d2 && showMyNumber && d2.my_number ? escHtml(d2.my_number) : "";
|
||
var kubun2 = d2 ? escHtml(d2.deduction_type || "") : "";
|
||
html +=
|
||
"<tr>" +
|
||
'<td class="sl" rowspan="3" style="font-size:5.5pt">16歳未満<br>扶養親族<br>' +
|
||
numLabel2 +
|
||
"</td>" +
|
||
'<td class="sh">(フリガナ)</td>' +
|
||
'<td class="sv" colspan="10">' +
|
||
kana2 +
|
||
"</td>" +
|
||
'<td class="sh" colspan="4">区分</td>' +
|
||
"</tr>" +
|
||
"<tr>" +
|
||
'<td class="sh">氏名</td>' +
|
||
'<td class="sv sf-dep" colspan="10">' +
|
||
name2 +
|
||
"</td>" +
|
||
'<td class="sv-c" colspan="4">' +
|
||
kubun2 +
|
||
"</td>" +
|
||
"</tr>" +
|
||
"<tr>" +
|
||
'<td class="sh">個人番号</td>' +
|
||
'<td class="sv" colspan="14">' +
|
||
myNum2 +
|
||
"</td>" +
|
||
"</tr>";
|
||
}
|
||
return html;
|
||
}
|
||
|
||
/* ====================================================
|
||
票面 HTML 生成
|
||
16列テーブル構造:
|
||
Col1: section label (4%)
|
||
Col2: field label (7%)
|
||
Col3-10: value area 8cols (6% each = 48%)
|
||
Col11-16: secondary area 6cols (5-6% each)
|
||
==================================================== */
|
||
function buildSlipHTML(slip, taxYear, payer, copyLabel, showMyNumber) {
|
||
var reiwa = taxYear - 2018;
|
||
var empAddr = escHtml(slip.employee_address || "");
|
||
var myNum = showMyNumber ? escHtml(slip.my_number || "") : "";
|
||
var empKana = escHtml(slip.employee_name_kana || "");
|
||
var empName = escHtml(slip.employee_name || "");
|
||
var empCode = escHtml(slip.employee_code || "");
|
||
var birthStr = toGengou(slip.employee_birth_date);
|
||
|
||
var deps16 = slip.dependents_over16 || [];
|
||
var deps0 = slip.dependents_under16 || [];
|
||
var cntTokutei = deps16.filter(function (d) {
|
||
return d.deduction_type === "特定扶養";
|
||
}).length;
|
||
var cntRojin = deps16.filter(function (d) {
|
||
return d.deduction_type === "老人扶養";
|
||
}).length;
|
||
var cntSonota = deps16.filter(function (d) {
|
||
return d.deduction_type === "一般扶養";
|
||
}).length;
|
||
var hasSpouse = slip.has_spouse_deduction;
|
||
var spouseIsRojin = slip.spouse_deduction_type === "老人配偶者控除";
|
||
|
||
var depRowsHTML = buildDependentRowsHTML(slip, showMyNumber);
|
||
|
||
var spouseIncome =
|
||
hasSpouse && slip.spouse_income ? fmtZ(slip.spouse_income) : "";
|
||
var spouseKubun = hasSpouse
|
||
? escHtml(slip.spouse_deduction_type || "")
|
||
: "";
|
||
|
||
return [
|
||
'<div class="withholding-slip">',
|
||
'<table class="st">',
|
||
"<colgroup>",
|
||
' <col style="width:4%"><col style="width:7%">',
|
||
' <col style="width:6%"><col style="width:6%">',
|
||
' <col style="width:6%"><col style="width:6%">',
|
||
' <col style="width:6%"><col style="width:6%">',
|
||
' <col style="width:6%"><col style="width:6%">',
|
||
' <col style="width:5%"><col style="width:5%">',
|
||
' <col style="width:5%"><col style="width:5%">',
|
||
' <col style="width:5%"><col style="width:6%">',
|
||
"</colgroup>",
|
||
"<tbody>",
|
||
|
||
/* ====== タイトル ====== */
|
||
'<tr><td class="st-title" colspan="16">令和 ' +
|
||
reiwa +
|
||
" 年分 給与所得の源泉徴収票</td></tr>",
|
||
|
||
/* ====== 受給者: 住所 ====== */
|
||
"<tr>",
|
||
' <td class="sl" rowspan="4">支払<br>を受<br>ける<br>者</td>',
|
||
' <td class="sh">住所又は居所</td>',
|
||
' <td class="sv" colspan="8">' + empAddr + "</td>",
|
||
' <td class="sh" colspan="2">(受給者番号)</td>',
|
||
' <td class="sv" colspan="4">' + empCode + "</td>",
|
||
"</tr>",
|
||
|
||
/* 個人番号 */
|
||
"<tr>",
|
||
' <td class="sh">(個人番号)</td>',
|
||
' <td class="sv" colspan="8">' + myNum + "</td>",
|
||
' <td class="sh" colspan="2">(役職名)</td>',
|
||
' <td class="sv" colspan="4"></td>',
|
||
"</tr>",
|
||
|
||
/* フリガナ */
|
||
"<tr>",
|
||
' <td class="sh">(フリガナ)</td>',
|
||
' <td class="sv" colspan="14">' + empKana + "</td>",
|
||
"</tr>",
|
||
|
||
/* 氏名 */
|
||
"<tr>",
|
||
' <td class="sh">氏 名</td>',
|
||
' <td class="sv sf-name" colspan="14">' + empName + "</td>",
|
||
"</tr>",
|
||
|
||
/* ====== 金額ヘッダー1 ====== */
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">種 別</td>',
|
||
' <td class="sh" colspan="3">支 払 金 額</td>',
|
||
' <td class="sh" colspan="4">給与所得控除後の金額<br>(調整控除後)</td>',
|
||
' <td class="sh" colspan="4">所得控除の額の合計額</td>',
|
||
' <td class="sh" colspan="3">源 泉 徴 収 税 額</td>',
|
||
"</tr>",
|
||
|
||
/* 金額ヘッダー2 */
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">給料・賞与</td>',
|
||
' <td class="sh-s">内</td>',
|
||
' <td class="sh-r" colspan="2">円</td>',
|
||
' <td class="sh-r" colspan="4">円</td>',
|
||
' <td class="sh-r" colspan="4">円</td>',
|
||
' <td class="sh-s">内</td>',
|
||
' <td class="sh-r" colspan="2">円</td>',
|
||
"</tr>",
|
||
|
||
/* 金額値 */
|
||
"<tr>",
|
||
' <td class="sv" colspan="2"></td>',
|
||
' <td class="sv-s"></td>',
|
||
' <td class="sv-r" colspan="2">' +
|
||
fmt(slip.total_payment_excl_commute) +
|
||
"</td>",
|
||
' <td class="sv-r" colspan="4">' + fmt(slip.kyuyo_shotoku) + "</td>",
|
||
' <td class="sv-r" colspan="4">' +
|
||
fmt(slip.total_deduction_amount) +
|
||
"</td>",
|
||
' <td class="sv-s"></td>',
|
||
' <td class="sv-r" colspan="2">' +
|
||
fmt(slip.income_tax_withheld) +
|
||
"</td>",
|
||
"</tr>",
|
||
|
||
/* ====== 控除概要ヘッダー1 ====== */
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">(源泉)控除対象配偶者<br>の有無等</td>',
|
||
' <td class="sh" colspan="2">配偶者(特別)<br>控除の額</td>',
|
||
' <td class="sh" colspan="4">控除対象扶養親族の数<br>(配偶者を除く。)</td>',
|
||
' <td class="sh" colspan="2">16歳未満<br>扶養親族の数</td>',
|
||
' <td class="sh" colspan="3">障害者の数<br>(本人を除く。)</td>',
|
||
' <td class="sh" colspan="3">非居住者<br>である<br>親族の数</td>',
|
||
"</tr>",
|
||
|
||
/* 控除概要ヘッダー2 */
|
||
"<tr>",
|
||
' <td class="sh">有</td>',
|
||
' <td class="sh-s">老人</td>',
|
||
' <td class="sh-r" colspan="2">円</td>',
|
||
' <td class="sh">特 定</td>',
|
||
' <td class="sh">老 人</td>',
|
||
' <td class="sh">その他</td>',
|
||
' <td class="sh">特 親</td>',
|
||
' <td class="sh" colspan="2">人</td>',
|
||
' <td class="sh">特 別</td>',
|
||
' <td class="sh" colspan="2">その他</td>',
|
||
' <td class="sh" colspan="3">人</td>',
|
||
"</tr>",
|
||
|
||
/* 控除概要値 */
|
||
"<tr>",
|
||
' <td class="sv-c">' + (hasSpouse ? "有" : "") + "</td>",
|
||
' <td class="sv-c">' + (spouseIsRojin ? "○" : "") + "</td>",
|
||
' <td class="sv-r" colspan="2">' +
|
||
(hasSpouse ? fmtZ(slip.spouse_deduction_amount) : "") +
|
||
"</td>",
|
||
' <td class="sv-c">' + (cntTokutei > 0 ? cntTokutei : "") + "</td>",
|
||
' <td class="sv-c">' + (cntRojin > 0 ? cntRojin : "") + "</td>",
|
||
' <td class="sv-c">' + (cntSonota > 0 ? cntSonota : "") + "</td>",
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c" colspan="2">' +
|
||
(deps0.length > 0 ? deps0.length : "") +
|
||
"</td>",
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c" colspan="2"></td>',
|
||
' <td class="sv-c" colspan="3"></td>',
|
||
"</tr>",
|
||
|
||
/* ====== その他控除 ====== */
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">特定親族特別控除の額</td>',
|
||
' <td class="sh" colspan="3">社 会 保 険 料 等 の 金 額</td>',
|
||
' <td class="sh" colspan="3">生命保険料の控除額</td>',
|
||
' <td class="sh" colspan="4">地震保険料の控除額</td>',
|
||
' <td class="sh" colspan="4">住宅借入金等特別控除の額</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sv-r" colspan="2"></td>',
|
||
' <td class="sh-s">内</td>',
|
||
' <td class="sv-r" colspan="2">' +
|
||
fmt(slip.social_insurance_total) +
|
||
"</td>",
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
' <td class="sv-r" colspan="4"></td>',
|
||
' <td class="sv-r" colspan="4"></td>',
|
||
"</tr>",
|
||
|
||
/* ====== 摘要 ====== */
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">(摘 要)</td>',
|
||
' <td class="sv remarks-cell" colspan="14">' +
|
||
escHtml(slip.remarks || "") +
|
||
"</td>",
|
||
"</tr>",
|
||
|
||
/* ====== 生命保険料内訳 ====== */
|
||
"<tr>",
|
||
' <td class="sl" rowspan="2" style="font-size:5.5pt">生命保険料の金額の内訳</td>',
|
||
' <td class="sh" colspan="2">新生命保険料の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">旧生命保険料の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">介護医療保険料の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">新個人年金保険料の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">旧個人年金保険料の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
"</tr>",
|
||
|
||
/* ====== 住宅借入金特別控除内訳 ====== */
|
||
"<tr>",
|
||
' <td class="sl" rowspan="4" style="font-size:5.5pt">住宅借入金等特別控除の額の内訳</td>',
|
||
' <td class="sh" rowspan="4" style="font-size:5.5pt">適<br>用<br>数</td>',
|
||
' <td class="sh" colspan="3">居住開始年月日(1回目)</td>',
|
||
' <td class="sh" rowspan="2" colspan="3">住宅借入金等<br>特別控除区分(1回目)</td>',
|
||
' <td class="sh" rowspan="2" colspan="4">住宅借入金等<br>年末残高(1回目)</td>',
|
||
' <td class="sh-r" rowspan="2" colspan="3">円</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sv"></td><td class="sh-s">年</td><td class="sh-s">月</td><td class="sh-s">日</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sh" colspan="3">居住開始年月日(2回目)</td>',
|
||
' <td class="sh" rowspan="2" colspan="3">住宅借入金等<br>特別控除区分(2回目)</td>',
|
||
' <td class="sh" rowspan="2" colspan="4">住宅借入金等<br>年末残高(2回目)</td>',
|
||
' <td class="sh-r" rowspan="2" colspan="3">円</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sv"></td><td class="sh-s">年</td><td class="sh-s">月</td><td class="sh-s">日</td>',
|
||
"</tr>",
|
||
|
||
/* ====== 配偶者詳細 ====== */
|
||
"<tr>",
|
||
' <td class="sl" rowspan="3" style="font-size:5.5pt">(源泉・特別)<br>控除対象<br>配偶者</td>',
|
||
' <td class="sh">(フリガナ)</td>',
|
||
' <td class="sv" colspan="4">' +
|
||
escHtml(slip.spouse_name_kana || "") +
|
||
"</td>",
|
||
' <td class="sh">区分</td>',
|
||
' <td class="sh" colspan="2">配偶者の合計所得</td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">国民年金保険料等の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">旧長期損害保険料の金額</td>',
|
||
' <td class="sh-r">円</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sh">氏名</td>',
|
||
' <td class="sv sf-dep" colspan="4">' +
|
||
escHtml(slip.spouse_name || "") +
|
||
"</td>",
|
||
' <td class="sv-c">' + spouseKubun + "</td>",
|
||
' <td class="sv-r" colspan="3">' + spouseIncome + "</td>",
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
' <td class="sv-r" colspan="3"></td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sh">個人番号</td>',
|
||
' <td class="sv" colspan="4"></td>',
|
||
' <td class="sh">基礎控除の額</td>',
|
||
' <td class="sv-r" colspan="2">' +
|
||
fmt(slip.basic_deduction) +
|
||
"</td>",
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sh" colspan="2">所得金額調整控除額</td>',
|
||
' <td class="sv-r" colspan="2"></td>',
|
||
' <td class="sh-r">円</td>',
|
||
' <td class="sv"></td>',
|
||
"</tr>",
|
||
|
||
/* ====== 扶養親族詳細 ====== */
|
||
depRowsHTML,
|
||
|
||
/* ====== 各種フラグ・生年月日 ====== */
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">未成年者</td>',
|
||
' <td class="sh">外国人</td>',
|
||
' <td class="sh">死亡退職</td>',
|
||
' <td class="sh">災害者</td>',
|
||
' <td class="sh">乙欄</td>',
|
||
' <td class="sh" colspan="2">本人が障害者</td>',
|
||
' <td class="sh">寡婦</td>',
|
||
' <td class="sh">ひとり親</td>',
|
||
' <td class="sh">勤労学生</td>',
|
||
' <td class="sh" colspan="2">中途就・退職</td>',
|
||
' <td class="sh" colspan="3">受給者生年月日</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sv-c" colspan="2"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sh-s">特別</td>',
|
||
' <td class="sh-s">その他</td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sh-s">就職</td>',
|
||
' <td class="sh-s">退職</td>',
|
||
' <td class="sh" colspan="3">元号 年 月 日</td>',
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sv-c" colspan="2"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv-c"></td>',
|
||
' <td class="sv" colspan="3">' + escHtml(birthStr) + "</td>",
|
||
"</tr>",
|
||
|
||
/* ====== コピーラベル ====== */
|
||
'<tr><td class="copy-label-cell" colspan="16">(' +
|
||
copyLabel +
|
||
")</td></tr>",
|
||
|
||
/* ====== 支払者情報 ====== */
|
||
"<tr>",
|
||
' <td class="sl" rowspan="3">支払者</td>',
|
||
' <td class="sh" colspan="2">個人番号又は法人番号</td>',
|
||
' <td class="sv-payer" colspan="13">' +
|
||
escHtml(payer.companyMyNumber || "") +
|
||
"</td>",
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">住所(居所)又は所在地</td>',
|
||
' <td class="sv-payer" colspan="13">' +
|
||
escHtml(payer.companyAddress || "") +
|
||
"</td>",
|
||
"</tr>",
|
||
"<tr>",
|
||
' <td class="sh" colspan="2">氏名又は名称</td>',
|
||
' <td class="sv-payer" colspan="9">' +
|
||
escHtml(payer.companyName || "") +
|
||
"</td>",
|
||
' <td class="sh">(電話)</td>',
|
||
' <td class="sv-payer" colspan="3">' +
|
||
escHtml(payer.companyPhone || "") +
|
||
"</td>",
|
||
"</tr>",
|
||
|
||
"</tbody></table></div>",
|
||
].join("\n");
|
||
}
|
||
|
||
function printSlips() {
|
||
window.print();
|
||
}
|
||
|
||
initYearSelect();
|
||
loadEmployees();
|
||
</script>
|
||
</body>
|
||
</html>
|