-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/bu 206: 급여 로직 수정 #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
918d61b
feat: 급여 계산 v1.1 입력 DTO 추가
moonhyeonmin 67b04e1
feat: 급여 계산 v1.1 결과 DTO 추가
moonhyeonmin 7302a9a
feat: 급여 계산 v1.1 통합 로직 구현
moonhyeonmin 70a9f98
feat: SalaryGenerationService에 PayrollCalculator v1.1 적용
moonhyeonmin 824aba3
test: v1.1 급여 계산 로직 테스트 코드 작성 및 버그 수정
moonhyeonmin ed0848e
fix: 근로계약서 서명 위치 수정
moonhyeonmin a26b4dc
fix: 일용직 4대보험 계산 시 monthlyWorkDaysAccumulated 값 반영
moonhyeonmin 24a0756
fix: workDays가 0일 때 ArithmeticException 방지 및 린터 경고 수정
moonhyeonmin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
src/main/java/com/concrete/buildup/domain/payroll/dto/InsuranceEligibility.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package com.concrete.buildup.domain.payroll.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| /** | ||
| * 4대보험 가입 여부 DTO | ||
| * | ||
| * <p>근로자의 4대보험 가입 여부 정보를 담는 DTO입니다.</p> | ||
| * <p>산재보험은 근로자 부담이 없으므로 포함하지 않습니다.</p> | ||
| * | ||
| * @author Build-Up Team | ||
| * @since 1.0 | ||
| */ | ||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @Schema(description = "4대보험 가입 여부") | ||
| public class InsuranceEligibility { | ||
|
|
||
| @Schema(description = "고용보험 가입 여부", example = "true", required = true) | ||
| private Boolean employmentInsurance; | ||
|
|
||
| @Schema(description = "건강보험 가입 여부", example = "true", required = true) | ||
| private Boolean healthInsurance; | ||
|
|
||
| @Schema(description = "국민연금 가입 여부", example = "false", required = true) | ||
| private Boolean nationalPension; | ||
|
|
||
| // 산재보험은 근로자 부담이 없으므로 제외 | ||
| } |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/concrete/buildup/domain/payroll/dto/InsuranceRates.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package com.concrete.buildup.domain.payroll.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| import java.math.BigDecimal; | ||
|
|
||
| /** | ||
| * 4대보험 요율 DTO | ||
| * | ||
| * <p>4대보험의 근로자 부담 요율 정보를 담는 DTO입니다.</p> | ||
| * <p>2025년 기준 요율: 국민연금 4.5%, 건강보험 3.545%, 장기요양 12.81%, 고용보험 0.9%</p> | ||
| * | ||
| * @author Build-Up Team | ||
| * @since 1.0 | ||
| */ | ||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @Schema(description = "4대보험 요율 정보") | ||
| public class InsuranceRates { | ||
|
|
||
| @Schema(description = "국민연금 요율 (2025년 기준: 0.045)", example = "0.045", required = true) | ||
| private BigDecimal nationalPension; | ||
|
|
||
| @Schema(description = "건강보험 요율 (2025년 기준: 0.03545)", example = "0.03545", required = true) | ||
| private BigDecimal healthInsurance; | ||
|
|
||
| @Schema(description = "장기요양보험 요율 (건강보험료의 비율, 2025년 기준: 0.1281)", example = "0.1281", required = true) | ||
| private BigDecimal longTermCare; | ||
|
|
||
| @Schema(description = "고용보험 요율 (2025년 기준: 0.009)", example = "0.009", required = true) | ||
| private BigDecimal employmentInsurance; | ||
|
|
||
| // 산재보험은 사업주 전액 부담이므로 제외 | ||
|
|
||
| /** | ||
| * 2025년 기준 기본 요율로 초기화된 InsuranceRates 생성 | ||
| * | ||
| * @return 2025년 기준 요율 | ||
| */ | ||
| public static InsuranceRates defaultRates2025() { | ||
| return InsuranceRates.builder() | ||
| .nationalPension(new BigDecimal("0.045")) | ||
| .healthInsurance(new BigDecimal("0.03545")) | ||
| .longTermCare(new BigDecimal("0.1281")) | ||
| .employmentInsurance(new BigDecimal("0.009")) | ||
| .build(); | ||
| } | ||
| } | ||
56 changes: 56 additions & 0 deletions
56
src/main/java/com/concrete/buildup/domain/payroll/dto/OvertimeConditions.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package com.concrete.buildup.domain.payroll.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| /** | ||
| * 가산수당 발생/지급 조건 DTO | ||
| * | ||
| * <p>연장/야간/휴일 가산수당의 지급 조건을 판단하기 위한 정보를 담는 DTO입니다.</p> | ||
| * <p>5인 이상 사업장은 가산수당 지급 의무, 5인 미만은 선택적 지급 가능합니다.</p> | ||
| * | ||
| * @author Build-Up Team | ||
| * @since 1.0 | ||
| */ | ||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @Schema(description = "가산수당 발생/지급 조건") | ||
| public class OvertimeConditions { | ||
|
|
||
| // ========== 사업장 규모 ========== | ||
|
|
||
| @Schema(description = "상시근로자 수 (5인 이상이면 가산수당 의무 지급)", example = "10", required = true) | ||
| private Integer totalEmployees; | ||
|
Comment on lines
+27
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
- @Schema(description = "상시근로자 수 (5인 이상이면 가산수당 의무 지급)", example = "10", required = true)
- private Integer totalEmployees;
+ @Schema(description = "상시근로자 수 (5인 이상이면 가산수당 의무 지급)", example = "10", required = true)
+ @Builder.Default
+ private Integer totalEmployees = 0;또는 🤖 Prompt for AI Agents |
||
|
|
||
| // ========== 5인 미만 사업장의 자율 지급 정책 ========== | ||
|
|
||
| @Schema(description = "연장수당 자율 지급 여부 (5인 미만일 때)", example = "true") | ||
| private Boolean autoPayOvertime; | ||
|
|
||
| @Schema(description = "야간수당 자율 지급 여부 (5인 미만일 때)", example = "true") | ||
| private Boolean autoPayNight; | ||
|
|
||
| @Schema(description = "휴일수당 자율 지급 여부 (5인 미만일 때)", example = "true") | ||
| private Boolean autoPayHoliday; | ||
|
|
||
| // ========== 연장근로 발생 조건 ========== | ||
|
|
||
| @Schema(description = "일 8시간 초과 여부", example = "true") | ||
| private Boolean exceedsDailyLimit; | ||
|
|
||
| @Schema(description = "주 40시간 초과 여부", example = "false") | ||
| private Boolean exceedsWeeklyLimit; | ||
|
|
||
| // ========== 야간/휴일 근로 존재 여부 ========== | ||
|
|
||
| @Schema(description = "야간근로 존재 여부 (22:00~06:00 구간 근로)", example = "true") | ||
| private Boolean hasNightWork; | ||
|
|
||
| @Schema(description = "휴일근로 존재 여부 (주휴일/법정공휴일 근로)", example = "false") | ||
| private Boolean hasHolidayWork; | ||
| } | ||
89 changes: 89 additions & 0 deletions
89
src/main/java/com/concrete/buildup/domain/payroll/dto/PayrollCalculationInput.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| package com.concrete.buildup.domain.payroll.dto; | ||
|
|
||
| import com.concrete.buildup.domain.contract.enums.EmpType; | ||
| import com.concrete.buildup.domain.contract.enums.PayPeriod; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| import java.math.BigDecimal; | ||
|
|
||
| /** | ||
| * 급여 계산 입력 DTO | ||
| * | ||
| * <p>급여 계산에 필요한 모든 입력 정보를 담는 DTO입니다.</p> | ||
| * <p>v1.1 급여 계산 로직의 입력 파라미터로 사용됩니다.</p> | ||
| * | ||
| * @author Build-Up Team | ||
| * @since 1.0 | ||
| */ | ||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @Schema(description = "급여 계산 입력 정보") | ||
| public class PayrollCalculationInput { | ||
|
|
||
| // ========== 기본 정보 ========== | ||
|
|
||
| @Schema(description = "고용 형태 (DAILY: 일용직, PERMANENT: 상용직)", example = "DAILY", required = true) | ||
| private EmpType empType; | ||
|
|
||
| @Schema(description = "지급 주기 (DAILY: 일, WEEKLY: 주, MONTHLY: 월)", example = "DAILY", required = true) | ||
| private PayPeriod payPeriod; | ||
|
|
||
| @Schema(description = "시급", example = "10000", required = true) | ||
| private BigDecimal hourlyRate; | ||
|
|
||
| @Schema(description = "1일 소정근로시간", example = "8", required = true) | ||
| private BigDecimal dailyWorkHours; | ||
|
|
||
| @Schema(description = "근로일수", example = "20", required = true) | ||
| private Integer workDays; | ||
|
|
||
| // ========== 가산 시간 (발생 시간) ========== | ||
|
|
||
| @Schema(description = "연장근로시간", example = "10") | ||
| private BigDecimal overtimeHours; | ||
|
|
||
| @Schema(description = "야간근로시간", example = "5") | ||
| private BigDecimal nightHours; | ||
|
|
||
| @Schema(description = "휴일근로시간", example = "8") | ||
| private BigDecimal holidayHours; | ||
|
|
||
| // ========== 주휴수당 ========== | ||
|
|
||
| @Schema(description = "주휴수당 대상 여부", example = "true") | ||
| private Boolean weeklyHolidayEligible; | ||
|
|
||
| // ========== 4대보험 가입 여부 ========== | ||
|
|
||
| @Schema(description = "보험 가입 여부", required = true) | ||
| private InsuranceEligibility insurance; | ||
|
|
||
| // ========== 세금 관련 (상용직) ========== | ||
|
|
||
| @Schema(description = "부양가족 수 (상용직 세금 계산용)", example = "2") | ||
| private Integer dependents; | ||
|
|
||
| // ========== 요율 ========== | ||
|
|
||
| @Schema(description = "보험 요율 정보", required = true) | ||
| private InsuranceRates rates; | ||
|
|
||
| // ========== 가산수당 조건 ========== | ||
|
|
||
| @Schema(description = "가산수당 발생/지급 조건", required = true) | ||
| private OvertimeConditions overtimeConditions; | ||
|
|
||
| // ========== 일용직 세금 계산용 (추가) ========== | ||
|
|
||
| @Schema(description = "당월 근로일수 누적 (일용직 4대보험 적용 판단용)", example = "8") | ||
| private Integer monthlyWorkDaysAccumulated; | ||
|
|
||
| @Schema(description = "월 환산 소득 (일용직 4대보험 적용 판단용)", example = "2200000") | ||
| private BigDecimal monthlyEstimatedIncome; | ||
| } |
122 changes: 122 additions & 0 deletions
122
src/main/java/com/concrete/buildup/domain/payroll/dto/PayrollCalculationResult.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| package com.concrete.buildup.domain.payroll.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| import java.math.BigDecimal; | ||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * 급여 계산 결과 DTO | ||
| * | ||
| * <p>급여 계산의 최종 결과를 담는 DTO입니다.</p> | ||
| * <p>지급 항목, 공제 항목, 실지급액을 모두 포함합니다.</p> | ||
| * | ||
| * @author Build-Up Team | ||
| * @since 1.0 | ||
| */ | ||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| @Schema(description = "급여 계산 결과") | ||
| public class PayrollCalculationResult { | ||
|
|
||
| // ========== 지급 항목 ========== | ||
|
|
||
| @Schema(description = "기본급 (시급 × 총 통상시간)", example = "1600000") | ||
| private BigDecimal basePay; | ||
|
|
||
| @Schema(description = "연장수당 (시급 × 연장시간 × 1.5)", example = "150000") | ||
| private BigDecimal overtimePay; | ||
|
|
||
| @Schema(description = "야간수당 (시급 × 야간시간 × 0.5)", example = "50000") | ||
| private BigDecimal nightPay; | ||
|
|
||
| @Schema(description = "휴일수당 (시급 × 휴일시간 × 1.5)", example = "120000") | ||
| private BigDecimal holidayPay; | ||
|
|
||
| @Schema(description = "주휴수당 (일용직 조건 충족 시)", example = "80000") | ||
| private BigDecimal weeklyHolidayPay; | ||
|
|
||
| @Schema(description = "총 지급액 (모든 지급 항목의 합)", example = "2000000") | ||
| private BigDecimal totalPay; | ||
|
|
||
| // ========== 공제 항목 ========== | ||
|
|
||
| @Schema(description = "소득세 (일용직: 일별 계산, 상용직: 간이세액표)", example = "33000") | ||
| private BigDecimal incomeTax; | ||
|
|
||
| @Schema(description = "지방소득세 (주민세, 소득세의 10%)", example = "3300") | ||
| private BigDecimal residentTax; | ||
|
|
||
| @Schema(description = "고용보험 (과세대상금액 × 0.9%)", example = "18000") | ||
| private BigDecimal employmentInsurance; | ||
|
|
||
| @Schema(description = "건강보험 (과세대상금액 × 3.545%)", example = "70900") | ||
| private BigDecimal healthInsurance; | ||
|
|
||
| @Schema(description = "장기요양보험 (건강보험료 × 12.81%)", example = "9084") | ||
| private BigDecimal longTermCareInsurance; | ||
|
|
||
| @Schema(description = "국민연금 (과세대상금액 × 4.5%)", example = "90000") | ||
| private BigDecimal nationalPension; | ||
|
|
||
| @Schema(description = "총 공제액 (모든 공제 항목의 합)", example = "224284") | ||
| private BigDecimal totalDeduction; | ||
|
|
||
| // ========== 최종 금액 ========== | ||
|
|
||
| @Schema(description = "실지급액 (총 지급액 - 총 공제액)", example = "1775716") | ||
| private BigDecimal netPay; | ||
|
|
||
| // ========== 계산 상세 (디버깅/로그용) ========== | ||
|
|
||
| @Schema(description = "계산 상세 정보 (디버깅용)", example = "{\"totalWorkHours\": 160, \"taxableIncome\": 2000000}") | ||
| private Map<String, Object> calculationDetails; | ||
|
|
||
| /** | ||
| * 총 지급액 계산 | ||
| * | ||
| * @return 모든 지급 항목의 합 | ||
| */ | ||
| public BigDecimal calculateTotalPay() { | ||
| BigDecimal total = BigDecimal.ZERO; | ||
| if (basePay != null) total = total.add(basePay); | ||
| if (overtimePay != null) total = total.add(overtimePay); | ||
| if (nightPay != null) total = total.add(nightPay); | ||
| if (holidayPay != null) total = total.add(holidayPay); | ||
| if (weeklyHolidayPay != null) total = total.add(weeklyHolidayPay); | ||
| return total; | ||
| } | ||
|
|
||
| /** | ||
| * 총 공제액 계산 | ||
| * | ||
| * @return 모든 공제 항목의 합 | ||
| */ | ||
| public BigDecimal calculateTotalDeduction() { | ||
| BigDecimal total = BigDecimal.ZERO; | ||
| if (incomeTax != null) total = total.add(incomeTax); | ||
| if (residentTax != null) total = total.add(residentTax); | ||
| if (employmentInsurance != null) total = total.add(employmentInsurance); | ||
| if (healthInsurance != null) total = total.add(healthInsurance); | ||
| if (longTermCareInsurance != null) total = total.add(longTermCareInsurance); | ||
| if (nationalPension != null) total = total.add(nationalPension); | ||
| return total; | ||
| } | ||
|
|
||
| /** | ||
| * 실지급액 계산 | ||
| * | ||
| * @return 총 지급액 - 총 공제액 | ||
| */ | ||
| public BigDecimal calculateNetPay() { | ||
| BigDecimal total = totalPay != null ? totalPay : calculateTotalPay(); | ||
| BigDecimal deduction = totalDeduction != null ? totalDeduction : calculateTotalDeduction(); | ||
| return total.subtract(deduction); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.