202 lines
8.1 KiB
Python
202 lines
8.1 KiB
Python
"""
|
|
従業員管理API (Employee Management API)
|
|
"""
|
|
from fastapi import APIRouter, HTTPException, status
|
|
from typing import List
|
|
from . import schemas
|
|
from ...core.database import get_connection
|
|
|
|
|
|
router = APIRouter(prefix="/payroll/employees", tags=["Payroll - Employees"])
|
|
|
|
|
|
@router.post("/", response_model=schemas.Employee, status_code=status.HTTP_201_CREATED)
|
|
def create_employee(employee: schemas.EmployeeCreate):
|
|
"""従業員を作成"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"""
|
|
INSERT INTO employees (
|
|
employee_code, name, name_kana, birth_date, gender, my_number,
|
|
email, phone, postal_code, address, hire_date, termination_date, is_active,
|
|
bank_name, bank_branch, bank_account_number, bank_account_type, notes,
|
|
photo_url, my_number_card_image_url, residence_card_image_url,
|
|
health_insurance_card_image_url, other_id_image_url
|
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
|
RETURNING *
|
|
""",
|
|
(
|
|
employee.employee_code, employee.name, employee.name_kana,
|
|
employee.birth_date, employee.gender, employee.my_number,
|
|
employee.email, employee.phone, employee.postal_code, employee.address,
|
|
employee.hire_date, employee.termination_date, employee.is_active,
|
|
employee.bank_name, employee.bank_branch,
|
|
employee.bank_account_number, employee.bank_account_type, employee.notes,
|
|
employee.photo_url, employee.my_number_card_image_url,
|
|
employee.residence_card_image_url, employee.health_insurance_card_image_url,
|
|
employee.other_id_image_url
|
|
),
|
|
)
|
|
result = cur.fetchone()
|
|
conn.commit()
|
|
return result
|
|
|
|
|
|
@router.get("/", response_model=List[schemas.Employee])
|
|
def get_employees(is_active: bool = None):
|
|
"""従業員一覧を取得"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
if is_active is not None:
|
|
cur.execute(
|
|
"SELECT * FROM employees WHERE is_active = %s ORDER BY employee_code",
|
|
(is_active,)
|
|
)
|
|
else:
|
|
cur.execute("SELECT * FROM employees ORDER BY employee_code")
|
|
return cur.fetchall()
|
|
|
|
|
|
@router.get("/{employee_id}", response_model=schemas.EmployeeWithDependents)
|
|
def get_employee(employee_id: int):
|
|
"""従業員の詳細を取得(扶養家族を含む)"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
# 従業員情報取得
|
|
cur.execute("SELECT * FROM employees WHERE employee_id = %s", (employee_id,))
|
|
employee = cur.fetchone()
|
|
if not employee:
|
|
raise HTTPException(status_code=404, detail="従業員が見つかりません")
|
|
|
|
# 扶養家族情報取得
|
|
cur.execute(
|
|
"""
|
|
SELECT * FROM dependents
|
|
WHERE employee_id = %s
|
|
AND (valid_to IS NULL OR valid_to >= CURRENT_DATE)
|
|
ORDER BY valid_from
|
|
""",
|
|
(employee_id,)
|
|
)
|
|
dependents = cur.fetchall()
|
|
|
|
return {**employee, "dependents": dependents}
|
|
|
|
|
|
@router.put("/{employee_id}", response_model=schemas.Employee)
|
|
def update_employee(employee_id: int, employee: schemas.EmployeeUpdate):
|
|
"""従業員情報を更新"""
|
|
update_data = employee.model_dump(exclude_unset=True)
|
|
if not update_data:
|
|
raise HTTPException(status_code=400, detail="更新するデータがありません")
|
|
|
|
set_clause = ", ".join([f"{key} = %s" for key in update_data.keys()])
|
|
values = list(update_data.values()) + [employee_id]
|
|
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
f"UPDATE employees SET {set_clause} WHERE employee_id = %s RETURNING *",
|
|
values,
|
|
)
|
|
result = cur.fetchone()
|
|
if not result:
|
|
raise HTTPException(status_code=404, detail="従業員が見つかりません")
|
|
conn.commit()
|
|
return result
|
|
|
|
|
|
@router.delete("/{employee_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
def delete_employee(employee_id: int):
|
|
"""従業員を削除"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute("DELETE FROM employees WHERE employee_id = %s", (employee_id,))
|
|
if cur.rowcount == 0:
|
|
raise HTTPException(status_code=404, detail="従業員が見つかりません")
|
|
conn.commit()
|
|
|
|
|
|
# ========================================
|
|
# 扶養家族管理
|
|
# ========================================
|
|
|
|
@router.post("/{employee_id}/dependents", response_model=schemas.Dependent, status_code=status.HTTP_201_CREATED)
|
|
def create_dependent(employee_id: int, dependent: schemas.DependentCreate):
|
|
"""扶養家族を追加"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
# 従業員の存在確認
|
|
cur.execute("SELECT employee_id FROM employees WHERE employee_id = %s", (employee_id,))
|
|
if not cur.fetchone():
|
|
raise HTTPException(status_code=404, detail="従業員が見つかりません")
|
|
|
|
cur.execute(
|
|
"""
|
|
INSERT INTO dependents (
|
|
employee_id, name, relationship, birth_date,
|
|
is_spouse, is_disabled, income_amount, valid_from, valid_to
|
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
|
|
RETURNING *
|
|
""",
|
|
(
|
|
employee_id, dependent.name, dependent.relationship, dependent.birth_date,
|
|
dependent.is_spouse, dependent.is_disabled, dependent.income_amount,
|
|
dependent.valid_from, dependent.valid_to
|
|
),
|
|
)
|
|
result = cur.fetchone()
|
|
conn.commit()
|
|
return result
|
|
|
|
|
|
@router.get("/{employee_id}/dependents", response_model=List[schemas.Dependent])
|
|
def get_dependents(employee_id: int):
|
|
"""従業員の扶養家族一覧を取得"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"""
|
|
SELECT * FROM dependents
|
|
WHERE employee_id = %s
|
|
ORDER BY valid_from DESC
|
|
""",
|
|
(employee_id,)
|
|
)
|
|
return cur.fetchall()
|
|
|
|
|
|
@router.put("/dependents/{dependent_id}", response_model=schemas.Dependent)
|
|
def update_dependent(dependent_id: int, dependent: schemas.DependentUpdate):
|
|
"""扶養家族情報を更新"""
|
|
update_data = dependent.model_dump(exclude_unset=True)
|
|
if not update_data:
|
|
raise HTTPException(status_code=400, detail="更新するデータがありません")
|
|
|
|
set_clause = ", ".join([f"{key} = %s" for key in update_data.keys()])
|
|
values = list(update_data.values()) + [dependent_id]
|
|
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
f"UPDATE dependents SET {set_clause} WHERE dependent_id = %s RETURNING *",
|
|
values,
|
|
)
|
|
result = cur.fetchone()
|
|
if not result:
|
|
raise HTTPException(status_code=404, detail="扶養家族が見つかりません")
|
|
conn.commit()
|
|
return result
|
|
|
|
|
|
@router.delete("/dependents/{dependent_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
def delete_dependent(dependent_id: int):
|
|
"""扶養家族を削除"""
|
|
with get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute("DELETE FROM dependents WHERE dependent_id = %s", (dependent_id,))
|
|
if cur.rowcount == 0:
|
|
raise HTTPException(status_code=404, detail="扶養家族が見つかりません")
|
|
conn.commit()
|