薪水支付案例
规格说明
用户素材
- 增加新雇员
- 删除雇员
- 登记时间卡
- 登记销售凭条
- 登记协会服务费
- 更改雇员明细
- 运行薪水支付系统
员工类型
- 钟点工
按小时计算薪水,每天正常工作 8 小时,超过 8 小时部分 1.5 倍薪水,每周五支付薪水。
- 销售雇员
有固定月薪,同时根据销售业绩有相应的酬金,每隔一周的周五支付薪水。
- 普通雇员
固定月薪,每月最后一天支付薪水。
薪水支付方式
- 将支票邮寄到指定地址
- 在出纳人员那儿领取支票
- 将薪水存入员工制定的银行账户
补充说明
- 员工如果加入一些公司的协会,每月会从薪水中扣除协会的服务费
- 薪水支付程序每个工作日运行一次,并在当天为相应的雇员进行支付。系统会被告知雇员的支付日期,这样它会计算从雇员是国内次支付日期到规定的本次支付日期间应支付的数额
基础类设计
支付方式
public interface PaymentMethod {}
public class HoldMethod implements PaymentMethod {}
public class DirectMethod implements PaymentMethod {
private String bank;
private String account;
}
public class MailMethod implements PaymentMethod {
private String address;
}
支付类型
public interface PaymentClassification {}
public class SalariedClassification implements PaymentClassification {
private Integer salary;
}
public class HourlyClassification implements PaymentClassification {
private Integer hourlyRate;
}
public class CommissionedClassification implements PaymentClassification {
private Integer commissionRate;
private Intger salary;
}
员工
public class Emplyee {
private String name;
private Integer employeeId;
private String address;
public Emplyee(String name, Integer employeeId, String address) {
this.name = name;
this.employeeId = employeeId;
this.address = address;
}
// setter/getter
}
public class HourlyEmployee extends Emplyee {
private Integer hourlyRate;
}
public class SalariedEmployee extends Emplyee {
private Integer monthlySalary;
}
public class CommissionedEmployee extends Emplyee {
private Integer monthlySalary;
private Integer commissionRate;
}
薪水支付时间表
public interface PaymentSchedule {}
public class WeeklySchedule implements PaymentSchedule {}
public class MonthlySchedule implements PaymentSchedule {}
public class BiweeklySchedule implements PaymentSchedule {}
时间卡
public class TimeCard {
private Date date;
private Integer hours;
}
销售凭条
public class SalesReceipt {
private Date date;
private Integer amount;
}
服务费用
public class ServiceCharge {
private Date date;
private Integer amount;
}
雇员与协会关系类
public interface Affiliation {
}
public class NoAffiliation implements Affiliation {
}
public class UnionAffiliation implements Affiliation {
}
数据库
使用 facade 模式
public class PayrollDatabase {
private Map itsEmployee;
public PayrollDatabase() {
itsEmployee = new HashMap<>();
}
public Emplyee getEmployee(Integer empId) {
return itsEmployee.get(empId);
}
public void addEmployee(Emplyee employee, Integer empId) {
itsEmployee.put(empId, employee);
}
public void clear() {}
}
用例分析
采用测试驱动开发的方式实现每一个模块
所有操作的抽象基类
使用 command 模式
public interface Transaction {
void execute();
}
增加雇员
- 增加雇员基础类结构
使用 template method 模式
public abstract AddEmployeeTransaction implements Transaction {
private Integer empId;
private String address;
private String name;
private PayrollDatabase payrollDatabase;
public abstract void execute() {}
// setter/getter
}
public class AddHourlyEmployee extends AddEmployeeTransaction {
private Integer hourlyRate;
public void execute() {}
}
public class AddSalariedEmployee extends AddEmployeeTransaction {
private Integer salary;
public void execute() {}
}
public class AddCommissionedEmployee extends AddEmployeeTransaction {
private Integer salary;
private Integer commissionRate;
public void execute() {}
}
- 测试用例
- 增加固定月薪类型雇员
public void testAddSalariedEmployee { // 1. 创建固定月薪类型员工 // 2. 通过员工 id 从数据库中查询员工,对结果进行断言 // 3. 从员工对象获取员工的支付类型,对结果进行断言 // 4. 从员工对象获取支付时间表,对结果进行断言 // 5. 从员工对象获取支付方式,对结果进行断言 }
- 增加销售类型雇员
public void testAddCommissionedEmployee { // 1. 创建销售类型雇员 // 2. 通过员工 id 从数据库中查询员工,对结果进行断言 // 3. 从员工对象获取员工的支付类型,对结果进行断言 // 4. 从员工对象获取支付时间表,对结果进行断言 // 5. 从员工对象获取支付方式,对结果进行断言 }
- 增加钟点类型雇员
public void testAddHourlyEmployee { // 1. 创建固钟点类型员工 // 2. 通过员工 id 从数据库中查询员工,对结果进行断言 // 3. 从员工对象获取员工的支付类型,对结果进行断言 // 4. 从员工对象获取支付时间表,对结果进行断言 // 5. 从员工对象获取支付方式,对结果进行断言 }
- 增加固定月薪类型雇员
删除雇员
- 测试用例
public void testDeleteEmployee { // 1. 创建一个雇员 // 2. 通过 id 从数据库中获取雇员,并对结果进行断言 // 3. 通过 ID 从数据库中删除雇员 // 4. 通过 ID 从数据库中获取雇员,并对结果进行断言 }
给钟点类型雇员添加时间卡
-
时间卡操作类
public class TimeCardTransaction implements Transaction { private Date date; private Integer hours; private Integer empId; private PayrollDatabase payrollDatabase; public void execute(); }
-
测试用例
public void testTimeCard { // 1. 创建一个雇员 // 2. 创建一个 TimeCardTransaction 对象,并执行 execute 方法 // 3. 通过 id 从数据库中获取雇员对象,并对结果断言 // 4. 从雇员对象中获取钟点支付类型,并对结果进行断言 // 5. 从钟点支付类型中获取时间卡,并对结果进行断言 }
给销售类型雇员添加销售凭条
-
销售凭条操作类
public class SalesReceiptTransaction implements Transaction { private Date date; private Integer amount; private Integer empId; private PayrollDatabase payrollDatabase; public void execute(); }
-
测试用例
public void testSalesReceipt { // 1. 创建一个雇员 // 2. 创建一个 SalesReceiptTransaction 对象,并执行 execute 方法 // 3. 通过 id 从数据库中获取雇员对象,并对结果断言 // 4. 从雇员对象中获取销售雇员支付类型,并对结果进行断言 // 5. 从钟点支付类型中获取销售凭条,并对结果进行断言 }
向协会成员登记服务费
-
操作类
public class ServiceChargeTransaction implements Transaction { private Date date; private Integer amount; private Integer memberID; private PayrollDatabase payrollDatabase; public void execute(); }
-
测试用例
public void testServiceCharge { // 1. 创建一个雇员 // 2. 根据 ID 从数据库中获取雇员对象,并对结果进行断言 // 3. 创建一个 UnionAffiliation 对象,并 set 雇员对象中 // 4. 在数据库中新增一个会员 // 5. 创建一个 ServiceChargeTransaction 对象 // 6. 从 UnionAffiliation 对象中获取 ServiceCharge 对象,并对结果进行断言 }
更改雇员属性
-
操作类
使用 template method 模式
public abstract ChangeEmployeeTransaction implements Transaction { private PayrollDatabase payrollDatabase; private Emplyee employee; private Integer empId; public abstract void execute(); } public class ChangeNameTransaction extends ChangeEmployeeTransaction { private String name; public void execute(); } public class ChangeAddressTransaction extends ChangeEmployeeTransaction { private String address; public void execute(); } public abstract ChangeClassificationTransaction extends ChangeEmployeeTransaction { private PaymentClassification paymentClassification; private PaymentSchedule paymentSchedule; public abstract void execute(); } public class ChangeHourlyTransaction extends ChangeClassificationTransaction { private Integer hourlyRate; public void execute(); } public class ChangeSalariedTransaction extends ChangeClassificationTransaction { private Integer salary; public void execute(); } public class ChangeCommissionedTransaction extends ChangeClassificationTransaction { private Integer salary; private Integer commissionRate; public void execute(); } public abstract ChangeMethodTransaction extends ChangeEmployeeTransaction { private PaymentMethod paymentMethod; public abstract void execute(); } public class ChangeDirectTransaction extends ChangeMethodTransaction { private String account; private String bank; public void execute(); } public class ChangeHoldTransaction extends ChangeMethodTransaction { public void execute(); } public class ChangeMailTransaction extends ChangeMethodTransaction { private String address; public void execute(); } public abstract ChangeAffiliationTransaction extends ChangeEmployeeTransaction { private Affiliation affiliation; public abstract void execute(); } public class ChangeMemberTransaction extends ChangeAffiliationTransaction { public void execute(); } public class ChangeUnaffiliatedransaction extends ChangeAffiliationTransaction { public void execute(); }
-
测试用例
- 更改名字
public void testChangeNameTransaction { //1. 创建一个雇员对象 //2. 创建一个 ChangeNameTransaction 对象,并执行 execute 方法 //3. 通过 id 从数据库中获取雇员对象,并对结果进行断言 }
- 更改雇员地址
public void testChangeAddressTransaction { //1. 创建一个雇员对象 //2. 创建一个 ChangeNameTransaction 对象,并执行 execute 方法 //3. 通过 id 从数据库中获取雇员对象,并对结果进行断言 }
- 更改雇员类型
public void testChangeHourlyTransaction { //1. 新增一个雇员对象 //2. 创建一个 ChangeNameTransaction 对象,并执行 execute 方法 //3. 通过 id 从数据库中获取雇员对象,并对结果进行断言 //4. 从雇员对象中获取 PaymentClassification 对象,并对结果进行断言 //5. 从 PaymentClassification 对象中获取 PaymentSchedule 对象,并对结果进行断言 }
- 更改薪水支付方式
public void testChangeMethodTransaction { //1. 新增一个雇员对象 //2. 创建一个 ChangeMethodTransaction 对象,并执行 execute 方法 //3. 通过 id 从数据库中获取雇员对象,并对结果进行断言 //4. 从雇员对象中获取 PaymentMethod 对象,并对结果进行断言 }
- 更改雇员与协会关联
public void testChangeMemberTransaction { //1. 新增一个雇员对象 //2. 创建一个 ChangeMemberTransaction 对象,并执行 execute 方法 //3. 通过 id 从数据库中获取雇员对象,并对结果进行断言 //4. 从雇员对象中获取 UnionAffiliation 对象,并对结果进行断言 //5. 根据 memberID 从数据库中获取雇员对象,并对结果进行断言 }
- 更改名字
支付雇员薪水
- 支付固定月薪雇员薪水
public void testPaySingleSalariedEmployee() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 //4. 断言支付方式 //5. 断言支付金额 } public void testPaySingleSalariedEmployeeOneWrongDate() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 }
- 支付钟点雇员薪水
public void testPaySingleHourlyEmployeeNoTimeCards() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 //4. 断言支付方式 //5. 断言支付金额 } public void testPaySingleHourlyEmployeeOneTimeCards() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 //4. 断言支付方式 //5. 断言支付金额 } public void testPaySingleHourlyEmployeeOneWrongDate() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 } public void testPaySingleHourlyEmployeeTwoTimeCards() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 //4. 断言支付方式 //5. 断言支付金额 } public void testPaySingleHourlyEmployeeWithTimeCardsSpanningTwoPayPeriods() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 //4. 断言支付方式 //5. 断言支付金额 }
- 支付带有销售酬金的雇员薪水
public void testPaySingleCommissionedEmployee() { //1. 创建一个雇员对象 //2. 创建一个支付日期 //3. 验证日期是否是发薪日 //4. 断言支付方式 //5. 断言支付金额 }
计算会费和服务费测试用例
public void testSalariedUnionMemberDues() {}
public void testHourlyUnionMemberServiceCharge() {}
public void testServiceSpanningMultiplePayPeriods() {}