src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
@@ -7,9 +7,12 @@ import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; @Mapper public interface SysUserDeptMapper extends BaseMapper<SysUserDept> { List<SysUserDeptVo> userLoginFacotryList(@Param("userDeptVo") SysUserDeptVo userDeptVo); List<Map<String, Object>> setSchemeApplicableStaffUserInfo(@Param("ids") List<Long> ids); } src/main/java/com/ruoyi/staff/controller/BankController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,61 @@ package com.ruoyi.staff.controller; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.staff.pojo.Bank; import com.ruoyi.staff.service.BankService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; /** * <p> * é¶è¡ç®¡ç表 å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 03:40:54 */ @Api(tags = "é¶è¡ç®¡ç表") @RestController @RequestMapping("/bank") public class BankController { @Autowired private BankService bankService; @GetMapping("/list") public AjaxResult list() { return AjaxResult.success(bankService.list()); } @PostMapping("/add") @ApiOperation("æ°å¢é¶è¡ç®¡ç表") @Transactional(rollbackFor = Exception.class) @Log(title = "é¶è¡ç®¡ç表", businessType = BusinessType.INSERT) public AjaxResult add(@RequestBody Bank bank) { return AjaxResult.success(bankService.save(bank)); } @PostMapping("/update") @ApiOperation("æ´æ°é¶è¡ç®¡ç表") @Transactional(rollbackFor = Exception.class) @Log(title = "é¶è¡ç®¡ç表", businessType = BusinessType.UPDATE) public AjaxResult update(@RequestBody Bank bank) { return AjaxResult.success(bankService.updateById(bank)); } @DeleteMapping("/delete") @ApiOperation("å é¤é¶è¡ç®¡ç表") @Transactional(rollbackFor = Exception.class) @Log(title = "é¶è¡ç®¡ç表", businessType = BusinessType.DELETE) public AjaxResult delete(@RequestBody List<Long> ids) { return AjaxResult.success(bankService.removeBatchByIds(ids)); } } src/main/java/com/ruoyi/staff/controller/StaffSalaryDetailController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.staff.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * åå·¥å·¥èµæç»è¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:24:35 */ @RestController @RequestMapping("/staffSalaryDetail") public class StaffSalaryDetailController { } src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,72 @@ package com.ruoyi.staff.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.staff.pojo.StaffSalaryMain; import com.ruoyi.staff.service.StaffSalaryMainService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.aspectj.weaver.loadtime.Aj; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; /** * <p> * å工工èµä¸»è¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:22:05 */ @Api(tags = "å工工èµä¸»è¡¨") @RestController @RequestMapping("/staffSalaryMain") public class StaffSalaryMainController { @Autowired private StaffSalaryMainService staffSalaryMainService; @GetMapping("/listPage") @ApiOperation("å工工èµä¸»è¡¨å页æ¥è¯¢") public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) { return staffSalaryMainService.listPage(page, staffSalaryMain); } @ApiOperation("éè¿é¨é¨idsè·åç¨æ·ä¿¡æ¯è®¡ç®æ¯ä¸ªåå·¥çå·¥èµ") @PostMapping("/calculateSalary") public AjaxResult calculateSalary(@RequestBody List<Long> ids) { return staffSalaryMainService.calculateSalary(ids); } @PostMapping("/add") @ApiOperation("æ°å»ºå·¥èµè¡¨") @Log(title = "æ°å»ºå·¥èµè¡¨", businessType = BusinessType.INSERT) @Transactional(rollbackFor = Exception.class) public AjaxResult add(@RequestBody StaffSalaryMain staffSalaryMain) { return staffSalaryMainService.add(staffSalaryMain); } @PostMapping("/update") @ApiOperation("ä¿®æ¹å·¥èµè¡¨") @Log(title = "ä¿®æ¹å·¥èµè¡¨", businessType = BusinessType.UPDATE) @Transactional(rollbackFor = Exception.class) public AjaxResult updateStaffSalaryMain(@RequestBody StaffSalaryMain staffSalaryMain) { return staffSalaryMainService.updateStaffSalaryMain(staffSalaryMain); } @DeleteMapping("/delete") @ApiOperation("å é¤å·¥èµè¡¨") @Log(title = "å é¤å·¥èµè¡¨", businessType = BusinessType.DELETE) @Transactional(rollbackFor = Exception.class) public AjaxResult delete(@RequestBody List<Long> ids) { return staffSalaryMainService.delete(ids); } } src/main/java/com/ruoyi/staff/controller/TaxCalculator.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,102 @@ package com.ruoyi.staff.controller; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; /** * æåº¦ä¸ªç¨è®¡ç®å·¥å ·ç±»ï¼ä» éæåº¦æ¶å ¥ã社ä¿ä¸ªäººãå ¬ç§¯é个人ä¸ä¸ªåæ°ï¼ */ public class TaxCalculator { // æåº¦å å¾é¢ï¼5000å ï¼ private static final BigDecimal MONTHLY_EXEMPTION = new BigDecimal("5000"); // æåº¦ä¸ªç¨ç¨ç表ï¼[åºçº³ç¨æå¾é¢ä¸é, ç¨ç, éç®æ£é¤æ°] private static final List<TaxBracket> MONTHLY_TAX_BRACKETS = new ArrayList<>(); // éæåå§åç¨çè¡¨ï¼ææåº¦æ¢ç®ï¼å¯¹åºå ¨å¹´è¡¨/12ï¼ static { MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("3000"), new BigDecimal("0.03"), new BigDecimal("0"))); MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("12000"), new BigDecimal("0.10"), new BigDecimal("210"))); MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("25000"), new BigDecimal("0.20"), new BigDecimal("1410"))); MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("35000"), new BigDecimal("0.25"), new BigDecimal("2660"))); MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("55000"), new BigDecimal("0.30"), new BigDecimal("4410"))); MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("80000"), new BigDecimal("0.35"), new BigDecimal("7160"))); MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("999999"), new BigDecimal("0.45"), new BigDecimal("15160"))); } // ç¨ç表å é¨ç±» private static class TaxBracket { final BigDecimal max; // 该档ä½åºçº³ç¨æå¾é¢ä¸é final BigDecimal rate; // ç¨ç final BigDecimal deduction; // éç®æ£é¤æ° TaxBracket(BigDecimal max, BigDecimal rate, BigDecimal deduction) { this.max = max; this.rate = rate; this.deduction = deduction; } } /** * 计ç®åæä¸ªäººæå¾ç¨ï¼ä» éä¸ä¸ªåæ°ï¼ * @param monthlyIncome æåº¦æ¶å ¥ï¼ç¨åï¼ * @param socialSecurity 社ä¿ä¸ªäººç¼´çº³éé¢ * @param fund å ¬ç§¯é个人缴纳éé¢ * @return æåº¦åºç¼´ä¸ªç¨ï¼ä¿ç2ä½å°æ°ï¼ */ public static BigDecimal calculateMonthlyTax( BigDecimal monthlyIncome, BigDecimal socialSecurity, BigDecimal fund ) { // 1. 空å¼/è´æ°å¤çï¼åæ°ä¸ºnullæè´æ°æ¶æ0è®¡ç® monthlyIncome = (monthlyIncome == null || monthlyIncome.compareTo(BigDecimal.ZERO) < 0) ? BigDecimal.ZERO : monthlyIncome; socialSecurity = (socialSecurity == null || socialSecurity.compareTo(BigDecimal.ZERO) < 0) ? BigDecimal.ZERO : socialSecurity; fund = (fund == null || fund.compareTo(BigDecimal.ZERO) < 0) ? BigDecimal.ZERO : fund; // 2. è®¡ç®æåº¦åºçº³ç¨æå¾é¢ = æåº¦æ¶å ¥ - 5000å å¾é¢ - 社ä¿ä¸ªäºº - å ¬ç§¯é个人 BigDecimal taxableIncome = monthlyIncome .subtract(MONTHLY_EXEMPTION) .subtract(socialSecurity) .subtract(fund); // 3. åºçº³ç¨æå¾é¢â¤0æ¶ï¼ä¸ªç¨ä¸º0 if (taxableIncome.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); } // 4. å¹é ç¨çæ¡£ä½è®¡ç®ä¸ªç¨ for (TaxBracket bracket : MONTHLY_TAX_BRACKETS) { if (taxableIncome.compareTo(bracket.max) <= 0) { return taxableIncome.multiply(bracket.rate) .subtract(bracket.deduction) .setScale(2, RoundingMode.HALF_UP); } } // 5. è¶ è¿æé«æ¡£ä½ï¼80000å ï¼çæ åµ TaxBracket lastBracket = MONTHLY_TAX_BRACKETS.get(MONTHLY_TAX_BRACKETS.size() - 1); return taxableIncome.multiply(lastBracket.rate) .subtract(lastBracket.deduction) .setScale(2, RoundingMode.HALF_UP); } // æµè¯ç¤ºä¾ public static void main(String[] args) { // 示ä¾1ï¼ææ¶å ¥10000ï¼ç¤¾ä¿ä¸ªäºº800ï¼å ¬ç§¯é个人500 BigDecimal income1 = new BigDecimal("10000"); BigDecimal social1 = new BigDecimal("800"); BigDecimal fund1 = new BigDecimal("500"); BigDecimal tax1 = calculateMonthlyTax(income1, social1, fund1); System.out.println("ææ¶å ¥10000ï¼ç¤¾ä¿800ï¼å ¬ç§¯é500ï¼ä¸ªç¨ï¼" + tax1 + " å "); // 计ç®ç»æï¼111.00 å // 示ä¾2ï¼ææ¶å ¥5000ï¼ç¤¾ä¿500ï¼å ¬ç§¯é200 BigDecimal income2 = new BigDecimal("5000"); BigDecimal social2 = new BigDecimal("500"); BigDecimal fund2 = new BigDecimal("200"); BigDecimal tax2 = calculateMonthlyTax(income2, social2, fund2); System.out.println("ææ¶å ¥5000ï¼ç¤¾ä¿500ï¼å ¬ç§¯é200ï¼ä¸ªç¨ï¼" + tax2 + " å "); // 计ç®ç»æï¼0.00 å } } src/main/java/com/ruoyi/staff/mapper/BankMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.staff.mapper; import com.ruoyi.staff.pojo.Bank; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * <p> * é¶è¡ç®¡ç表 Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 03:40:54 */ @Mapper public interface BankMapper extends BaseMapper<Bank> { } src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java
@@ -2,7 +2,11 @@ import com.ruoyi.staff.pojo.SchemeApplicableStaff; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.staff.pojo.SchemeInsuranceDetail; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <p> @@ -14,5 +18,17 @@ */ @Mapper public interface SchemeApplicableStaffMapper extends BaseMapper<SchemeApplicableStaff> { /** * æ ¹æ®äººåIDæ¥è¯¢å¯¹åºçç¤¾ä¿æ¹æ¡ï¼æ ¸å¿æ¹æ³ï¼ * @param staffId 人åID * @return 该人åéç¨çææç¤¾ä¿æ¹æ¡å表 */ List<SchemeApplicableStaff> selectSchemeByStaffId(@Param("staffId") Long staffId); /** * æ ¹æ®ç¤¾ä¿æ¹æ¡IDæ¥è¯¢å¯¹åºçæç»å表 * @param schemeId ç¤¾ä¿æ¹æ¡ID * @return æ¹æ¡æç»å表 */ List<SchemeInsuranceDetail> selectDetailBySchemeId(@Param("schemeId") Long schemeId); } src/main/java/com/ruoyi/staff/mapper/StaffSalaryDetailMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.staff.mapper; import com.ruoyi.staff.pojo.StaffSalaryDetail; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * <p> * åå·¥å·¥èµæç»è¡¨ Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:24:35 */ @Mapper public interface StaffSalaryDetailMapper extends BaseMapper<StaffSalaryDetail> { } src/main/java/com/ruoyi/staff/mapper/StaffSalaryMainMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.staff.mapper; import com.ruoyi.staff.pojo.StaffSalaryMain; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * <p> * å工工èµä¸»è¡¨ Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:22:05 */ @Mapper public interface StaffSalaryMainMapper extends BaseMapper<StaffSalaryMain> { } src/main/java/com/ruoyi/staff/pojo/Bank.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,33 @@ package com.ruoyi.staff.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; /** * <p> * é¶è¡ç®¡ç表 * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 03:40:54 */ @Getter @Setter @TableName("bank") @ApiModel(value = "Bank对象", description = "é¶è¡ç®¡ç表") public class Bank implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) private Long id; @ApiModelProperty("é¶è¡åç§°") private String bankName; } src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,102 @@ package com.ruoyi.staff.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; /** * <p> * åå·¥å·¥èµæç»è¡¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:24:35 */ @Getter @Setter @TableName("staff_salary_detail") @ApiModel(value = "StaffSalaryDetail对象", description = "åå·¥å·¥èµæç»è¡¨") public class StaffSalaryDetail implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty("主é®ID") @TableId(value = "id", type = IdType.AUTO) private Long id; @ApiModelProperty("å ³èå·¥èµä¸»è¡¨ID") private Long mainId; @ApiModelProperty("å ³èstaff_on_job表主é®ID") private Long staffOnJobId; @ApiModelProperty("åå·¥å§å") private String staffName; @ApiModelProperty("èä½åç§°") private String postName; @ApiModelProperty("é¨é¨åç§°") private String deptName; @ApiModelProperty("åºæ¬å·¥èµ") private BigDecimal basicSalary; @ApiModelProperty("计件工èµ") private BigDecimal pieceSalary; @ApiModelProperty("计æ¶å·¥èµ") private BigDecimal hourlySalary; @ApiModelProperty("å ¶ä»æ¶å ¥") private BigDecimal otherIncome; @ApiModelProperty("社ä¿ä¸ªäºº") private BigDecimal socialPersonal; @ApiModelProperty("å ¬ç§¯é个人") private BigDecimal fundPersonal; @ApiModelProperty("å ¶ä»æ¯åº") private BigDecimal otherDeduct; @ApiModelProperty("å·¥èµä¸ªç¨") private BigDecimal salaryTax; @ApiModelProperty("åºåå·¥èµ") private BigDecimal grossSalary; @ApiModelProperty("åºæ£å·¥èµ") private BigDecimal deductSalary; @ApiModelProperty("å®åå·¥èµ") private BigDecimal netSalary; @ApiModelProperty("夿³¨") private String remark; @ApiModelProperty("å建æ¶é´") @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @ApiModelProperty("åå»ºç¨æ·") @TableField(fill = FieldFill.INSERT) private Long createUser; @ApiModelProperty("ä¿®æ¹æ¶é´") @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @ApiModelProperty("ä¿®æ¹ç¨æ·") @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUser; } src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,93 @@ package com.ruoyi.staff.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; /** * <p> * å工工èµä¸»è¡¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:22:05 */ @Getter @Setter @TableName("staff_salary_main") @ApiModel(value = "StaffSalaryMain对象", description = "å工工èµä¸»è¡¨") public class StaffSalaryMain implements Serializable { private static final long serialVersionUID = 1L; @TableField(exist = false) private List<StaffSalaryDetail> staffSalaryDetailList; @ApiModelProperty("主é®ID") @TableId(value = "id", type = IdType.AUTO) private Long id; @ApiModelProperty("å®¡æ ¸äººId") private Long auditUserId; @ApiModelProperty("å®¡æ ¸äººåç§°") private String auditUserName; @ApiModelProperty("å·¥èµä¸»é¢") private String salaryTitle; @ApiModelProperty("å ³èé¨é¨IDï¼å¤ä¸ªç¨éå·åé") private String deptIds; @ApiModelProperty("å·¥èµæä»½ï¼æ ¼å¼ï¼yyyy-MM") private String salaryMonth; @ApiModelProperty("夿³¨") private String remark; @ApiModelProperty("ç¶æï¼1-è稿 2-å®¡æ ¸æªéè¿ 3-å¾ å®¡æ ¸ 4-å¾ åæ¾ 5-已忾") private Integer status; @ApiModelProperty("å·¥èµæ»é¢") private BigDecimal totalSalary; @ApiModelProperty("æ¯ä»é¶è¡") private String payBank; @TableField(exist = false) @ApiModelProperty("å建人") private String createUserName; @ApiModelProperty("åæ¾æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING) private LocalDateTime payTime; @ApiModelProperty("å建æ¶é´") @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING) private LocalDateTime createTime; @ApiModelProperty("åå»ºç¨æ·") @TableField(fill = FieldFill.INSERT) private Long createUser; @ApiModelProperty("ä¿®æ¹æ¶é´") @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @ApiModelProperty("ä¿®æ¹ç¨æ·") @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUser; } src/main/java/com/ruoyi/staff/service/BankService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.staff.service; import com.ruoyi.staff.pojo.Bank; import com.baomidou.mybatisplus.extension.service.IService; /** * <p> * é¶è¡ç®¡ç表 æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 03:40:54 */ public interface BankService extends IService<Bank> { } src/main/java/com/ruoyi/staff/service/StaffSalaryDetailService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.staff.service; import com.ruoyi.staff.pojo.StaffSalaryDetail; import com.baomidou.mybatisplus.extension.service.IService; /** * <p> * åå·¥å·¥èµæç»è¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:24:35 */ public interface StaffSalaryDetailService extends IService<StaffSalaryDetail> { } src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ package com.ruoyi.staff.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.staff.pojo.StaffSalaryMain; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; /** * <p> * å工工èµä¸»è¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:22:05 */ public interface StaffSalaryMainService extends IService<StaffSalaryMain> { AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain); AjaxResult add(StaffSalaryMain staffSalaryMain); AjaxResult updateStaffSalaryMain(StaffSalaryMain staffSalaryMain); AjaxResult delete(List<Long> ids); AjaxResult calculateSalary(List<Long> ids); } src/main/java/com/ruoyi/staff/service/impl/BankServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.ruoyi.staff.service.impl; import com.ruoyi.staff.pojo.Bank; import com.ruoyi.staff.mapper.BankMapper; import com.ruoyi.staff.service.BankService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * <p> * é¶è¡ç®¡ç表 æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 03:40:54 */ @Service public class BankServiceImpl extends ServiceImpl<BankMapper, Bank> implements BankService { } src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
@@ -10,19 +10,24 @@ import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysUserDeptMapper; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.staff.controller.TaxCalculator; import com.ruoyi.staff.dto.StaffOnJobDto; import com.ruoyi.staff.mapper.SchemeInsuranceDetailMapper; import com.ruoyi.staff.mapper.StaffOnJobMapper; import com.ruoyi.staff.pojo.SchemeApplicableStaff; import com.ruoyi.staff.mapper.SchemeApplicableStaffMapper; import com.ruoyi.staff.pojo.SchemeInsuranceDetail; import com.ruoyi.staff.pojo.StaffOnJob; import com.ruoyi.staff.service.IStaffOnJobService; import com.ruoyi.staff.service.SchemeApplicableStaffService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Arrays; import java.util.List; import java.util.Objects; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** @@ -50,6 +55,9 @@ @Autowired private SysDeptMapper sysDeptMapper; @Autowired private StaffOnJobMapper staffOnJobMapper; @Override @@ -88,22 +96,19 @@ public void setSchemeApplicableStaffUserInfo(SchemeApplicableStaff schemeApplicableStaff) { // éè¿é¨é¨è·å人åid List<SysUserDept> sysUserDepts = sysUserDeptMapper.selectList(new LambdaQueryWrapper<SysUserDept>() .in(SysUserDept::getDeptId, schemeApplicableStaff.getDeptIds())); if(CollectionUtils.isEmpty(sysUserDepts)){ String[] split = schemeApplicableStaff.getDeptIds().split(","); List<StaffOnJob> staffOnJobs = staffOnJobMapper.selectList(new LambdaQueryWrapper<StaffOnJob>() .in(StaffOnJob::getSysDeptId, Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList()))); if(CollectionUtils.isEmpty(staffOnJobs)){ throw new IllegalArgumentException("é¨é¨ä¸æ åå·¥"); } List<SysUser> sysUsers = sysUserMapper.selectUserByIds(sysUserDepts.stream().map(SysUserDept::getUserId).collect(Collectors.toList())); if(CollectionUtils.isEmpty(sysUsers)){ throw new IllegalArgumentException("é¨é¨ä¸æ åå·¥"); } schemeApplicableStaff.setStaffIds(sysUsers schemeApplicableStaff.setStaffIds(staffOnJobs .stream() .map(SysUser::getUserId) .map(StaffOnJob::getId) .filter(Objects::nonNull) // è¿æ»¤æ null å¼ .map(String::valueOf) .collect(Collectors.joining( ","))); schemeApplicableStaff.setStaffNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(","))); schemeApplicableStaff.setStaffNames(staffOnJobs.stream().map(StaffOnJob::getStaffName).collect(Collectors.joining(","))); } @Override @@ -150,4 +155,113 @@ .in(SchemeInsuranceDetail::getSchemeId, ids)); return AjaxResult.success(delete); } /** * éè¿åå·¥id计ç®ç¤¾ä¿æ¹æ¡ * @param id */ public void calculateByEmployeeId(Integer id,Map<String, Object> map) { // 1. å ¥åæ ¡éª if (id == null) { return; // æè¿å空åè¡¨ï¼æ ¹æ®ä¸å¡éæ±è°æ´ } Long staffId = id.longValue(); // 社ä¿éé¢ BigDecimal schemeAmount = new BigDecimal("0.00"); // å ¬ç§¯ééé¢ BigDecimal gjj = new BigDecimal("0.00"); // åºæ¬å·¥èµ BigDecimal basicSalary = new BigDecimal("0.00"); map.put("gjj", gjj); // å ¬ç§¯é map.put("schemeAmount", schemeAmount); // 社ä¿éé¢ map.put("basicSalary", basicSalary); // åºæ¬å·¥èµ // 个ç¨éé¢ BigDecimal salaryTax = new BigDecimal("0.00"); map.put("salaryTax", salaryTax); // è®¡ä»¶å·¥èµ BigDecimal pieceSalary = new BigDecimal("0.00"); map.put("pieceSalary", pieceSalary); // 计æ¶å·¥èµ BigDecimal hourlySalary = new BigDecimal("0.00"); map.put("hourlySalary", hourlySalary); // å ¶ä»æ¶å ¥ BigDecimal otherIncome = new BigDecimal("0.00"); map.put("otherIncome", otherIncome); // å ¶ä»æ¯åº BigDecimal otherDeduct = new BigDecimal("0.00"); map.put("otherDeduct", otherDeduct); // åºåå·¥èµ BigDecimal grossSalary = new BigDecimal("0.00"); map.put("grossSalary", grossSalary); // åºæ£å·¥èµ BigDecimal deductSalary = new BigDecimal("0.00"); map.put("deductSalary", deductSalary); // å®åå·¥èµ BigDecimal netSalary = new BigDecimal("0.00"); map.put("netSalary", netSalary); // è°ç¨åºæ¬å·¥èµ StaffOnJob staffOnJobDto = staffOnJobMapper.selectById(staffId); if(staffOnJobDto == null){ return; } basicSalary = staffOnJobDto.getBasicSalary(); map.put("basicSalary", basicSalary); // åºåå·¥èµ map.put("grossSalary", basicSalary); // 个ç¨éé¢ï¼æ 社ä¿çï¼ BigDecimal bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, schemeAmount, gjj); map.put("salaryTax", bigDecimal); // 2. æ¥è¯¢è¯¥äººå对åºçç¤¾ä¿æ¹æ¡ List<SchemeApplicableStaff> schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId); if (CollectionUtils.isEmpty(schemeList)) { return; // æ å¹é æ¹æ¡ï¼è¿å空å表 } // 3. 为æ¯ä¸ªæ¹æ¡å ³èæç»å表 for (SchemeApplicableStaff scheme : schemeList) { List<SchemeInsuranceDetail> detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(scheme.getId()); // æ ¹æ®æç»å表计ç®ç¤¾ä¿ç¼´è´¹éé¢ if(CollectionUtils.isEmpty(detailList)){ continue; } for (SchemeInsuranceDetail detail : detailList) { if("使¿å ¬ç§¯é".equals(detail.getInsuranceType())){ gjj = gjj.add(calculateByEmployeeIdType(detail.getInsuranceType(),gjj, staffOnJobDto, detail)); }else{ schemeAmount = schemeAmount.add(calculateByEmployeeIdType(detail.getInsuranceType(),schemeAmount, staffOnJobDto, detail)); } } } map.put("schemeAmount", schemeAmount); map.put("gjj", gjj); // 个ç¨éé¢ï¼ç¤¾ä¿çï¼ bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, schemeAmount, gjj); map.put("salaryTax", bigDecimal); // åºæ£å·¥èµ map.put("deductSalary", bigDecimal.add(gjj).add(schemeAmount)); // å®åå·¥èµ map.put("netSalary", basicSalary.subtract(bigDecimal).subtract(gjj).subtract(schemeAmount)); } /** * è®¡ç® * @param type * @param bigDecimal * @param staffOnJobDto * @param detail * @return */ public BigDecimal calculateByEmployeeIdType(String type,BigDecimal bigDecimal, StaffOnJob staffOnJobDto,SchemeInsuranceDetail detail) { // 夿æ¯å¦è°ç¨åºæ¬å·¥èµ if (detail.getUseBasicSalary() == 1) { BigDecimal divide = detail.getPaymentBase().multiply(detail.getPersonalRatio()).divide(new BigDecimal("100"), 2); bigDecimal = bigDecimal.add(divide); }else{ // è°ç¨åºæ¬å·¥èµ BigDecimal multiply = staffOnJobDto.getBasicSalary().multiply(detail.getPersonalRatio().divide(new BigDecimal("100"), 2)); bigDecimal = bigDecimal.add(multiply); } bigDecimal = bigDecimal.add(detail.getPersonalFixed()); return bigDecimal; } } src/main/java/com/ruoyi/staff/service/impl/StaffSalaryDetailServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.ruoyi.staff.service.impl; import com.ruoyi.staff.pojo.StaffSalaryDetail; import com.ruoyi.staff.mapper.StaffSalaryDetailMapper; import com.ruoyi.staff.service.StaffSalaryDetailService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * <p> * åå·¥å·¥èµæç»è¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:24:35 */ @Service public class StaffSalaryDetailServiceImpl extends ServiceImpl<StaffSalaryDetailMapper, StaffSalaryDetail> implements StaffSalaryDetailService { } src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,142 @@ package com.ruoyi.staff.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUserDept; import com.ruoyi.project.system.mapper.SysUserDeptMapper; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.staff.mapper.StaffSalaryDetailMapper; import com.ruoyi.staff.pojo.SchemeApplicableStaff; import com.ruoyi.staff.pojo.StaffSalaryDetail; import com.ruoyi.staff.pojo.StaffSalaryMain; import com.ruoyi.staff.mapper.StaffSalaryMainMapper; import com.ruoyi.staff.service.StaffSalaryDetailService; import com.ruoyi.staff.service.StaffSalaryMainService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * <p> * å工工èµä¸»è¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-03-06 01:22:05 */ @Service public class StaffSalaryMainServiceImpl extends ServiceImpl<StaffSalaryMainMapper, StaffSalaryMain> implements StaffSalaryMainService { @Autowired private StaffSalaryMainMapper staffSalaryMainMapper; @Autowired private StaffSalaryDetailService staffSalaryDetailService; @Autowired private StaffSalaryDetailMapper staffSalaryDetailMapper; @Autowired private SchemeApplicableStaffServiceImpl schemeApplicableStaffService; @Autowired private SysUserDeptMapper sysUserDeptMapper; @Autowired private SysUserMapper sysUserMapper; @Override public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) { LambdaQueryWrapper<StaffSalaryMain> staffSalaryMainLambdaQueryWrapper = new LambdaQueryWrapper<>(); if(staffSalaryMain != null){ if(StringUtils.isNotEmpty(staffSalaryMain.getSalaryTitle())){ staffSalaryMainLambdaQueryWrapper.like(StaffSalaryMain::getSalaryTitle, staffSalaryMain.getSalaryTitle()); } if(StringUtils.isNotEmpty(staffSalaryMain.getSalaryMonth())){ staffSalaryMainLambdaQueryWrapper.like(StaffSalaryMain::getSalaryMonth, staffSalaryMain.getSalaryMonth()); } if(staffSalaryMain.getStatus() != null){ staffSalaryMainLambdaQueryWrapper.eq(StaffSalaryMain::getStatus, staffSalaryMain.getStatus()); } } Page<StaffSalaryMain> page1 = staffSalaryMainMapper.selectPage(page, staffSalaryMainLambdaQueryWrapper); page1.getRecords().forEach(main -> { List<StaffSalaryDetail> staffSalaryDetailList = staffSalaryDetailMapper.selectList(new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, main.getId())); main.setStaffSalaryDetailList(staffSalaryDetailList); }); return AjaxResult.success(page1); } @Override public AjaxResult add(StaffSalaryMain staffSalaryMain) { staffSalaryMainMapper.insert(staffSalaryMain); staffSalaryMain.getStaffSalaryDetailList().forEach(detail -> { detail.setMainId(staffSalaryMain.getId()); }); staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList()); return AjaxResult.success("æ°å¢æå"); } @Override public AjaxResult updateStaffSalaryMain(StaffSalaryMain staffSalaryMain) { if(staffSalaryMain == null){ return AjaxResult.error("åæ°é误"); } StaffSalaryMain staffSalaryMain1 = staffSalaryMainMapper.selectById(staffSalaryMain.getId()); if(staffSalaryMain1 == null){ return AjaxResult.error("åæ°é误"); } // å¾ å®¡æ ¸ä¸å¯ç¼è¾ if(staffSalaryMain1.getStatus() > 2){ return AjaxResult.error("å¾ å®¡æ ¸ä¸å¯ç¼è¾"); } staffSalaryMainMapper.updateById(staffSalaryMain); staffSalaryDetailMapper.delete(new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, staffSalaryMain.getId())); staffSalaryMain.getStaffSalaryDetailList().forEach(detail -> { detail.setMainId(staffSalaryMain.getId()); }); staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList()); return AjaxResult.success("ä¿®æ¹æå"); } @Override public AjaxResult delete(List<Long> ids) { if(CollectionUtils.isEmpty(ids)){ return AjaxResult.error("åæ°é误"); } staffSalaryMainMapper.deleteBatchIds(ids); staffSalaryDetailMapper.delete(new LambdaQueryWrapper<StaffSalaryDetail>().in(StaffSalaryDetail::getMainId, ids)); return AjaxResult.success("å 餿å"); } @Override public AjaxResult calculateSalary(List<Long> ids) { if(CollectionUtils.isEmpty(ids)){ return AjaxResult.error("åæ°é误"); } List<Map<String, Object>> longs = setSchemeApplicableStaffUserInfo(ids); // éè¿é¨é¨idsè·åç¨æ·ä¿¡æ¯ if(CollectionUtils.isEmpty(longs)){ return AjaxResult.error("æ åå·¥"); } for (Map<String, Object> id : longs) { schemeApplicableStaffService.calculateByEmployeeId((Integer) id.get("id"),id); } return AjaxResult.success(longs); } public List<Map<String, Object>> setSchemeApplicableStaffUserInfo(List<Long> ids) { if(CollectionUtils.isEmpty(ids)){ return new ArrayList<>(); } // éè¿é¨é¨è·å人åid return sysUserDeptMapper.setSchemeApplicableStaffUserInfo(ids); } } src/main/resources/mapper/staff/BankMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.staff.mapper.BankMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.Bank"> <id column="id" property="id" /> <result column="bank_name" property="bankName" /> </resultMap> </mapper> src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml
@@ -2,19 +2,39 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.staff.mapper.SchemeApplicableStaffMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.SchemeApplicableStaff"> <id column="id" property="id" /> <result column="title" property="title" /> <result column="dept_ids" property="deptIds" /> <result column="staff_names" property="staffNames" /> <result column="staff_ids" property="staffIds" /> <result column="insurance_types" property="insuranceTypes" /> <result column="remark" property="remark" /> <result column="create_time" property="createTime" /> <result column="update_time" property="updateTime" /> <result column="create_user" property="createUser" /> <result column="update_user" property="updateUser" /> </resultMap> <!-- åºç¡å段æ¥è¯¢ --> <sql id="schemeColumns"> id, title, dept_ids, staff_names, staff_ids, insurance_types, remark, create_time, update_time, create_user, update_user </sql> <!-- æ ¹æ®äººåIDæ¥è¯¢ç¤¾ä¿æ¹æ¡ --> <select id="selectSchemeByStaffId" resultType="com.ruoyi.staff.pojo.SchemeApplicableStaff"> SELECT <include refid="schemeColumns"/> FROM scheme_applicable_staff WHERE 1 = 1 <!-- æ ¸å¿ï¼å¹é staff_idsä¸å å«ç®æ 人åIDçè®°å½ --> AND FIND_IN_SET(#{staffId}, staff_ids) <!-- å¯éï¼å¢å ææç¶æè¿æ»¤ï¼å¦æè¡¨ä¸æç¶æåæ®µï¼ --> <!-- AND status = 1 --> ORDER BY create_time DESC </select> <!-- æ¥è¯¢æ¹æ¡å¯¹åºçæç» --> <select id="selectDetailBySchemeId" resultType="com.ruoyi.staff.pojo.SchemeInsuranceDetail"> SELECT id, scheme_id, insurance_type, payment_base, use_basic_salary, personal_ratio, personal_fixed, create_time, update_time, create_user, update_user FROM scheme_insurance_detail WHERE scheme_id = #{schemeId} </select> </mapper> src/main/resources/mapper/staff/StaffSalaryDetailMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,31 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.staff.mapper.StaffSalaryDetailMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.StaffSalaryDetail"> <id column="id" property="id" /> <result column="main_id" property="mainId" /> <result column="staff_on_job_id" property="staffOnJobId" /> <result column="staff_name" property="staffName" /> <result column="post_name" property="postName" /> <result column="dept_name" property="deptName" /> <result column="basic_salary" property="basicSalary" /> <result column="piece_salary" property="pieceSalary" /> <result column="hourly_salary" property="hourlySalary" /> <result column="other_income" property="otherIncome" /> <result column="social_personal" property="socialPersonal" /> <result column="fund_personal" property="fundPersonal" /> <result column="other_deduct" property="otherDeduct" /> <result column="salary_tax" property="salaryTax" /> <result column="gross_salary" property="grossSalary" /> <result column="deduct_salary" property="deductSalary" /> <result column="net_salary" property="netSalary" /> <result column="remark" property="remark" /> <result column="create_time" property="createTime" /> <result column="create_user" property="createUser" /> <result column="update_time" property="updateTime" /> <result column="update_user" property="updateUser" /> </resultMap> </mapper> src/main/resources/mapper/staff/StaffSalaryMainMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,19 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.staff.mapper.StaffSalaryMainMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.StaffSalaryMain"> <id column="id" property="id" /> <result column="salary_title" property="salaryTitle" /> <result column="dept_ids" property="deptIds" /> <result column="salary_month" property="salaryMonth" /> <result column="remark" property="remark" /> <result column="status" property="status" /> <result column="create_time" property="createTime" /> <result column="create_user" property="createUser" /> <result column="update_time" property="updateTime" /> <result column="update_user" property="updateUser" /> </resultMap> </mapper> src/main/resources/mapper/system/SysUserDeptMapper.xml
@@ -3,7 +3,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.project.system.mapper.SysUserDeptMapper"> <select id="setSchemeApplicableStaffUserInfo" resultType="java.util.Map"> SELECT T1.id as id, T1.staff_no as staffNo, T1.staff_name as staffName, T2.dept_id as deptId, T2.dept_name as deptName FROM staff_on_job T1 LEFT JOIN sys_dept T2 ON T1.sys_dept_id = T2.dept_id <where> T1.sys_dept_id in<foreach collection="ids" item="id" separator="," close=")" open="(">#{id}</foreach> </where> GROUP BY T1.id </select> <select id="userLoginFacotryList" resultType="com.ruoyi.project.system.domain.vo.SysUserDeptVo"> SELECT T1.user_id,