This commit is contained in:
2025-12-30 13:47:53 +08:00
parent f1637501b2
commit a623c5673f
137 changed files with 11031 additions and 4043 deletions

View File

@@ -27,40 +27,35 @@ public class HrmCertificateController extends BaseController {
private final IHrmCertificateService service;
@SaCheckPermission("hrm:certificate:list")
@GetMapping("/list")
public TableDataInfo<HrmCertificateVo> list(HrmCertificateBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:certificate:query")
@GetMapping("/{certId}")
public R<HrmCertificateVo> getInfo(@PathVariable @NotNull Long certId) {
return R.ok(service.queryById(certId));
}
@SaCheckPermission("hrm:certificate:add")
@Log(title = "证书", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmCertificateBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:certificate:edit")
@Log(title = "证书", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmCertificateBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:certificate:remove")
@Log(title = "证书", businessType = BusinessType.DELETE)
@DeleteMapping("/{certIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] certIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(certIds), true));
}
@SaCheckPermission("hrm:certificate:list")
@GetMapping("/all")
public R<List<HrmCertificateVo>> all(HrmCertificateBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -27,40 +27,34 @@ public class HrmContractController extends BaseController {
private final IHrmContractService service;
@SaCheckPermission("hrm:contract:list")
@GetMapping("/list")
public TableDataInfo<HrmContractVo> list(HrmContractBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:contract:query")
@GetMapping("/{contractId}")
public R<HrmContractVo> getInfo(@PathVariable @NotNull Long contractId) {
return R.ok(service.queryById(contractId));
}
@SaCheckPermission("hrm:contract:add")
@Log(title = "劳动合同", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmContractBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:contract:edit")
@Log(title = "劳动合同", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmContractBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:contract:remove")
@Log(title = "劳动合同", businessType = BusinessType.DELETE)
@DeleteMapping("/{contractIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] contractIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(contractIds), true));
}
@SaCheckPermission("hrm:contract:list")
@GetMapping("/all")
public R<List<HrmContractVo>> all(HrmContractBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -27,40 +27,34 @@ public class HrmEmpOrgPositionController extends BaseController {
private final IHrmEmpOrgPositionService service;
@SaCheckPermission("hrm:emporg:list")
@GetMapping("/list")
public TableDataInfo<HrmEmpOrgPositionVo> list(HrmEmpOrgPositionBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:emporg:query")
@GetMapping("/{relId}")
public R<HrmEmpOrgPositionVo> getInfo(@PathVariable @NotNull Long relId) {
return R.ok(service.queryById(relId));
}
@SaCheckPermission("hrm:emporg:add")
@Log(title = "员工组织岗位关系", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmEmpOrgPositionBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:emporg:edit")
@Log(title = "员工组织岗位关系", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmEmpOrgPositionBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:emporg:remove")
@Log(title = "员工组织岗位关系", businessType = BusinessType.DELETE)
@DeleteMapping("/{relIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] relIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(relIds), true));
}
@SaCheckPermission("hrm:emporg:list")
@GetMapping("/all")
public R<List<HrmEmpOrgPositionVo>> all(HrmEmpOrgPositionBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -27,42 +27,50 @@ public class HrmEmployeeController extends BaseController {
private final IHrmEmployeeService service;
@SaCheckPermission("hrm:employee:list")
@GetMapping("/list")
public TableDataInfo<HrmEmployeeVo> list(HrmEmployeeBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:employee:query")
@GetMapping("/{empId}")
public R<HrmEmployeeVo> getInfo(@PathVariable @NotNull Long empId) {
return R.ok(service.queryById(empId));
}
@SaCheckPermission("hrm:employee:add")
@Log(title = "员工管理", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmEmployeeBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:employee:edit")
@Log(title = "员工管理", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmEmployeeBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:employee:remove")
@Log(title = "员工管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{empIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] empIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(empIds), true));
}
@SaCheckPermission("hrm:employee:list")
@GetMapping("/all")
public R<List<HrmEmployeeVo>> all(HrmEmployeeBo bo) {
return R.ok(service.queryList(bo));
}
/**
* 根据用户ID获取员工信息
*/
@GetMapping("/byUserId/{userId}")
public R<HrmEmployeeVo> getByUserId(@PathVariable @NotNull Long userId) {
HrmEmployeeBo bo = new HrmEmployeeBo();
bo.setUserId(userId);
List<HrmEmployeeVo> list = service.queryList(bo);
if (list != null && !list.isEmpty()) {
return R.ok(list.get(0));
}
return R.fail("未找到该用户对应的员工信息");
}
}

View File

@@ -25,13 +25,11 @@ public class HrmFlowActionController extends BaseController {
private final IHrmFlowActionService service;
@SaCheckPermission("hrm:flow:list")
@GetMapping("/list")
public TableDataInfo<HrmFlowActionVo> list(HrmFlowActionBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:flow:query")
@GetMapping("/{actionId}")
public R<HrmFlowActionVo> getInfo(@PathVariable @NotNull Long actionId) {
return R.ok(service.queryById(actionId));

View File

@@ -0,0 +1,70 @@
package com.klp.hrm.controller;
import cn.dev33.satoken.stp.StpUtil;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmFlowCcBo;
import com.klp.hrm.domain.vo.HrmFlowCcVo;
import com.klp.hrm.service.IHrmFlowCcService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/hrm/flow/cc")
public class HrmFlowCcController extends BaseController {
private final IHrmFlowCcService service;
/**
* 抄送我的
*/
@GetMapping("/my")
public TableDataInfo<HrmFlowCcVo> my(@RequestParam(required = false) Long ccUserId, PageQuery pageQuery) {
Long uid = ccUserId;
if (uid == null) {
try {
uid = StpUtil.getLoginIdAsLong();
} catch (Exception e) {
uid = null;
}
}
HrmFlowCcBo bo = new HrmFlowCcBo();
bo.setCcUserId(uid);
return service.queryPageList(bo, pageQuery);
}
@GetMapping("/list")
public TableDataInfo<HrmFlowCcVo> list(HrmFlowCcBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
/**
* 手动抄送(支持批量)
*/
@PostMapping
public R<Void> add(@RequestBody HrmFlowCcBo bo) {
return toAjax(service.insertBatch(bo));
}
/**
* 标记抄送已读
*/
@PostMapping("/{ccId}/read")
public R<Void> read(@PathVariable Long ccId) {
Long uid = StpUtil.getLoginIdAsLong();
return toAjax(service.markRead(ccId, uid));
}
@GetMapping("/ping")
public R<String> ping(@RequestParam @NotNull String x) {
return R.ok(x);
}
}

View File

@@ -25,13 +25,11 @@ public class HrmFlowFormDataController extends BaseController {
private final IHrmFormDataService service;
@SaCheckPermission("hrm:flow:list")
@GetMapping("/list")
public TableDataInfo<HrmFormDataVo> list(HrmFormDataBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:flow:query")
@GetMapping("/{formId}")
public R<HrmFormDataVo> getInfo(@PathVariable @NotNull Long formId) {
return R.ok(service.queryById(formId));

View File

@@ -28,47 +28,48 @@ public class HrmFlowInstanceController extends BaseController {
private final IHrmFlowInstanceService service;
@SaCheckPermission("hrm:flow:list")
@GetMapping("/list")
public TableDataInfo<HrmFlowInstanceVo> list(HrmFlowInstanceBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:flow:query")
/**
* 查询我的申请列表
*/
@GetMapping("/myList")
public TableDataInfo<HrmFlowInstanceVo> myList(HrmFlowInstanceBo bo, PageQuery pageQuery) {
return service.queryMyInstancePageList(bo, pageQuery);
}
@GetMapping("/{instId}")
public R<HrmFlowInstanceVo> getInfo(@PathVariable @NotNull Long instId) {
return R.ok(service.queryById(instId));
}
@SaCheckPermission("hrm:flow:add")
@Log(title = "流程实例", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmFlowInstanceBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程实例", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmFlowInstanceBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:flow:remove")
@Log(title = "流程实例", businessType = BusinessType.DELETE)
@DeleteMapping("/{instIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] instIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(instIds), true));
}
@SaCheckPermission("hrm:flow:add")
@Log(title = "流程实例启动", businessType = BusinessType.INSERT)
@PostMapping("/start")
public R<Long> start(@Validated @RequestBody HrmFlowStartBo bo) {
return R.ok(service.startInstance(bo));
}
@SaCheckPermission("hrm:flow:list")
@GetMapping("/all")
public R<List<HrmFlowInstanceVo>> all(HrmFlowInstanceBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -27,40 +27,34 @@ public class HrmFlowNodeController extends BaseController {
private final IHrmFlowNodeService service;
@SaCheckPermission("hrm:flow:list")
@GetMapping("/list")
public TableDataInfo<HrmFlowNodeVo> list(HrmFlowNodeBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:flow:query")
@GetMapping("/{nodeId}")
public R<HrmFlowNodeVo> getInfo(@PathVariable @NotNull Long nodeId) {
return R.ok(service.queryById(nodeId));
}
@SaCheckPermission("hrm:flow:add")
@Log(title = "流程节点", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmFlowNodeBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程节点", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmFlowNodeBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:flow:remove")
@Log(title = "流程节点", businessType = BusinessType.DELETE)
@DeleteMapping("/{nodeIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] nodeIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(nodeIds), true));
}
@SaCheckPermission("hrm:flow:list")
@GetMapping("/all")
public R<List<HrmFlowNodeVo>> all(HrmFlowNodeBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -1,7 +1,5 @@
package com.klp.hrm.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
@@ -9,6 +7,7 @@ import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.enums.BusinessType;
import com.klp.hrm.domain.bo.HrmFlowTaskBo;
import com.klp.hrm.domain.bo.HrmFlowTaskApproveBo;
import com.klp.hrm.domain.bo.HrmSealStampBo;
import com.klp.hrm.domain.vo.HrmFlowTaskVo;
import com.klp.hrm.service.IHrmFlowTaskService;
@@ -29,59 +28,66 @@ public class HrmFlowTaskController extends BaseController {
private final IHrmFlowTaskService service;
@SaCheckPermission("hrm:flow:list")
@GetMapping("/list")
public TableDataInfo<HrmFlowTaskVo> list(HrmFlowTaskBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:flow:list")
@GetMapping("/todo")
public R<List<HrmFlowTaskVo>> todo(@RequestParam(required = false) Long assigneeUserId) {
HrmFlowTaskBo bo = new HrmFlowTaskBo();
bo.setAssigneeUserId(assigneeUserId != null ? assigneeUserId : StpUtil.getLoginIdAsLong());
bo.setAssigneeUserId(assigneeUserId);
bo.setStatus("pending");
return R.ok(service.queryList(bo));
}
/**
* 详情页使用:按 bizType + bizId 查询当前用户的待办任务pending
*/
@GetMapping("/todoByBiz")
public R<HrmFlowTaskVo> todoByBiz(@RequestParam @NotNull String bizType,
@RequestParam @NotNull Long bizId,
@RequestParam(required = false) Long assigneeUserId) {
return R.ok(service.queryTodoByBiz(bizType, bizId, assigneeUserId));
}
@SaCheckPermission("hrm:flow:query")
@GetMapping("/{taskId}")
public R<HrmFlowTaskVo> getInfo(@PathVariable @NotNull Long taskId) {
return R.ok(service.queryById(taskId));
}
@SaCheckPermission("hrm:flow:add")
@Log(title = "流程任务", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmFlowTaskBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程任务", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmFlowTaskBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:flow:remove")
@Log(title = "流程任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{taskIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] taskIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(taskIds), true));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程任务审批通过", businessType = BusinessType.UPDATE)
@PostMapping("/{taskId}/approve")
public R<Void> approve(@PathVariable @NotNull Long taskId,
@RequestParam(required = false) Long actionUserId,
@RequestParam(required = false) String remark,
@RequestBody(required = false) HrmSealStampBo stampBo) {
@RequestBody(required = false) HrmFlowTaskApproveBo approveBo) {
String remark = approveBo != null ? approveBo.getRemark() : null;
HrmSealStampBo stampBo = approveBo != null ? approveBo.getStampBo() : null;
return toAjax(service.approve(taskId, actionUserId, remark, stampBo));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程任务审批驳回", businessType = BusinessType.UPDATE)
@PostMapping("/{taskId}/reject")
public R<Void> reject(@PathVariable @NotNull Long taskId,
@@ -90,7 +96,6 @@ public class HrmFlowTaskController extends BaseController {
return toAjax(service.reject(taskId, actionUserId, remark));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程任务撤回", businessType = BusinessType.UPDATE)
@PostMapping("/{taskId}/withdraw")
public R<Void> withdraw(@PathVariable @NotNull Long taskId,
@@ -98,4 +103,13 @@ public class HrmFlowTaskController extends BaseController {
@RequestParam(required = false) String remark) {
return toAjax(service.withdraw(taskId, actionUserId, remark));
}
@Log(title = "流程任务转发", businessType = BusinessType.UPDATE)
@PostMapping("/{taskId}/transfer")
public R<Void> transfer(@PathVariable @NotNull Long taskId,
@RequestParam @NotNull Long newAssigneeUserId,
@RequestParam(required = false) Long actionUserId,
@RequestParam(required = false) String remark) {
return toAjax(service.transfer(taskId, newAssigneeUserId, actionUserId, remark));
}
}

View File

@@ -27,40 +27,34 @@ public class HrmFlowTemplateController extends BaseController {
private final IHrmFlowTemplateService service;
@SaCheckPermission("hrm:flow:list")
@GetMapping("/list")
public TableDataInfo<HrmFlowTemplateVo> list(HrmFlowTemplateBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:flow:query")
@GetMapping("/{tplId}")
public R<HrmFlowTemplateVo> getInfo(@PathVariable @NotNull Long tplId) {
return R.ok(service.queryById(tplId));
}
@SaCheckPermission("hrm:flow:add")
@Log(title = "流程模板", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmFlowTemplateBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:flow:edit")
@Log(title = "流程模板", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmFlowTemplateBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:flow:remove")
@Log(title = "流程模板", businessType = BusinessType.DELETE)
@DeleteMapping("/{tplIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] tplIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(tplIds), true));
}
@SaCheckPermission("hrm:flow:list")
@GetMapping("/all")
public R<List<HrmFlowTemplateVo>> all(HrmFlowTemplateBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -1,68 +0,0 @@
package com.klp.hrm.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.enums.BusinessType;
import com.klp.hrm.domain.bo.HrmGradeBo;
import com.klp.hrm.domain.vo.HrmGradeVo;
import com.klp.hrm.service.IHrmGradeService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/hrm/grade")
public class HrmGradeController extends BaseController {
private final IHrmGradeService service;
@SaCheckPermission("hrm:grade:list")
@GetMapping("/list")
public TableDataInfo<HrmGradeVo> list(HrmGradeBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:grade:query")
@GetMapping("/{gradeId}")
public R<HrmGradeVo> getInfo(@PathVariable @NotNull Long gradeId) {
return R.ok(service.queryById(gradeId));
}
@SaCheckPermission("hrm:grade:add")
@Log(title = "职级管理", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmGradeBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:grade:edit")
@Log(title = "职级管理", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmGradeBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:grade:remove")
@Log(title = "职级管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{gradeIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] gradeIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(gradeIds), true));
}
@SaCheckPermission("hrm:grade:list")
@GetMapping("/all")
public R<List<HrmGradeVo>> all(HrmGradeBo bo) {
return R.ok(service.queryList(bo));
}
}

View File

@@ -27,40 +27,34 @@ public class HrmHeadcountPlanController extends BaseController {
private final IHrmHeadcountPlanService service;
@SaCheckPermission("hrm:headcount:list")
@GetMapping("/list")
public TableDataInfo<HrmHeadcountPlanVo> list(HrmHeadcountPlanBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:headcount:query")
@GetMapping("/{planId}")
public R<HrmHeadcountPlanVo> getInfo(@PathVariable @NotNull Long planId) {
return R.ok(service.queryById(planId));
}
@SaCheckPermission("hrm:headcount:add")
@Log(title = "编制管理", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmHeadcountPlanBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:headcount:edit")
@Log(title = "编制管理", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmHeadcountPlanBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:headcount:remove")
@Log(title = "编制管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{planIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] planIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(planIds), true));
}
@SaCheckPermission("hrm:headcount:list")
@GetMapping("/all")
public R<List<HrmHeadcountPlanVo>> all(HrmHeadcountPlanBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -27,40 +27,34 @@ public class HrmLeaveBalanceController extends BaseController {
private final IHrmLeaveBalanceService service;
@SaCheckPermission("hrm:leavebal:list")
@GetMapping("/list")
public TableDataInfo<HrmLeaveBalanceVo> list(HrmLeaveBalanceBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:leavebal:query")
@GetMapping("/{balId}")
public R<HrmLeaveBalanceVo> getInfo(@PathVariable @NotNull Long balId) {
return R.ok(service.queryById(balId));
}
@SaCheckPermission("hrm:leavebal:add")
@Log(title = "假期余额", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmLeaveBalanceBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:leavebal:edit")
@Log(title = "假期余额", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmLeaveBalanceBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:leavebal:remove")
@Log(title = "假期余额", businessType = BusinessType.DELETE)
@DeleteMapping("/{balIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] balIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(balIds), true));
}
@SaCheckPermission("hrm:leavebal:list")
@GetMapping("/all")
public R<List<HrmLeaveBalanceVo>> all(HrmLeaveBalanceBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -27,40 +27,34 @@ public class HrmLeaveReqController extends BaseController {
private final IHrmLeaveReqService service;
@SaCheckPermission("hrm:leave:req:list")
@GetMapping("/list")
public TableDataInfo<HrmLeaveReqVo> list(HrmLeaveReqBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:leave:req:query")
@GetMapping("/{bizId}")
public R<HrmLeaveReqVo> getInfo(@PathVariable @NotNull Long bizId) {
return R.ok(service.queryById(bizId));
}
@SaCheckPermission("hrm:leave:req:add")
@Log(title = "请假单", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmLeaveReqBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:leave:req:edit")
@Log(title = "请假单", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmLeaveReqBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:leave:req:remove")
@Log(title = "请假单", businessType = BusinessType.DELETE)
@DeleteMapping("/{bizIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] bizIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(bizIds), true));
}
@SaCheckPermission("hrm:leave:req:list")
@GetMapping("/all")
public R<List<HrmLeaveReqVo>> all(HrmLeaveReqBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -1,68 +0,0 @@
package com.klp.hrm.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.enums.BusinessType;
import com.klp.hrm.domain.bo.HrmOrgBo;
import com.klp.hrm.domain.vo.HrmOrgVo;
import com.klp.hrm.service.IHrmOrgService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/hrm/org")
public class HrmOrgController extends BaseController {
private final IHrmOrgService service;
@SaCheckPermission("hrm:org:list")
@GetMapping("/list")
public TableDataInfo<HrmOrgVo> list(HrmOrgBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:org:query")
@GetMapping("/{orgId}")
public R<HrmOrgVo> getInfo(@PathVariable @NotNull Long orgId) {
return R.ok(service.queryById(orgId));
}
@SaCheckPermission("hrm:org:add")
@Log(title = "组织管理", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmOrgBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:org:edit")
@Log(title = "组织管理", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmOrgBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:org:remove")
@Log(title = "组织管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{orgIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] orgIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(orgIds), true));
}
@SaCheckPermission("hrm:org:list")
@GetMapping("/all")
public R<List<HrmOrgVo>> all(HrmOrgBo bo) {
return R.ok(service.queryList(bo));
}
}

View File

@@ -1,68 +0,0 @@
package com.klp.hrm.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.enums.BusinessType;
import com.klp.hrm.domain.bo.HrmPositionBo;
import com.klp.hrm.domain.vo.HrmPositionVo;
import com.klp.hrm.service.IHrmPositionService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/hrm/position")
public class HrmPositionController extends BaseController {
private final IHrmPositionService service;
@SaCheckPermission("hrm:position:list")
@GetMapping("/list")
public TableDataInfo<HrmPositionVo> list(HrmPositionBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:position:query")
@GetMapping("/{positionId}")
public R<HrmPositionVo> getInfo(@PathVariable @NotNull Long positionId) {
return R.ok(service.queryById(positionId));
}
@SaCheckPermission("hrm:position:add")
@Log(title = "岗位管理", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmPositionBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:position:edit")
@Log(title = "岗位管理", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmPositionBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:position:remove")
@Log(title = "岗位管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{positionIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] positionIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(positionIds), true));
}
@SaCheckPermission("hrm:position:list")
@GetMapping("/all")
public R<List<HrmPositionVo>> all(HrmPositionBo bo) {
return R.ok(service.queryList(bo));
}
}

View File

@@ -27,40 +27,34 @@ public class HrmPunchController extends BaseController {
private final IHrmPunchService service;
@SaCheckPermission("hrm:punch:list")
@GetMapping("/list")
public TableDataInfo<HrmPunchVo> list(HrmPunchBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:punch:query")
@GetMapping("/{punchId}")
public R<HrmPunchVo> getInfo(@PathVariable @NotNull Long punchId) {
return R.ok(service.queryById(punchId));
}
@SaCheckPermission("hrm:punch:add")
@Log(title = "打卡记录", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmPunchBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:punch:edit")
@Log(title = "打卡记录", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmPunchBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:punch:remove")
@Log(title = "打卡记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{punchIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] punchIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(punchIds), true));
}
@SaCheckPermission("hrm:punch:list")
@GetMapping("/all")
public R<List<HrmPunchVo>> all(HrmPunchBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -6,9 +6,9 @@ import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.enums.BusinessType;
import com.klp.hrm.domain.bo.HrmOvertimeReqBo;
import com.klp.hrm.domain.vo.HrmOvertimeReqVo;
import com.klp.hrm.service.IHrmOvertimeReqService;
import com.klp.hrm.domain.bo.HrmReimburseReqBo;
import com.klp.hrm.domain.vo.HrmReimburseReqVo;
import com.klp.hrm.service.IHrmReimburseReqService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -19,46 +19,47 @@ import java.util.Arrays;
import java.util.List;
/**
* 加班单按用户要求不做鉴权
* 日常报销申请
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/hrm/overtime")
public class HrmOvertimeReqController extends BaseController {
@RequestMapping("/hrm/reimburse")
public class HrmReimburseReqController extends BaseController {
private final IHrmOvertimeReqService service;
private final IHrmReimburseReqService service;
@GetMapping("/list")
public TableDataInfo<HrmOvertimeReqVo> list(HrmOvertimeReqBo bo, PageQuery pageQuery) {
public TableDataInfo<HrmReimburseReqVo> list(HrmReimburseReqBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@GetMapping("/{bizId}")
public R<HrmOvertimeReqVo> getInfo(@PathVariable @NotNull Long bizId) {
public R<HrmReimburseReqVo> getInfo(@PathVariable @NotNull Long bizId) {
return R.ok(service.queryById(bizId));
}
@Log(title = "加班", businessType = BusinessType.INSERT)
@Log(title = "日常报销", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmOvertimeReqBo bo) {
public R<Void> add(@Validated @RequestBody HrmReimburseReqBo bo) {
return toAjax(service.insertByBo(bo));
}
@Log(title = "加班", businessType = BusinessType.UPDATE)
@Log(title = "日常报销", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmOvertimeReqBo bo) {
public R<Void> edit(@Validated @RequestBody HrmReimburseReqBo bo) {
return toAjax(service.updateByBo(bo));
}
@Log(title = "加班", businessType = BusinessType.DELETE)
@Log(title = "日常报销", businessType = BusinessType.DELETE)
@DeleteMapping("/{bizIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] bizIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(bizIds), true));
}
@GetMapping("/all")
public R<List<HrmOvertimeReqVo>> all(HrmOvertimeReqBo bo) {
public R<List<HrmReimburseReqVo>> all(HrmReimburseReqBo bo) {
return R.ok(service.queryList(bo));
}
}

View File

@@ -27,40 +27,34 @@ public class HrmScheduleController extends BaseController {
private final IHrmScheduleService service;
@SaCheckPermission("hrm:schedule:list")
@GetMapping("/list")
public TableDataInfo<HrmScheduleVo> list(HrmScheduleBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:schedule:query")
@GetMapping("/{schedId}")
public R<HrmScheduleVo> getInfo(@PathVariable @NotNull Long schedId) {
return R.ok(service.queryById(schedId));
}
@SaCheckPermission("hrm:schedule:add")
@Log(title = "排班", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmScheduleBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:schedule:edit")
@Log(title = "排班", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmScheduleBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:schedule:remove")
@Log(title = "排班", businessType = BusinessType.DELETE)
@DeleteMapping("/{schedIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] schedIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(schedIds), true));
}
@SaCheckPermission("hrm:schedule:list")
@GetMapping("/all")
public R<List<HrmScheduleVo>> all(HrmScheduleBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -12,6 +12,7 @@ import com.klp.hrm.domain.bo.HrmSealStampBo;
import com.klp.hrm.domain.vo.HrmSealReqVo;
import com.klp.hrm.service.IHrmSealReqService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -21,6 +22,7 @@ import javax.validation.constraints.NotNull;
/**
* 用印申请
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@@ -29,68 +31,65 @@ public class HrmSealReqController extends BaseController {
private final IHrmSealReqService service;
@SaCheckPermission("hrm:seal:list")
@GetMapping("/list")
public TableDataInfo<HrmSealReqVo> list(HrmSealReqBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:seal:query")
@GetMapping("/{bizId}")
public R<HrmSealReqVo> getInfo(@PathVariable @NotNull Long bizId) {
return R.ok(service.queryById(bizId));
}
@SaCheckPermission("hrm:seal:add")
@Log(title = "用印申请", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmSealReqBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:seal:edit")
@Log(title = "用印申请", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmSealReqBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:seal:remove")
@Log(title = "用印申请", businessType = BusinessType.DELETE)
@DeleteMapping("/{bizIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] bizIds) {
return toAjax(service.deleteWithValidByIds(java.util.Arrays.asList(bizIds), true));
}
@SaCheckPermission("hrm:seal:approve")
@Log(title = "用印申请", businessType = BusinessType.UPDATE)
@PostMapping("/{bizId}/approve")
public R<Void> approve(@PathVariable @NotNull Long bizId) {
return toAjax(service.updateStatus(bizId, "approved"));
}
@SaCheckPermission("hrm:seal:reject")
@Log(title = "用印申请", businessType = BusinessType.UPDATE)
@PostMapping("/{bizId}/reject")
public R<Void> reject(@PathVariable @NotNull Long bizId) {
return toAjax(service.updateStatus(bizId, "rejected"));
}
@SaCheckPermission("hrm:seal:cancel")
@Log(title = "用印申请", businessType = BusinessType.UPDATE)
@PostMapping("/{bizId}/cancel")
public R<Void> cancel(@PathVariable @NotNull Long bizId) {
return toAjax(service.updateStatus(bizId, "canceled"));
}
@SaCheckPermission("hrm:seal:stamp")
@Log(title = "用印盖章(Java)", businessType = BusinessType.UPDATE)
@PostMapping("/{bizId}/stamp/java")
public R<String> stampJava(@PathVariable @NotNull Long bizId, @Validated @RequestBody HrmSealStampBo bo) {
// 添加日志,检查接收到的数据
log.info("收到盖章请求 - bizId: {}, yPx: {}, xPx: {}, pageNo: {}, yPx类型: {}",
bizId, bo.getYPx(), bo.getXPx(), bo.getPageNo(),
bo.getYPx() != null ? bo.getYPx().getClass().getName() : "null");
if (bo.getYPx() == null) {
log.error("yPx 为 null接收到的 bo 对象: {}", bo);
}
return R.ok(service.stampWithJava(bizId, bo));
}
@SaCheckPermission("hrm:seal:stamp")
@Log(title = "用印盖章(Python)", businessType = BusinessType.UPDATE)
@PostMapping("/{bizId}/stamp/python")
public R<String> stampPython(@PathVariable @NotNull Long bizId, @Validated @RequestBody HrmSealStampBo bo) {

View File

@@ -27,40 +27,34 @@ public class HrmShiftController extends BaseController {
private final IHrmShiftService service;
@SaCheckPermission("hrm:shift:list")
@GetMapping("/list")
public TableDataInfo<HrmShiftVo> list(HrmShiftBo bo, PageQuery pageQuery) {
return service.queryPageList(bo, pageQuery);
}
@SaCheckPermission("hrm:shift:query")
@GetMapping("/{shiftId}")
public R<HrmShiftVo> getInfo(@PathVariable @NotNull Long shiftId) {
return R.ok(service.queryById(shiftId));
}
@SaCheckPermission("hrm:shift:add")
@Log(title = "班次", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody HrmShiftBo bo) {
return toAjax(service.insertByBo(bo));
}
@SaCheckPermission("hrm:shift:edit")
@Log(title = "班次", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody HrmShiftBo bo) {
return toAjax(service.updateByBo(bo));
}
@SaCheckPermission("hrm:shift:remove")
@Log(title = "班次", businessType = BusinessType.DELETE)
@DeleteMapping("/{shiftIds}")
public R<Void> remove(@PathVariable @NotEmpty Long[] shiftIds) {
return toAjax(service.deleteWithValidByIds(Arrays.asList(shiftIds), true));
}
@SaCheckPermission("hrm:shift:list")
@GetMapping("/all")
public R<List<HrmShiftVo>> all(HrmShiftBo bo) {
return R.ok(service.queryList(bo));

View File

@@ -22,8 +22,10 @@ public class HrmEmpOrgPosition extends BaseEntity implements Serializable {
@TableId
private Long relId;
private Long empId;
private Long orgId;
private Long positionId;
/** 部门ID引用 sys_dept.dept_id */
private Long deptId;
/** 岗位ID引用 sys_post.post_id */
private Long postId;
private Integer isPrimary;
private Date startDate;
private Date endDate;

View File

@@ -32,9 +32,10 @@ public class HrmEmployee extends BaseEntity implements Serializable {
private Date hireDate;
private String employmentType;
private String status;
private Long gradeId;
private Long mainOrgId;
private Long mainPositionId;
/** 主部门ID引用 sys_dept.dept_id */
private Long deptId;
/** 主岗位ID引用 sys_post.post_id */
private Long postId;
private BigDecimal seniorityYears;
private Date contractEndDate;
private String remark;

View File

@@ -0,0 +1,46 @@
package com.klp.hrm.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 抄送记录
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hrm_flow_cc")
public class HrmFlowCc extends BaseEntity {
@TableId
private Long ccId;
private Long instId;
private String bizType;
private Long bizId;
private Long nodeId;
/** 触发抄送的节点名称(可读名) */
private String nodeName;
/** 是否已读 0未读 1已读 */
private Integer readFlag;
/** 被抄送的用户ID */
private Long ccUserId;
/** 触发抄送的操作人(一般为当前审批人) */
private Long fromUserId;
private String remark;
@TableLogic
private Integer delFlag;
}

View File

@@ -24,6 +24,13 @@ public class HrmFlowTask extends BaseEntity implements Serializable {
private String status;
private Date expireTime;
private String remark;
/** 业务类型leave/travel/seal */
private String bizType;
/** 业务ID对应请假/出差/用印的 bizId */
private Long bizId;
@TableLogic
private Integer delFlag;
}

View File

@@ -1,29 +0,0 @@
package com.klp.hrm.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 职级
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hrm_grade")
public class HrmGrade extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private Long gradeId;
private String gradeCode;
private String gradeName;
private Integer levelNo;
private String remark;
@TableLogic
private Integer delFlag;
}

View File

@@ -20,8 +20,10 @@ public class HrmHeadcountPlan extends BaseEntity implements Serializable {
@TableId
private Long planId;
private Long orgId;
private Long positionId;
/** 部门ID引用 sys_dept.dept_id */
private Long deptId;
/** 岗位ID引用 sys_post.post_id */
private Long postId;
private Integer year;
private Integer month;
private Integer budgetCount;

View File

@@ -1,33 +0,0 @@
package com.klp.hrm.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 组织/部门/班组
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hrm_org")
public class HrmOrg extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private Long orgId;
private Long parentId;
private String orgCode;
private String orgName;
private String orgType;
private Long leaderUserId;
private Integer orderNum;
private Integer status;
private String remark;
@TableLogic
private Integer delFlag;
}

View File

@@ -1,31 +0,0 @@
package com.klp.hrm.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 岗位
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hrm_position")
public class HrmPosition extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private Long positionId;
private String positionCode;
private String positionName;
private Long gradeId;
private Integer orderNum;
private Integer status;
private String remark;
@TableLogic
private Integer delFlag;
}

View File

@@ -7,27 +7,33 @@ import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hrm_overtime_req")
public class HrmOvertimeReq extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableName("hrm_reimburse_req")
public class HrmReimburseReq extends BaseEntity {
@TableId
private Long bizId;
private Long empId;
private String otType;
private Date startTime;
private Date endTime;
private java.math.BigDecimal hours;
private String reimburseType;
private BigDecimal totalAmount;
private String reason;
private String status;
private String accessoryApplyIds;
private String accessoryReceiptIds;
private String remark;
@TableLogic
private Integer delFlag;
}

View File

@@ -7,13 +7,12 @@ import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("hrm_travel_req")
public class HrmTravelReq extends BaseEntity implements Serializable {
public class HrmTravelReq extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId
@@ -21,11 +20,16 @@ public class HrmTravelReq extends BaseEntity implements Serializable {
private Long empId;
private Date startTime;
private Date endTime;
private String travelType;
private String destination;
private String reason;
private String status;
private String accessoryApplyIds;
private String accessoryReceiptIds;
private String payeeName;
private Double estimatedCost;
private String bankName;
private String bankAccount;
private String remark;
@TableLogic
private Integer delFlag;

View File

@@ -16,11 +16,13 @@ public class HrmEmpOrgPositionBo extends BaseEntity {
@NotNull(message = "员工不能为空")
private Long empId;
@NotNull(message = "组织不能为空")
private Long orgId;
@NotNull(message = "部门不能为空")
/** 部门ID引用 sys_dept.dept_id */
private Long deptId;
@NotNull(message = "岗位不能为空")
private Long positionId;
/** 岗位ID引用 sys_post.post_id */
private Long postId;
private Integer isPrimary;

View File

@@ -39,11 +39,11 @@ public class HrmEmployeeBo extends BaseEntity {
private String status;
private Long gradeId;
/** 主部门ID引用 sys_dept.dept_id */
private Long deptId;
private Long mainOrgId;
private Long mainPositionId;
/** 主岗位ID引用 sys_post.post_id */
private Long postId;
private String remark;
}

View File

@@ -0,0 +1,33 @@
package com.klp.hrm.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class HrmFlowCcBo extends BaseEntity {
private Long ccId;
private Long instId;
private String bizType;
private Long bizId;
/** 业务类型名称(列表展示用,可选条件) */
private String bizTypeName;
/** 业务标题/摘要(列表展示用,可选条件) */
private String bizTitle;
private Long nodeId;
private String nodeName;
private Integer readFlag;
private Long ccUserId;
/** 手动抄送:支持批量被抄送用户 */
private List<Long> ccUserIds;
private Long fromUserId;
private String remark;
}

View File

@@ -7,12 +7,19 @@ import javax.validation.constraints.NotNull;
@Data
public class HrmFlowStartBo {
@NotNull(message = "模板ID不能为空")
// 模板ID存在则按模板启动为空则走“自选审批人一次性审批”
private Long tplId;
// 无模板时:自选审批人 userId一次性审批审批完成即结束流程
private Long manualAssigneeUserId;
@NotBlank(message = "业务类型不能为空")
private String bizType;
@NotNull(message = "业务ID不能为空")
private Long bizId;
private Long startUserId;
private String contentJson;
}

View File

@@ -0,0 +1,17 @@
package com.klp.hrm.domain.bo;
import lombok.Data;
/**
* 流程任务审批请求体
*/
@Data
public class HrmFlowTaskApproveBo {
/** 审批意见 */
private String remark;
/** 盖章参数(仅用于用印业务) */
private HrmSealStampBo stampBo;
}

View File

@@ -20,4 +20,10 @@ public class HrmFlowTaskBo extends BaseEntity {
private String status;
private Date expireTime;
private String remark;
/** 业务类型leave/travel/seal */
private String bizType;
/** 业务ID对应请假/出差/用印的 bizId */
private Long bizId;
}

View File

@@ -1,24 +0,0 @@
package com.klp.hrm.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
@Data
@EqualsAndHashCode(callSuper = true)
public class HrmGradeBo extends BaseEntity {
private Long gradeId;
@NotBlank(message = "职级编码不能为空")
private String gradeCode;
@NotBlank(message = "职级名称不能为空")
private String gradeName;
private Integer levelNo;
private String remark;
}

View File

@@ -12,11 +12,13 @@ public class HrmHeadcountPlanBo extends BaseEntity {
private Long planId;
@NotNull(message = "组织不能为空")
private Long orgId;
@NotNull(message = "部门不能为空")
/** 部门ID引用 sys_dept.dept_id */
private Long deptId;
@NotNull(message = "岗位不能为空")
private Long positionId;
/** 岗位ID引用 sys_post.post_id */
private Long postId;
@NotNull(message = "年份不能为空")
private Integer year;

View File

@@ -1,5 +1,6 @@
package com.klp.hrm.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -21,9 +22,11 @@ public class HrmLeaveReqBo extends BaseEntity {
private String leaveType;
@NotNull(message = "开始时间不能为空")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "GMT+8")
private Date startTime;
@NotNull(message = "结束时间不能为空")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "GMT+8")
private Date endTime;
@NotNull(message = "时长不能为空")
@@ -31,6 +34,18 @@ public class HrmLeaveReqBo extends BaseEntity {
private String reason;
private String status;
/**
* 流程模板ID前端选择模板流程时传入
*
* 不传则后端按 bizType 自动选择启用的最新版本模板;
* 若也未配置模板,则可通过 manualAssigneeUserId 走一次性审批。
*/
private Long tplId;
// 无模板时,自选审批人 userId
private Long manualAssigneeUserId;
private String accessoryApplyIds;
private String accessoryReceiptIds;
private String remark;

View File

@@ -1,39 +0,0 @@
package com.klp.hrm.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 组织 Bo
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class HrmOrgBo extends BaseEntity {
/** 组织ID */
private Long orgId;
/** 父级组织ID */
private Long parentId;
@NotBlank(message = "组织编码不能为空")
private String orgCode;
@NotBlank(message = "组织名称不能为空")
private String orgName;
@NotBlank(message = "组织类型不能为空")
private String orgType;
private Long leaderUserId;
private Integer orderNum;
private Integer status;
private String remark;
}

View File

@@ -1,28 +0,0 @@
package com.klp.hrm.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
@Data
@EqualsAndHashCode(callSuper = true)
public class HrmPositionBo extends BaseEntity {
private Long positionId;
@NotBlank(message = "岗位编码不能为空")
private String positionCode;
@NotBlank(message = "岗位名称不能为空")
private String positionName;
private Long gradeId;
private Integer orderNum;
private Integer status;
private String remark;
}

View File

@@ -5,31 +5,35 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = true)
public class HrmOvertimeReqBo extends BaseEntity {
public class HrmReimburseReqBo extends BaseEntity {
private Long bizId;
@NotNull(message = "员工ID不能为空")
private Long empId;
private String otType;
private String reimburseType;
@NotNull(message = "开始时间不能为空")
private Date startTime;
@NotNull(message = "结束时间不能为空")
private Date endTime;
@NotNull(message = "时长不能为空")
private java.math.BigDecimal hours;
@NotNull(message = "报销总金额不能为空")
private BigDecimal totalAmount;
private String reason;
private String status;
// 无模板时自选审批人 userId
private Long manualAssigneeUserId;
/** 报销单据附件oss_id列表(CSV) */
private String accessoryApplyIds;
/** 回执附件oss_id列表(CSV) */
private String accessoryReceiptIds;
private String remark;
}

View File

@@ -40,9 +40,20 @@ public class HrmSealReqBo extends BaseEntity {
/** 状态 draft/running/approved/rejected/canceled */
private String status;
/** 关联流程模板ID提交时可选,存在则自动发起审批 */
/** 关联流程模板ID旧字段,兼容历史前端/代码 */
private Long flowTplId;
/**
* 流程模板ID新字段前端选择模板流程时传入
* 优先级高于 flowTplId。
*/
private Long tplId;
/**
* 手动选择的审批人ID前端选择手动审批时传入
*/
private Long manualAssigneeUserId;
/** 流程发起人ID可选不填可由服务侧取当前登录人 */
private Long startUserId;

View File

@@ -1,6 +1,13 @@
package com.klp.hrm.domain.bo;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
@@ -9,37 +16,83 @@ import javax.validation.constraints.NotNull;
/**
* 盖章命令Java/Python 坐标统一使用 px
*/
@Data
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.ALWAYS)
public class HrmSealStampBo {
/** 待盖章 PDF 的 OSS 完整 URL */
@NotBlank(message = "待盖章文件地址不能为空")
@JsonProperty("targetFileUrl")
private String targetFileUrl;
/** 章图片 OSS 完整 URL透明 PNG/JPG */
@NotBlank(message = "章图片地址不能为空")
@JsonProperty("stampImageUrl")
private String stampImageUrl;
/** 页码从1开始 */
@NotNull
@Min(1)
@JsonProperty("pageNo")
private Integer pageNo;
/** 左下角 X 坐标px */
@NotNull
@Min(0)
@JsonProperty("xPx")
@JsonInclude(JsonInclude.Include.ALWAYS)
@Setter(lombok.AccessLevel.NONE) // 禁用 Lombok 生成 setter使用手动 setter
private Integer xPx;
/** 左下角 Y 坐标px */
@NotNull
@Min(0)
@JsonProperty("yPx")
@JsonInclude(JsonInclude.Include.ALWAYS)
@Setter(lombok.AccessLevel.NONE) // 禁用 Lombok 生成 setter使用手动 setter
private Integer yPx;
/** 盖章宽度px可选 */
@Min(1)
@JsonProperty("widthPx")
private Integer widthPx;
/** 盖章高度px可选 */
@Min(1)
@JsonProperty("heightPx")
private Integer heightPx;
/**
* 前端渲染的 viewport 宽度(像素):用于把前端点击坐标换算成 PDFBox 坐标pt
* 注意:这不是 PDF 页面原始宽度,而是 pdf.js 按 scale 渲染到 canvas 的宽度。
*/
@Min(1)
@JsonProperty("viewportWidth")
private Integer viewportWidth;
/** 前端渲染的 viewport 高度(像素):用于坐标换算 */
@Min(1)
@JsonProperty("viewportHeight")
private Integer viewportHeight;
/**
* 手动添加 setter 方法,确保 Jackson 能够正确映射 yPx 字段
* Lombok 生成的 setYPx() 可能与 Jackson 的字段名映射不匹配
*/
@JsonSetter("yPx")
public void setYPx(Integer yPx) {
this.yPx = yPx;
}
/**
* 手动添加 setter 方法,确保 Jackson 能够正确映射 xPx 字段
*/
@JsonSetter("xPx")
public void setXPx(Integer xPx) {
this.xPx = xPx;
}
}

View File

@@ -1,5 +1,6 @@
package com.klp.hrm.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -17,15 +18,26 @@ public class HrmTravelReqBo extends BaseEntity {
private Long empId;
@NotNull(message = "开始时间不能为空")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "GMT+8")
private Date startTime;
@NotNull(message = "结束时间不能为空")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "GMT+8")
private Date endTime;
private String travelType;
private String destination;
private String reason;
private String status;
// 无模板时,自选审批人 userId
private Long manualAssigneeUserId;
private String accessoryApplyIds;
private String accessoryReceiptIds;
private String payeeName;
private Double estimatedCost;
private String bankName;
private String bankAccount;
private String remark;
}

View File

@@ -16,11 +16,17 @@ public class HrmEmpOrgPositionVo implements Serializable {
@Excel(name = "员工ID")
private Long empId;
@Excel(name = "组织ID")
private Long orgId;
@Excel(name = "部门ID")
private Long deptId;
/** 部门名称 */
private String deptName;
@Excel(name = "岗位ID")
private Long positionId;
private Long postId;
/** 岗位名称 */
private String postName;
@Excel(name = "是否主岗")
private Integer isPrimary;

View File

@@ -43,14 +43,17 @@ public class HrmEmployeeVo implements Serializable {
@Excel(name = "在职状态")
private String status;
@Excel(name = "职级ID")
private Long gradeId;
@Excel(name = "主部门ID")
private Long deptId;
@Excel(name = "主组织ID")
private Long mainOrgId;
/** 主部门名称 */
private String deptName;
@Excel(name = "主岗位ID")
private Long mainPositionId;
private Long postId;
/** 主岗位名称 */
private String postName;
@Excel(name = "备注")
private String remark;

View File

@@ -0,0 +1,26 @@
package com.klp.hrm.domain.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class HrmFlowCcVo implements Serializable {
private static final long serialVersionUID = 1L;
private Long ccId;
private Long instId;
private String bizType;
private Long bizId;
private String bizTypeName;
private String bizTitle;
private Long nodeId;
private String nodeName;
private Integer readFlag;
private Long ccUserId;
private Long fromUserId;
private String remark;
private Date createTime;
}

View File

@@ -4,6 +4,7 @@ import com.klp.common.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
@Data
@@ -26,6 +27,14 @@ public class HrmFlowInstanceVo implements Serializable {
private Long startUserId;
@Excel(name = "备注")
private String remark;
/** 列表展示字段(联查业务表) */
private String bizTitle;
private Date startTime;
private Date endTime;
private BigDecimal hours;
private String procStatus;
private String createBy;
private Date createTime;
private String updateBy;

View File

@@ -5,6 +5,7 @@ import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
@Data
public class HrmFlowTaskVo implements Serializable {
@@ -24,6 +25,18 @@ public class HrmFlowTaskVo implements Serializable {
private Date expireTime;
@Excel(name = "备注")
private String remark;
/** 业务类型leave/travel/seal/reimburse */
private String bizType;
/** 业务ID */
private Long bizId;
/**
* 业务摘要数据(审批中心展示用),由后端联查后回填。
* key/字段根据不同 bizType 不同。
*/
private Map<String, Object> bizData;
private String createBy;
private Date createTime;
private String updateBy;

View File

@@ -1,32 +0,0 @@
package com.klp.hrm.domain.vo;
import com.klp.common.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class HrmGradeVo implements Serializable {
private static final long serialVersionUID = 1L;
@Excel(name = "职级ID")
private Long gradeId;
@Excel(name = "职级编码")
private String gradeCode;
@Excel(name = "职级名称")
private String gradeName;
@Excel(name = "层级序号")
private Integer levelNo;
@Excel(name = "备注")
private String remark;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}

View File

@@ -13,11 +13,11 @@ public class HrmHeadcountPlanVo implements Serializable {
@Excel(name = "编制ID")
private Long planId;
@Excel(name = "组织ID")
private Long orgId;
@Excel(name = "部门ID")
private Long deptId;
@Excel(name = "岗位ID")
private Long positionId;
private Long postId;
@Excel(name = "年份")
private Integer year;

View File

@@ -1,44 +0,0 @@
package com.klp.hrm.domain.vo;
import com.klp.common.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 组织 VO
*/
@Data
public class HrmOrgVo implements Serializable {
private static final long serialVersionUID = 1L;
@Excel(name = "组织ID")
private Long orgId;
@Excel(name = "父级ID")
private Long parentId;
@Excel(name = "组织编码")
private String orgCode;
@Excel(name = "组织名称")
private String orgName;
@Excel(name = "组织类型")
private String orgType;
@Excel(name = "负责人用户ID")
private Long leaderUserId;
private Integer orderNum;
private Integer status;
private String remark;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}

View File

@@ -1,38 +0,0 @@
package com.klp.hrm.domain.vo;
import com.klp.common.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class HrmPositionVo implements Serializable {
private static final long serialVersionUID = 1L;
@Excel(name = "岗位ID")
private Long positionId;
@Excel(name = "岗位编码")
private String positionCode;
@Excel(name = "岗位名称")
private String positionName;
@Excel(name = "职级ID")
private Long gradeId;
@Excel(name = "排序")
private Integer orderNum;
@Excel(name = "状态")
private Integer status;
@Excel(name = "备注")
private String remark;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}

View File

@@ -8,33 +8,39 @@ import java.math.BigDecimal;
import java.util.Date;
@Data
public class HrmOvertimeReqVo implements Serializable {
public class HrmReimburseReqVo implements Serializable {
private static final long serialVersionUID = 1L;
@Excel(name = "业务ID")
private Long bizId;
@Excel(name = "员工ID")
private Long empId;
@Excel(name = "加班类型")
private String otType;
@Excel(name = "开始时间", width = 25, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
@Excel(name = "结束时间", width = 25, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
@Excel(name = "时长(小时)")
private BigDecimal hours;
@Excel(name = "原因")
@Excel(name = "报销类型")
private String reimburseType;
@Excel(name = "报销总金额")
private BigDecimal totalAmount;
@Excel(name = "报销事由")
private String reason;
@Excel(name = "状态")
private String status;
@Excel(name = "申请附件")
@Excel(name = "报销单据附件")
private String accessoryApplyIds;
@Excel(name = "回执附件")
private String accessoryReceiptIds;
@Excel(name = "备注")
private String remark;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}

View File

@@ -18,6 +18,8 @@ public class HrmTravelReqVo implements Serializable {
private Date startTime;
@Excel(name = "结束时间", width = 25, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
@Excel(name = "出差类型")
private String travelType;
@Excel(name = "目的地")
private String destination;
@Excel(name = "原因")
@@ -28,6 +30,14 @@ public class HrmTravelReqVo implements Serializable {
private String accessoryApplyIds;
@Excel(name = "回执附件")
private String accessoryReceiptIds;
@Excel(name = "收款人")
private String payeeName;
@Excel(name = "预估费用")
private Double estimatedCost;
@Excel(name = "开户行")
private String bankName;
@Excel(name = "银行账号")
private String bankAccount;
@Excel(name = "备注")
private String remark;
private String createBy;

View File

@@ -0,0 +1,9 @@
package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmFlowCc;
import com.klp.hrm.domain.vo.HrmFlowCcVo;
public interface HrmFlowCcMapper extends BaseMapperPlus<HrmFlowCcMapper, HrmFlowCc, HrmFlowCcVo> {
}

View File

@@ -2,7 +2,17 @@ package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmFlowInstance;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.hrm.domain.vo.HrmFlowInstanceVo;
import org.apache.ibatis.annotations.Param;
public interface HrmFlowInstanceMapper extends BaseMapperPlus<HrmFlowInstanceMapper, HrmFlowInstance, HrmFlowInstanceVo> {
IPage<HrmFlowInstanceVo> selectMyInstancePageWithBiz(
Page<?> page,
@Param("startUserId") Long startUserId,
@Param("bizType") String bizType,
@Param("status") String status);
}

View File

@@ -1,8 +0,0 @@
package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmGrade;
import com.klp.hrm.domain.vo.HrmGradeVo;
public interface HrmGradeMapper extends BaseMapperPlus<HrmGradeMapper, HrmGrade, HrmGradeVo> {
}

View File

@@ -1,8 +0,0 @@
package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmOrg;
import com.klp.hrm.domain.vo.HrmOrgVo;
public interface HrmOrgMapper extends BaseMapperPlus<HrmOrgMapper, HrmOrg, HrmOrgVo> {
}

View File

@@ -1,8 +0,0 @@
package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmOvertimeReq;
import com.klp.hrm.domain.vo.HrmOvertimeReqVo;
public interface HrmOvertimeReqMapper extends BaseMapperPlus<HrmOvertimeReqMapper, HrmOvertimeReq, HrmOvertimeReqVo> {
}

View File

@@ -1,8 +0,0 @@
package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmPosition;
import com.klp.hrm.domain.vo.HrmPositionVo;
public interface HrmPositionMapper extends BaseMapperPlus<HrmPositionMapper, HrmPosition, HrmPositionVo> {
}

View File

@@ -0,0 +1,9 @@
package com.klp.hrm.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.hrm.domain.HrmReimburseReq;
import com.klp.hrm.domain.vo.HrmReimburseReqVo;
public interface HrmReimburseReqMapper extends BaseMapperPlus<HrmReimburseReqMapper, HrmReimburseReq, HrmReimburseReqVo> {
}

View File

@@ -0,0 +1,31 @@
package com.klp.hrm.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmFlowCcBo;
import com.klp.hrm.domain.vo.HrmFlowCcVo;
import java.util.Collection;
import java.util.List;
public interface IHrmFlowCcService {
TableDataInfo<HrmFlowCcVo> queryPageList(HrmFlowCcBo bo, PageQuery pageQuery);
List<HrmFlowCcVo> queryList(HrmFlowCcBo bo);
Boolean insert(HrmFlowCcBo bo);
/**
* 批量新增抄送
*/
Boolean insertBatch(HrmFlowCcBo bo);
Boolean deleteByIds(Collection<Long> ids);
/**
* 标记已读
*/
Boolean markRead(Long ccId, Long userId);
}

View File

@@ -19,6 +19,11 @@ public interface IHrmFlowInstanceService {
TableDataInfo<HrmFlowInstanceVo> queryPageList(HrmFlowInstanceBo bo, PageQuery pageQuery);
/**
* 查询当前登录用户“我的申请”(我发起的流程实例)分页列表
*/
TableDataInfo<HrmFlowInstanceVo> queryMyInstancePageList(HrmFlowInstanceBo bo, PageQuery pageQuery);
List<HrmFlowInstanceVo> queryList(HrmFlowInstanceBo bo);
Boolean insertByBo(HrmFlowInstanceBo bo);

View File

@@ -36,4 +36,14 @@ public interface IHrmFlowTaskService {
* 撤回/取消
*/
Boolean withdraw(Long taskId, Long actionUserId, String remark);
/**
* 转发/转办当前待办给其他审批人
*/
Boolean transfer(Long taskId, Long newAssigneeUserId, Long actionUserId, String remark);
/**
* 根据业务类型 + 业务ID 查询当前待办任务pending用于详情页自动带出 currentTaskId
*/
HrmFlowTaskVo queryTodoByBiz(String bizType, Long bizId, Long assigneeUserId);
}

View File

@@ -1,23 +0,0 @@
package com.klp.hrm.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmGradeBo;
import com.klp.hrm.domain.vo.HrmGradeVo;
import java.util.Collection;
import java.util.List;
public interface IHrmGradeService {
HrmGradeVo queryById(Long gradeId);
TableDataInfo<HrmGradeVo> queryPageList(HrmGradeBo bo, PageQuery pageQuery);
List<HrmGradeVo> queryList(HrmGradeBo bo);
Boolean insertByBo(HrmGradeBo bo);
Boolean updateByBo(HrmGradeBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -1,23 +0,0 @@
package com.klp.hrm.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmOrgBo;
import com.klp.hrm.domain.vo.HrmOrgVo;
import java.util.Collection;
import java.util.List;
public interface IHrmOrgService {
HrmOrgVo queryById(Long orgId);
TableDataInfo<HrmOrgVo> queryPageList(HrmOrgBo bo, PageQuery pageQuery);
List<HrmOrgVo> queryList(HrmOrgBo bo);
Boolean insertByBo(HrmOrgBo bo);
Boolean updateByBo(HrmOrgBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -1,24 +0,0 @@
package com.klp.hrm.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmOvertimeReqBo;
import com.klp.hrm.domain.vo.HrmOvertimeReqVo;
import java.util.Collection;
import java.util.List;
public interface IHrmOvertimeReqService {
HrmOvertimeReqVo queryById(Long bizId);
TableDataInfo<HrmOvertimeReqVo> queryPageList(HrmOvertimeReqBo bo, PageQuery pageQuery);
List<HrmOvertimeReqVo> queryList(HrmOvertimeReqBo bo);
Boolean insertByBo(HrmOvertimeReqBo bo);
Boolean updateByBo(HrmOvertimeReqBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -1,23 +0,0 @@
package com.klp.hrm.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmPositionBo;
import com.klp.hrm.domain.vo.HrmPositionVo;
import java.util.Collection;
import java.util.List;
public interface IHrmPositionService {
HrmPositionVo queryById(Long positionId);
TableDataInfo<HrmPositionVo> queryPageList(HrmPositionBo bo, PageQuery pageQuery);
List<HrmPositionVo> queryList(HrmPositionBo bo);
Boolean insertByBo(HrmPositionBo bo);
Boolean updateByBo(HrmPositionBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,25 @@
package com.klp.hrm.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.bo.HrmReimburseReqBo;
import com.klp.hrm.domain.vo.HrmReimburseReqVo;
import java.util.Collection;
import java.util.List;
public interface IHrmReimburseReqService {
HrmReimburseReqVo queryById(Long bizId);
TableDataInfo<HrmReimburseReqVo> queryPageList(HrmReimburseReqBo bo, PageQuery pageQuery);
List<HrmReimburseReqVo> queryList(HrmReimburseReqBo bo);
Boolean insertByBo(HrmReimburseReqBo bo);
Boolean updateByBo(HrmReimburseReqBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,102 @@
package com.klp.hrm.service.impl;
import com.klp.hrm.domain.HrmLeaveReq;
import com.klp.hrm.domain.HrmReimburseReq;
import com.klp.hrm.domain.HrmTravelReq;
import com.klp.hrm.domain.HrmSealReq;
import com.klp.hrm.mapper.HrmLeaveReqMapper;
import com.klp.hrm.mapper.HrmReimburseReqMapper;
import com.klp.hrm.mapper.HrmTravelReqMapper;
import com.klp.hrm.mapper.HrmSealReqMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 将流程结果同步到业务表状态。
* 业务表状态规范pending/approved/rejected
*/
@Component
@RequiredArgsConstructor
public class BizStatusSyncHelper {
private final HrmLeaveReqMapper leaveReqMapper;
private final HrmTravelReqMapper travelReqMapper;
private final HrmSealReqMapper sealReqMapper;
private final HrmReimburseReqMapper reimburseReqMapper;
public void setBizApproved(String bizType, Long bizId) {
if (bizType == null || bizId == null) return;
if ("leave".equalsIgnoreCase(bizType)) {
HrmLeaveReq u = new HrmLeaveReq();
u.setBizId(bizId);
u.setStatus("approved");
leaveReqMapper.updateById(u);
} else if ("travel".equalsIgnoreCase(bizType)) {
HrmTravelReq u = new HrmTravelReq();
u.setBizId(bizId);
u.setStatus("approved");
travelReqMapper.updateById(u);
} else if ("seal".equalsIgnoreCase(bizType)) {
HrmSealReq u = new HrmSealReq();
u.setBizId(bizId);
u.setStatus("approved");
sealReqMapper.updateById(u);
} else if ("reimburse".equalsIgnoreCase(bizType)) {
HrmReimburseReq u = new HrmReimburseReq();
u.setBizId(bizId);
u.setStatus("approved");
reimburseReqMapper.updateById(u);
}
}
public void setBizPending(String bizType, Long bizId) {
if (bizType == null || bizId == null) return;
if ("leave".equalsIgnoreCase(bizType)) {
HrmLeaveReq u = new HrmLeaveReq();
u.setBizId(bizId);
u.setStatus("pending");
leaveReqMapper.updateById(u);
} else if ("travel".equalsIgnoreCase(bizType)) {
HrmTravelReq u = new HrmTravelReq();
u.setBizId(bizId);
u.setStatus("pending");
travelReqMapper.updateById(u);
} else if ("seal".equalsIgnoreCase(bizType)) {
HrmSealReq u = new HrmSealReq();
u.setBizId(bizId);
u.setStatus("pending");
sealReqMapper.updateById(u);
} else if ("reimburse".equalsIgnoreCase(bizType)) {
HrmReimburseReq u = new HrmReimburseReq();
u.setBizId(bizId);
u.setStatus("pending");
reimburseReqMapper.updateById(u);
}
}
public void setBizRejected(String bizType, Long bizId) {
if (bizType == null || bizId == null) return;
if ("leave".equalsIgnoreCase(bizType)) {
HrmLeaveReq u = new HrmLeaveReq();
u.setBizId(bizId);
u.setStatus("rejected");
leaveReqMapper.updateById(u);
} else if ("travel".equalsIgnoreCase(bizType)) {
HrmTravelReq u = new HrmTravelReq();
u.setBizId(bizId);
u.setStatus("rejected");
travelReqMapper.updateById(u);
} else if ("seal".equalsIgnoreCase(bizType)) {
HrmSealReq u = new HrmSealReq();
u.setBizId(bizId);
u.setStatus("rejected");
sealReqMapper.updateById(u);
} else if ("reimburse".equalsIgnoreCase(bizType)) {
HrmReimburseReq u = new HrmReimburseReq();
u.setBizId(bizId);
u.setStatus("rejected");
reimburseReqMapper.updateById(u);
}
}
}

View File

@@ -0,0 +1,132 @@
package com.klp.hrm.service.impl;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.core.domain.entity.SysDept;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.exception.ServiceException;
import com.klp.hrm.domain.HrmEmployee;
import com.klp.hrm.domain.HrmFlowNode;
import com.klp.hrm.mapper.HrmEmployeeMapper;
import com.klp.system.mapper.SysDeptMapper;
import com.klp.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 流程审批人解析器:根据节点 approverRule/approverValue 解析出 assigneeUserId。
*/
@Component
@RequiredArgsConstructor
public class FlowAssigneeHelper {
private final HrmEmployeeMapper employeeMapper;
private final SysDeptMapper deptMapper;
private final SysUserMapper userMapper;
public List<Long> resolveAssigneeUserIds(HrmFlowNode node, Long startUserId) {
if (node == null) {
return Collections.emptyList();
}
String rule = node.getApproverRule();
// 默认:如果没配规则,就当发起人
if (rule == null || rule.trim().isEmpty() || "initiator".equalsIgnoreCase(rule)) {
return startUserId == null ? Collections.emptyList() : Collections.singletonList(startUserId);
}
switch (rule.toLowerCase()) {
case "fixed_user":
return resolveFixedUser(node);
case "dept_leader":
case "leader": // 兼容 "leader" 写法
return resolveDeptLeader(startUserId);
default:
throw new ServiceException("审批人规则 '" + rule + "' 正在开发中,暂不支持");
}
}
private List<Long> resolveFixedUser(HrmFlowNode node) {
String v = node.getApproverValue();
if (v == null || v.trim().isEmpty()) {
throw new ServiceException("节点未配置指定人员");
}
List<String> arr;
try {
arr = JSONUtil.toList(JSONUtil.parseArray(v), String.class);
} catch (Exception e) {
// 兼容非 JSON
arr = Collections.singletonList(v);
}
// 允许 value 既可能是 userId也可能是 empId
return arr.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(s -> !s.trim().isEmpty())
.map(this::toUserId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
}
private List<Long> resolveDeptLeader(Long startUserId) {
if (startUserId == null) {
throw new ServiceException("无法解析部门负责人发起人ID为空");
}
// 1. 根据发起人ID查询员工信息获取其部门ID
HrmEmployee starter = employeeMapper.selectOne(Wrappers.<HrmEmployee>lambdaQuery().eq(HrmEmployee::getUserId, startUserId).last("limit 1"));
if (starter == null || starter.getDeptId() == null) {
throw new ServiceException("无法解析部门负责人:发起人未关联员工或部门信息");
}
// 2. 根据部门ID查询部门信息获取负责人姓名
SysDept dept = deptMapper.selectById(starter.getDeptId());
if (dept == null) {
throw new ServiceException("无法解析部门负责人:部门信息不存在");
}
if (!StringUtils.hasText(dept.getLeader())) {
throw new ServiceException("无法解析部门负责人:部门 '" + dept.getDeptName() + "' 未配置负责人");
}
// 3. sys_dept.leader 存的是 nick_name优先按 nickName 匹配,兜底按 userName 匹配
SysUser leaderUser = userMapper.selectOne(Wrappers.<SysUser>lambdaQuery()
.eq(SysUser::getNickName, dept.getLeader())
.last("limit 1"));
if (leaderUser == null) {
leaderUser = userMapper.selectOne(Wrappers.<SysUser>lambdaQuery()
.eq(SysUser::getUserName, dept.getLeader())
.last("limit 1"));
}
if (leaderUser == null) {
throw new ServiceException("无法解析部门负责人:部门负责人(nickName/userName)='" + dept.getLeader() + "' 未匹配到系统用户");
}
return Collections.singletonList(leaderUser.getUserId());
}
private Long toUserId(String s) {
// 纯数字:可能是 userId 或 empId
Long id;
try {
id = Long.parseLong(s);
} catch (Exception e) {
return null;
}
// 先当 userId 直接用
// 但为了兼容你们前端可能传 empId这里做一次 hrm_employee.user_id 映射
HrmEmployee emp = employeeMapper.selectOne(Wrappers.<HrmEmployee>lambdaQuery().eq(HrmEmployee::getEmpId, id));
if (emp != null && emp.getUserId() != null) {
return emp.getUserId();
}
return id;
}
}

View File

@@ -11,6 +11,8 @@ import com.klp.hrm.domain.bo.HrmEmpOrgPositionBo;
import com.klp.hrm.domain.vo.HrmEmpOrgPositionVo;
import com.klp.hrm.mapper.HrmEmpOrgPositionMapper;
import com.klp.hrm.service.IHrmEmpOrgPositionService;
import com.klp.system.service.ISysDeptService;
import com.klp.system.service.ISysPostService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -23,23 +25,58 @@ import java.util.List;
public class HrmEmpOrgPositionServiceImpl implements IHrmEmpOrgPositionService {
private final HrmEmpOrgPositionMapper baseMapper;
private final ISysDeptService deptService;
private final ISysPostService postService;
@Override
public HrmEmpOrgPositionVo queryById(Long relId) {
return baseMapper.selectVoById(relId);
HrmEmpOrgPositionVo vo = baseMapper.selectVoById(relId);
fillNames(vo);
return vo;
}
@Override
public TableDataInfo<HrmEmpOrgPositionVo> queryPageList(HrmEmpOrgPositionBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmEmpOrgPosition> lqw = buildQueryWrapper(bo);
Page<HrmEmpOrgPositionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
if (result.getRecords() != null) {
result.getRecords().forEach(this::fillNames);
}
return TableDataInfo.build(result);
}
@Override
public List<HrmEmpOrgPositionVo> queryList(HrmEmpOrgPositionBo bo) {
LambdaQueryWrapper<HrmEmpOrgPosition> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
List<HrmEmpOrgPositionVo> list = baseMapper.selectVoList(lqw);
if (list != null) {
list.forEach(this::fillNames);
}
return list;
}
private void fillNames(HrmEmpOrgPositionVo vo) {
if (vo == null) return;
if (vo.getDeptId() != null) {
try {
com.klp.common.core.domain.entity.SysDept dept = deptService.selectDeptById(vo.getDeptId());
if (dept != null) {
vo.setDeptName(dept.getDeptName());
}
} catch (Exception e) {
// 忽略查询失败
}
}
if (vo.getPostId() != null) {
try {
com.klp.system.domain.SysPost post = postService.selectPostById(vo.getPostId());
if (post != null) {
vo.setPostName(post.getPostName());
}
} catch (Exception e) {
// 忽略查询失败
}
}
}
@Override
@@ -65,8 +102,8 @@ public class HrmEmpOrgPositionServiceImpl implements IHrmEmpOrgPositionService {
LambdaQueryWrapper<HrmEmpOrgPosition> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getRelId() != null, HrmEmpOrgPosition::getRelId, bo.getRelId());
lqw.eq(bo.getEmpId() != null, HrmEmpOrgPosition::getEmpId, bo.getEmpId());
lqw.eq(bo.getOrgId() != null, HrmEmpOrgPosition::getOrgId, bo.getOrgId());
lqw.eq(bo.getPositionId() != null, HrmEmpOrgPosition::getPositionId, bo.getPositionId());
lqw.eq(bo.getDeptId() != null, HrmEmpOrgPosition::getDeptId, bo.getDeptId());
lqw.eq(bo.getPostId() != null, HrmEmpOrgPosition::getPostId, bo.getPostId());
lqw.eq(bo.getIsPrimary() != null, HrmEmpOrgPosition::getIsPrimary, bo.getIsPrimary());
return lqw;
}

View File

@@ -64,11 +64,12 @@ public class HrmEmployeeServiceImpl implements IHrmEmployeeService {
private LambdaQueryWrapper<HrmEmployee> buildQueryWrapper(HrmEmployeeBo bo) {
LambdaQueryWrapper<HrmEmployee> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getEmpId() != null, HrmEmployee::getEmpId, bo.getEmpId());
lqw.eq(bo.getUserId() != null, HrmEmployee::getUserId, bo.getUserId());
lqw.like(bo.getEmpNo() != null, HrmEmployee::getEmpNo, bo.getEmpNo());
lqw.like(bo.getEmpName() != null, HrmEmployee::getEmpName, bo.getEmpName());
lqw.eq(bo.getStatus() != null, HrmEmployee::getStatus, bo.getStatus());
lqw.eq(bo.getMainOrgId() != null, HrmEmployee::getMainOrgId, bo.getMainOrgId());
lqw.eq(bo.getMainPositionId() != null, HrmEmployee::getMainPositionId, bo.getMainPositionId());
lqw.eq(bo.getDeptId() != null, HrmEmployee::getDeptId, bo.getDeptId());
lqw.eq(bo.getPostId() != null, HrmEmployee::getPostId, bo.getPostId());
lqw.orderByAsc(HrmEmployee::getEmpNo);
return lqw;
}

View File

@@ -0,0 +1,163 @@
package com.klp.hrm.service.impl;
import cn.hutool.core.bean.BeanUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmFlowCc;
import com.klp.hrm.domain.bo.HrmFlowCcBo;
import com.klp.hrm.domain.vo.HrmFlowCcVo;
import com.klp.hrm.mapper.HrmFlowCcMapper;
import com.klp.hrm.service.IHrmFlowCcService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
@Service
public class HrmFlowCcServiceImpl implements IHrmFlowCcService {
private final HrmFlowCcMapper baseMapper;
private final com.klp.hrm.mapper.HrmLeaveReqMapper leaveReqMapper;
private final com.klp.hrm.mapper.HrmTravelReqMapper travelReqMapper;
private final com.klp.hrm.mapper.HrmReimburseReqMapper reimburseReqMapper;
private final com.klp.hrm.mapper.HrmSealReqMapper sealReqMapper;
@Override
public TableDataInfo<HrmFlowCcVo> queryPageList(HrmFlowCcBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmFlowCc> lqw = buildQueryWrapper(bo);
Page<HrmFlowCcVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
fillBizDisplay(result.getRecords());
return TableDataInfo.build(result);
}
@Override
public List<HrmFlowCcVo> queryList(HrmFlowCcBo bo) {
LambdaQueryWrapper<HrmFlowCc> lqw = buildQueryWrapper(bo);
List<HrmFlowCcVo> list = baseMapper.selectVoList(lqw);
fillBizDisplay(list);
return list;
}
@Override
public Boolean insert(HrmFlowCcBo bo) {
HrmFlowCc add = BeanUtil.toBean(bo, HrmFlowCc.class);
return baseMapper.insert(add) > 0;
}
@Override
public Boolean insertBatch(HrmFlowCcBo bo) {
if (bo == null) {
return false;
}
List<Long> ids = bo.getCcUserIds();
if (ids == null || ids.isEmpty()) {
// 兼容单人
if (bo.getCcUserId() == null) {
return false;
}
return insert(bo);
}
boolean ok = true;
for (Long uid : ids) {
if (uid == null) {
continue;
}
HrmFlowCc one = BeanUtil.toBean(bo, HrmFlowCc.class);
one.setCcId(null);
one.setCcUserId(uid);
one.setReadFlag(0);
ok = baseMapper.insert(one) > 0 && ok;
}
return ok;
}
@Override
public Boolean deleteByIds(Collection<Long> ids) {
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public Boolean markRead(Long ccId, Long userId) {
if (ccId == null || userId == null) {
return false;
}
return baseMapper.update(
null,
Wrappers.<HrmFlowCc>lambdaUpdate()
.set(HrmFlowCc::getReadFlag, 1)
.eq(HrmFlowCc::getCcId, ccId)
.eq(HrmFlowCc::getCcUserId, userId)
.eq(HrmFlowCc::getDelFlag, 0)
) > 0;
}
private LambdaQueryWrapper<HrmFlowCc> buildQueryWrapper(HrmFlowCcBo bo) {
LambdaQueryWrapper<HrmFlowCc> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getCcUserId() != null, HrmFlowCc::getCcUserId, bo.getCcUserId());
lqw.eq(bo.getInstId() != null, HrmFlowCc::getInstId, bo.getInstId());
lqw.eq(bo.getBizType() != null, HrmFlowCc::getBizType, bo.getBizType());
lqw.eq(bo.getReadFlag() != null, HrmFlowCc::getReadFlag, bo.getReadFlag());
lqw.orderByDesc(HrmFlowCc::getCreateTime);
return lqw;
}
/**
* 回填业务展示字段bizTypeName + bizTitle
*/
private void fillBizDisplay(List<HrmFlowCcVo> list) {
if (list == null || list.isEmpty()) {
return;
}
for (HrmFlowCcVo vo : list) {
if (vo == null) {
continue;
}
String bt = vo.getBizType();
Long bid = vo.getBizId();
if (bt == null || bid == null) {
continue;
}
// 默认兜底
vo.setBizTypeName(bt);
vo.setBizTitle(vo.getRemark());
try {
if ("leave".equalsIgnoreCase(bt)) {
vo.setBizTypeName("请假申请");
com.klp.hrm.domain.HrmLeaveReq req = leaveReqMapper.selectById(bid);
if (req != null) {
vo.setBizTitle(req.getLeaveType() + " | " + req.getReason());
}
} else if ("travel".equalsIgnoreCase(bt)) {
vo.setBizTypeName("出差申请");
com.klp.hrm.domain.HrmTravelReq req = travelReqMapper.selectById(bid);
if (req != null) {
vo.setBizTitle(req.getDestination() + " | " + req.getReason());
}
} else if ("reimburse".equalsIgnoreCase(bt)) {
vo.setBizTypeName("报销申请");
com.klp.hrm.domain.HrmReimburseReq req = reimburseReqMapper.selectById(bid);
if (req != null) {
vo.setBizTitle(req.getReimburseType() + " | " + req.getTotalAmount());
}
} else if ("seal".equalsIgnoreCase(bt)) {
vo.setBizTypeName("用印申请");
com.klp.hrm.domain.HrmSealReq req = sealReqMapper.selectById(bid);
if (req != null) {
vo.setBizTitle(req.getSealType() + " | " + req.getPurpose());
}
}
} catch (Exception ignore) {
// 不影响列表返回
}
}
}
}

View File

@@ -24,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@RequiredArgsConstructor
@Service
@@ -34,6 +33,7 @@ public class HrmFlowInstanceServiceImpl implements IHrmFlowInstanceService {
private final HrmFlowNodeMapper nodeMapper;
private final HrmFlowTaskMapper taskMapper;
private final HrmFormDataMapper formDataMapper;
private final FlowAssigneeHelper assigneeHelper;
@Override
public HrmFlowInstanceVo queryById(Long instId) {
@@ -43,7 +43,44 @@ public class HrmFlowInstanceServiceImpl implements IHrmFlowInstanceService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long startInstance(HrmFlowStartBo bo) {
// 找首节点
// 无模板:自选审批人(一次性审批)
if (bo.getTplId() == null) {
if (bo.getManualAssigneeUserId() == null) {
throw new RuntimeException("未配置流程模板且未指定审批人,无法启动");
}
HrmFlowInstance inst = new HrmFlowInstance();
inst.setTplId(0L);
inst.setBizType(bo.getBizType());
inst.setBizId(bo.getBizId());
inst.setStatus("running");
inst.setCurrentNodeId(0L);
inst.setStartUserId(bo.getStartUserId());
baseMapper.insert(inst);
// 保存表单(可选)
if (bo.getContentJson() != null) {
HrmFormData form = new HrmFormData();
form.setBizType(bo.getBizType());
form.setBizId(bo.getBizId());
form.setContentJson(bo.getContentJson());
formDataMapper.insert(form);
}
// 创建唯一待办:指派给自选审批人
HrmFlowTask task = new HrmFlowTask();
task.setInstId(inst.getInstId());
task.setNodeId(0L);
task.setAssigneeUserId(bo.getManualAssigneeUserId());
task.setStatus("pending");
// 关键:写入业务关联字段,便于审批中心联查业务数据
task.setBizType(bo.getBizType());
task.setBizId(bo.getBizId());
taskMapper.insert(task);
return inst.getInstId();
}
// 有模板:找首节点
HrmFlowNode firstNode = nodeMapper.selectOne(Wrappers.<HrmFlowNode>lambdaQuery()
.eq(HrmFlowNode::getTplId, bo.getTplId())
.orderByAsc(HrmFlowNode::getOrderNo)
@@ -70,14 +107,20 @@ public class HrmFlowInstanceServiceImpl implements IHrmFlowInstanceService {
formDataMapper.insert(form);
}
// 创建首个待办
// 创建首个待办:按首节点规则分配审批人,而不是写死发起人
List<Long> assignees = assigneeHelper.resolveAssigneeUserIds(firstNode, bo.getStartUserId());
if (assignees == null || assignees.isEmpty()) {
throw new RuntimeException("未解析到首节点审批人,无法启动流程");
}
// 简化:目前每个节点只创建一个待办(取第一个审批人)
HrmFlowTask task = new HrmFlowTask();
task.setInstId(inst.getInstId());
task.setNodeId(firstNode.getNodeId());
//task.setAssigneeUserId(Objects.requireNonNullElse(bo.getStartUserId(), 0L));
// 修复:使用三元运算符替代 Objects.requireNonNullElse
task.setAssigneeUserId(bo.getStartUserId() != null ? bo.getStartUserId() : 0L);
task.setAssigneeUserId(assignees.get(0));
task.setStatus("pending");
// 关键:写入业务关联字段,便于审批中心联查业务数据
task.setBizType(bo.getBizType());
task.setBizId(bo.getBizId());
taskMapper.insert(task);
return inst.getInstId();
@@ -90,6 +133,19 @@ public class HrmFlowInstanceServiceImpl implements IHrmFlowInstanceService {
return TableDataInfo.build(result);
}
@Override
public TableDataInfo<HrmFlowInstanceVo> queryMyInstancePageList(HrmFlowInstanceBo bo, PageQuery pageQuery) {
// “我的申请”= 当前登录用户发起的流程实例
// 这里不信任前端传 startUserId统一以登录态为准
Long userId = com.klp.common.helper.LoginHelper.getUserId();
LambdaQueryWrapper<HrmFlowInstance> lqw = buildQueryWrapper(bo);
lqw.eq(userId != null, HrmFlowInstance::getStartUserId, userId);
// 默认按发起时间倒序如果表里没createTime字段这里可改成instId倒序
lqw.orderByDesc(HrmFlowInstance::getInstId);
Page<HrmFlowInstanceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<HrmFlowInstanceVo> queryList(HrmFlowInstanceBo bo) {
LambdaQueryWrapper<HrmFlowInstance> lqw = buildQueryWrapper(bo);

View File

@@ -4,30 +4,24 @@ import cn.hutool.core.bean.BeanUtil;
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.fasterxml.jackson.databind.ObjectMapper;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmFlowTask;
import com.klp.hrm.domain.HrmFlowAction;
import com.klp.hrm.domain.HrmFlowInstance;
import com.klp.hrm.domain.HrmFlowNode;
import com.klp.hrm.domain.*;
import com.klp.hrm.domain.bo.HrmFlowTaskBo;
import com.klp.hrm.domain.bo.HrmSealStampBo;
import com.klp.hrm.domain.vo.HrmFlowTaskVo;
import com.klp.hrm.mapper.HrmFlowActionMapper;
import com.klp.hrm.mapper.HrmFlowInstanceMapper;
import com.klp.hrm.mapper.HrmFlowNodeMapper;
import com.klp.hrm.mapper.HrmFlowTaskMapper;
import com.klp.hrm.mapper.*;
import com.klp.hrm.service.IHrmFlowTaskService;
import com.klp.hrm.service.IHrmSealReqService;
import com.klp.hrm.service.IHrmFlowCcService;
import com.klp.hrm.domain.bo.HrmFlowCcBo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
@@ -38,6 +32,16 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
private final HrmFlowInstanceMapper instanceMapper;
private final HrmFlowNodeMapper nodeMapper;
private final IHrmSealReqService sealReqService;
private final IHrmFlowCcService ccService;
private final FlowAssigneeHelper assigneeHelper;
private final BizStatusSyncHelper bizStatusSyncHelper;
// 注入四个业务Mapper
private final HrmLeaveReqMapper leaveReqMapper;
private final HrmTravelReqMapper travelReqMapper;
private final HrmSealReqMapper sealReqMapper;
private final HrmReimburseReqMapper reimburseReqMapper;
private final ObjectMapper objectMapper; // Spring Boot 默认提供
@Override
public HrmFlowTaskVo queryById(Long taskId) {
@@ -48,15 +52,66 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
public TableDataInfo<HrmFlowTaskVo> queryPageList(HrmFlowTaskBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmFlowTask> lqw = buildQueryWrapper(bo);
Page<HrmFlowTaskVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
// 分页查询同样需要填充业务数据
if (result.getRecords() != null && !result.getRecords().isEmpty()) {
fillBizData(result.getRecords());
}
return TableDataInfo.build(result);
}
@Override
public List<HrmFlowTaskVo> queryList(HrmFlowTaskBo bo) {
LambdaQueryWrapper<HrmFlowTask> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
List<HrmFlowTaskVo> tasks = baseMapper.selectVoList(lqw);
if (tasks != null && !tasks.isEmpty()) {
fillBizData(tasks);
}
return tasks;
}
private void fillBizData(List<HrmFlowTaskVo> tasks) {
// 1. 按 bizType 分组,并收集 bizId
Map<String, List<Long>> bizIdsByType = tasks.stream()
.filter(t -> t.getBizType() != null && t.getBizId() != null)
.collect(Collectors.groupingBy(
HrmFlowTaskVo::getBizType,
Collectors.mapping(HrmFlowTaskVo::getBizId, Collectors.toList())
));
// 2. 批量查询各个业务表
Map<String, Object> bizDataMap = new HashMap<>();
bizIdsByType.forEach((bizType, bizIds) -> {
if (bizIds.isEmpty()) return;
switch (bizType) {
case "leave":
leaveReqMapper.selectBatchIds(bizIds).forEach(d -> bizDataMap.put("leave_" + d.getBizId(), d));
break;
case "travel":
travelReqMapper.selectBatchIds(bizIds).forEach(d -> bizDataMap.put("travel_" + d.getBizId(), d));
break;
case "seal":
sealReqMapper.selectBatchIds(bizIds).forEach(d -> bizDataMap.put("seal_" + d.getBizId(), d));
break;
case "reimburse":
reimburseReqMapper.selectBatchIds(bizIds).forEach(d -> bizDataMap.put("reimburse_" + d.getBizId(), d));
break;
}
});
// 3. 将业务数据回填到 task 的 bizData 字段
tasks.forEach(task -> {
String key = task.getBizType() + "_" + task.getBizId();
Object data = bizDataMap.get(key);
if (data != null) {
// 将实体对象转换为 Map<String, Object>,方便前端使用
Map<String, Object> dataMap = objectMapper.convertValue(data, Map.class);
task.setBizData(dataMap);
}
});
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(HrmFlowTaskBo bo) {
@@ -87,6 +142,31 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
if (inst == null) {
return false;
}
// 无模板一次性审批tplId=0 或 nodeId=0直接结束流程
if (inst.getTplId() != null && inst.getTplId() == 0L) {
// 记录动作
saveAction(taskId, inst.getInstId(), "approve", remark, actionUserId);
if (stampBo != null) {
saveAction(taskId, inst.getInstId(), "stamp", "盖章", actionUserId);
}
task.setStatus("approved");
baseMapper.updateById(task);
inst.setStatus("approved");
inst.setCurrentNodeId(null);
instanceMapper.updateById(inst);
// 若业务为用印,更新用印状态为已批准,并执行盖章
if ("seal".equalsIgnoreCase(inst.getBizType())) {
sealReqService.updateStatus(inst.getBizId(), "approved");
if (stampBo != null) {
// 盖章动作也写入流转历史
saveAction(taskId, inst.getInstId(), "stamp", "盖章", actionUserId);
sealReqService.stampWithJava(inst.getBizId(), stampBo);
}
}
bizStatusSyncHelper.setBizApproved(inst.getBizType(), inst.getBizId());
return true;
}
HrmFlowNode currentNode = nodeMapper.selectById(task.getNodeId());
if (currentNode == null) {
return false;
@@ -103,14 +183,48 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
.gt(HrmFlowNode::getOrderNo, currentNode.getOrderNo())
.orderByAsc(HrmFlowNode::getOrderNo)
.last("limit 1"));
// 若后续存在抄送节点,需要:写抄送记录 + 自动继续流转到下一个非抄送节点
while (next != null && "cc".equalsIgnoreCase(next.getNodeType())) {
// 写抄送记录
List<Long> ccUserIds = assigneeHelper.resolveAssigneeUserIds(next, inst.getStartUserId());
if (ccUserIds != null && !ccUserIds.isEmpty()) {
HrmFlowCcBo ccBo = new HrmFlowCcBo();
ccBo.setInstId(inst.getInstId());
ccBo.setBizType(inst.getBizType());
ccBo.setBizId(inst.getBizId());
ccBo.setNodeId(next.getNodeId());
// hrm_flow_node 没有 nodeName 字段,这里用 remark 作为可读名兜底
ccBo.setNodeName(next.getRemark());
ccBo.setFromUserId(actionUserId);
ccBo.setCcUserIds(ccUserIds);
ccBo.setReadFlag(0);
ccBo.setRemark("系统自动抄送");
ccService.insertBatch(ccBo);
}
// 继续找下一个节点
HrmFlowNode tmp = next;
next = nodeMapper.selectOne(Wrappers.<HrmFlowNode>lambdaQuery()
.eq(HrmFlowNode::getTplId, inst.getTplId())
.gt(HrmFlowNode::getOrderNo, tmp.getOrderNo())
.orderByAsc(HrmFlowNode::getOrderNo)
.last("limit 1"));
}
if (next != null) {
inst.setCurrentNodeId(next.getNodeId());
inst.setStatus("running");
instanceMapper.updateById(inst);
// 创建下一节点待办:按下一节点规则分配审批人
List<Long> assignees = assigneeHelper.resolveAssigneeUserIds(next, inst.getStartUserId());
if (assignees == null || assignees.isEmpty()) {
throw new RuntimeException("未解析到下一节点审批人,无法流转");
}
HrmFlowTask nextTask = new HrmFlowTask();
nextTask.setInstId(inst.getInstId());
nextTask.setNodeId(next.getNodeId());
nextTask.setAssigneeUserId(actionUserId != null ? actionUserId : 0L);
nextTask.setAssigneeUserId(assignees.get(0));
nextTask.setStatus("pending");
baseMapper.insert(nextTask);
} else {
@@ -144,10 +258,12 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
task.setStatus("rejected");
baseMapper.updateById(task);
inst.setStatus("rejected");
inst.setCurrentNodeId(null);
instanceMapper.updateById(inst);
if ("seal".equalsIgnoreCase(inst.getBizType())) {
sealReqService.updateStatus(inst.getBizId(), "rejected");
}
bizStatusSyncHelper.setBizRejected(inst.getBizType(), inst.getBizId());
return true;
}
@@ -165,6 +281,23 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
saveAction(taskId, inst.getInstId(), "withdraw", remark, actionUserId);
task.setStatus("withdraw");
baseMapper.updateById(task);
// 无模板一次性审批:撤回后业务回到 pending并重新生成一个待办仍然只允许一次审批
if (inst.getTplId() != null && inst.getTplId() == 0L) {
inst.setStatus("running");
instanceMapper.updateById(inst);
HrmFlowTask reTask = new HrmFlowTask();
reTask.setInstId(inst.getInstId());
reTask.setNodeId(0L);
// 撤回后回到“原审批人”(撤回前的办理人)
reTask.setAssigneeUserId(task.getAssigneeUserId());
reTask.setStatus("pending");
baseMapper.insert(reTask);
bizStatusSyncHelper.setBizPending(inst.getBizType(), inst.getBizId());
return true;
}
// 撤回后重新生成当前节点待办实例回到running
inst.setStatus("running");
instanceMapper.updateById(inst);
@@ -191,6 +324,43 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
actionMapper.insert(log);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean transfer(Long taskId, Long newAssigneeUserId, Long actionUserId, String remark) {
HrmFlowTask task = baseMapper.selectById(taskId);
if (task == null) {
return false;
}
if (!"pending".equalsIgnoreCase(task.getStatus())) {
return false;
}
HrmFlowInstance inst = instanceMapper.selectById(task.getInstId());
if (inst == null) {
return false;
}
// 记录动作
saveAction(taskId, inst.getInstId(), "transfer", remark, actionUserId);
// 更新办理人
HrmFlowTask u = new HrmFlowTask();
u.setTaskId(taskId);
u.setAssigneeUserId(newAssigneeUserId);
return baseMapper.updateById(u) > 0;
}
@Override
public HrmFlowTaskVo queryTodoByBiz(String bizType, Long bizId, Long assigneeUserId) {
// 只取“待办 pending”的一条理论上同一 biz 同一时刻最多一条待办)
LambdaQueryWrapper<HrmFlowTask> lqw = Wrappers.<HrmFlowTask>lambdaQuery()
.eq(bizType != null, HrmFlowTask::getBizType, bizType)
.eq(bizId != null, HrmFlowTask::getBizId, bizId)
.eq(assigneeUserId != null, HrmFlowTask::getAssigneeUserId, assigneeUserId)
.eq(HrmFlowTask::getStatus, "pending")
.orderByDesc(HrmFlowTask::getTaskId)
.last("limit 1");
return baseMapper.selectVoOne(lqw);
}
private LambdaQueryWrapper<HrmFlowTask> buildQueryWrapper(HrmFlowTaskBo bo) {
LambdaQueryWrapper<HrmFlowTask> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getTaskId() != null, HrmFlowTask::getTaskId, bo.getTaskId());
@@ -198,6 +368,8 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
lqw.eq(bo.getNodeId() != null, HrmFlowTask::getNodeId, bo.getNodeId());
lqw.eq(bo.getAssigneeUserId() != null, HrmFlowTask::getAssigneeUserId, bo.getAssigneeUserId());
lqw.eq(bo.getStatus() != null, HrmFlowTask::getStatus, bo.getStatus());
lqw.eq(bo.getBizType() != null, HrmFlowTask::getBizType, bo.getBizType());
lqw.eq(bo.getBizId() != null, HrmFlowTask::getBizId, bo.getBizId());
return lqw;
}
}

View File

@@ -1,72 +0,0 @@
package com.klp.hrm.service.impl;
import cn.hutool.core.bean.BeanUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmGrade;
import com.klp.hrm.domain.bo.HrmGradeBo;
import com.klp.hrm.domain.vo.HrmGradeVo;
import com.klp.hrm.mapper.HrmGradeMapper;
import com.klp.hrm.service.IHrmGradeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
@Service
public class HrmGradeServiceImpl implements IHrmGradeService {
private final HrmGradeMapper baseMapper;
@Override
public HrmGradeVo queryById(Long gradeId) {
return baseMapper.selectVoById(gradeId);
}
@Override
public TableDataInfo<HrmGradeVo> queryPageList(HrmGradeBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmGrade> lqw = buildQueryWrapper(bo);
Page<HrmGradeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<HrmGradeVo> queryList(HrmGradeBo bo) {
LambdaQueryWrapper<HrmGrade> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(HrmGradeBo bo) {
HrmGrade add = BeanUtil.toBean(bo, HrmGrade.class);
return baseMapper.insert(add) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(HrmGradeBo bo) {
HrmGrade update = BeanUtil.toBean(bo, HrmGrade.class);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<HrmGrade> buildQueryWrapper(HrmGradeBo bo) {
LambdaQueryWrapper<HrmGrade> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getGradeId() != null, HrmGrade::getGradeId, bo.getGradeId());
lqw.like(bo.getGradeCode() != null, HrmGrade::getGradeCode, bo.getGradeCode());
lqw.like(bo.getGradeName() != null, HrmGrade::getGradeName, bo.getGradeName());
lqw.orderByAsc(HrmGrade::getLevelNo);
return lqw;
}
}

View File

@@ -64,8 +64,8 @@ public class HrmHeadcountPlanServiceImpl implements IHrmHeadcountPlanService {
private LambdaQueryWrapper<HrmHeadcountPlan> buildQueryWrapper(HrmHeadcountPlanBo bo) {
LambdaQueryWrapper<HrmHeadcountPlan> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getPlanId() != null, HrmHeadcountPlan::getPlanId, bo.getPlanId());
lqw.eq(bo.getOrgId() != null, HrmHeadcountPlan::getOrgId, bo.getOrgId());
lqw.eq(bo.getPositionId() != null, HrmHeadcountPlan::getPositionId, bo.getPositionId());
lqw.eq(bo.getDeptId() != null, HrmHeadcountPlan::getDeptId, bo.getDeptId());
lqw.eq(bo.getPostId() != null, HrmHeadcountPlan::getPostId, bo.getPostId());
lqw.eq(bo.getYear() != null, HrmHeadcountPlan::getYear, bo.getYear());
lqw.eq(bo.getMonth() != null, HrmHeadcountPlan::getMonth, bo.getMonth());
lqw.orderByDesc(HrmHeadcountPlan::getYear).orderByDesc(HrmHeadcountPlan::getMonth);

View File

@@ -6,10 +6,15 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.helper.LoginHelper;
import com.klp.hrm.domain.HrmFlowTemplate;
import com.klp.hrm.domain.HrmLeaveReq;
import com.klp.hrm.domain.bo.HrmFlowStartBo;
import com.klp.hrm.domain.bo.HrmLeaveReqBo;
import com.klp.hrm.domain.vo.HrmLeaveReqVo;
import com.klp.hrm.mapper.HrmFlowTemplateMapper;
import com.klp.hrm.mapper.HrmLeaveReqMapper;
import com.klp.hrm.service.IHrmFlowInstanceService;
import com.klp.hrm.service.IHrmLeaveReqService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -23,6 +28,8 @@ import java.util.List;
public class HrmLeaveReqServiceImpl implements IHrmLeaveReqService {
private final HrmLeaveReqMapper baseMapper;
private final HrmFlowTemplateMapper flowTemplateMapper;
private final IHrmFlowInstanceService flowInstanceService;
@Override
public HrmLeaveReqVo queryById(Long bizId) {
@@ -47,7 +54,48 @@ public class HrmLeaveReqServiceImpl implements IHrmLeaveReqService {
public Boolean insertByBo(HrmLeaveReqBo bo) {
HrmLeaveReq add = BeanUtil.toBean(bo, HrmLeaveReq.class);
add.setStatus(defaultStatus(add.getStatus()));
return baseMapper.insert(add) > 0;
boolean ok = baseMapper.insert(add) > 0;
// 当提交为 pending 时自动启动流程实例hrm_flow_instance/hrm_flow_task
if (ok && "pending".equalsIgnoreCase(add.getStatus())) {
Long startUserId = LoginHelper.getUserId();
// 1) 优先前端明确选择了模板tplId 不为空)
HrmFlowTemplate tpl = null;
if (bo.getTplId() != null) {
tpl = flowTemplateMapper.selectOne(Wrappers.<HrmFlowTemplate>lambdaQuery()
.eq(HrmFlowTemplate::getTplId, bo.getTplId())
.eq(HrmFlowTemplate::getBizType, "leave")
.eq(HrmFlowTemplate::getEnabled, 1)
.last("limit 1"));
}
// 2) 手动审批:前端选择了手动审批人时,不允许兜底去找模板,否则会意外走到模板里的规则(例如 dept_leader
boolean manualMode = bo.getTplId() == null && bo.getManualAssigneeUserId() != null;
// 3) 兜底:只有在既没有 tplId、也没有手动审批人的情况下才自动选择最新启用模板
if (!manualMode && tpl == null) {
tpl = flowTemplateMapper.selectOne(Wrappers.<HrmFlowTemplate>lambdaQuery()
.eq(HrmFlowTemplate::getBizType, "leave")
.eq(HrmFlowTemplate::getEnabled, 1)
.orderByDesc(HrmFlowTemplate::getVersion)
.last("limit 1"));
}
HrmFlowStartBo start = new HrmFlowStartBo();
if (tpl != null) {
start.setTplId(tpl.getTplId());
}
start.setManualAssigneeUserId(bo.getManualAssigneeUserId());
start.setBizType("leave");
start.setBizId(add.getBizId());
start.setStartUserId(startUserId);
flowInstanceService.startInstance(start);
}
return ok;
}
@Override

View File

@@ -1,82 +0,0 @@
package com.klp.hrm.service.impl;
import cn.hutool.core.bean.BeanUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmOrg;
import com.klp.hrm.domain.bo.HrmOrgBo;
import com.klp.hrm.domain.vo.HrmOrgVo;
import com.klp.hrm.mapper.HrmOrgMapper;
import com.klp.hrm.service.IHrmOrgService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
@Service
public class HrmOrgServiceImpl implements IHrmOrgService {
private final HrmOrgMapper baseMapper;
@Override
public HrmOrgVo queryById(Long orgId) {
return baseMapper.selectVoById(orgId);
}
@Override
public TableDataInfo<HrmOrgVo> queryPageList(HrmOrgBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmOrg> lqw = buildQueryWrapper(bo);
Page<HrmOrgVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<HrmOrgVo> queryList(HrmOrgBo bo) {
LambdaQueryWrapper<HrmOrg> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(HrmOrgBo bo) {
HrmOrg add = BeanUtil.toBean(bo, HrmOrg.class);
validEntityBeforeSave(add);
return baseMapper.insert(add) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(HrmOrgBo bo) {
HrmOrg update = BeanUtil.toBean(bo, HrmOrg.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
// 可按需添加校验
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<HrmOrg> buildQueryWrapper(HrmOrgBo bo) {
LambdaQueryWrapper<HrmOrg> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getOrgId() != null, HrmOrg::getOrgId, bo.getOrgId());
lqw.eq(bo.getParentId() != null, HrmOrg::getParentId, bo.getParentId());
lqw.like(bo.getOrgCode() != null, HrmOrg::getOrgCode, bo.getOrgCode());
lqw.like(bo.getOrgName() != null, HrmOrg::getOrgName, bo.getOrgName());
lqw.eq(bo.getOrgType() != null, HrmOrg::getOrgType, bo.getOrgType());
lqw.eq(bo.getStatus() != null, HrmOrg::getStatus, bo.getStatus());
lqw.orderByAsc(HrmOrg::getParentId).orderByAsc(HrmOrg::getOrderNum);
return lqw;
}
private void validEntityBeforeSave(HrmOrg entity) {
// 可添加唯一性校验: org_code
}
}

View File

@@ -1,78 +0,0 @@
package com.klp.hrm.service.impl;
import cn.hutool.core.bean.BeanUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmOvertimeReq;
import com.klp.hrm.domain.bo.HrmOvertimeReqBo;
import com.klp.hrm.domain.vo.HrmOvertimeReqVo;
import com.klp.hrm.mapper.HrmOvertimeReqMapper;
import com.klp.hrm.service.IHrmOvertimeReqService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
@Service
public class HrmOvertimeReqServiceImpl implements IHrmOvertimeReqService {
private final HrmOvertimeReqMapper baseMapper;
@Override
public HrmOvertimeReqVo queryById(Long bizId) {
return baseMapper.selectVoById(bizId);
}
@Override
public TableDataInfo<HrmOvertimeReqVo> queryPageList(HrmOvertimeReqBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmOvertimeReq> lqw = buildQueryWrapper(bo);
Page<HrmOvertimeReqVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<HrmOvertimeReqVo> queryList(HrmOvertimeReqBo bo) {
LambdaQueryWrapper<HrmOvertimeReq> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(HrmOvertimeReqBo bo) {
HrmOvertimeReq add = BeanUtil.toBean(bo, HrmOvertimeReq.class);
add.setStatus(defaultStatus(add.getStatus()));
return baseMapper.insert(add) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(HrmOvertimeReqBo bo) {
HrmOvertimeReq update = BeanUtil.toBean(bo, HrmOvertimeReq.class);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<HrmOvertimeReq> buildQueryWrapper(HrmOvertimeReqBo bo) {
LambdaQueryWrapper<HrmOvertimeReq> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getBizId() != null, HrmOvertimeReq::getBizId, bo.getBizId());
lqw.eq(bo.getEmpId() != null, HrmOvertimeReq::getEmpId, bo.getEmpId());
lqw.eq(bo.getOtType() != null, HrmOvertimeReq::getOtType, bo.getOtType());
lqw.eq(bo.getStatus() != null, HrmOvertimeReq::getStatus, bo.getStatus());
lqw.eq(bo.getStartTime() != null, HrmOvertimeReq::getStartTime, bo.getStartTime());
return lqw;
}
private String defaultStatus(String status) {
return status == null ? "draft" : status;
}
}

View File

@@ -1,74 +0,0 @@
package com.klp.hrm.service.impl;
import cn.hutool.core.bean.BeanUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmPosition;
import com.klp.hrm.domain.bo.HrmPositionBo;
import com.klp.hrm.domain.vo.HrmPositionVo;
import com.klp.hrm.mapper.HrmPositionMapper;
import com.klp.hrm.service.IHrmPositionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
@Service
public class HrmPositionServiceImpl implements IHrmPositionService {
private final HrmPositionMapper baseMapper;
@Override
public HrmPositionVo queryById(Long positionId) {
return baseMapper.selectVoById(positionId);
}
@Override
public TableDataInfo<HrmPositionVo> queryPageList(HrmPositionBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmPosition> lqw = buildQueryWrapper(bo);
Page<HrmPositionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<HrmPositionVo> queryList(HrmPositionBo bo) {
LambdaQueryWrapper<HrmPosition> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(HrmPositionBo bo) {
HrmPosition add = BeanUtil.toBean(bo, HrmPosition.class);
return baseMapper.insert(add) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(HrmPositionBo bo) {
HrmPosition update = BeanUtil.toBean(bo, HrmPosition.class);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<HrmPosition> buildQueryWrapper(HrmPositionBo bo) {
LambdaQueryWrapper<HrmPosition> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getPositionId() != null, HrmPosition::getPositionId, bo.getPositionId());
lqw.like(bo.getPositionCode() != null, HrmPosition::getPositionCode, bo.getPositionCode());
lqw.like(bo.getPositionName() != null, HrmPosition::getPositionName, bo.getPositionName());
lqw.eq(bo.getGradeId() != null, HrmPosition::getGradeId, bo.getGradeId());
lqw.eq(bo.getStatus() != null, HrmPosition::getStatus, bo.getStatus());
lqw.orderByAsc(HrmPosition::getOrderNum);
return lqw;
}
}

View File

@@ -0,0 +1,107 @@
package com.klp.hrm.service.impl;
import com.klp.common.helper.LoginHelper;
import cn.hutool.core.bean.BeanUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmFlowTemplate;
import com.klp.hrm.domain.HrmReimburseReq;
import com.klp.hrm.domain.bo.HrmFlowStartBo;
import com.klp.hrm.domain.bo.HrmReimburseReqBo;
import com.klp.hrm.domain.vo.HrmReimburseReqVo;
import com.klp.hrm.mapper.HrmFlowTemplateMapper;
import com.klp.hrm.mapper.HrmReimburseReqMapper;
import com.klp.hrm.service.IHrmFlowInstanceService;
import com.klp.hrm.service.IHrmReimburseReqService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
@Service
public class HrmReimburseReqServiceImpl implements IHrmReimburseReqService {
private final HrmReimburseReqMapper baseMapper;
private final HrmFlowTemplateMapper flowTemplateMapper;
private final IHrmFlowInstanceService flowInstanceService;
@Override
public HrmReimburseReqVo queryById(Long bizId) {
return baseMapper.selectVoById(bizId);
}
@Override
public TableDataInfo<HrmReimburseReqVo> queryPageList(HrmReimburseReqBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<HrmReimburseReq> lqw = buildQueryWrapper(bo);
Page<HrmReimburseReqVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<HrmReimburseReqVo> queryList(HrmReimburseReqBo bo) {
LambdaQueryWrapper<HrmReimburseReq> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(HrmReimburseReqBo bo) {
HrmReimburseReq add = BeanUtil.toBean(bo, HrmReimburseReq.class);
add.setStatus(defaultStatus(add.getStatus()));
boolean ok = baseMapper.insert(add) > 0;
if (ok && "pending".equalsIgnoreCase(add.getStatus())) {
// 选择启用的最高版本模板(允许无模板:走自选审批人一次性审批)
HrmFlowTemplate tpl = flowTemplateMapper.selectOne(Wrappers.<HrmFlowTemplate>lambdaQuery()
.eq(HrmFlowTemplate::getBizType, "reimburse")
.eq(HrmFlowTemplate::getEnabled, 1)
.orderByDesc(HrmFlowTemplate::getVersion)
.last("limit 1"));
Long startUserId = LoginHelper.getUserId();
HrmFlowStartBo start = new HrmFlowStartBo();
if (tpl != null) {
start.setTplId(tpl.getTplId());
}
start.setManualAssigneeUserId(bo.getManualAssigneeUserId());
start.setBizType("reimburse");
start.setBizId(add.getBizId());
start.setStartUserId(startUserId);
flowInstanceService.startInstance(start);
}
return ok;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(HrmReimburseReqBo bo) {
HrmReimburseReq update = BeanUtil.toBean(bo, HrmReimburseReq.class);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<HrmReimburseReq> buildQueryWrapper(HrmReimburseReqBo bo) {
LambdaQueryWrapper<HrmReimburseReq> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getBizId() != null, HrmReimburseReq::getBizId, bo.getBizId());
lqw.eq(bo.getEmpId() != null, HrmReimburseReq::getEmpId, bo.getEmpId());
lqw.eq(bo.getReimburseType() != null, HrmReimburseReq::getReimburseType, bo.getReimburseType());
lqw.eq(bo.getStatus() != null, HrmReimburseReq::getStatus, bo.getStatus());
return lqw;
}
private String defaultStatus(String status) {
return status == null ? "draft" : status;
}
}

View File

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.exception.ServiceException;
import com.klp.common.helper.LoginHelper;
import com.klp.hrm.config.StampProperties;
import com.klp.hrm.domain.HrmSealReq;
import com.klp.hrm.domain.bo.HrmSealReqBo;
@@ -72,14 +73,20 @@ public class HrmSealReqServiceImpl implements IHrmSealReqService {
add.setStatus(defaultStatus(add.getStatus()));
validEntityBeforeSave(add);
boolean ok = baseMapper.insert(add) > 0;
// 提交即发起流程(可选)
if (ok && bo.getFlowTplId() != null) {
// 只要传入了 tplId 或 manualAssigneeUserId就代表需要启动流程
Long tplId = bo.getTplId() != null ? bo.getTplId() : bo.getFlowTplId();
boolean shouldStartFlow = tplId != null || bo.getManualAssigneeUserId() != null;
if (ok && shouldStartFlow) {
HrmFlowStartBo start = new HrmFlowStartBo();
start.setTplId(bo.getFlowTplId());
start.setTplId(tplId);
start.setManualAssigneeUserId(bo.getManualAssigneeUserId());
start.setBizType("seal");
start.setBizId(add.getBizId());
start.setStartUserId(bo.getStartUserId());
start.setStartUserId(LoginHelper.getUserId());
start.setContentJson(bo.getContentJson());
flowInstanceService.startInstance(start);
// 更新状态为流转中
updateStatus(add.getBizId(), "running");
@@ -171,20 +178,70 @@ public class HrmSealReqServiceImpl implements IHrmSealReqService {
PDPage page = document.getPage(pageIndex);
PDRectangle mediaBox = page.getMediaBox();
// 坐标约定说明:
// 1) PdfStamper emitStamp():输出的是“左下角为原点”的 viewport 像素坐标xPx,yPx
// 2) PDFBox使用“左下角为原点”的 PDF 用户单位(pt)。
// 3) 因此后端只做比例换算px -> pt不要再做 y 翻转。
byte[] imgBytes = IoUtil.readBytes(imgIn);
PDImageXObject image = PDImageXObject.createFromByteArray(document, imgBytes, "stamp");
float width = cmd.getWidthPx() != null ? cmd.getWidthPx() : image.getWidth();
float height = cmd.getHeightPx() != null ? cmd.getHeightPx() : image.getHeight();
float x = cmd.getXPx();
float y = cmd.getYPx();
// 方案B严格使用印章原图尺寸不使用前端传来的 widthPx/heightPx
float stampW = image.getWidth();
float stampH = image.getHeight();
// 保证不越界
// 坐标换算:前端 xPx/yPx 是基于 pdf.js 渲染后的 viewport 像素PDFBox 使用的是 PDF 用户单位(pt)。
// 前端 PdfStamper emitStamp() 输出的 yPx 已经是“左下角为原点”的 viewport 像素坐标。
float pdfW = mediaBox.getWidth();
float pdfH = mediaBox.getHeight();
float x;
float y;
if (cmd.getViewportWidth() != null && cmd.getViewportHeight() != null
&& cmd.getViewportWidth() > 0 && cmd.getViewportHeight() > 0) {
float ratioX = pdfW / cmd.getViewportWidth();
float ratioY = pdfH / cmd.getViewportHeight();
x = cmd.getXPx() * ratioX;
// yPx 的约定:
// - PdfStamper emitStamp() 输出的是“左下角为原点”的 viewport 像素坐标
// - PDFBox 也以左下角为原点
// 因此只需要做比例换算,不要再翻转。
y = cmd.getYPx() * ratioY;
} else {
// 兼容:若老客户端未传 viewport 尺寸,则按“直接当作 PDF 坐标”处理(可能有偏差)
x = cmd.getXPx();
y = cmd.getYPx();
}
// 方案B1等比例缩放到“外接框不超过 4cm x 4cm”保持比例
// PDFBox 的单位是 pt1 inch = 72pt1cm = 72/2.54 ≈ 28.346pt
final float maxCm = 4.0f;
final float maxPt = maxCm * 72.0f / 2.54f;
// 缩放因子:让宽高都不超过 maxPt
float scale = Math.min(maxPt / stampW, maxPt / stampH);
// 不放大(避免小图被放大到很糊);如需允许放大,可删除这行限制
scale = Math.min(scale, 1.0f);
float width = stampW * scale;
float height = stampH * scale;
log.info("[stamp] pdfW={},pdfH={}, viewportW={},viewportH={}, ratioX={},ratioY={}, xPx={},yPx={}, x={},y={}, stampW={},stampH={}, drawW={},drawH={}",
pdfW, pdfH,
cmd.getViewportWidth(), cmd.getViewportHeight(),
(cmd.getViewportWidth()!=null&&cmd.getViewportWidth()>0)?(pdfW/cmd.getViewportWidth()):null,
(cmd.getViewportHeight()!=null&&cmd.getViewportHeight()>0)?(pdfH/cmd.getViewportHeight()):null,
cmd.getXPx(), cmd.getYPx(),
x, y,
stampW, stampH,
width, height);
// 保证不越界方案B下不裁剪宽高否则会变形/不是原图大小),而是回退到页面内。
if (x + width > mediaBox.getWidth()) {
width = mediaBox.getWidth() - x;
x = Math.max(0, mediaBox.getWidth() - width);
}
if (y + height > mediaBox.getHeight()) {
height = mediaBox.getHeight() - y;
y = Math.max(0, mediaBox.getHeight() - height);
}
try (PDPageContentStream contentStream = new PDPageContentStream(document, page,
@@ -197,9 +254,8 @@ public class HrmSealReqServiceImpl implements IHrmSealReqService {
OssClient storage = OssFactory.instance();
UploadResult uploadResult = storage.uploadSuffix(bos.toByteArray(), ".pdf", "application/pdf");
return uploadResult.getUrl();
} catch (ServiceException se) {
throw se;
} catch (Exception e) {
}
catch (Exception e) {
log.error("PDF盖章失败", e);
throw new ServiceException("PDF盖章失败: " + e.getMessage());
}

View File

@@ -1,15 +1,20 @@
package com.klp.hrm.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.helper.LoginHelper;
import com.klp.hrm.domain.HrmFlowTemplate;
import com.klp.hrm.domain.HrmTravelReq;
import com.klp.hrm.domain.bo.HrmFlowStartBo;
import com.klp.hrm.domain.bo.HrmTravelReqBo;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.hrm.domain.HrmTravelReq;
import com.klp.hrm.domain.bo.HrmTravelReqBo;
import cn.hutool.core.bean.BeanUtil;
import com.klp.hrm.domain.vo.HrmTravelReqVo;
import com.klp.hrm.mapper.HrmFlowTemplateMapper;
import com.klp.hrm.mapper.HrmTravelReqMapper;
import com.klp.hrm.service.IHrmFlowInstanceService;
import com.klp.hrm.service.IHrmTravelReqService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -23,6 +28,8 @@ import java.util.List;
public class HrmTravelReqServiceImpl implements IHrmTravelReqService {
private final HrmTravelReqMapper baseMapper;
private final HrmFlowTemplateMapper flowTemplateMapper;
private final IHrmFlowInstanceService flowInstanceService;
@Override
public HrmTravelReqVo queryById(Long bizId) {
@@ -47,7 +54,33 @@ public class HrmTravelReqServiceImpl implements IHrmTravelReqService {
public Boolean insertByBo(HrmTravelReqBo bo) {
HrmTravelReq add = BeanUtil.toBean(bo, HrmTravelReq.class);
add.setStatus(defaultStatus(add.getStatus()));
return baseMapper.insert(add) > 0;
boolean ok = baseMapper.insert(add) > 0;
// 业务表状态规范pending/approved/rejected
// 当提交为 pending 时自动启动流程实例hrm_flow_instance/hrm_flow_task
if (ok && "pending".equalsIgnoreCase(add.getStatus())) {
// 选择启用的最高版本模板(允许无模板:走自选审批人一次性审批)
HrmFlowTemplate tpl = flowTemplateMapper.selectOne(Wrappers.<HrmFlowTemplate>lambdaQuery()
.eq(HrmFlowTemplate::getBizType, "travel")
.eq(HrmFlowTemplate::getEnabled, 1)
.orderByDesc(HrmFlowTemplate::getVersion)
.last("limit 1"));
Long startUserId = LoginHelper.getUserId();
HrmFlowStartBo start = new HrmFlowStartBo();
if (tpl != null) {
start.setTplId(tpl.getTplId());
}
start.setManualAssigneeUserId(bo.getManualAssigneeUserId());
start.setBizType("travel");
start.setBizId(add.getBizId());
start.setStartUserId(startUserId);
// 暂不保存 contentJson
flowInstanceService.startInstance(start);
}
return ok;
}
@Override