diff --git a/backend/app/main.py b/backend/app/main.py
index b7f2a06..0414da1 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -6,7 +6,6 @@ from fastapi.responses import JSONResponse, RedirectResponse
from pydantic import ValidationError
from fastapi.middleware.cors import CORSMiddleware
-
# FastAPI アプリケーション作成
app = FastAPI(
title="日本小規模企業向け会計システム"
@@ -32,13 +31,15 @@ async def validation_exception_handler(request: Request, exc: ValidationError):
# ─────────────────────────
# ルート(稼働確認)
# ─────────────────────────
-#@app.get("/", include_in_schema=False)
-#def root():
-# return RedirectResponse(url="/index.html")
-
+@app.get("/", include_in_schema=False)
+def root():
+ return RedirectResponse("/login.html")
# ─────────────────────────
# ルーター登録(※ 必ず app 定義の後)
# ─────────────────────────
+from app.modules.users.router import router as users_router
+app.include_router(users_router)
+
from app.modules.accounts.router import router as accounts_router
app.include_router(accounts_router)
@@ -139,7 +140,7 @@ print("Frontend path =", frontend_path)
if frontend_path.exists():
app.mount(
"/",
- StaticFiles(directory=frontend_path, html=True),
+ StaticFiles(directory=frontend_path),
name="frontend",
)
else:
diff --git a/backend/app/modules/users/__init__.py b/backend/app/modules/users/__init__.py
new file mode 100644
index 0000000..a9e9188
--- /dev/null
+++ b/backend/app/modules/users/__init__.py
@@ -0,0 +1 @@
+# Users Module
diff --git a/backend/app/modules/users/router.py b/backend/app/modules/users/router.py
new file mode 100644
index 0000000..2633201
--- /dev/null
+++ b/backend/app/modules/users/router.py
@@ -0,0 +1,104 @@
+from fastapi import APIRouter, HTTPException
+from pydantic import BaseModel
+import hashlib
+import os
+from app.core.database import get_connection
+
+router = APIRouter(prefix="/api/users", tags=["users"])
+
+
+class LoginRequest(BaseModel):
+ username: str
+ password: str
+
+
+class LoginResponse(BaseModel):
+ id: int
+ username: str
+ full_name: str | None
+ email: str | None
+ message: str
+
+
+def hash_password(password: str) -> str:
+ """パスワードをハッシュ化"""
+ # 実運用ではより安全なハッシュアルゴリズムを使用してください
+ return hashlib.sha256(password.encode()).hexdigest()
+
+
+@router.post("/login", response_model=LoginResponse)
+async def login(request: LoginRequest):
+ """ユーザーのログイン処理"""
+ try:
+ conn = get_connection()
+ cur = conn.cursor()
+
+ # ユーザーが存在するか確認
+ cur.execute(
+ "SELECT id, username, password, full_name, email FROM users WHERE username = %s AND is_active = TRUE",
+ (request.username,)
+ )
+ user = cur.fetchone()
+ cur.close()
+ conn.close()
+
+ if not user:
+ raise HTTPException(status_code=401, detail="ユーザー名またはパスワードが正しくありません")
+
+ # パスワードの検証
+ hashed_password = hash_password(request.password)
+ if user["password"] != hashed_password:
+ raise HTTPException(status_code=401, detail="ユーザー名またはパスワードが正しくありません")
+
+ return LoginResponse(
+ id=user["id"],
+ username=user["username"],
+ full_name=user["full_name"],
+ email=user["email"],
+ message="ログインに成功しました"
+ )
+
+ except HTTPException:
+ raise
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=f"ログイン処理エラー: {str(e)}")
+
+
+@router.post("/register")
+async def register(request: LoginRequest):
+ """新規ユーザー登録"""
+ try:
+ if len(request.password) < 6:
+ raise HTTPException(status_code=400, detail="パスワードは6文字以上である必要があります")
+
+ conn = get_connection()
+ cur = conn.cursor()
+
+ # ユーザーが既に存在するか確認
+ cur.execute("SELECT id FROM users WHERE username = %s", (request.username,))
+ if cur.fetchone():
+ cur.close()
+ conn.close()
+ raise HTTPException(status_code=400, detail="このユーザー名は既に使用されています")
+
+ # ユーザーを登録
+ hashed_password = hash_password(request.password)
+ cur.execute(
+ "INSERT INTO users (username, password) VALUES (%s, %s) RETURNING id, username",
+ (request.username, hashed_password)
+ )
+ new_user = cur.fetchone()
+ conn.commit()
+ cur.close()
+ conn.close()
+
+ return {
+ "id": new_user["id"],
+ "username": new_user["username"],
+ "message": "ユーザー登録が完了しました"
+ }
+
+ except HTTPException:
+ raise
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=f"登録処理エラー: {str(e)}")
diff --git a/backend/sql/create_users_table.sql b/backend/sql/create_users_table.sql
new file mode 100644
index 0000000..dcad310
--- /dev/null
+++ b/backend/sql/create_users_table.sql
@@ -0,0 +1,14 @@
+-- ユーザーテーブル作成
+CREATE TABLE IF NOT EXISTS users (
+ id SERIAL PRIMARY KEY,
+ username VARCHAR(50) UNIQUE NOT NULL,
+ password VARCHAR(255) NOT NULL,
+ email VARCHAR(100),
+ full_name VARCHAR(100),
+ is_active BOOLEAN DEFAULT TRUE,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- ユーザーの一覧表示用インデックス
+CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
diff --git a/frontend/accounts.html b/frontend/accounts.html
index 0b43cfb..4bdc632 100644
--- a/frontend/accounts.html
+++ b/frontend/accounts.html
@@ -1,7 +1,8 @@
-
+
+
科目マスタ
diff --git a/frontend/index.html b/frontend/index.html
index 1965dfb..afeb497 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,13 +1,19 @@
-
+
NJTS 会計システム - メイン
+
@@ -78,6 +107,14 @@
修正仕訳入力
+
+
+
+
+
+
+
+
diff --git a/frontend/opening_balance.html b/frontend/opening_balance.html
index f13279a..52c2838 100644
--- a/frontend/opening_balance.html
+++ b/frontend/opening_balance.html
@@ -1,7 +1,8 @@
-
+
+
期首残高入力
@@ -39,7 +40,7 @@
-
+
diff --git a/frontend/payroll-calculation.html b/frontend/payroll-calculation.html
index 7e21560..2c95485 100644
--- a/frontend/payroll-calculation.html
+++ b/frontend/payroll-calculation.html
@@ -2,6 +2,7 @@
+
給与管理 - 月次給与計算
diff --git a/frontend/payroll-employees.html b/frontend/payroll-employees.html
index 7c2229b..ace0574 100644
--- a/frontend/payroll-employees.html
+++ b/frontend/payroll-employees.html
@@ -2,6 +2,7 @@
+
給与管理 - 従業員管理
diff --git a/frontend/payroll-salary-settings.html b/frontend/payroll-salary-settings.html
index 4dbdba7..17c6d1a 100644
--- a/frontend/payroll-salary-settings.html
+++ b/frontend/payroll-salary-settings.html
@@ -1,7 +1,8 @@
-
+
+
給与管理 - 給与設定
@@ -213,7 +214,7 @@
async function loadEmployees() {
try {
const response = await fetch(
- `${API_BASE}/payroll/employees/?is_active=true`
+ `${API_BASE}/payroll/employees/?is_active=true`,
);
employees = await response.json();
@@ -223,7 +224,7 @@
employees
.map(
(emp) =>
- ``
+ ``,
)
.join("");
@@ -241,7 +242,7 @@
for (const emp of employees) {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/salary/${emp.employee_id}/current`
+ `${API_BASE}/payroll/settings/salary/${emp.employee_id}/current`,
);
if (response.ok) {
const setting = await response.json();
@@ -255,7 +256,7 @@
} catch (error) {
console.error(
`従業員 ${emp.employee_id} の給与設定取得失敗`,
- error
+ error,
);
}
}
@@ -316,7 +317,7 @@
})" style="padding: 5px 10px; font-size: 12px;">編集
- `
+ `,
)
.join("")
: '| 給与設定が登録されていません |
'
@@ -334,7 +335,7 @@
// 全従業員の設定を取得して該当するものを探す
for (const emp of employees) {
const response = await fetch(
- `${API_BASE}/payroll/settings/salary/${emp.employee_id}`
+ `${API_BASE}/payroll/settings/salary/${emp.employee_id}`,
);
const settings = await response.json();
const setting = settings.find((s) => s.setting_id === settingId);
@@ -408,7 +409,7 @@
commute_allowance: parseFloat(formData.get("commute_allowance")) || 0,
other_allowance: parseFloat(formData.get("other_allowance")) || 0,
employment_insurance_eligible: document.getElementById(
- "employment_insurance_eligible"
+ "employment_insurance_eligible",
).checked,
valid_from: formData.get("valid_from"),
};
@@ -431,7 +432,7 @@
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
- }
+ },
);
} else {
// 新規追加
@@ -444,7 +445,7 @@
if (response.ok) {
alert(
- settingId ? "給与設定を更新しました" : "給与設定を保存しました"
+ settingId ? "給与設定を更新しました" : "給与設定を保存しました",
);
hideAddForm();
loadAllSalarySettings();
diff --git a/frontend/payroll-settings.html b/frontend/payroll-settings.html
index da76445..4505611 100644
--- a/frontend/payroll-settings.html
+++ b/frontend/payroll-settings.html
@@ -1,7 +1,8 @@
-
+
+
給与管理 - 設定
@@ -651,7 +652,7 @@
async function loadStdRemunerationYears() {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/standard-remuneration/years`
+ `${API_BASE}/payroll/settings/standard-remuneration/years`,
);
const years = await response.json();
@@ -678,7 +679,7 @@
読み込み中...
- `
+ `,
)
.join("");
@@ -729,7 +730,7 @@
// セッションストレージからメタデータを取得
const metadata = JSON.parse(
- sessionStorage.getItem("stdRemunMetadata") || "{}"
+ sessionStorage.getItem("stdRemunMetadata") || "{}",
);
console.log("取得したメタデータ:", metadata);
@@ -752,9 +753,8 @@
document.getElementById(`std-table-${year}`).innerHTML = tablesHtml;
} catch (error) {
console.error("データ読み込みエラー:", error);
- document.getElementById(
- `std-table-${year}`
- ).innerHTML = `データの取得に失敗しました: ${error.message}
`;
+ document.getElementById(`std-table-${year}`).innerHTML =
+ `データの取得に失敗しました: ${error.message}
`;
}
}
@@ -768,7 +768,7 @@
console.log("renderStdRemunerationTable - metadata内容:", metadata);
console.log(
"renderStdRemunerationTable - metadata.source:",
- metadata.source
+ metadata.source,
);
if (metadata.source) {
sourceHtml = `対象期間: ${metadata.source}
`;
@@ -831,7 +831,7 @@
step1Data.map((d) => ({
grade: d.grade,
pension: d.pension_insurance,
- }))
+ })),
);
// ステップ2: 非ゼロ値を下方へ延続(前の有効値が0以下になったら、前の非ゼロ値を使用)
@@ -856,7 +856,7 @@
adjustedData.map((d) => ({
grade: d.grade,
pension: d.pension_insurance,
- }))
+ })),
);
console.log("調整後のデータ(最初の3件):", adjustedData.slice(0, 3));
@@ -927,15 +927,15 @@
${Number(row.salary_from ?? 0).toLocaleString()} |
${Number(row.salary_to ?? 0).toLocaleString()} |
${Number(
- row.health_insurance_no_care ?? 0
+ row.health_insurance_no_care ?? 0,
).toLocaleString()} |
${Number(healthNoCareHalf ?? 0).toLocaleString()} |
${Number(
- row.health_insurance_with_care ?? 0
+ row.health_insurance_with_care ?? 0,
).toLocaleString()} |
${Number(healthWithCareHalf ?? 0).toLocaleString()} |
${Number(
- row.pension_insurance ?? 0
+ row.pension_insurance ?? 0,
).toLocaleString()} |
${Number(pensionHalf ?? 0).toLocaleString()} |
@@ -958,7 +958,7 @@
async function deleteStdRemunerationYear(year) {
const confirmed = confirm(
- `⚠️ 警告\n\n${year}年度の標準報酬月額表データを削除します。\nこの操作は取り消せません。\n\n本当に削除してもよろしいですか?`
+ `⚠️ 警告\n\n${year}年度の標準報酬月額表データを削除します。\nこの操作は取り消せません。\n\n本当に削除してもよろしいですか?`,
);
if (!confirmed) {
console.log(`${year}年度の削除がキャンセルされました`);
@@ -970,7 +970,7 @@
try {
const response = await fetch(
`${API_BASE}/payroll/settings/standard-remuneration/year/${year}`,
- { method: "DELETE" }
+ { method: "DELETE" },
);
console.log("削除レスポンスステータス:", response.status);
@@ -979,7 +979,7 @@
if (response.ok) {
alert(
- `✓ ${year}年度のデータ(${result.deleted_count}件)を削除しました`
+ `✓ ${year}年度のデータ(${result.deleted_count}件)を削除しました`,
);
console.log(`=== ${year}年度データ削除完了 ===`);
@@ -987,7 +987,7 @@
await loadStdRemunerationYears();
} else {
alert(
- "削除に失敗しました:\n" + JSON.stringify(result.detail || result)
+ "削除に失敗しました:\n" + JSON.stringify(result.detail || result),
);
}
} catch (error) {
@@ -998,7 +998,7 @@
async function clearAllStdRemunerationData() {
const confirmed = confirm(
- "⚠️ 警告\n\n標準報酬月額表のすべてのデータを削除します。\nこの操作は取り消せません。\n\n本当に削除してもよろしいですか?"
+ "⚠️ 警告\n\n標準報酬月額表のすべてのデータを削除します。\nこの操作は取り消せません。\n\n本当に削除してもよろしいですか?",
);
if (!confirmed) {
console.log("削除操作がキャンセルされました");
@@ -1010,7 +1010,7 @@
try {
const response = await fetch(
`${API_BASE}/payroll/settings/standard-remuneration/all`,
- { method: "DELETE" }
+ { method: "DELETE" },
);
console.log("削除レスポンスステータス:", response.status);
@@ -1019,7 +1019,7 @@
if (response.ok) {
alert(
- `✓ ${result.deleted_count}件のデータを削除しました\n\n再度Excelファイルをインポートしてください`
+ `✓ ${result.deleted_count}件のデータを削除しました\n\n再度Excelファイルをインポートしてください`,
);
console.log("=== 全データ削除完了 ===");
@@ -1028,7 +1028,7 @@
"データが削除されました。Excelファイルを再度インポートしてください。
";
} else {
alert(
- "削除に失敗しました:\n" + JSON.stringify(result.detail || result)
+ "削除に失敗しました:\n" + JSON.stringify(result.detail || result),
);
}
} catch (error) {
@@ -1150,7 +1150,7 @@
async function editInsuranceRate(rateId) {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/insurance-rates`
+ `${API_BASE}/payroll/settings/insurance-rates`,
);
const rates = await response.json();
const rate = rates.find((r) => r.rate_id === rateId);
@@ -1184,7 +1184,7 @@
async function copyInsuranceRate(rateId) {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/insurance-rates`
+ `${API_BASE}/payroll/settings/insurance-rates`,
);
const rates = await response.json();
const rate = rates.find((r) => r.rate_id === rateId);
@@ -1265,7 +1265,7 @@
// 介護保険年齢を数値に変換(空の場合はnull)
if (data.care_insurance_age_threshold) {
data.care_insurance_age_threshold = parseInt(
- data.care_insurance_age_threshold
+ data.care_insurance_age_threshold,
);
} else {
data.care_insurance_age_threshold = null;
@@ -1278,7 +1278,7 @@
"送信するURL:",
isEditMode
? `${API_BASE}/payroll/settings/insurance-rates/${rateId}`
- : `${API_BASE}/payroll/settings/insurance-rates`
+ : `${API_BASE}/payroll/settings/insurance-rates`,
);
console.log("送信するデータ:", JSON.stringify(data, null, 2));
@@ -1302,7 +1302,7 @@
const result = await response.json();
console.log("成功レスポンス:", result);
alert(
- isEditMode ? "保険料率を更新しました" : "保険料率を登録しました"
+ isEditMode ? "保険料率を更新しました" : "保険料率を登録しました",
);
hideInsuranceForm();
loadInsuranceRates();
@@ -1312,7 +1312,7 @@
alert(
(isEditMode ? "更新" : "登録") +
"に失敗しました: " +
- JSON.stringify(error.detail)
+ JSON.stringify(error.detail),
);
}
} catch (error) {
@@ -1328,7 +1328,7 @@
try {
const response = await fetch(
`${API_BASE}/payroll/settings/insurance-rates/${rateId}`,
- { method: "DELETE" }
+ { method: "DELETE" },
);
if (response.ok) {
@@ -1362,7 +1362,7 @@
async function loadChildSupportRates() {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/child-support-rates`
+ `${API_BASE}/payroll/settings/child-support-rates`,
);
const rates = await response.json();
@@ -1390,10 +1390,10 @@
| ${rate.rate_year} |
¥${Number(
- rate.income_threshold
+ rate.income_threshold,
).toLocaleString()} |
${(parseFloat(rate.contribution_rate) * 100).toFixed(
- 3
+ 3,
)}% |
${rate.notes || "-"} |
@@ -1405,7 +1405,7 @@
})">削除
|
- `
+ `,
)
.join("")}
@@ -1422,7 +1422,7 @@
async function editChildSupportRate(contributionId) {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/child-support-rates`
+ `${API_BASE}/payroll/settings/child-support-rates`,
);
const rates = await response.json();
const rate = rates.find((r) => r.contribution_id === contributionId);
@@ -1493,7 +1493,7 @@
alert(
isEditMode
? "子ども・子育て拠出金率を更新しました"
- : "子ども・子育て拠出金率を登録しました"
+ : "子ども・子育て拠出金率を登録しました",
);
hideChildSupportForm();
loadChildSupportRates();
@@ -1502,7 +1502,7 @@
alert(
(isEditMode ? "更新" : "登録") +
"に失敗しました: " +
- JSON.stringify(error.detail)
+ JSON.stringify(error.detail),
);
}
} catch (error) {
@@ -1517,7 +1517,7 @@
try {
const response = await fetch(
`${API_BASE}/payroll/settings/child-support-rates/${contributionId}`,
- { method: "DELETE" }
+ { method: "DELETE" },
);
if (response.ok) {
@@ -1550,7 +1550,7 @@
async function loadLimitSettings() {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/insurance-limits`
+ `${API_BASE}/payroll/settings/insurance-limits`,
);
const limits = await response.json();
@@ -1579,8 +1579,8 @@
${limit.setting_type} |
¥${Number(limit.limit_amount).toLocaleString()} |
${limit.valid_from} ~ ${
- limit.valid_to || "現在"
- } |
+ limit.valid_to || "現在"
+ }
${limit.notes || "-"} |
|
- `
+ `,
)
.join("")}
@@ -1608,7 +1608,7 @@
async function editLimitSetting(limitId) {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/insurance-limits`
+ `${API_BASE}/payroll/settings/insurance-limits`,
);
const limits = await response.json();
const limit = limits.find((l) => l.limit_id === limitId);
@@ -1676,7 +1676,7 @@
if (response.ok) {
alert(
- isEditMode ? "上限設定を更新しました" : "上限設定を登録しました"
+ isEditMode ? "上限設定を更新しました" : "上限設定を登録しました",
);
hideLimitForm();
loadLimitSettings();
@@ -1685,7 +1685,7 @@
alert(
(isEditMode ? "更新" : "登録") +
"に失敗しました: " +
- JSON.stringify(error.detail)
+ JSON.stringify(error.detail),
);
}
} catch (error) {
@@ -1700,7 +1700,7 @@
try {
const response = await fetch(
`${API_BASE}/payroll/settings/insurance-limits/${limitId}`,
- { method: "DELETE" }
+ { method: "DELETE" },
);
if (response.ok) {
@@ -1732,7 +1732,7 @@
async function loadIncomeTaxYears() {
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/income-tax/years`
+ `${API_BASE}/payroll/settings/income-tax/years`,
);
const data = await response.json();
@@ -1772,7 +1772,7 @@
読み込み中...
- `
+ `,
)
.join("");
@@ -1785,7 +1785,7 @@
async function deleteTaxDataYear(year) {
const confirmed = confirm(
- `⚠️ 警告\n\n${year}年度の所得税率表データを削除します。\nこの操作は取り消せません。\n\n本当に削除してもよろしいですか?`
+ `⚠️ 警告\n\n${year}年度の所得税率表データを削除します。\nこの操作は取り消せません。\n\n本当に削除してもよろしいですか?`,
);
if (!confirmed) {
console.log(`${year}年度の削除がキャンセルされました`);
@@ -1797,7 +1797,7 @@
try {
const response = await fetch(
`${API_BASE}/payroll/settings/income-tax/year/${year}`,
- { method: "DELETE" }
+ { method: "DELETE" },
);
console.log("削除レスポンスステータス:", response.status);
@@ -1806,7 +1806,7 @@
if (response.ok) {
alert(
- `✓ ${year}年度のデータ(${result.deleted_count}件)を削除しました`
+ `✓ ${year}年度のデータ(${result.deleted_count}件)を削除しました`,
);
console.log(`=== ${year}年度所得税データ削除完了 ===`);
@@ -1814,7 +1814,7 @@
await loadIncomeTaxYears();
} else {
alert(
- "削除に失敗しました:\n" + JSON.stringify(result.detail || result)
+ "削除に失敗しました:\n" + JSON.stringify(result.detail || result),
);
}
} catch (error) {
@@ -1851,7 +1851,7 @@
try {
const response = await fetch(
- `${API_BASE}/payroll/settings/income-tax?${params}`
+ `${API_BASE}/payroll/settings/income-tax?${params}`,
);
const taxes = await response.json();
@@ -1879,13 +1879,13 @@
| ${tax.dependents_count}人 |
¥${Number(
- tax.monthly_income_from
+ tax.monthly_income_from,
).toLocaleString()} |
¥${Number(tax.monthly_income_to).toLocaleString()} |
¥${Number(tax.tax_amount).toLocaleString()} |
${tax.valid_from} ~ ${tax.valid_to || "現在"} |
- `
+ `,
)
.join("")}
@@ -1908,7 +1908,7 @@
const taxYear = prompt(
"税年度を入力してください(空欄の場合はファイルから自動抽出):",
- ""
+ "",
);
try {
@@ -1948,7 +1948,7 @@
// 都道府県をプロンプトで取得
const prefecture = prompt(
"都道府県を入力してください(例: 東京、神奈川):",
- ""
+ "",
);
if (!prefecture || !prefecture.trim()) {
alert("都道府県を入力してください");
@@ -1970,7 +1970,7 @@
{
method: "POST",
body: formData,
- }
+ },
);
console.log("レスポンスステータス:", response.status);
@@ -1990,7 +1990,7 @@
console.log("メタデータ保存:", result.metadata);
sessionStorage.setItem(
"stdRemunMetadata",
- JSON.stringify(result.metadata)
+ JSON.stringify(result.metadata),
);
}
@@ -2009,7 +2009,7 @@
} else if (typeof errorDetail === "object") {
errorMessage += JSON.stringify(errorDetail, null, 2).substring(
0,
- 1000
+ 1000,
);
} else {
errorMessage += String(errorDetail).substring(0, 500);
diff --git a/frontend/payroll.html b/frontend/payroll.html
index 606af90..d4ad1de 100644
--- a/frontend/payroll.html
+++ b/frontend/payroll.html
@@ -1,7 +1,8 @@
-
+
+
給与管理システム
@@ -60,7 +61,10 @@
従業員の給与計算、扶養管理、保険料・税金の管理を行います