Commit 59500381 authored by 刘斌's avatar 刘斌

feat: 增加兼职模块

parent 5f221ddd
......@@ -25,4 +25,8 @@ public interface HrEmployeeConstants {
* 是否-是
*/
String YES = "Y";
/**
* 是否-否
*/
String NO = "N";
}
......@@ -37,9 +37,7 @@ public class EmployeeBaseInfoForH5Ctrl {
@PinSysLog(value = "基础员工信息", businessType = BusinessType.INSERT)
@PostMapping()
public Response addBaseInfo(@RequestBody EmployeeBaseInfoParam param) {
EmployeeInfoParam employeeInfoParam = new EmployeeInfoParam();
employeeInfoParam.setIdCardNumber(param.getIdCardNumber());
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(employeeInfoParam)) {
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(param.getIdCardNumber(), null)) {
return Response.buildFailure(ResultCode.FAIL.getCode(), "员工身份证号已存在");
}
return ResponseUtils.ofResult(employeeInfoServ.insertBaseInfoForH5(param));
......
......@@ -81,6 +81,7 @@ public class EmployeeInfoCtrl {
/**
* 导出员工信息列表
*/
@NoRepeatSubmit(interval = 60_000)
@ExcelExport(template = "简历模板.xlsx", fill = true, fillObjectFields = {"familyMembers", "trainings"})
@SaCheckPermission("employee:info:export")
@PinSysLog(value = "员工信息", businessType = BusinessType.EXPORT)
......@@ -144,7 +145,7 @@ public class EmployeeInfoCtrl {
@PinSysLog(value = "员工信息", businessType = BusinessType.INSERT)
@PostMapping()
public Response add(@Validated(AddGroup.class) @RequestBody EmployeeInfoParam param) {
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(param)) {
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(param.getIdCardNumber(), param.getId())) {
return Response.buildFailure(ResultCode.FAIL.getCode(), "员工身份证号已存在");
}
return ResponseUtils.ofResult(employeeInfoServ.insertByParam(param));
......@@ -158,7 +159,7 @@ public class EmployeeInfoCtrl {
@PinSysLog(value = "员工信息", businessType = BusinessType.UPDATE)
@PutMapping()
public Response edit(@Validated(EditGroup.class) @RequestBody EmployeeInfoParam param) {
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(param)) {
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(param.getIdCardNumber(), param.getId())) {
return Response.buildFailure(ResultCode.FAIL.getCode(), "员工身份证号已存在");
}
return ResponseUtils.ofResult(employeeInfoServ.updateByParam(param));
......
package com.anplus.hr.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.anplus.hr.domain.params.EmployeePartTimeInfoListParam;
import com.anplus.hr.domain.params.EmployeePartTimeInfoParam;
import com.anplus.hr.domain.vo.EmployeePartTimeInfoImportVo;
import com.anplus.hr.domain.vo.EmployeePartTimeInfoVo;
import com.anplus.hr.service.EmployeePartTimeInfoServ;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import org.dromara.core.trans.anno.TransMethodResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.binfast.common.core.constant.BusinessType;
import top.binfast.common.core.util.ResponseUtils;
import top.binfast.common.core.validate.AddGroup;
import top.binfast.common.core.validate.EditGroup;
import top.binfast.common.excel.annotion.ExcelExport;
import top.binfast.common.excel.annotion.ExcelStream;
import top.binfast.common.idempotent.annotation.NoRepeatSubmit;
import top.binfast.common.log.annotation.PinSysLog;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* 兼职员工信息
*
* @author LiuBin
* @date 2025-12-10
*/
@Validated
@RestController
@RequestMapping("/employee/partTimeInfo")
public class EmployeePartTimeInfoCtrl {
@Resource
private EmployeePartTimeInfoServ employeePartTimeInfoServ;
/**
* 查询兼职员工信息列表
*/
@SaCheckPermission("employee:partTimeInfo:list")
@GetMapping("/page")
public PageResponse<EmployeePartTimeInfoVo> pageList(EmployeePartTimeInfoListParam param) {
return employeePartTimeInfoServ.queryPageList(param);
}
/**
* 导出兼职员工信息列表
*/
@ExcelExport
@NoRepeatSubmit(interval = 60_000)
@SaCheckPermission("employee:partTimeInfo:export")
@PinSysLog(value = "兼职员工信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public List<EmployeePartTimeInfoVo> export(EmployeePartTimeInfoListParam param) {
return employeePartTimeInfoServ.queryList(param);
}
/**
* 导入兼职员工信息列表
*/
// @NoRepeatSubmit(interval = 60_000)
@PinSysLog(value = "兼职员工-导入", businessType = BusinessType.IMPORT)
@SaCheckPermission("employee:partTimeInfo:import")
@PostMapping(value = "/import")
public Response importEmployees(@ExcelStream(headRowNumber = 2) Stream<EmployeePartTimeInfoImportVo> stream) {
return employeePartTimeInfoServ.importPartTimeEmployeeList(stream);
}
/**
* 获取导入模板
*/
@ExcelExport(template = "兼职模板.xlsx", fill = true)
@PostMapping("/importTemplate")
public List<EmployeePartTimeInfoImportVo> importTemplate() {
return new ArrayList<>();
}
/**
* 获取兼职员工信息详细信息
*
* @param id 主键
*/
@SaCheckPermission("employee:partTimeInfo:query")
@GetMapping("/{id}")
public SingleResponse<EmployeePartTimeInfoVo> getDetail(@PathVariable @Min(1)
Long id) {
return SingleResponse.of(employeePartTimeInfoServ.queryById(id));
}
/**
* 展示员工信息详细信息
*
* @param id 主键
*/
@TransMethodResult
@SaCheckPermission("employee:partTimeInfo:query")
@GetMapping("/detail/{id}")
public SingleResponse<EmployeePartTimeInfoVo> infoDetail(@PathVariable @Min(1)
Long id) {
return SingleResponse.of(employeePartTimeInfoServ.infoDetail(id));
}
/**
* 新增兼职员工信息
*/
@NoRepeatSubmit(interval = 60_000)
@SaCheckPermission("employee:partTimeInfo:add")
@PinSysLog(value = "兼职员工信息", businessType = BusinessType.INSERT)
@PostMapping()
public Response add(@Validated(AddGroup.class) @RequestBody EmployeePartTimeInfoParam param) {
return ResponseUtils.ofResult(employeePartTimeInfoServ.insertByParam(param));
}
/**
* 修改兼职员工信息
*/
@NoRepeatSubmit(interval = 60_000)
@SaCheckPermission("employee:partTimeInfo:edit")
@PinSysLog(value = "兼职员工信息", businessType = BusinessType.UPDATE)
@PutMapping()
public Response edit(@Validated(EditGroup.class) @RequestBody EmployeePartTimeInfoParam param) {
return ResponseUtils.ofResult(employeePartTimeInfoServ.updateByParam(param));
}
/**
* 删除兼职员工信息
*
* @param ids 主键串
*/
@NoRepeatSubmit(interval = 60_000)
@SaCheckPermission("employee:partTimeInfo:remove")
@PinSysLog(value = "兼职员工信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public Response remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return ResponseUtils.ofResult(employeePartTimeInfoServ.delByIds(List.of(ids)));
}
}
\ No newline at end of file
......@@ -475,6 +475,36 @@ public class EmployeeInfo extends TenantModel {
*/
private String antaiCommunityInfo;
/**
* 是否兼职标记
*/
private String partTimeFlag;
/**
* 签订兼职协议
*/
private String partTimeAgreement;
/**
* 兼职协议主体
*/
private String agreementEntity;
/**
* 兼职协议期限
*/
private String agreementPeriod;
/**
* 兼职协议开始时间
*/
private LocalDate agreementStartDate;
/**
* 兼职协议截止时间
*/
private LocalDate agreementEndDate;
/**
* 离职类型
*/
......
......@@ -448,6 +448,36 @@ public class EmployeeInfoListParam extends PageQueryParam {
*/
private String antaiCommunityInfo;
/**
* 是否兼职标记
*/
private String partTimeFlag;
/**
* 签订兼职协议
*/
private String partTimeAgreement;
/**
* 兼职协议主体
*/
private String agreementEntity;
/**
* 兼职协议期限
*/
private String agreementPeriod;
/**
* 兼职协议开始时间
*/
private LocalDate agreementStartDate;
/**
* 兼职协议截止时间
*/
private LocalDate agreementEndDate;
/**
* 离职类型
*/
......
......@@ -555,6 +555,31 @@ public class EmployeeInfoParam {
*/
private String antaiCommunityInfo;
/**
* 签订兼职协议
*/
private String partTimeAgreement;
/**
* 兼职协议主体
*/
private String agreementEntity;
/**
* 兼职协议期限
*/
private String agreementPeriod;
/**
* 兼职协议开始时间
*/
private LocalDate agreementStartDate;
/**
* 兼职协议截止时间
*/
private LocalDate agreementEndDate;
/**
* 家庭成员
*/
......
package com.anplus.hr.domain.params;
import lombok.Getter;
import lombok.Setter;
import top.binfast.common.core.bean.params.PageQueryParam;
import java.util.HashMap;
import java.util.Map;
import java.time.LocalDate;
/**
* 兼职员工信息分页对象 employee_part_time_info
*
* @author LiuBin
* @date 2025-12-10
*/
@Getter
@Setter
public class EmployeePartTimeInfoListParam extends PageQueryParam {
/**
* 板块
*/
private String plate;
/**
* 一级部门
*/
private String firstLevelDepartment;
/**
* 二级部门
*/
private String secondLevelDepartment;
/**
* 三级部门
*/
private String thirdLevelDepartment;
/**
* 部门ID
*/
private Long deptId;
/**
* 岗位类型
*/
private String positionType;
/**
* 主岗位
*/
private String position;
/**
* 姓名
*/
private String name;
/**
* 性别
*/
private String gender;
/**
* 身份证号码
*/
private String idCardNumber;
/**
* 照片ID
*/
private Long ossId;
/**
* 出生日期
*/
private LocalDate birthDate;
/**
* 年龄
*/
private Integer age;
/**
* 籍贯
*/
private String nativePlace;
/**
* 民族
*/
private String ethnicity;
/**
* 婚姻状况
*/
private String maritalStatus;
/**
* 政治面貌
*/
private String politicalStatus;
/**
* 手机号码
*/
private String phoneNumber;
/**
* 紧急联系人
*/
private String emergencyContact;
/**
* 紧急联系人电话
*/
private String emergencyContactPhone;
/**
* 家庭地址
*/
private String homeAddress;
/**
* 入职时间
*/
private LocalDate entryDate;
/**
* 全日制学历
*/
private String fulltimeEducation;
/**
* 全日制毕业院校
*/
private String fulltimeSchool;
/**
* 全日制专业
*/
private String fulltimeMajor;
/**
* 全日制毕业日期
*/
private LocalDate fulltimeGraduationDate;
/**
* 全日制学位
*/
private String fulltimeDegree;
/**
* 用工形式
*/
private String employmentForm;
/**
* 是否兼职
*/
private String partTimeFlag;
/**
* 签订兼职协议
*/
private String partTimeAgreement;
/**
* 协议主体
*/
private String agreementEntity;
/**
* 协议期限
*/
private String agreementPeriod;
/**
* 协议开始时间
*/
private LocalDate agreementStartDate;
/**
* 协议截止时间
*/
private LocalDate agreementEndDate;
/**
* 备注
*/
private String remarks;
/**
* 银行卡号
*/
private String bankCardNumber;
/**
* 开户行
*/
private String bankName;
/**
* 公司内是否有亲属关系
*/
private String hasRelativeInCompany;
/**
* 亲属姓名
*/
private String relativeName;
/**
* 介绍人
*/
private String introducer;
/**
* 介绍人关系
*/
private String introducerRelation;
/**
* 工资发放地
*/
private String salaryLocation;
/**
* 成本费用所属
*/
private String costOfDept;
/**
* 归属部门id(部门树)
*/
private Long belongDeptId;
private Map<String, Object> params = new HashMap<>();
}
package com.anplus.hr.domain.params;
import com.anplus.hr.domain.EmployeeInfo;
import top.binfast.common.core.validate.AddGroup;
import top.binfast.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import jakarta.validation.constraints.*;
import java.time.LocalDate;
/**
* 兼职员工信息业务对象 employee_part_time_info
*
* @author LiuBin
* @date 2025-12-10
*/
@Data
@AutoMapper(target = EmployeeInfo.class, reverseConvertGenerate = false)
public class EmployeePartTimeInfoParam {
/**
* 序号
*/
@NotNull(message = "序号不能为空", groups = { EditGroup.class })
private Long id;
/**
* 板块
*/
@NotBlank(message = "板块不能为空", groups = { AddGroup.class, EditGroup.class })
private String plate;
/**
* 一级部门
*/
@NotBlank(message = "一级部门不能为空", groups = { AddGroup.class, EditGroup.class })
private String firstLevelDepartment;
/**
* 二级部门
*/
@NotBlank(message = "二级部门不能为空", groups = { AddGroup.class, EditGroup.class })
private String secondLevelDepartment;
/**
* 三级部门
*/
@NotBlank(message = "三级部门不能为空", groups = { AddGroup.class, EditGroup.class })
private String thirdLevelDepartment;
/**
* 部门ID
*/
@NotNull(message = "部门ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long deptId;
/**
* 岗位类型
*/
// @NotBlank(message = "岗位类型不能为空", groups = { AddGroup.class, EditGroup.class })
private String positionType;
/**
* 主岗位
*/
@NotBlank(message = "主岗位不能为空", groups = { AddGroup.class, EditGroup.class })
private String position;
/**
* 姓名
*/
@NotBlank(message = "姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String name;
/**
* 性别
*/
@NotBlank(message = "性别不能为空", groups = { AddGroup.class, EditGroup.class })
private String gender;
/**
* 身份证号码
*/
@NotBlank(message = "身份证号码不能为空", groups = { AddGroup.class, EditGroup.class })
private String idCardNumber;
/**
* 照片ID
*/
// @NotNull(message = "照片ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long ossId;
/**
* 出生日期
*/
@NotNull(message = "出生日期不能为空", groups = { AddGroup.class, EditGroup.class })
private LocalDate birthDate;
/**
* 年龄
*/
@NotNull(message = "年龄不能为空", groups = { AddGroup.class, EditGroup.class })
private Integer age;
/**
* 籍贯
*/
// @NotBlank(message = "籍贯不能为空", groups = { AddGroup.class, EditGroup.class })
private String nativePlace;
/**
* 民族
*/
// @NotBlank(message = "民族不能为空", groups = { AddGroup.class, EditGroup.class })
private String ethnicity;
/**
* 婚姻状况
*/
// @NotBlank(message = "婚姻状况不能为空", groups = { AddGroup.class, EditGroup.class })
private String maritalStatus;
/**
* 政治面貌
*/
// @NotBlank(message = "政治面貌不能为空", groups = { AddGroup.class, EditGroup.class })
private String politicalStatus;
/**
* 手机号码
*/
@NotBlank(message = "手机号码不能为空", groups = { AddGroup.class, EditGroup.class })
private String phoneNumber;
/**
* 紧急联系人
*/
// @NotBlank(message = "紧急联系人不能为空", groups = { AddGroup.class, EditGroup.class })
private String emergencyContact;
/**
* 紧急联系人电话
*/
// @NotBlank(message = "紧急联系人电话不能为空", groups = { AddGroup.class, EditGroup.class })
private String emergencyContactPhone;
/**
* 家庭地址
*/
@NotBlank(message = "家庭地址不能为空", groups = { AddGroup.class, EditGroup.class })
private String homeAddress;
/**
* 入职时间
*/
// @NotNull(message = "入职时间不能为空", groups = { AddGroup.class, EditGroup.class })
private LocalDate entryDate;
/**
* 全日制学历
*/
// @NotBlank(message = "全日制学历不能为空", groups = { AddGroup.class, EditGroup.class })
private String fulltimeEducation;
/**
* 全日制毕业院校
*/
// @NotBlank(message = "全日制毕业院校不能为空", groups = { AddGroup.class, EditGroup.class })
private String fulltimeSchool;
/**
* 全日制专业
*/
// @NotBlank(message = "全日制专业不能为空", groups = { AddGroup.class, EditGroup.class })
private String fulltimeMajor;
/**
* 全日制毕业日期
*/
// @NotNull(message = "全日制毕业日期不能为空", groups = { AddGroup.class, EditGroup.class })
private LocalDate fulltimeGraduationDate;
/**
* 全日制学位
*/
// @NotBlank(message = "全日制学位不能为空", groups = { AddGroup.class, EditGroup.class })
private String fulltimeDegree;
/**
* 用工形式
*/
// @NotBlank(message = "用工形式不能为空", groups = { AddGroup.class, EditGroup.class })
private String employmentForm;
/**
* 是否兼职
*/
// @NotBlank(message = "是否兼职不能为空", groups = { AddGroup.class, EditGroup.class })
private String partTimeFlag;
/**
* 签订兼职协议
*/
// @NotBlank(message = "兼职协议不能为空", groups = { AddGroup.class, EditGroup.class })
private String partTimeAgreement;
/**
* 协议主体
*/
// @NotBlank(message = "协议主体不能为空", groups = { AddGroup.class, EditGroup.class })
private String agreementEntity;
/**
* 协议期限
*/
// @NotBlank(message = "协议期限不能为空", groups = { AddGroup.class, EditGroup.class })
private String agreementPeriod;
/**
* 协议开始时间
*/
// @NotNull(message = "协议开始时间不能为空", groups = { AddGroup.class, EditGroup.class })
private LocalDate agreementStartDate;
/**
* 协议截止时间
*/
// @NotNull(message = "协议截止时间不能为空", groups = { AddGroup.class, EditGroup.class })
private LocalDate agreementEndDate;
/**
* 备注
*/
// @NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
private String remarks;
/**
* 银行卡号
*/
// @NotBlank(message = "银行卡号不能为空", groups = { AddGroup.class, EditGroup.class })
private String bankCardNumber;
/**
* 开户行
*/
// @NotBlank(message = "开户行不能为空", groups = { AddGroup.class, EditGroup.class })
private String bankName;
/**
* 公司内是否有亲属关系
*/
// @NotBlank(message = "公司内是否有亲属关系不能为空", groups = { AddGroup.class, EditGroup.class })
private String hasRelativeInCompany;
/**
* 亲属姓名
*/
// @NotBlank(message = "亲属姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String relativeName;
/**
* 介绍人
*/
// @NotBlank(message = "介绍人不能为空", groups = { AddGroup.class, EditGroup.class })
private String introducer;
/**
* 介绍人关系
*/
// @NotBlank(message = "介绍人关系不能为空", groups = { AddGroup.class, EditGroup.class })
private String introducerRelation;
/**
* 工资发放地
*/
// @NotBlank(message = "工资发放地不能为空", groups = { AddGroup.class, EditGroup.class })
private String salaryLocation;
/**
* 成本费用所属
*/
// @NotBlank(message = "成本费用所属不能为空", groups = { AddGroup.class, EditGroup.class })
private String costOfDept;
}
......@@ -5,7 +5,6 @@ import cn.idev.excel.annotation.ExcelProperty;
import com.anplus.hr.config.SeniorityUtils;
import com.anplus.hr.constant.HrConstant;
import com.anplus.hr.domain.EmployeeInfo;
import com.anplus.hr.domain.params.EmployeeInfoParam;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMappers;
import jakarta.validation.constraints.NotBlank;
......@@ -27,7 +26,6 @@ import java.time.LocalDate;
@Getter
@AutoMappers({
@AutoMapper(target = EmployeeInfo.class, reverseConvertGenerate = false),
@AutoMapper(target = EmployeeInfoParam.class, reverseConvertGenerate = false)
})
public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializable {
@Serial
......@@ -36,14 +34,14 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
/**
* 板块
*/
@NotBlank(message = "板块不能为空", groups = { AddGroup.class })
@NotBlank(message = "板块不能为空", groups = {AddGroup.class})
@ExcelProperty(value = "板块")
private String plate;
/**
* 一级部门
*/
@NotBlank(message = "一级部门不能为空", groups = { AddGroup.class })
@NotBlank(message = "一级部门不能为空", groups = {AddGroup.class})
@ExcelProperty(value = "一级部门")
private String firstLevelDepartment;
......@@ -101,7 +99,7 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
/**
* 姓名
*/
@NotBlank(message = "姓名不能为空", groups = { AddGroup.class })
@NotBlank(message = "姓名不能为空", groups = {AddGroup.class})
@ExcelProperty(value = "姓名")
private String name;
......@@ -115,7 +113,7 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
/**
* 身份证号码
*/
@NotBlank(message = "身份证号码不能为空", groups = { AddGroup.class, EditGroup.class })
@NotBlank(message = "身份证号码不能为空", groups = {AddGroup.class, EditGroup.class})
@ExcelProperty(value = "身份证号码")
private String idCardNumber;
......@@ -584,6 +582,37 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
@ExcelProperty(value = "小区具体信息")
private String antaiCommunityInfo;
/**
* 签订兼职协议
*/
@ExcelProperty(value = "签订兼职协议", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
private String partTimeAgreement;
/**
* 兼职协议主体
*/
@ExcelProperty(value = "协议主体")
private String agreementEntity;
/**
* 兼职协议期限
*/
@ExcelProperty(value = "协议期限")
private String agreementPeriod;
/**
* 兼职协议开始时间
*/
@ExcelProperty(value = "协议开始时间")
private LocalDate agreementStartDate;
/**
* 兼职协议截止时间
*/
@ExcelProperty(value = "协议截止时间")
private LocalDate agreementEndDate;
/**
* 家庭主要成员
*/
......@@ -950,4 +979,24 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
public void setYearsOfServiceMonths(Integer yearsOfServiceMonths) {
this.yearsOfServiceMonths = yearsOfServiceMonths;
}
public void setPartTimeAgreement(String partTimeAgreement) {
this.partTimeAgreement = partTimeAgreement == null ? null : partTimeAgreement.trim();
}
public void setAgreementEntity(String agreementEntity) {
this.agreementEntity = agreementEntity == null ? null : agreementEntity.trim();
}
public void setAgreementPeriod(String agreementPeriod) {
this.agreementPeriod = agreementPeriod == null ? null : agreementPeriod.trim();
}
public void setAgreementStartDate(LocalDate agreementStartDate) {
this.agreementStartDate = agreementStartDate;
}
public void setAgreementEndDate(LocalDate agreementEndDate) {
this.agreementEndDate = agreementEndDate;
}
}
......@@ -3,7 +3,6 @@ package com.anplus.hr.domain.vo;
import cn.idev.excel.annotation.ExcelProperty;
import com.anplus.hr.constant.HrConstant;
import com.anplus.hr.domain.EmployeeInfo;
import com.anplus.hr.domain.params.EmployeeInfoParam;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMappers;
import lombok.Getter;
......@@ -21,7 +20,6 @@ import java.time.LocalDate;
@Getter
@AutoMappers({
@AutoMapper(target = EmployeeInfo.class, reverseConvertGenerate = false),
@AutoMapper(target = EmployeeInfoParam.class, reverseConvertGenerate = false)
})
public class EmployeeInfoResignImportVo extends EmployeeInfoImportVo {
@Serial
......
......@@ -600,6 +600,43 @@ public class EmployeeInfoVo implements TransPojo, Serializable {
@ExcelProperty(value = "小区具体信息")
private String antaiCommunityInfo;
// /**
// * 是否兼职标记
// */
// private String partTimeFlag;
//
// /**
// * 签订兼职协议
// */
// @ExcelProperty(value = "签订兼职协议", converter = ExcelDictConvert.class)
// @ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
// @Trans(type = TransType.DICTIONARY, key = HrConstant.SYS_YES_NO)
// private String partTimeAgreement;
//
// /**
// * 兼职协议主体
// */
// @ExcelProperty(value = "协议主体")
// private String agreementEntity;
//
// /**
// * 兼职协议期限
// */
// @ExcelProperty(value = "协议期限")
// private String agreementPeriod;
//
// /**
// * 兼职协议开始时间
// */
// @ExcelProperty(value = "协议开始时间")
// private LocalDate agreementStartDate;
//
// /**
// * 兼职协议截止时间
// */
// @ExcelProperty(value = "协议截止时间")
// private LocalDate agreementEndDate;
/**
* 员工家庭成员
*/
......
package com.anplus.hr.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.anplus.hr.constant.HrConstant;
import com.anplus.hr.domain.EmployeeInfo;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.core.trans.anno.Trans;
import org.dromara.core.trans.constant.TransType;
import top.binfast.common.excel.annotion.ExcelDictFormat;
import top.binfast.common.excel.converters.ExcelDictConvert;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author 刘斌
* @date 2025/12/12 09:10
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EmployeeInfo.class, convertGenerate = false)
public class EmployeePartTimeInfoDetailVo extends EmployeeInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 是否兼职
*/
// @ExcelProperty(value = "是否兼职")
private String partTimeFlag;
/**
* 签订兼职协议
*/
@ExcelProperty(value = "签订兼职协议", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
@Trans(type = TransType.DICTIONARY, key = HrConstant.SYS_YES_NO)
private String partTimeAgreement;
/**
* 协议主体
*/
@ExcelProperty(value = "协议主体")
private String agreementEntity;
/**
* 协议期限
*/
@ExcelProperty(value = "协议期限")
private String agreementPeriod;
/**
* 协议开始时间
*/
@ExcelProperty(value = "协议开始时间")
private LocalDate agreementStartDate;
/**
* 协议截止时间
*/
@ExcelProperty(value = "协议截止时间")
private LocalDate agreementEndDate;
}
package com.anplus.hr.domain.vo;
import cn.idev.excel.annotation.ExcelProperty;
import com.anplus.hr.constant.HrConstant;
import com.anplus.hr.domain.EmployeeInfo;
import com.anplus.hr.domain.params.EmployeePartTimeInfoParam;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMappers;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import top.binfast.common.core.validate.AddGroup;
import top.binfast.common.core.validate.EditGroup;
import top.binfast.common.excel.annotion.ExcelDictFormat;
import top.binfast.common.excel.bean.ExcelBaseEntity;
import top.binfast.common.excel.converters.ExcelDictConvert;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author 刘斌
* @date 2025/12/11 15:53
*/
@Getter
@AutoMappers({
@AutoMapper(target = EmployeeInfo.class, reverseConvertGenerate = false),
@AutoMapper(target = EmployeeInfoImportVo.class, reverseConvertGenerate = false)
})
public class EmployeePartTimeInfoImportVo extends ExcelBaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 板块
*/
@NotBlank(message = "板块不能为空", groups = {AddGroup.class})
@ExcelProperty(value = "板块")
private String plate;
/**
* 一级部门
*/
@NotBlank(message = "一级部门不能为空", groups = {AddGroup.class})
@ExcelProperty(value = "一级部门")
private String firstLevelDepartment;
/**
* 二级部门
*/
@ExcelProperty(value = "二级部门")
private String secondLevelDepartment;
/**
* 三级部门
*/
@ExcelProperty(value = "三级部门")
private String thirdLevelDepartment;
// /**
// * 部门ID
// */
// @ExcelProperty(value = "部门ID")
// private Long deptId;
/**
* 岗位类型
*/
@ExcelProperty(value = "岗位类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_POSITION_TYPE)
private String positionType;
/**
* 主岗位
*/
@ExcelProperty(value = "主岗位")
private String position;
/**
* 姓名
*/
@ExcelProperty(value = "姓名")
private String name;
/**
* 性别
*/
@ExcelProperty(value = "性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_USER_SEX)
private String gender;
/**
* 身份证号码
*/
@NotBlank(message = "身份证号码不能为空", groups = {AddGroup.class, EditGroup.class})
@ExcelProperty(value = "身份证号码")
private String idCardNumber;
/**
// * OSS_ID
// */
// @ExcelIgnore
// private Long ossId;
// /**
// * 照片
// */
// @ExcelProperty(value = "照片", converter = ExcelUrlImageConverter.class)
// private String photo;
/**
* 出生日期
*/
@ExcelProperty(value = "出生日期")
private LocalDate birthDate;
/**
* 年龄
*/
@ExcelProperty(value = "年龄")
private Integer age;
// /**
// * 年龄段
// */
// @ExcelProperty(value = "年龄段", converter = ExcelDictConvert.class)
// @ExcelDictFormat(dictType = HrConstant.HR_AGE_GROUP)
// private String ageGroup;
/**
* 籍贯
*/
@ExcelProperty(value = "籍贯")
private String nativePlace;
/**
* 民族
*/
@ExcelProperty(value = "民族")
private String ethnicity;
/**
* 婚姻状况
*/
@ExcelProperty(value = "婚姻状况", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_MARITAL_STATUS)
private String maritalStatus;
/**
* 政治面貌
*/
@ExcelProperty(value = "政治面貌", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_POLITICAL_STATUS)
private String politicalStatus;
/**
* 手机号码
*/
@ExcelProperty(value = "手机号码")
private String phoneNumber;
/**
* 紧急联系人
*/
@ExcelProperty(value = "紧急联系人")
private String emergencyContact;
/**
* 紧急联系人电话
*/
@ExcelProperty(value = "紧急联系人电话")
private String emergencyContactPhone;
/**
* 家庭地址
*/
@ExcelProperty(value = "家庭地址")
private String homeAddress;
/**
* 入职时间
*/
@ExcelProperty(value = "入职时间")
private LocalDate entryDate;
/**
* 全日制学历
*/
@ExcelProperty(value = "全日制学历")
private String fulltimeEducation;
/**
* 全日制毕业院校
*/
@ExcelProperty(value = "全日制毕业院校")
private String fulltimeSchool;
/**
* 全日制专业
*/
@ExcelProperty(value = "全日制专业")
private String fulltimeMajor;
/**
* 全日制毕业日期
*/
@ExcelProperty(value = "全日制毕业日期")
private LocalDate fulltimeGraduationDate;
/**
* 全日制学位
*/
@ExcelProperty(value = "全日制学位")
private String fulltimeDegree;
/**
* 用工形式
*/
@ExcelProperty(value = "用工形式", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_EMPLOYMENT_FORM)
private String employmentForm;
// /**
// * 是否兼职
// */
// @ExcelProperty(value = "是否兼职")
// private String partTimeFlag;
/**
* 签订兼职协议
*/
@ExcelProperty(value = "签订兼职协议", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
private String partTimeAgreement;
/**
* 协议主体
*/
@ExcelProperty(value = "协议主体")
private String agreementEntity;
/**
* 协议期限
*/
@ExcelProperty(value = "协议期限")
private String agreementPeriod;
/**
* 协议开始时间
*/
@ExcelProperty(value = "协议开始时间")
private LocalDate agreementStartDate;
/**
* 协议截止时间
*/
@ExcelProperty(value = "协议截止时间")
private LocalDate agreementEndDate;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remarks;
/**
* 银行卡号
*/
@ExcelProperty(value = "银行卡号")
private String bankCardNumber;
/**
* 开户行
*/
@ExcelProperty(value = "开户行")
private String bankName;
/**
* 公司内是否有亲属关系
*/
@ExcelProperty(value = "公司内是否有亲属关系", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
private String hasRelativeInCompany;
/**
* 亲属姓名
*/
@ExcelProperty(value = "亲属姓名")
private String relativeName;
/**
* 介绍人
*/
@ExcelProperty(value = "介绍人")
private String introducer;
/**
* 介绍人关系
*/
@ExcelProperty(value = "介绍人关系")
private String introducerRelation;
/**
* 工资发放地
*/
@ExcelProperty(value = "工资发放地")
private String salaryLocation;
/**
* 成本费用所属
*/
@ExcelProperty(value = "成本费用所属")
private String costOfDept;
public void setPlate(String plate) {
this.plate = plate == null ? null : plate.trim();
}
public void setFirstLevelDepartment(String firstLevelDepartment) {
this.firstLevelDepartment = firstLevelDepartment == null ? null : firstLevelDepartment.trim();
}
public void setSecondLevelDepartment(String secondLevelDepartment) {
this.secondLevelDepartment = secondLevelDepartment == null ? null : secondLevelDepartment.trim();
}
public void setThirdLevelDepartment(String thirdLevelDepartment) {
this.thirdLevelDepartment = thirdLevelDepartment == null ? null : thirdLevelDepartment.trim();
}
public void setPositionType(String positionType) {
this.positionType = positionType == null ? null : positionType.trim();
}
public void setPosition(String position) {
this.position = position == null ? null : position.trim();
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public void setGender(String gender) {
this.gender = gender == null ? null : gender.trim();
}
public void setIdCardNumber(String idCardNumber) {
this.idCardNumber = idCardNumber == null ? null : idCardNumber.trim();
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public void setAge(Integer age) {
this.age = age;
}
public void setNativePlace(String nativePlace) {
this.nativePlace = nativePlace == null ? null : nativePlace.trim();
}
public void setEthnicity(String ethnicity) {
this.ethnicity = ethnicity == null ? null : ethnicity.trim();
}
public void setMaritalStatus(String maritalStatus) {
this.maritalStatus = maritalStatus == null ? null : maritalStatus.trim();
}
public void setPoliticalStatus(String politicalStatus) {
this.politicalStatus = politicalStatus == null ? null : politicalStatus.trim();
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber == null ? null : phoneNumber.trim();
}
public void setEmergencyContact(String emergencyContact) {
this.emergencyContact = emergencyContact == null ? null : emergencyContact.trim();
}
public void setEmergencyContactPhone(String emergencyContactPhone) {
this.emergencyContactPhone = emergencyContactPhone == null ? null : emergencyContactPhone.trim();
}
public void setHomeAddress(String homeAddress) {
this.homeAddress = homeAddress == null ? null : homeAddress.trim();
}
public void setEntryDate(LocalDate entryDate) {
this.entryDate = entryDate;
}
public void setFulltimeEducation(String fulltimeEducation) {
this.fulltimeEducation = fulltimeEducation == null ? null : fulltimeEducation.trim();
}
public void setFulltimeSchool(String fulltimeSchool) {
this.fulltimeSchool = fulltimeSchool == null ? null : fulltimeSchool.trim();
}
public void setFulltimeMajor(String fulltimeMajor) {
this.fulltimeMajor = fulltimeMajor == null ? null : fulltimeMajor.trim();
}
public void setFulltimeGraduationDate(LocalDate fulltimeGraduationDate) {
this.fulltimeGraduationDate = fulltimeGraduationDate;
}
public void setFulltimeDegree(String fulltimeDegree) {
this.fulltimeDegree = fulltimeDegree == null ? null : fulltimeDegree.trim();
}
public void setEmploymentForm(String employmentForm) {
this.employmentForm = employmentForm == null ? null : employmentForm.trim();
}
public void setPartTimeAgreement(String partTimeAgreement) {
this.partTimeAgreement = partTimeAgreement == null ? null : partTimeAgreement.trim();
}
public void setAgreementEntity(String agreementEntity) {
this.agreementEntity = agreementEntity == null ? null : agreementEntity.trim();
}
public void setAgreementPeriod(String agreementPeriod) {
this.agreementPeriod = agreementPeriod == null ? null : agreementPeriod.trim();
}
public void setAgreementStartDate(LocalDate agreementStartDate) {
this.agreementStartDate = agreementStartDate;
}
public void setAgreementEndDate(LocalDate agreementEndDate) {
this.agreementEndDate = agreementEndDate;
}
public void setRemarks(String remarks) {
this.remarks = remarks == null ? null : remarks.trim();
}
public void setBankCardNumber(String bankCardNumber) {
this.bankCardNumber = bankCardNumber == null ? null : bankCardNumber.trim();
}
public void setBankName(String bankName) {
this.bankName = bankName == null ? null : bankName.trim();
}
public void setHasRelativeInCompany(String hasRelativeInCompany) {
this.hasRelativeInCompany = hasRelativeInCompany == null ? null : hasRelativeInCompany.trim();
}
public void setRelativeName(String relativeName) {
this.relativeName = relativeName == null ? null : relativeName.trim();
}
public void setIntroducer(String introducer) {
this.introducer = introducer == null ? null : introducer.trim();
}
public void setIntroducerRelation(String introducerRelation) {
this.introducerRelation = introducerRelation == null ? null : introducerRelation.trim();
}
public void setSalaryLocation(String salaryLocation) {
this.salaryLocation = salaryLocation == null ? null : salaryLocation.trim();
}
public void setCostOfDept(String costOfDept) {
this.costOfDept = costOfDept == null ? null : costOfDept.trim();
}
}
package com.anplus.hr.domain.vo;
import java.time.LocalDate;
import com.anplus.hr.constant.HrConstant;
import com.anplus.hr.domain.EmployeeInfo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.ExcelIgnore;
import org.dromara.core.trans.anno.Trans;
import org.dromara.core.trans.constant.TransType;
import org.dromara.core.trans.vo.TransPojo;
import top.binfast.common.excel.annotion.ExcelDictFormat;
import top.binfast.common.excel.converters.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import top.binfast.common.excel.converters.ExcelUrlImageConverter;
import java.io.Serial;
import java.io.Serializable;
/**
* 兼职员工信息视图对象 employee_part_time_info
*
* @author LiuBin
* @date 2025-12-10
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EmployeeInfo.class)
public class EmployeePartTimeInfoVo implements TransPojo, Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 序号
*/
private Long id;
/**
* 板块
*/
@ExcelProperty(value = "板块")
private String plate;
/**
* 一级部门
*/
@ExcelProperty(value = "一级部门")
private String firstLevelDepartment;
/**
* 二级部门
*/
@ExcelProperty(value = "二级部门")
private String secondLevelDepartment;
/**
* 三级部门
*/
@ExcelProperty(value = "三级部门")
private String thirdLevelDepartment;
/**
* 部门ID
*/
@ExcelProperty(value = "部门ID")
private Long deptId;
/**
* 岗位类型
*/
@ExcelProperty(value = "岗位类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_POSITION_TYPE)
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_POSITION_TYPE)
private String positionType;
/**
* 主岗位
*/
@ExcelProperty(value = "主岗位")
private String position;
/**
* 姓名
*/
@ExcelProperty(value = "姓名")
private String name;
/**
* 性别
*/
@ExcelProperty(value = "性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_USER_SEX)
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_USER_SEX)
private String gender;
/**
* 身份证号码
*/
@ExcelProperty(value = "身份证号码")
private String idCardNumber;
/**
* OSS_ID
*/
@ExcelIgnore
private Long ossId;
/**
* 照片
*/
@ExcelProperty(value = "照片", converter = ExcelUrlImageConverter.class)
private String photo;
/**
* 出生日期
*/
@ExcelProperty(value = "出生日期")
private LocalDate birthDate;
/**
* 年龄
*/
@ExcelProperty(value = "年龄")
private Integer age;
/**
* 年龄段
*/
@ExcelProperty(value = "年龄段", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_AGE_GROUP)
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_AGE_GROUP)
private String ageGroup;
/**
* 籍贯
*/
@ExcelProperty(value = "籍贯")
private String nativePlace;
/**
* 民族
*/
@ExcelProperty(value = "民族")
private String ethnicity;
/**
* 婚姻状况
*/
@ExcelProperty(value = "婚姻状况", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_MARITAL_STATUS)
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_MARITAL_STATUS)
private String maritalStatus;
/**
* 政治面貌
*/
@ExcelProperty(value = "政治面貌", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_POLITICAL_STATUS)
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_POLITICAL_STATUS)
private String politicalStatus;
/**
* 手机号码
*/
@ExcelProperty(value = "手机号码")
private String phoneNumber;
/**
* 紧急联系人
*/
@ExcelProperty(value = "紧急联系人")
private String emergencyContact;
/**
* 紧急联系人电话
*/
@ExcelProperty(value = "紧急联系人电话")
private String emergencyContactPhone;
/**
* 家庭地址
*/
@ExcelProperty(value = "家庭地址")
private String homeAddress;
/**
* 入职时间
*/
@ExcelProperty(value = "入职时间")
private LocalDate entryDate;
/**
* 全日制学历
*/
@ExcelProperty(value = "全日制学历")
private String fulltimeEducation;
/**
* 全日制毕业院校
*/
@ExcelProperty(value = "全日制毕业院校")
private String fulltimeSchool;
/**
* 全日制专业
*/
@ExcelProperty(value = "全日制专业")
private String fulltimeMajor;
/**
* 全日制毕业日期
*/
@ExcelProperty(value = "全日制毕业日期")
private LocalDate fulltimeGraduationDate;
/**
* 全日制学位
*/
@ExcelProperty(value = "全日制学位")
private String fulltimeDegree;
/**
* 用工形式
*/
@ExcelProperty(value = "用工形式", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.HR_EMPLOYMENT_FORM)
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_EMPLOYMENT_FORM)
private String employmentForm;
/**
* 是否兼职
*/
// @ExcelProperty(value = "是否兼职")
private String partTimeFlag;
/**
* 签订兼职协议
*/
@ExcelProperty(value = "签订兼职协议", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
@Trans(type = TransType.DICTIONARY, key = HrConstant.SYS_YES_NO)
private String partTimeAgreement;
/**
* 协议主体
*/
@ExcelProperty(value = "协议主体")
private String agreementEntity;
/**
* 协议期限
*/
@ExcelProperty(value = "协议期限")
private String agreementPeriod;
/**
* 协议开始时间
*/
@ExcelProperty(value = "协议开始时间")
private LocalDate agreementStartDate;
/**
* 协议截止时间
*/
@ExcelProperty(value = "协议截止时间")
private LocalDate agreementEndDate;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remarks;
/**
* 银行卡号
*/
@ExcelProperty(value = "银行卡号")
private String bankCardNumber;
/**
* 开户行
*/
@ExcelProperty(value = "开户行")
private String bankName;
/**
* 公司内是否有亲属关系
*/
@ExcelProperty(value = "公司内是否有亲属关系", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = HrConstant.SYS_YES_NO)
@Trans(type = TransType.DICTIONARY, key = HrConstant.SYS_YES_NO)
private String hasRelativeInCompany;
/**
* 亲属姓名
*/
@ExcelProperty(value = "亲属姓名")
private String relativeName;
/**
* 介绍人
*/
@ExcelProperty(value = "介绍人")
private String introducer;
/**
* 介绍人关系
*/
@ExcelProperty(value = "介绍人关系")
private String introducerRelation;
/**
* 工资发放地
*/
@ExcelProperty(value = "工资发放地")
private String salaryLocation;
/**
* 成本费用所属
*/
@ExcelProperty(value = "成本费用所属")
private String costOfDept;
/**
* 员工状态
*/
private Integer status;
}
package com.anplus.hr.service;
import cn.hutool.core.util.StrUtil;
import top.binfast.common.log.model.SysAuditLog;
import java.util.List;
......@@ -17,6 +18,9 @@ public interface EmployeeAuditLogServ {
Boolean removeAuditLogs(List<Long> logIds);
default void initAuditLog(String auditName, String auditField, String auditFieldName, String afterVal, List<SysAuditLog> list) {
if (StrUtil.isBlank(afterVal)) {
return;
}
SysAuditLog auditLog = new SysAuditLog();
auditLog.setAuditName(auditName);
auditLog.setAuditField(auditField);
......
......@@ -68,10 +68,11 @@ public interface EmployeeInfoServ extends IService<EmployeeInfo> {
/**
* 校验员工名称是否唯一
*
* @param param 员工信息
* @param idCardNumber 员工身份证号
* @param employeeId 员工主键
* @return 是否唯一
*/
Boolean checkEmployeeIdCardNumberUnique(EmployeeInfoParam param);
Boolean checkEmployeeIdCardNumberUnique(String idCardNumber, Long employeeId);
/**
* 查询员工信息
*
......
package com.anplus.hr.service;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.anplus.hr.domain.EmployeeInfo;
import com.anplus.hr.domain.params.EmployeePartTimeInfoListParam;
import com.anplus.hr.domain.params.EmployeePartTimeInfoParam;
import com.anplus.hr.domain.vo.EmployeePartTimeInfoImportVo;
import com.anplus.hr.domain.vo.EmployeePartTimeInfoVo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.stream.Stream;
/**
* 兼职员工信息Service接口
*
* @author LiuBin
* @date 2025-12-10
*/
public interface EmployeePartTimeInfoServ extends IService<EmployeeInfo> {
/**
* 分页查询兼职员工信息列表
*
* @param param 查询条件
* @return 兼职员工信息分页列表
*/
PageResponse<EmployeePartTimeInfoVo> queryPageList(EmployeePartTimeInfoListParam param);
/**
* 查询符合条件的兼职员工信息列表
*
* @param param 查询条件
* @return 兼职员工信息列表
*/
List<EmployeePartTimeInfoVo> queryList(EmployeePartTimeInfoListParam param);
/**
* 导入兼职员工信息列表
*
* @param stream 员工信息列表
* @return 是否导入成功
*/
Response importPartTimeEmployeeList(Stream<EmployeePartTimeInfoImportVo> stream);
/**
* 查询兼职员工信息
*
* @param id 主键
* @return 兼职员工信息
*/
EmployeePartTimeInfoVo queryById(Long id);
/**
* 员工信息详情
*
* @param id 主键
* @return 员工信息
*/
EmployeePartTimeInfoVo infoDetail(Long id);
/**
* 新增兼职员工信息
*
* @param param 兼职员工信息
* @return 是否新增成功
*/
Boolean insertByParam(EmployeePartTimeInfoParam param);
/**
* 修改兼职员工信息
*
* @param param 兼职员工信息
* @return 是否修改成功
*/
Boolean updateByParam(EmployeePartTimeInfoParam param);
/**
* 校验并批量删除兼职员工信息信息
*
* @param ids 待删除的主键集合
* @return 是否删除成功
*/
Boolean delByIds(List<Long> ids);
}
......@@ -24,6 +24,9 @@ public interface EmployeeSysDeptServ {
*/
List<SysDeptDTO> selectDeptTreeForEmployee(SysDeptParam param);
/**
* 查询部门名称和叶子部门ID,部门名拼接成串作为key
*/
Map<String, Long> selectJoinDeptNames();
/**
......
......@@ -112,8 +112,8 @@ public class EmployeeInfoResignServImpl extends ServiceImpl<EmployeeInfoMapper,
errorList.add(item);
return;
}
EmployeeInfoParam employeeInfoParam = MapstructUtils.convert(item, EmployeeInfoParam.class);
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(employeeInfoParam) || idCardNumberSet.contains(item.getIdCardNumber())) {
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(item.getIdCardNumber(), null) ||
idCardNumberSet.contains(item.getIdCardNumber())) {
item.addError("身份证号已存在");
errorList.add(item);
return;
......
......@@ -223,7 +223,7 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
lambdaQuery.eq(param.getResignationDate() != null, EmployeeInfo::getResignationDate, param.getResignationDate());
lambdaQuery.eq(StrUtil.isNotBlank(param.getResignationReason()), EmployeeInfo::getResignationReason, param.getResignationReason());
lambdaQuery.eq(param.getFinalPayDate() != null, EmployeeInfo::getFinalPayDate, param.getFinalPayDate());
lambdaQuery.eq(StrUtil.isNotBlank(param.getCostOfDept()), EmployeeInfo::getCostOfDept, param.getCostOfDept());
lambdaQuery.like(StrUtil.isNotBlank(param.getCostOfDept()), EmployeeInfo::getCostOfDept, param.getCostOfDept());
lambdaQuery.eq(StrUtil.isNotBlank(param.getCostType()), EmployeeInfo::getCostType, param.getCostType());
// lambdaQuery.eq(param.getResignationApplyStatus() != null, EmployeeInfo::getResignationApplyStatus, param.getResignationApplyStatus());
......@@ -260,8 +260,8 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
errorList.add(item);
return;
}
EmployeeInfoParam employeeInfoParam = MapstructUtils.convert(item, EmployeeInfoParam.class);
if (checkEmployeeIdCardNumberUnique(employeeInfoParam) || idCardNumberSet.contains(item.getIdCardNumber())) {
if (checkEmployeeIdCardNumberUnique(item.getIdCardNumber(), null) ||
idCardNumberSet.contains(item.getIdCardNumber())) {
item.addError("身份证号已存在");
errorList.add(item);
return;
......@@ -381,10 +381,10 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
}
@Override
public Boolean checkEmployeeIdCardNumberUnique(EmployeeInfoParam employee) {
public Boolean checkEmployeeIdCardNumberUnique(String idCardNumber, Long employeeId) {
return employeeInfoMapper.exists(new LambdaQueryWrapper<EmployeeInfo>()
.eq(EmployeeInfo::getIdCardNumber, employee.getIdCardNumber())
.ne(ObjectUtil.isNotNull(employee.getId()), EmployeeInfo::getId, employee.getId()));
.eq(EmployeeInfo::getIdCardNumber, idCardNumber)
.ne(ObjectUtil.isNotNull(employeeId), EmployeeInfo::getId, employeeId));
}
/**
......@@ -410,7 +410,14 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
@Override
public EmployeeInfoVo infoDetail(Long id) {
EmployeeInfo employeeInfo = employeeInfoMapper.selectById(id);
EmployeeInfoVo employeeInfoVo = MapstructUtils.convert(employeeInfo, EmployeeInfoVo.class);
EmployeeInfoVo employeeInfoVo;
if (Objects.equals(employeeInfo.getStatus(), HrStatusEnum.RESIGN.getStatus())) {
employeeInfoVo = MapstructUtils.convert(employeeInfo, EmployeeInfoResignVo.class);
} else if (HrEmployeeConstants.YES.equals(employeeInfo.getPartTimeFlag())) {
employeeInfoVo = MapstructUtils.convert(employeeInfo, EmployeePartTimeInfoDetailVo.class);
} else {
employeeInfoVo = MapstructUtils.convert(employeeInfo, EmployeeInfoVo.class);
}
if (employeeInfo.getOssId() != null && employeeInfo.getOssId() > 0) {
SysOss sysOss = sysOssMapper.selectById(employeeInfo.getOssId());
if (sysOss != null) {
......@@ -651,21 +658,14 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
List<SysAuditLog> list = new ArrayList<>(6);
employeeAuditLogServ.initAuditLog("离职申请", "resignationType",
"离职类型", param.getResignationType(), list);
employeeAuditLogServ.initAuditLog("离职申请", "resignationDate",
"离职时间", LocalDateTimeUtil.format(param.getResignationDate(), DatePattern.NORM_DATE_PATTERN), list);
if (StrUtil.isNotBlank(param.getResignationCategory())) {
employeeAuditLogServ.initAuditLog("离职申请", "resignationCategory",
"离职类别", param.getResignationCategory(), list);
}
if (StrUtil.isNotBlank(param.getResignationReason())) {
employeeAuditLogServ.initAuditLog("离职申请", "resignationReason",
"离职原因", param.getResignationReason(), list);
}
if (ObjectUtil.isNotNull(param.getFinalPayDate())) {
employeeAuditLogServ.initAuditLog("离职申请", "finalPayDate",
"最后结薪日", LocalDateTimeUtil.format(param.getFinalPayDate(), DatePattern.NORM_DATE_PATTERN), list);
}
employeeAuditLogServ.saveAuditLogs(list);
String logIds = LambdaUtil.join(list, (item) -> item.getId() + StrUtil.EMPTY, StrUtil.COMMA);
EmployeeFlowParam flowParam = new EmployeeFlowParam();
......
package com.anplus.hr.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.anplus.hr.config.EmployeeInfoCalcUtils;
import com.anplus.hr.constant.HrEmployeeConstants;
import com.anplus.hr.constant.HrFlowEnum;
import com.anplus.hr.constant.HrStatusEnum;
import com.anplus.hr.domain.EmployeeInfo;
import com.anplus.hr.domain.params.EmployeePartTimeInfoListParam;
import com.anplus.hr.domain.params.EmployeePartTimeInfoParam;
import com.anplus.hr.domain.vo.EmployeeInfoImportVo;
import com.anplus.hr.domain.vo.EmployeeInfoVo;
import com.anplus.hr.domain.vo.EmployeePartTimeInfoImportVo;
import com.anplus.hr.domain.vo.EmployeePartTimeInfoVo;
import com.anplus.hr.mapper.EmployeeInfoMapper;
import com.anplus.hr.service.EmployeeInfoServ;
import com.anplus.hr.service.EmployeePartTimeInfoServ;
import com.anplus.hr.service.EmployeeSysDeptServ;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.dromara.trans.service.impl.TransService;
import org.springframework.stereotype.Service;
import top.binfast.app.biz.sysapi.bean.model.oss.SysOss;
import top.binfast.common.core.enums.ResultCode;
import top.binfast.common.core.util.MapstructUtils;
import top.binfast.common.core.validate.AddGroup;
import top.binfast.common.excel.core.ExcelContextHolder;
import top.binfast.common.mybatis.util.QueryUtil;
import java.util.*;
import java.util.stream.Stream;
/**
* 兼职员工信息Service业务层处理
*
* @author LiuBin
* @date 2025-12-10
*/
@RequiredArgsConstructor
@Service
public class EmployeePartTimeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, EmployeeInfo> implements EmployeePartTimeInfoServ {
private final EmployeeInfoMapper employeeInfoMapper;
private final EmployeeInfoServ employeeInfoServ;
private final EmployeeSysDeptServ employeeSysDeptServ;
private final TransService transService;
/**
* 分页查询兼职员工信息列表
*
* @param param 查询条件
* @return 兼职员工信息分页列表
*/
@Override
public PageResponse<EmployeePartTimeInfoVo> queryPageList(EmployeePartTimeInfoListParam param) {
Page<EmployeeInfo> page = QueryUtil.getPage(param);
LambdaQueryWrapper<EmployeeInfo> lambdaQuery = this.buildQueryWrapper(param);
employeeInfoMapper.selectPage(page, lambdaQuery);
return QueryUtil.getPageResponse(page, MapstructUtils.convert(page.getRecords(), EmployeePartTimeInfoVo.class));
}
/**
* 查询符合条件的兼职员工信息列表
*
* @param param 查询条件
* @return 兼职员工信息列表
*/
@Override
public List<EmployeePartTimeInfoVo> queryList(EmployeePartTimeInfoListParam param) {
LambdaQueryWrapper<EmployeeInfo> lambdaQuery = this.buildQueryWrapper(param);
return MapstructUtils.convert(employeeInfoMapper.selectList(lambdaQuery), EmployeePartTimeInfoVo.class);
}
private LambdaQueryWrapper<EmployeeInfo> buildQueryWrapper(EmployeePartTimeInfoListParam param) {
LambdaQueryWrapper<EmployeeInfo> lambdaQuery = Wrappers.<EmployeeInfo>lambdaQuery();
lambdaQuery.orderByDesc(EmployeeInfo::getId);
lambdaQuery.eq(EmployeeInfo::getPartTimeFlag, HrEmployeeConstants.YES);
// lambdaQuery.eq(StrUtil.isNotBlank(param.getPlate()), EmployeeInfo::getPlate, param.getPlate());
// lambdaQuery.eq(StrUtil.isNotBlank(param.getFirstLevelDepartment()), EmployeeInfo::getFirstLevelDepartment, param.getFirstLevelDepartment());
// lambdaQuery.eq(StrUtil.isNotBlank(param.getSecondLevelDepartment()), EmployeeInfo::getSecondLevelDepartment, param.getSecondLevelDepartment());
// lambdaQuery.eq(StrUtil.isNotBlank(param.getThirdLevelDepartment()), EmployeeInfo::getThirdLevelDepartment, param.getThirdLevelDepartment());
// lambdaQuery.eq(param.getDeptId() != null, EmployeeInfo::getDeptId, param.getDeptId());
if (ObjectUtil.isNotNull(param.getDeptId())) {
//优先单部门搜索
lambdaQuery.eq(EmployeeInfo::getDeptId, param.getDeptId());
} else if (ObjectUtil.isNotNull(param.getBelongDeptId())) {
//部门树搜索
lambdaQuery.and(x -> {
x.in(EmployeeInfo::getDeptId, employeeSysDeptServ.buildQueryWrapper(param.getBelongDeptId()));
});
}
lambdaQuery.eq(StrUtil.isNotBlank(param.getPositionType()), EmployeeInfo::getPositionType, param.getPositionType());
lambdaQuery.eq(StrUtil.isNotBlank(param.getPosition()), EmployeeInfo::getPosition, param.getPosition());
lambdaQuery.like(StrUtil.isNotBlank(param.getName()), EmployeeInfo::getName, param.getName());
lambdaQuery.eq(StrUtil.isNotBlank(param.getGender()), EmployeeInfo::getGender, param.getGender());
lambdaQuery.eq(StrUtil.isNotBlank(param.getIdCardNumber()), EmployeeInfo::getIdCardNumber, param.getIdCardNumber());
lambdaQuery.eq(param.getOssId() != null, EmployeeInfo::getOssId, param.getOssId());
lambdaQuery.eq(param.getBirthDate() != null, EmployeeInfo::getBirthDate, param.getBirthDate());
lambdaQuery.eq(param.getAge() != null, EmployeeInfo::getAge, param.getAge());
lambdaQuery.eq(StrUtil.isNotBlank(param.getNativePlace()), EmployeeInfo::getNativePlace, param.getNativePlace());
lambdaQuery.eq(StrUtil.isNotBlank(param.getEthnicity()), EmployeeInfo::getEthnicity, param.getEthnicity());
lambdaQuery.eq(StrUtil.isNotBlank(param.getMaritalStatus()), EmployeeInfo::getMaritalStatus, param.getMaritalStatus());
lambdaQuery.eq(StrUtil.isNotBlank(param.getPoliticalStatus()), EmployeeInfo::getPoliticalStatus, param.getPoliticalStatus());
lambdaQuery.eq(StrUtil.isNotBlank(param.getPhoneNumber()), EmployeeInfo::getPhoneNumber, param.getPhoneNumber());
lambdaQuery.eq(StrUtil.isNotBlank(param.getEmergencyContact()), EmployeeInfo::getEmergencyContact, param.getEmergencyContact());
lambdaQuery.eq(StrUtil.isNotBlank(param.getEmergencyContactPhone()), EmployeeInfo::getEmergencyContactPhone, param.getEmergencyContactPhone());
lambdaQuery.eq(StrUtil.isNotBlank(param.getHomeAddress()), EmployeeInfo::getHomeAddress, param.getHomeAddress());
lambdaQuery.eq(param.getEntryDate() != null, EmployeeInfo::getEntryDate, param.getEntryDate());
lambdaQuery.eq(StrUtil.isNotBlank(param.getFulltimeEducation()), EmployeeInfo::getFulltimeEducation, param.getFulltimeEducation());
lambdaQuery.eq(StrUtil.isNotBlank(param.getFulltimeSchool()), EmployeeInfo::getFulltimeSchool, param.getFulltimeSchool());
lambdaQuery.eq(StrUtil.isNotBlank(param.getFulltimeMajor()), EmployeeInfo::getFulltimeMajor, param.getFulltimeMajor());
lambdaQuery.eq(param.getFulltimeGraduationDate() != null, EmployeeInfo::getFulltimeGraduationDate, param.getFulltimeGraduationDate());
lambdaQuery.eq(StrUtil.isNotBlank(param.getFulltimeDegree()), EmployeeInfo::getFulltimeDegree, param.getFulltimeDegree());
lambdaQuery.eq(StrUtil.isNotBlank(param.getEmploymentForm()), EmployeeInfo::getEmploymentForm, param.getEmploymentForm());
lambdaQuery.eq(StrUtil.isNotBlank(param.getPartTimeFlag()), EmployeeInfo::getPartTimeFlag, param.getPartTimeFlag());
lambdaQuery.eq(StrUtil.isNotBlank(param.getPartTimeAgreement()), EmployeeInfo::getPartTimeAgreement, param.getPartTimeAgreement());
lambdaQuery.eq(StrUtil.isNotBlank(param.getAgreementEntity()), EmployeeInfo::getAgreementEntity, param.getAgreementEntity());
lambdaQuery.eq(StrUtil.isNotBlank(param.getAgreementPeriod()), EmployeeInfo::getAgreementPeriod, param.getAgreementPeriod());
lambdaQuery.eq(param.getAgreementStartDate() != null, EmployeeInfo::getAgreementStartDate, param.getAgreementStartDate());
lambdaQuery.eq(param.getAgreementEndDate() != null, EmployeeInfo::getAgreementEndDate, param.getAgreementEndDate());
lambdaQuery.eq(StrUtil.isNotBlank(param.getRemarks()), EmployeeInfo::getRemarks, param.getRemarks());
lambdaQuery.eq(StrUtil.isNotBlank(param.getBankCardNumber()), EmployeeInfo::getBankCardNumber, param.getBankCardNumber());
lambdaQuery.like(StrUtil.isNotBlank(param.getBankName()), EmployeeInfo::getBankName, param.getBankName());
lambdaQuery.eq(StrUtil.isNotBlank(param.getHasRelativeInCompany()), EmployeeInfo::getHasRelativeInCompany, param.getHasRelativeInCompany());
lambdaQuery.like(StrUtil.isNotBlank(param.getRelativeName()), EmployeeInfo::getRelativeName, param.getRelativeName());
lambdaQuery.eq(StrUtil.isNotBlank(param.getIntroducer()), EmployeeInfo::getIntroducer, param.getIntroducer());
lambdaQuery.eq(StrUtil.isNotBlank(param.getIntroducerRelation()), EmployeeInfo::getIntroducerRelation, param.getIntroducerRelation());
lambdaQuery.eq(StrUtil.isNotBlank(param.getSalaryLocation()), EmployeeInfo::getSalaryLocation, param.getSalaryLocation());
lambdaQuery.like(StrUtil.isNotBlank(param.getCostOfDept()), EmployeeInfo::getCostOfDept, param.getCostOfDept());
return lambdaQuery;
}
@Override
public Response importPartTimeEmployeeList(Stream<EmployeePartTimeInfoImportVo> list) {
List<EmployeePartTimeInfoImportVo> errorList = new ArrayList<>();
List<EmployeePartTimeInfoImportVo> successList = new ArrayList<>();
Set<String> idCardNumberSet = new HashSet<>();
list.forEach(item -> {
item.validGroup(AddGroup.class);
if (item.hasError()) {
errorList.add(item);
return;
}
if (employeeInfoServ.checkEmployeeIdCardNumberUnique(item.getIdCardNumber(), null) ||
idCardNumberSet.contains(item.getIdCardNumber())) {
item.addError("身份证号已存在");
errorList.add(item);
return;
}
idCardNumberSet.add(item.getIdCardNumber());
successList.add(item);
});
if (CollUtil.isNotEmpty(successList)) {
Map<String, Long> deptNamesIdMap = employeeSysDeptServ.selectJoinDeptNames();
List<EmployeeInfo> insertList = new ArrayList<>(successList.size());
for (EmployeePartTimeInfoImportVo importVo : successList) {
EmployeeInfoImportVo deptInfo = MapstructUtils.convert(importVo, EmployeeInfoImportVo.class);
Long leafDeptId = deptNamesIdMap.get(employeeInfoServ.buildDeptNameStr(deptInfo));
if (leafDeptId == null) {
importVo.addError("部门不存在");
errorList.add(importVo);
continue;
}
EmployeeInfo employeeInfo = MapstructUtils.convert(importVo, EmployeeInfo.class);
employeeInfo.setDeptId(leafDeptId);
employeeInfo.setStatus(employeeInfo.getEntryDate() == null
? HrStatusEnum.DRAFT.getStatus() : HrStatusEnum.ENTRY.getStatus());
employeeInfo.setPartTimeFlag(HrEmployeeConstants.YES);
EmployeeInfoCalcUtils.calcAgeGroup(employeeInfo);
// EmployeeInfoCalcUtils.calcExpectedRegularDate(employeeInfo);
insertList.add(employeeInfo);
}
employeeInfoMapper.insert(insertList);
}
StringBuilder message;
if (CollUtil.isNotEmpty(errorList)) {
ExcelContextHolder.setErrorExist();
message = new StringBuilder("共" + errorList.size() + "条数据导入失败,错误如下:<br/>");
errorList.forEach(item -> message.append(item.defaultFailMsg()));
return Response.buildFailure(ResultCode.FAIL.getCode(), message.toString());
} else {
message = new StringBuilder("共" + successList.size() + "条数据导入成功");
Response response = Response.buildSuccess();
response.setErrMessage(message.toString());
return response;
}
}
/**
* 查询兼职员工信息
*
* @param id 主键
* @return 兼职员工信息
*/
@Override
public EmployeePartTimeInfoVo queryById(Long id) {
EmployeeInfo employeePartTimeInfo = employeeInfoMapper.selectById(id);
return MapstructUtils.convert(employeePartTimeInfo, EmployeePartTimeInfoVo.class);
}
@Override
public EmployeePartTimeInfoVo infoDetail(Long id) {
EmployeeInfo employeeInfo = employeeInfoMapper.selectById(id);
EmployeePartTimeInfoVo employeeInfoVo = MapstructUtils.convert(employeeInfo, EmployeePartTimeInfoVo.class);
transService.transOne(employeeInfoVo);
return employeeInfoVo;
}
/**
* 新增兼职员工信息
*
* @param param 兼职员工信息
* @return 是否新增成功
*/
@Override
public Boolean insertByParam(EmployeePartTimeInfoParam param) {
EmployeeInfo employeePartTimeInfo = MapstructUtils.convert(param, EmployeeInfo.class);
// 更新员工年龄组
EmployeeInfoCalcUtils.calcAgeGroup(employeePartTimeInfo);
employeePartTimeInfo.setPartTimeFlag(HrEmployeeConstants.YES);
employeePartTimeInfo.setEntryApplyStatus(HrFlowEnum.DRAFT.getStatus());
employeePartTimeInfo.setStatus(HrStatusEnum.DRAFT.getStatus());
return this.save(employeePartTimeInfo);
}
/**
* 修改兼职员工信息
*
* @param param 兼职员工信息
* @return 是否修改成功
*/
@Override
public Boolean updateByParam(EmployeePartTimeInfoParam param) {
EmployeeInfo employeePartTimeInfo = MapstructUtils.convert(param, EmployeeInfo.class);
return this.updateById(employeePartTimeInfo);
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(EmployeeInfo entity) {
// 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除兼职员工信息信息
*
* @param ids 待删除的主键集合
* @return 是否删除成功
*/
@Override
// @Transactional(rollbackFor = {Exception.class})
public Boolean delByIds(List<Long> ids) {
//做一些业务上的校验,判断是否需要校验
return this.removeByIds(ids);
}
}
......@@ -52,6 +52,9 @@ public class EmployeeSysDeptServImpl implements EmployeeSysDeptServ {
return sysDeptServ.selectDeptTreeList(param);
}
/**
* 获取部门名称,拼接成xx/xx/xx/xx
*/
@Override
public Map<String, Long> selectJoinDeptNames() {
Map<String, Long> result = new HashMap<>();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment