[ERP project] 급여정산
사용자 화면
유스케이스
이 컴포넌트에서 제공하는 주요 기능을 간략하게 요약하면 다음과 같다. 👇🏻
### **1. 급여 데이터 표시 및 관리**
API를 호출하여 **`/api/timeManagement`** 에서 직원 정보를 가져와서 테이블 형태로 화면에 표시합니다. 각 직원에 대한 정보로는 사원번호, 이름, 무급휴가일수, 유급휴가일수, 실제근로일수, 실제근로시간, 이메일, 지급 여부 등이 포함된다. 이 테이블은 **`@coreui/react`** 라이브러리를 사용하여 구성되어 있다. ### **2. 급여 지급 여부 관리**
테이블의 각 행에는 급여 지급 버튼이 있습니다. 버튼을 클릭하면 사용자에게 확인 메시지가 표시되고, "확인"을 선택하면 해당 직원의 급여 지급 상태가 "yes"로 변경된다. 이 변경은 테이블의 해당 행에 즉시 반영된다.
### **3. 개별 직원 급여 정보 PDF 다운로드**
테이블의 각 행 마지막에는 PDF 다운로드 버튼이 있다. 이 버튼을 클릭하면 해당 직원의 급여 정보가 PDF 형식으로 다운로드 된다. 이 기능은 **`Pdf`** 컴포넌트를 통해 제공되고 있다.
**요약하자면, 이 컴포넌트는 직원의 급여 정보를 테이블 형태로 표시하고, 각 직원의 급여 지급 여부를 관리하며, 각 직원의 급여 정보를 PDF 형식으로 다운로드할 수 있는 기능을 제공하고 있다.**
front-end
1. 서버에서 데이터 받아오기
useEffect(() => {
fetch("/api/timeManagement")
.then((response) => response.json())
.then((data) => {
setUsers(data);
});
}, []);
useEffect(() => {
setRows(
users.map((user) => [
user.empNum, //사원번호
user.empName, //사원이름
user.unpaid, //무급휴가
user.vacation, //유급휴가
user.actualWorkDays, //실제근로일수
user.workingHours, //실제근로시간
user.email, //이메일
"no", //지급여부 초깃값
])
);
}, [users]);
React에서 사용되는
useEffect
훅을 활용하여 데이터를 가져오고 가공한다.
1-1. 첫 번째 useEffect
useEffect(() => {
fetch("/api/timeManagement")
.then((response) => response.json())
.then((data) => {
setUsers(data);
});
}, []);
해당 훅은 컴포넌트가 처음 마운트 될 때 (
[]
빈 종속성 배열 때문에)/api/timeManagement
URL에서 데이터를 가져온다. →가져온 데이터를 JSON 형태로 변환한 후,
setUsers
를 통해users
상태를 설정한다.
1-2. 두 번째 useEffect
useEffect(() => {
setRows(
users.map((user) => [
user.empNum, //사원번호
user.empName, //사원이름
user.unpaid, //무급휴가
user.vacation, //유급휴가
user.actualWorkDays, //실제근로일수
user.workingHours, //실제근로시간
user.email, //이메일
"no", //지급여부 초깃값
])
);
}, [users]);
이 훅은
users
상태가 변경될 때마다 실행된다.users
배열의 각 사용자에 대해 배열 형태로 데이터를 재구성하고, 이를setRows
를 사용하여rows
상태를 업데이트한다.
2. 급여 지급 여부 관리
const handlePayClick = (index) => {
const confirmed = window.confirm("결제 완료 하시겠습니까?");
if (confirmed) {
alert("결제 완료되었습니다!");
const newRows = [...rows];
newRows[index][7] = "yes";
setRows(newRows);
} else {
alert("취소 되었습니다.");
}
};
handlePayClick 함수는 사용자의 인터랙션에 따라 데이터를 실시간으로 업데이트하는 중요한 역할을 한다! 사용자가 급여를 지급하도록 선택할 경우, 해당 데이터가 즉시 업데이트되어 사용자에게 피드백을 제공한다.
2-1. 함수 인자 ‘index’
const handlePayClick = (index) => { ... }
이 함수는
index
라는 인자를 받습니다.index
는 현재 클릭한 직원의 테이블 행 번호를 나타낸다. 이를 통해 특정 직원의 데이터를 업데이트할 수 있다.
2-2. 사용자에게 급여 지급 여부 확인
const confirmed = window.confirm("결제 완료 하시겠습니까?");
window.confirm
함수는 사용자에게 확인 대화상자를 표시하고, “확인” 또는 “취소” 버튼을 통해 사용자의 응답을 받는다. 사용자가 “확인”을 클릭하면true
를 반환하고, “취소”를 클릭하면false
를 반환한다.
2-3. 급여 지급 상태 업데이트
javascriptCopy code
if (confirmed) {
alert("결제 완료되었습니다!");
const newRows = [...rows];
newRows[index][7] = "yes";
setRows(newRows);
}
...rows
를 사용하는 것은 현재의rows
배열을 복사하는 것이다. 이를 “spread operator“라고 부르며, 배열 또는 객체의 내용을 새 배열 또는 객체로 복사한다.
→ 이렇게 하는 이유는 상태를 직접 수정하는 것이 아니라 새로운 배열을 생성하여 상태를 수정하는 것이 React의 권장 사항이기 때문이다.
newRows[index][7] = "yes";
에서index
는 현재 클릭한 직원의 행 번호를 나타다.[7]
은 해당 직원의 “지급 여부” 데이터가 저장된 열(column) 번호를 나타낸다. 즉, 선택된 컬럼의 급여 “지급 여부”를 “yes”로 변경할 수 있게 된다.
setRows(newRows);
는setRows
라는 상태 업데이트 함수를 호출하여rows
상태를newRows
로 업데이트한다. 이렇게 함으로써 UI에 급여가 지급이 된 상태의 (변경 된) 내용이 반영된다.
2-4. 지급 취소
else {
alert("취소 되었습니다.");
}
서비스 이용 시 실수로 눌렀을 경우를 고려하여 취소도 가능하도록 구현했다. 만약 사용자가 급여 지급을 취소하면 “취소 되었습니다.”라는 알림이 표시된다.
3. 개별 직원 급여 정보, QR코드가 담긴 PDF 다운로드
사용 라이브러리 보러가기 JsPDF 기술 정의서
3-1. PDF 생성 함수
const generatePdf = async () => {
const doc = new jsPDF();
// ... 중략 ...
doc.save("급여명세.pdf");
};
해당 코드는 급여명세서를 생성하는 함수이다.
jsPDF
를 사용하여 PDF를 생성하고 설정한 정보와 표를 PDF에 추가한 뒤,doc.save("급여명세.pdf")
를 호출하여 PDF를 다운로드 한다.jsPDF
라이브러리를 이용하여 간단하게 PDF를 생성한다.
3-2. QR코드 생성 함수
const generateQrCode = async (pdfUrl) => {
try {
const url = await QRCode.toDataURL(pdfUrl);
setQrCodeURL(url);
return url;
} catch (err) {
console.error(err);
return "";
}
};
이 함수는 PDF 문서의 URL을 입력으로 받아 QR코드 이미지의 Data URL을 생성하고, 상태 변수
qrCodeURL
에 저장하는 역할을 한다.
여기에 대한 설명은 다음과 같다 👇🏻
QRCode.toDataURL(pdfUrl)
는pdfUrl
을 이용하여 QR코드를 생성하고, 그 결과를 Data URL 형식으로 반환한다.await
를 사용하여 비동기로 QR코드 생성을 기다립니다. QR코드 생성이 완료되면 결과 URL을url
변수에 저장한다.setQrCodeURL(url)
을 사용하여qrCodeURL
상태를 업데이트하고, 나중에 컴포넌트에서 호출하여 사용할 수 있도록 한다.- 오류가 발생하면
try-catch
블록에서 오류를 처리하고 빈 문자열을 반환한다.
- QR코드는 데이터를 특별한 방식으로 인코딩하여 텍스트 또는 URL로 표현하는 2차원 매트릭스 바코드이다.
- PDF 생성: `jsPDF` 라이브러리를 사용하여 빈 PDF 문서를 생성하고, `doc.text()` 및 `doc.autoTable()` 함수를 사용하여 문서에 텍스트와 표를 추가합니다. 이렇게 추가한 정보는 PDF 파일로 저장하거나 브라우저에서 렌더링할 수 있다 !
→ 즉, 부트스트랩 처럼 하나의 라이브러리로 사용하는 방식 또는 문법이 있어 사용하면 된다.
3-3. 부모 컴포넌트(급여 정산)에서 데이터를 받아오기
function Pdf({ userData }) {
//부모 컴포넌트에서 porp를 통해 전달 받는다.
// ...
// 데이터를 받아오는 함수
const generatePdf = async () => {
const doc = new jsPDF();
// userData를 사용하여 PDF 생성
const headers = [
["이름", "생년월일", "사원번호", "부서명", "직급", "주소", "이메일"],
];
const data = [
[
userData.empName,
userData.birthDate,
userData.empNum,
userData.dept,
userData.position,
userData.address,
userData.email,
],
];
doc.autoTable({
head: headers,
body: data,
startY: 50,
// ...
});
// 나머지 PDF 생성 부분
doc.save("급여명세.pdf");
};
return (
<div>
<CButton onClick={generatePdf} size="sm">
<CIcon icon={cilCloudDownload} />
</CButton>
</div>
);
}
위의 코드에서 데이터를 받아오는 부분은
userData
prop을 통해 이루어진다. PDF에 들어가는 데이터는 컴포넌트가 부모 컴포넌트로부터 전달 받게 된다. 이 데이터는 사용자 정보를 포함하고 있으며, 이 정보를 활용하여 PDF 문서를 생성한다.데이터를 받아올 때 주요한 부분은
generatePdf
함수 내부에서 사용자 정보를 PDF로 출력하는 부분이다.userData
객체 내의 필드들을 이용하여 테이블 데이터를 생성하고, 생성된 데이터를 PDF로 변환하고 저장하는 역할을 하게된다.이 부분은
userData
객체의 속성을 접근하여 데이터를 추출하고, 그 데이터를 PDF로 포맷하여 출력하는 것으로, 사용자 정보를 기반으로 동적인 PDF를 생성하는 역할을 하게된다!
해당 코드는 PayManagementSystemManagement
라는 React 컴포넌트를 정의하고 있으며, 주요 기능들은 급여 정보의 테이블 뷰, 급여 지급 및 취소, PDF 다운로드 등으로 나누어져 있습니다.
아래는 코드 내에서 주요 기능을 설명하며 주석을 추가하는 방식으로 구성되어 있습니다:
import React, { useState, useEffect } from "react";
// 필요한 UI 컴포넌트들을 가져옵니다.
import { Table, Container, Row, Col, Button } from "reactstrap";
import GetThisMonth from "../TimeManagementSystem/CountWeekdays";
import Pdf from "./Pdf";
import { Pagination, message } from "antd";
import Cookies from "js-cookie";
import {
CContainer,
CTable,
CTableBody,
CTableHead,
CTableHeaderCell,
CTableRow,
CTableDataCell,
} from "@coreui/react";
function PayManagementSystemManagement() {
// 각종 상태값들을 정의합니다.
const [rows, setRows] = useState([]);
const [users, setUsers] = useState([]);
const [selectedRowIndex, setSelectedRowIndex] = useState(null);
const staffInfo = JSON.parse(Cookies.get("staffInfo")); // 쿠키에서 staff 정보를 가져옵니다.
// 컴포넌트 마운트 시점에 서버로부터 사용자(직원) 정보를 가져옵니다.
useEffect(() => {
fetch("/api/timeManagement")
.then((response) => response.json())
.then((data) => {
setUsers(data);
});
}, []);
// users 상태값이 변경될 때마다 rows 상태를 업데이트합니다.
useEffect(() => {
setRows(
users.map((user) => [
user.empNum,
user.empName,
0,
user.vacation,
user.actualWorkDays,
user.workingHours,
user.email,
"no",
])
);
}, [users]);
// 테이블의 컬럼 이름을 정의합니다.
const tableColumns = [
// ... (이전 코드를 유지합니다.)
];
// 급여 지급 버튼을 클릭했을 때의 로직입니다.
const handlePayClick = (index) => {
// ... (이전 코드를 유지합니다.)
};
// 무작위 문자열 생성 로직입니다.
const randum = (max) => Math.floor(Math.random() * max);
// ... (이전 코드를 유지합니다.)
// 지급 완료 버튼을 클릭했을 때의 알림 로직입니다.
const clickTobtn = () => {
// ... (이전 코드를 유지합니다.)
};
// 테이블의 특정 행을 클릭했을 때의 로직입니다.
const handleRowClick = (index) => {
setSelectedRowIndex(index);
};
const someData = selectedRowIndex !== null ? users[selectedRowIndex] : null;
return (
<>
<CContainer className="d-flex justify-content-around ">
// ... (이전 코드를 유지합니다.) // 급여 정보를 나타내는 테이블 뷰를
렌더링합니다.
<CTable striped bordered hover style=>
// ... (이전 코드를 유지합니다.)
</CTable>
<Pagination />
</CContainer>
</>
);
}
export default PayManagementSystemManagement;
이 코드는 전체적으로 React의 useState
와 useEffect
훅을 활용하여 급여 관리 시스템의 기능을 구현합니다. 테이블에는 각 직원의 급여 정보가 나타나며, 직원별로 급여 지급 및 취소, PDF 다운로드 기능이 제공됩니다.
1. 상태값 정의 및 초기화
javascriptCopy code
const [rows, setRows] = useState([]);
const [users, setUsers] = useState([]);
const [selectedRowIndex, setSelectedRowIndex] = useState(null);
const staffInfo = JSON.parse(Cookies.get("staffInfo")); // 쿠키에서 staff 정보를 가져옵니다.
2. 사용자(직원) 정보 로딩
데이터는 “/api/timeManagement” 엔드포인트에서 가져옵니다.
// 컴포넌트가 처음 렌더링될 때 사용자 정보를 가져옵니다.
useEffect(() => {
fetch("/api/timeManagement")
.then((response) => response.json())
.then((data) => {
setUsers(data); // 사용자 정보를 users 상태값에 저장합니다.
});
}, []);
3. 사용자 정보를 테이블 행 데이터로 변환
javascriptCopy code
// users 상태값이 변경될 때마다 rows 상태를 업데이트합니다.
useEffect(() => {
setRows(
users.map((user) => [
user.empNum,
user.empName,
0,
user.vacation,
user.actualWorkDays,
user.workingHours,
user.email,
"no",
])
);
}, [users]);
4. 급여 지급 확인 및 취소
javascriptCopy code
// 급여 지급 버튼을 클릭했을 때의 액션입니다.
const handlePayClick = (index) => {
const confirmed = window.confirm("결제 완료 하시겠습니까?");
if (confirmed) {
alert("결제 완료되었습니다!");
const newRows = [...rows];
newRows[index][7] = "yes";
setRows(newRows);
} else {
alert("취소 되었습니다.");
}
};
5. 무작위 문자열 생성
급여 지급 후, 관리자 코드를 생성하기 위한 로직입니다.
const randum = (max) => Math.floor(Math.random() * max);
const numbers = "0123456789";
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let ran = "";
for (let i = 0; i < 4; i++) {
ran += numbers[randum(numbers.length)] + letters[randum(letters.length)];
}
6. 지급 완료 버튼 클릭 이벤트
급여가 지급되면 관리자에게 결제 정보를 보여줍니다.
const clickTobtn = () => {
alert(`
결제자: ${staffInfo.empName}
결제 일시 : ${new Date()}
관리자 코드: ${staffInfo.empNum}${ran}`);
};
7. 특정 행 클릭 이벤트
javascriptCopy code
// 테이블의 특정 행을 클릭하면 해당 행의 인덱스를 저장합니다.
const handleRowClick = (index) => {
setSelectedRowIndex(index);
};
8. UI 렌더링
컴포넌트의 반환 부분에서 UI가 구성되어 있습니다. 이곳에는 직원의 급여 정보를 나타내는 테이블, 급여 지급 및 취소 버튼, PDF 다운로드 버튼 등의 UI 요소가 포함되어 있습니다.
코드는 주로 “@coreui/react” 및 “reactstrap” 라이브러리를 활용하여 구현되었습니다.
9. PDF 다운로드
테이블의 각 행마다 PDF 다운로드 버튼이 있으며, 해당 버튼을 클릭하면 Pdf
컴포넌트가 실행됩니다.
<Pdf userData={users[rowIndex]} />
위의 코드로 각 사용자의 데이터를 PDF 컴포넌트로 전달하여, 해당 사용자의 정보를 포함한 PDF 파일을 다운로드할 수 있습니다.
전체적으로 이 컴포넌트는 React 훅을 활용하여 서버에서 직원의 급여 정보를 가져와 테이블 형태로 보여주고, 급여 지급 및 취소, PDF 다운로드 등의 기능을 제공합니다.
급여 정산 페이지
CountWeekdays 컴포넌트 코드 분석:
1. 상태(State) 설정:
javascriptCopy code
const [year, setYear] = useState(new Date().getFullYear());
const [month, setMonth] = useState(new Date().getMonth() + 1);
const [weekdays, setWeekdays] = useState(0);
const [workHours, setWorkHours] = useState(0);
- year, setYear: 현재 연도를 기본 값으로 가지는 상태입니다.
- month, setMonth: 현재 월을 기본 값으로 가지는 상태입니다.
- weekdays, setWeekdays: 해당 월의 평일 수를 표시하는 상태입니다.
- workHours, setWorkHours: 소정 근로 시간을 표시하는 상태입니다.
2. 함수:
const countWeekdaysInMonth = (year, month) => {...}
- 이 함수는 주어진 연도와 월에 대해 해당 월의 평일 수를 계산합니다.
date.getDay()
를 사용하여 해당 날짜가 일요일(0) 또는 토요일(6)인지 확인합니다. 주말이 아닐 경우 평일 수를 증가시킵니다.
const calculateWorkHours = (weekdays) => {...}
- 평일 수를 인자로 받아 소정 근로 시간을 계산합니다. 여기서는 하루의 근무 시간을 8시간으로 가정하고 있습니다.
const handleSubmit = () => {...}
- ‘Calculate Weekdays’ 버튼을 클릭하면 실행되는 함수입니다.
- 위의 두 함수를 호출하여 평일 수와 소정 근로 시간을 계산하고, 그 값을 상태에 저장합니다.
3. UI 요소:
- 연도 및 월 입력:
- 사용자는 연도와 월을 숫자로 입력할 수 있습니다.
- 월 입력에 변경이 발생하면 범위를 검사하여 1보다 작거나 12보다 큰 값을 처리합니다.
<CFormInput
type="number"
value={year}
onChange={(e) => setYear(e.target.value)}
/>
- ‘Calculate Weekdays’ 버튼:
- 이 버튼을 클릭하면
handleSubmit
함수가 호출됩니다.
- 이 버튼을 클릭하면
<CButton onClick={handleSubmit}>Calculate Weekdays</CButton>
- 결과 출력:
<CCallout color="primary" className="zzzz">
<CRow>
<CCol md={3}>
{year}년 {month}월의 평일 수: <b>{weekdays}</b>일
</CCol>
<CCol md={2}>
소정근로일수: <b>{weekdays}</b>일
</CCol>
<CCol md={2}>
소정근로시간: <b>{workHours}</b>시간
</CCol>
</CRow>
</CCallout>
- 계산된 평일 수와 소정 근로 시간을 보여줍니다.
Leave a comment