工资计算系统设计实现

Posted mask哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工资计算系统设计实现相关的知识,希望对你有一定的参考价值。

part1

XX 公司有三种类型的雇工, 不同类型的员工有不同的工资计算方式, 具体薪资计算规则如下。

• 小时工,每小时薪资为 40 元。

• 经理,每小时薪资为 60 元,每月工作满 150 小时就可以得到全额工资 10000 元。如果工作不满 150 小时,则按照 实际工作时间和时薪计算工资

• 销售人员, 基础工资为每月 3000,每月基础销售额应为 20000,如果销售额为 20000-30000,则超出部分(超出 20000 部分)提成率为 5%,如果销售额为 30000 及以上,则超出部分(超出 20000 部分)提成率为 8%。

• 加班工资计算规则。 对于小时工和经理,当他们每月工作超过 160 小时,则超出部分时长按照时薪 1.3 倍计算工资

请注意:

1. 员工的固定工资,时薪,提成率和底薪都可能会调整。

2. 员工类型可能会增加。

3. 加班规则和其适用的雇员规则都可能变化,比如小时工或者经理可能不再计算加班工资

公司现有雇员如下:

经理: Lisa 
小时工:Alex, Jack 
销售人员:Leo

解析以下 xml 数据,并计算 9 月和 10 月份,公司应支付员工工资总额。最终结果应该四舍五入为两位小 数。

<department>

<month value="9">

<employee name="Lisa" workingHours="145"/>

<employee name="Alex" workingHours="170.5"/>

<employee name="Leo" amount="34100.8"/>

</month>

<month value="10">

<employee name="Lisa" workingHours="165"/>

<employee name="Alex" workingHours="155.75"/>

<employee name="Jack" workingHours ="188.25"/>

<employee name="Leo" amount ="23500.7"/>

</month> 
</department>

part2

分析需求得出:

   1.解析xml数据

    2.计薪规则设计

   3.动态调整计薪规则

part3.设计实现

 采用策略模式实现计薪规则+  Dom4j xpath解析xml文件:

/**
 * 定义计薪规则接口
 */
public interface CalculateSalaryStrategy 
    BigDecimal CalculateSalary(Double workHours,BigDecimal amount,AdjustSalary adjustSalary);





/**
 * 小时工计薪规则
 */
public class HourCalSalaryStrategy implements  CalculateSalaryStrategy
    @Override
    public BigDecimal CalculateSalary(Double workHours,BigDecimal amount,AdjustSalary adjustSalary) 
       BigDecimal workHoursTmp= new BigDecimal(workHours);
       if(workHours>160)
           BigDecimal FixedHours=new BigDecimal(160);

          //计算固定时间的薪资
           BigDecimal fixedSalary= FixedHours.multiply(adjustSalary.getHourSalary());

           //计算加班时间的薪资
           BigDecimal extraSalary=workHoursTmp.subtract(FixedHours).multiply(adjustSalary.getHourSalary().multiply(new BigDecimal(adjustSalary.getWorkExtra())));

           return fixedSalary.add(extraSalary);
       else
           return workHoursTmp.multiply(adjustSalary.getHourSalary());
       
    






/**
 * 经理记薪规则
 */
public class ManagerCalSalaryStrategy implements  CalculateSalaryStrategy
    @Override
    public BigDecimal CalculateSalary(Double workHours,BigDecimal amount,AdjustSalary adjustSalary) 
        BigDecimal workHoursTmp= new BigDecimal(workHours);
        if(workHours>=150)
           if(workHours>160)
               BigDecimal FixedHours=new BigDecimal(160);
               //计算加班时间的薪资
               BigDecimal extraSalary=workHoursTmp.subtract(FixedHours).multiply(adjustSalary.getHourSalary().multiply(new BigDecimal(adjustSalary.getWorkExtra())));

               //固定工资+加班费
               return adjustSalary.getFixedSalary().add(extraSalary);
           else
               //只发固定薪资
               return adjustSalary.getFixedSalary();
           
        else
          //实际工作时间和时薪计算工资
            return workHoursTmp.multiply(adjustSalary.getHourSalary());
        
    



import java.math.BigDecimal;

/**
 * 销售计薪规则
 */
public class SalesCalSalaryStrategy implements CalculateSalaryStrategy 
    @Override
    public BigDecimal CalculateSalary(Double workHours, BigDecimal amount, AdjustSalary adjustSalary) 
        if (amount.doubleValue() >= 30000) 
            //计算佣金
            BigDecimal commissionSalary = amount.subtract(new BigDecimal(20000)).multiply(new BigDecimal(adjustSalary.getCommissionRate().get("L2")));
            return adjustSalary.getBaseSalary().add(commissionSalary);
         else if (amount.doubleValue()<=20000)
         return  adjustSalary.getBaseSalary();
        else 
            //计算佣金
            BigDecimal commissionSalary = amount.subtract(new BigDecimal(20000)).multiply(new BigDecimal(adjustSalary.getCommissionRate().get("L1")));
            return adjustSalary.getBaseSalary().add(commissionSalary);
        
    






/**
 *创建计薪上下文
 */
public class CalculateSalaryContext 
    private CalculateSalaryStrategy calculateSalaryStrategy;
    public CalculateSalaryContext(CalculateSalaryStrategy calculateSalaryStrategy)
        this.calculateSalaryStrategy=calculateSalaryStrategy;
    
    public BigDecimal callCalculateSalary(Double workHours,BigDecimal amount,AdjustSalary adjustSalary)
        return this.calculateSalaryStrategy.CalculateSalary(workHours,amount,adjustSalary);
    






import lombok.Data;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 员工调薪
 */
@Data
public class AdjustSalary 
    /**
     * 固定工资
     */
    private BigDecimal fixedSalary;
    /**
     * 时薪
     */
    private BigDecimal hourSalary;

    /**
     * 提成率
     */
    private Map<String,Double> commissionRate=new HashMap<>();
    /**
     * 底薪
     */
    private BigDecimal baseSalary;

    /**
     * 加班计薪系数
     */
    private  Double workExtra;




import lombok.Data;

@Data
public class Employee 
    private String name;
    private String workingHours;
    private String amount;




import com.xx.calculaterule.*;
import com.xx.entity.Employee;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.math.BigDecimal;
import java.util.*;

/**
 * 计算公司应支付员工工资总额
 */
public class CalculateEmpTotalSalary 
    private static List<Employee> getEmployeeList() throws DocumentException 
        SAXReader reader = new SAXReader();
        Document document = reader.read(CalculateEmpTotalSalary.class.getResourceAsStream("salary.xml"));
        //获取整个文档
        Element rootElement = document.getRootElement();
        System.out.println("整个文档:" + rootElement.asXML());
        List<Element> elements = rootElement.selectNodes("/department/month/employee");

        List<Employee> employees = new ArrayList<>();
        for(int i=0;i<elements.size();i++)
            Element element= elements.get(i);
            Employee employee = new Employee();
            employee.setName(element.attributeValue("name"));
            employee.setWorkingHours(element.attributeValue("workingHours"));
            employee.setAmount(element.attributeValue("amount"));
            employees.add(employee);
        
        return employees;
    

    public static void main(String[] args) throws DocumentException 
        /**
         * step0 构建员工与员工类型关系数据
         */
        Set<String> managers = new HashSet<>();
        managers.add("Lisa");
        Set<String> hours = new HashSet<>();
        hours.add("Alex");
        hours.add("Jack");
        Set<String> sales = new HashSet<>();
        sales.add("Leo");

        Map<String, Set<String>> storeEmployRSData = new HashMap<>();
        storeEmployRSData.put("manager", managers);
        storeEmployRSData.put("hours", hours);
        storeEmployRSData.put("sales", sales);

        /**
         * step1.获取解析xml数据成对象
         */
        List<Employee> employees = getEmployeeList();
        System.out.println("employees:"+employees.toString());

        /**
         *step2.计算公司支付员工总工资
         */
        BigDecimal payTotalSalary=new BigDecimal(0.00);
        for (Employee employee:employees)
            if(managers.contains(employee.getName()))
                CalculateSalaryContext managerCalSalary=new CalculateSalaryContext(new ManagerCalSalaryStrategy());

                //员工的固定工资,时薪,提成率和底薪调整配置
                AdjustSalary adjustSalary=new AdjustSalary();
                adjustSalary.setHourSalary(new BigDecimal(60));
                adjustSalary.setFixedSalary(new BigDecimal(10000));
                adjustSalary.setBaseSalary(new BigDecimal(0.00));
                adjustSalary.setCommissionRate(null);
                adjustSalary.setWorkExtra(1.3);

                Double workingHours=Double.parseDouble(employee.getWorkingHours());
                payTotalSalary=payTotalSalary.add(managerCalSalary.callCalculateSalary(workingHours,null,adjustSalary));
            else if(hours.contains(employee.getName()))
                CalculateSalaryContext hourCalSalary=new CalculateSalaryContext(new HourCalSalaryStrategy());

                //员工的固定工资,时薪,提成率和底薪调整配置
                AdjustSalary adjustSalary=new AdjustSalary();
                adjustSalary.setHourSalary(new BigDecimal(40));
                adjustSalary.setFixedSalary(new BigDecimal(0.00));
                adjustSalary.setBaseSalary(new BigDecimal(0.00));
                adjustSalary.setCommissionRate(null);
                adjustSalary.setWorkExtra(1.3);

                Double workingHours=Double.parseDouble(employee.getWorkingHours());
                payTotalSalary=payTotalSalary.add(hourCalSalary.callCalculateSalary(workingHours,null,adjustSalary));
            else if(sales.contains(employee.getName()))
                CalculateSalaryContext salesCalSalary=new CalculateSalaryContext(new SalesCalSalaryStrategy());

                //构建
                Map<String, Double> commissionRates=new HashMap<>();
                commissionRates.put("L1",0.05);
                commissionRates.put("L2",0.08);

                //员工的固定工资,时薪,提成率和底薪调整配置
                AdjustSalary adjustSalary=new AdjustSalary();
                adjustSalary.setHourSalary(new BigDecimal(0.00));
                adjustSalary.setFixedSalary(new BigDecimal(0.00));
                adjustSalary.setBaseSalary(new BigDecimal((3000)));
                adjustSalary.setCommissionRate(commissionRates);
                adjustSalary.setWorkExtra(0.00);

                BigDecimal amountTmp=new BigDecimal(employee.getAmount());
                //调用销售计薪规则
                payTotalSalary=payTotalSalary.add(salesCalSalary.callCalculateSalary(null,amountTmp,adjustSalary));
            
        

        System.out.println("公司应支付员工工资总额:"+payTotalSalary.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
    

解析xml文件方法:

      1.采用dom4j

       2.xstream

需要注意的是解析的xml内容格式决定采用以上哪种更恰当。

以上是关于工资计算系统设计实现的主要内容,如果未能解决你的问题,请参考以下文章

头歌:Python开发技术—面向对象程序设计3 详细注释(第1关:工资结算系统+第2关:设计LFU缓存类)

C++小型公司工资管理系统[2023-04-19]

python面向对象总结

Python第三周习题集

python 设计并实现计算不同职称的教师工资(类的练习)

Pthon100天学习笔记Day19 面向对象基础