Files
njts-accounting-core/frontend/withholding-slip.html
2026-05-22 23:05:25 +09:00

691 lines
29 KiB
HTML
Raw 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.
<!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;">
&#8592; 給与管理メニューに戻る
</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, '&amp;').replace(/</g, '&lt;')
.replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
/* 数値フォーマット */
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>