diff --git a/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/AttendanceMapper.java b/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/AttendanceMapper.java new file mode 100644 index 000000000..9a135e75a --- /dev/null +++ b/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/AttendanceMapper.java @@ -0,0 +1,23 @@ +package org.javaboy.vhr.mapper; + +import org.javaboy.vhr.model.Attendance; + +import java.util.List; + +public interface AttendanceMapper { + int deleteByPrimaryKey(Integer id); + + int insert(Attendance record); + + int insertSelective(Attendance record); + + Attendance selectByPrimaryKey(Integer id); + + int updateByPrimaryKeySelective(Attendance record); + + int updateByPrimaryKey(Attendance record); + + List getAllAttendance(); + + List getAttendanceByEmpId(Integer empId); +} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.java b/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.java index fcecbc2f9..8530e8753 100644 --- a/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.java +++ b/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.java @@ -32,4 +32,6 @@ public interface EmployeeMapper { List getEmployeeByPageWithSalary(@Param("page") Integer page, @Param("size") Integer size); Integer updateEmployeeSalaryById(@Param("eid") Integer eid, @Param("sid") Integer sid); + +List getEmployeesBySalaryId(@Param("salaryId") Integer salaryId); } \ No newline at end of file diff --git a/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.xml b/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.xml index 709d5a8dd..72f4fbc49 100644 --- a/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.xml +++ b/vhr/vhrserver/vhr-mapper/src/main/java/org/javaboy/vhr/mapper/EmployeeMapper.xml @@ -99,6 +99,17 @@ REPLACE INTO empsalary (eid,sid) VALUES(#{eid},#{sid}) + select @@ -41,12 +42,12 @@ lunchSalary, trafficSalary, allSalary, pensionBase, pensionPer, createDate, medicalBase, medicalPer, accumulationFundBase, - accumulationFundPer, name) + accumulationFundPer, name, enabled) values (#{id,jdbcType=INTEGER}, #{basicSalary,jdbcType=INTEGER}, #{bonus,jdbcType=INTEGER}, #{lunchSalary,jdbcType=INTEGER}, #{trafficSalary,jdbcType=INTEGER}, #{allSalary,jdbcType=INTEGER}, #{pensionBase,jdbcType=INTEGER}, #{pensionPer,jdbcType=REAL}, #{createDate,jdbcType=TIMESTAMP}, #{medicalBase,jdbcType=INTEGER}, #{medicalPer,jdbcType=REAL}, #{accumulationFundBase,jdbcType=INTEGER}, - #{accumulationFundPer,jdbcType=REAL}, #{name,jdbcType=VARCHAR}) + #{accumulationFundPer,jdbcType=REAL}, #{name,jdbcType=VARCHAR}, #{enabled,jdbcType=BIT}) insert into salary @@ -93,6 +94,9 @@ name, + + enabled, + @@ -137,6 +141,9 @@ #{name,jdbcType=VARCHAR}, + + #{enabled,jdbcType=BIT}, + @@ -181,6 +188,9 @@ name = #{name,jdbcType=VARCHAR}, + + enabled = #{enabled,jdbcType=BIT}, + where id = #{id,jdbcType=INTEGER} @@ -198,7 +208,8 @@ medicalPer = #{medicalPer,jdbcType=REAL}, accumulationFundBase = #{accumulationFundBase,jdbcType=INTEGER}, accumulationFundPer = #{accumulationFundPer,jdbcType=REAL}, - name = #{name,jdbcType=VARCHAR} + name = #{name,jdbcType=VARCHAR}, + enabled = #{enabled,jdbcType=BIT} where id = #{id,jdbcType=INTEGER} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-mapper/src/main/resources/mapper/AttendanceMapper.xml b/vhr/vhrserver/vhr-mapper/src/main/resources/mapper/AttendanceMapper.xml new file mode 100644 index 000000000..8cbcc7cfd --- /dev/null +++ b/vhr/vhrserver/vhr-mapper/src/main/resources/mapper/AttendanceMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + id, eid, attendDate, type, remark + + + + + + delete from attendance + where id = #{id,jdbcType=INTEGER} + + + + insert into attendance (id, eid, attendDate, type, remark) + values (#{id,jdbcType=INTEGER}, #{eid,jdbcType=INTEGER}, #{attendDate,jdbcType=DATE}, #{type,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}) + + + + insert into attendance + + id, + eid, + attendDate, + type, + remark, + + + #{id,jdbcType=INTEGER}, + #{eid,jdbcType=INTEGER}, + #{attendDate,jdbcType=DATE}, + #{type,jdbcType=VARCHAR}, + #{remark,jdbcType=VARCHAR}, + + + + + update attendance + + eid = #{eid,jdbcType=INTEGER}, + attendDate = #{attendDate,jdbcType=DATE}, + type = #{type,jdbcType=VARCHAR}, + remark = #{remark,jdbcType=VARCHAR}, + + where id = #{id,jdbcType=INTEGER} + + + + update attendance + set eid = #{eid,jdbcType=INTEGER}, attendDate = #{attendDate,jdbcType=DATE}, type = #{type,jdbcType=VARCHAR}, remark = #{remark,jdbcType=VARCHAR} + where id = #{id,jdbcType=INTEGER} + + + + + + \ No newline at end of file diff --git a/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Attendance.java b/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Attendance.java new file mode 100644 index 000000000..6d96b86c5 --- /dev/null +++ b/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Attendance.java @@ -0,0 +1,54 @@ +package org.javaboy.vhr.model; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class Attendance { + private Integer id; + private Integer eid; + private Date attendDate; + private String type; + private String remark; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getEid() { + return eid; + } + + public void setEid(Integer eid) { + this.eid = eid; + } + + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai") + public Date getAttendDate() { + return attendDate; + } + + public void setAttendDate(Date attendDate) { + this.attendDate = attendDate; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } +} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Salary.java b/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Salary.java index 2c82202be..7981c7c6d 100644 --- a/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Salary.java +++ b/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/Salary.java @@ -34,6 +34,8 @@ public class Salary { private String name; + private Boolean enabled; + public Integer getId() { return id; } @@ -145,4 +147,12 @@ public String getName() { public void setName(String name) { this.name = name; } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } } \ No newline at end of file diff --git a/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/SalaryHistory.java b/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/SalaryHistory.java new file mode 100644 index 000000000..2c5f3c0f7 --- /dev/null +++ b/vhr/vhrserver/vhr-model/src/main/java/org/javaboy/vhr/model/SalaryHistory.java @@ -0,0 +1,172 @@ +package org.javaboy.vhr.model; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class SalaryHistory { + private Integer id; + private Integer salaryId; + private Integer basicSalary; + private Integer bonus; + private Integer lunchSalary; + private Integer trafficSalary; + private Integer allSalary; + private Integer pensionBase; + private Float pensionPer; + private Integer medicalBase; + private Float medicalPer; + private Integer accumulationFundBase; + private Float accumulationFundPer; + private String name; + private Boolean enabled; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date createDate; + private Integer operatorId; + private String operatorName; + + // Getters and Setters + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getSalaryId() { + return salaryId; + } + + public void setSalaryId(Integer salaryId) { + this.salaryId = salaryId; + } + + public Integer getBasicSalary() { + return basicSalary; + } + + public void setBasicSalary(Integer basicSalary) { + this.basicSalary = basicSalary; + } + + public Integer getBonus() { + return bonus; + } + + public void setBonus(Integer bonus) { + this.bonus = bonus; + } + + public Integer getLunchSalary() { + return lunchSalary; + } + + public void setLunchSalary(Integer lunchSalary) { + this.lunchSalary = lunchSalary; + } + + public Integer getTrafficSalary() { + return trafficSalary; + } + + public void setTrafficSalary(Integer trafficSalary) { + this.trafficSalary = trafficSalary; + } + + public Integer getAllSalary() { + return allSalary; + } + + public void setAllSalary(Integer allSalary) { + this.allSalary = allSalary; + } + + public Integer getPensionBase() { + return pensionBase; + } + + public void setPensionBase(Integer pensionBase) { + this.pensionBase = pensionBase; + } + + public Float getPensionPer() { + return pensionPer; + } + + public void setPensionPer(Float pensionPer) { + this.pensionPer = pensionPer; + } + + public Integer getMedicalBase() { + return medicalBase; + } + + public void setMedicalBase(Integer medicalBase) { + this.medicalBase = medicalBase; + } + + public Float getMedicalPer() { + return medicalPer; + } + + public void setMedicalPer(Float medicalPer) { + this.medicalPer = medicalPer; + } + + public Integer getAccumulationFundBase() { + return accumulationFundBase; + } + + public void setAccumulationFundBase(Integer accumulationFundBase) { + this.accumulationFundBase = accumulationFundBase; + } + + public Float getAccumulationFundPer() { + return accumulationFundPer; + } + + public void setAccumulationFundPer(Float accumulationFundPer) { + this.accumulationFundPer = accumulationFundPer; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public Integer getOperatorId() { + return operatorId; + } + + public void setOperatorId(Integer operatorId) { + this.operatorId = operatorId; + } + + public String getOperatorName() { + return operatorName; + } + + public void setOperatorName(String operatorName) { + this.operatorName = operatorName; + } +} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/AttendanceService.java b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/AttendanceService.java new file mode 100644 index 000000000..36b215540 --- /dev/null +++ b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/AttendanceService.java @@ -0,0 +1,59 @@ +package org.javaboy.vhr.service; + +import org.javaboy.vhr.model.Attendance; +import org.javaboy.vhr.mapper.AttendanceMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class AttendanceService { + + @Autowired + private AttendanceMapper attendanceMapper; + + /** + * 获取所有考勤记录 + * @return 考勤记录列表 + */ + public List getAllAttendance() { + return attendanceMapper.getAllAttendance(); + } + + /** + * 根据员工ID获取考勤记录 + * @param empId 员工ID + * @return 考勤记录列表 + */ + public List getAttendanceByEmpId(Integer empId) { + return attendanceMapper.getAttendanceByEmpId(empId); + } + + /** + * 添加考勤记录 + * @param attendance 考勤记录 + * @return 添加结果 + */ + public int addAttendance(Attendance attendance) { + return attendanceMapper.insertSelective(attendance); + } + + /** + * 更新考勤记录 + * @param attendance 考勤记录 + * @return 更新结果 + */ + public int updateAttendance(Attendance attendance) { + return attendanceMapper.updateByPrimaryKeySelective(attendance); + } + + /** + * 删除考勤记录 + * @param id 考勤记录ID + * @return 删除结果 + */ + public int deleteAttendance(Integer id) { + return attendanceMapper.deleteByPrimaryKey(id); + } +} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/EmployeeService.java b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/EmployeeService.java index 4834a7ef7..26ecd4b99 100644 --- a/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/EmployeeService.java +++ b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/EmployeeService.java @@ -109,4 +109,8 @@ public Integer updateEmployeeSalaryById(Integer eid, Integer sid) { public Employee getEmployeeById(Integer empId) { return employeeMapper.getEmployeeById(empId); } + + public List getEmployeesBySalaryId(Integer salaryId) { + return employeeMapper.getEmployeesBySalaryId(salaryId); + } } diff --git a/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryCalculateService.java b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryCalculateService.java new file mode 100644 index 000000000..b97fd45f9 --- /dev/null +++ b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryCalculateService.java @@ -0,0 +1,155 @@ +package org.javaboy.vhr.service; + +import org.javaboy.vhr.model.Employee; +import org.javaboy.vhr.model.Salary; +import org.javaboy.vhr.model.Attendance; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SalaryCalculateService { + + /** + * 计算员工工资 + * @param employee 员工信息 + * @param attendanceList 考勤记录 + * @return 计算后的工资信息 + */ + public Salary calculateSalary(Employee employee, List attendanceList) { + Salary salary = employee.getSalary(); + if (salary == null) { + return null; + } + + // 计算应发工资 + int grossSalary = calculateGrossSalary(salary); + // 计算社保公积金 + int socialSecurity = calculateSocialSecurity(salary); + // 计算考勤扣款 + int attendanceDeduction = calculateAttendanceDeduction(salary, attendanceList); + // 计算个人所得税 + int incomeTax = calculateIncomeTax(grossSalary - socialSecurity); + // 计算实发工资 + int netSalary = grossSalary - socialSecurity - attendanceDeduction - incomeTax; + + // 创建新的工资对象返回计算结果 + Salary calculatedSalary = new Salary(); + calculatedSalary.setId(salary.getId()); + calculatedSalary.setName(salary.getName()); + calculatedSalary.setBasicSalary(salary.getBasicSalary()); + calculatedSalary.setBonus(salary.getBonus()); + calculatedSalary.setLunchSalary(salary.getLunchSalary()); + calculatedSalary.setTrafficSalary(salary.getTrafficSalary()); + calculatedSalary.setPensionBase(salary.getPensionBase()); + calculatedSalary.setPensionPer(salary.getPensionPer()); + calculatedSalary.setMedicalBase(salary.getMedicalBase()); + calculatedSalary.setMedicalPer(salary.getMedicalPer()); + calculatedSalary.setAccumulationFundBase(salary.getAccumulationFundBase()); + calculatedSalary.setAccumulationFundPer(salary.getAccumulationFundPer()); + calculatedSalary.setCreateDate(salary.getCreateDate()); + calculatedSalary.setEnabled(salary.getEnabled()); + // 设置计算后的总工资 + calculatedSalary.setAllSalary(netSalary); + + return calculatedSalary; + } + + /** + * 计算应发工资 + * @param salary 工资账套 + * @return 应发工资 + */ + private int calculateGrossSalary(Salary salary) { + int gross = 0; + gross += salary.getBasicSalary() != null ? salary.getBasicSalary() : 0; + gross += salary.getBonus() != null ? salary.getBonus() : 0; + gross += salary.getLunchSalary() != null ? salary.getLunchSalary() : 0; + gross += salary.getTrafficSalary() != null ? salary.getTrafficSalary() : 0; + return gross; + } + + /** + * 计算社保公积金 + * @param salary 工资账套 + * @return 社保公积金总额 + */ + private int calculateSocialSecurity(Salary salary) { + int socialSecurity = 0; + // 养老金 + if (salary.getPensionBase() != null && salary.getPensionPer() != null) { + socialSecurity += (int) (salary.getPensionBase() * salary.getPensionPer() / 100); + } + // 医疗保险 + if (salary.getMedicalBase() != null && salary.getMedicalPer() != null) { + socialSecurity += (int) (salary.getMedicalBase() * salary.getMedicalPer() / 100); + } + // 公积金 + if (salary.getAccumulationFundBase() != null && salary.getAccumulationFundPer() != null) { + socialSecurity += (int) (salary.getAccumulationFundBase() * salary.getAccumulationFundPer() / 100); + } + return socialSecurity; + } + + /** + * 计算考勤扣款 + * @param salary 工资账套 + * @param attendanceList 考勤记录 + * @return 考勤扣款 + */ + private int calculateAttendanceDeduction(Salary salary, List attendanceList) { + if (attendanceList == null || attendanceList.isEmpty()) { + return 0; + } + + int deduction = 0; + int basicSalary = salary.getBasicSalary() != null ? salary.getBasicSalary() : 0; + // 假设每月工作日为22天 + int dailySalary = basicSalary / 22; + + for (Attendance attendance : attendanceList) { + if ("旷工".equals(attendance.getType())) { + deduction += dailySalary; + } else if ("迟到".equals(attendance.getType())) { + deduction += 20; + } else if ("早退".equals(attendance.getType())) { + deduction += 20; + } + } + + return deduction; + } + + /** + * 计算个人所得税 + * @param taxableIncome 应纳税所得额 + * @return 个人所得税 + */ + private int calculateIncomeTax(int taxableIncome) { + // 起征点为5000元 + if (taxableIncome <= 5000) { + return 0; + } + + int tax = 0; + int excess = taxableIncome - 5000; + + if (excess <= 3000) { + tax = (int) (excess * 0.03); + } else if (excess <= 12000) { + tax = (int) (3000 * 0.03 + (excess - 3000) * 0.1); + } else if (excess <= 25000) { + tax = (int) (3000 * 0.03 + 9000 * 0.1 + (excess - 12000) * 0.2); + } else if (excess <= 35000) { + tax = (int) (3000 * 0.03 + 9000 * 0.1 + 13000 * 0.2 + (excess - 25000) * 0.25); + } else if (excess <= 55000) { + tax = (int) (3000 * 0.03 + 9000 * 0.1 + 13000 * 0.2 + 10000 * 0.25 + (excess - 35000) * 0.3); + } else if (excess <= 80000) { + tax = (int) (3000 * 0.03 + 9000 * 0.1 + 13000 * 0.2 + 10000 * 0.25 + 20000 * 0.3 + (excess - 55000) * 0.35); + } else { + tax = (int) (3000 * 0.03 + 9000 * 0.1 + 13000 * 0.2 + 10000 * 0.25 + 20000 * 0.3 + 25000 * 0.35 + (excess - 80000) * 0.45); + } + + return tax; + } +} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryService.java b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryService.java index 76715e6ec..2e95d1749 100644 --- a/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryService.java +++ b/vhr/vhrserver/vhr-service/src/main/java/org/javaboy/vhr/service/SalaryService.java @@ -29,4 +29,28 @@ public Integer deleteSalaryById(Integer id) { public Integer updateSalaryById(Salary salary) { return salaryMapper.updateByPrimaryKeySelective(salary); } + + public Integer copySalary(Integer id) { + Salary originalSalary = salaryMapper.selectByPrimaryKey(id); + if (originalSalary == null) { + return 0; + } + // 创建新的工资账套对象 + Salary newSalary = new Salary(); + newSalary.setBasicSalary(originalSalary.getBasicSalary()); + newSalary.setBonus(originalSalary.getBonus()); + newSalary.setLunchSalary(originalSalary.getLunchSalary()); + newSalary.setTrafficSalary(originalSalary.getTrafficSalary()); + newSalary.setAllSalary(originalSalary.getAllSalary()); + newSalary.setPensionBase(originalSalary.getPensionBase()); + newSalary.setPensionPer(originalSalary.getPensionPer()); + newSalary.setMedicalBase(originalSalary.getMedicalBase()); + newSalary.setMedicalPer(originalSalary.getMedicalPer()); + newSalary.setAccumulationFundBase(originalSalary.getAccumulationFundBase()); + newSalary.setAccumulationFundPer(originalSalary.getAccumulationFundPer()); + newSalary.setName(originalSalary.getName() + " (Copy)"); + newSalary.setEnabled(true); + newSalary.setCreateDate(new Date()); + return salaryMapper.insertSelective(newSalary); + } } diff --git a/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/SalaryCalculateController.java b/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/SalaryCalculateController.java new file mode 100644 index 000000000..9a2232204 --- /dev/null +++ b/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/SalaryCalculateController.java @@ -0,0 +1,78 @@ +package org.javaboy.vhr.controller; + +import org.javaboy.vhr.model.Employee; +import org.javaboy.vhr.model.Salary; +import org.javaboy.vhr.model.Attendance; +import org.javaboy.vhr.service.EmployeeService; +import org.javaboy.vhr.service.SalaryCalculateService; +import org.javaboy.vhr.service.AttendanceService; +import org.javaboy.vhr.model.RespBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/salary/calculate") +public class SalaryCalculateController { + + @Autowired + private SalaryCalculateService salaryCalculateService; + + @Autowired + private EmployeeService employeeService; + + @Autowired + private AttendanceService attendanceService; + + /** + * 计算单个员工工资 + * @param empId 员工ID + * @return 计算结果 + */ + @GetMapping("/employee/{empId}") + public RespBean calculateEmployeeSalary(@PathVariable Integer empId) { + Employee employee = employeeService.getEmployeeById(empId); + if (employee == null) { + return RespBean.error("员工不存在"); + } + + List attendanceList = attendanceService.getAttendanceByEmpId(empId); + Salary calculatedSalary = salaryCalculateService.calculateSalary(employee, attendanceList); + + return RespBean.success("工资计算成功", calculatedSalary); + } + + /** + * 计算所有员工工资 + * @return 计算结果 + */ + @GetMapping("/all") + public RespBean calculateAllEmployeeSalary() { + List employees = employeeService.getAllEmployees(); + for (Employee employee : employees) { + List attendanceList = attendanceService.getAttendanceByEmpId(employee.getId()); + Salary calculatedSalary = salaryCalculateService.calculateSalary(employee, attendanceList); + // 可以将计算结果保存到数据库 + // salaryService.updateSalaryById(calculatedSalary); + } + return RespBean.success("所有员工工资计算完成"); + } + + /** + * 根据工资账套计算工资 + * @param salaryId 工资账套ID + * @return 计算结果 + */ + @GetMapping("/salary/{salaryId}") + public RespBean calculateSalaryBySalaryId(@PathVariable Integer salaryId) { + List employees = employeeService.getEmployeesBySalaryId(salaryId); + for (Employee employee : employees) { + List attendanceList = attendanceService.getAttendanceByEmpId(employee.getId()); + Salary calculatedSalary = salaryCalculateService.calculateSalary(employee, attendanceList); + // 可以将计算结果保存到数据库 + // salaryService.updateSalaryById(calculatedSalary); + } + return RespBean.success("工资计算完成"); + } +} \ No newline at end of file diff --git a/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/salary/SalaryController.java b/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/salary/SalaryController.java index 88469563a..e8b5ff642 100644 --- a/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/salary/SalaryController.java +++ b/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/controller/salary/SalaryController.java @@ -42,4 +42,34 @@ public RespBean updateSalaryById(@RequestBody Salary salary) { } return RespBean.error("更新失败!"); } + + @PutMapping("/enable/{id}") + public RespBean enableSalary(@PathVariable Integer id) { + Salary salary = new Salary(); + salary.setId(id); + salary.setEnabled(true); + if (salaryService.updateSalaryById(salary) == 1) { + return RespBean.ok("启用成功!"); + } + return RespBean.error("启用失败!"); + } + + @PutMapping("/disable/{id}") + public RespBean disableSalary(@PathVariable Integer id) { + Salary salary = new Salary(); + salary.setId(id); + salary.setEnabled(false); + if (salaryService.updateSalaryById(salary) == 1) { + return RespBean.ok("禁用成功!"); + } + return RespBean.error("禁用失败!"); + } + + @PostMapping("/copy/{id}") + public RespBean copySalary(@PathVariable Integer id) { + if (salaryService.copySalary(id) == 1) { + return RespBean.ok("复制成功!"); + } + return RespBean.error("复制失败!"); + } } \ No newline at end of file diff --git a/vuehr/src/views/sal/SalSob.vue b/vuehr/src/views/sal/SalSob.vue index 1e2613709..260b5ae52 100644 --- a/vuehr/src/views/sal/SalSob.vue +++ b/vuehr/src/views/sal/SalSob.vue @@ -28,6 +28,10 @@ @@ -135,12 +139,73 @@ this.activeItemIndex--; }, nextStep() { + // 表单验证 + let isValid = true; + let errorMsg = ''; + + switch (this.activeItemIndex) { + case 0: // 基本工资 + if (this.salary.basicSalary <= 0) { + isValid = false; + errorMsg = '基本工资必须大于0'; + } + break; + case 1: // 交通补助 + if (this.salary.trafficSalary < 0) { + isValid = false; + errorMsg = '交通补助不能为负数'; + } + break; + case 2: // 午餐补助 + if (this.salary.lunchSalary < 0) { + isValid = false; + errorMsg = '午餐补助不能为负数'; + } + break; + case 3: // 奖金 + if (this.salary.bonus < 0) { + isValid = false; + errorMsg = '奖金不能为负数'; + } + break; + case 4: // 养老金比率 + case 6: // 医疗保险比率 + case 8: // 公积金比率 + const ratio = this.salary[Object.keys(this.salary)[this.activeItemIndex]]; + if (ratio < 0 || ratio > 100) { + isValid = false; + errorMsg = '比率必须在0-100之间'; + } + break; + case 5: // 养老金基数 + case 7: // 医疗保险基数 + case 9: // 公积金基数 + const base = this.salary[Object.keys(this.salary)[this.activeItemIndex]]; + if (base < 0) { + isValid = false; + errorMsg = '基数不能为负数'; + } + break; + case 10: // 账套名称 + if (!this.salary.name || this.salary.name.trim() === '') { + isValid = false; + errorMsg = '账套名称不能为空'; + } + break; + } + + if (!isValid) { + this.$message.error(errorMsg); + return; + } + if (this.activeItemIndex == 10) { if (this.salary.id) { this.putRequest("/salary/sob/", this.salary).then(resp=>{ if (resp) { this.initSalaries(); this.dialogVisible = false; + this.$message.success('账套修改成功'); } }) } else { @@ -148,6 +213,7 @@ if (resp) { this.initSalaries(); this.dialogVisible = false; + this.$message.success('账套添加成功'); } }); } @@ -180,6 +246,23 @@ this.salaries = resp; } }) + }, + toggleEnable(salary) { + const url = salary.enabled ? "/salary/sob/disable/" + salary.id : "/salary/sob/enable/" + salary.id; + this.putRequest(url).then(resp => { + if (resp) { + this.initSalaries(); + this.$message.success(salary.enabled ? '账套已禁用' : '账套已启用'); + } + }); + }, + copySalary(salary) { + this.postRequest("/salary/sob/copy/" + salary.id).then(resp => { + if (resp) { + this.initSalaries(); + this.$message.success('账套复制成功'); + } + }); } } }