feat(resource): 初始化权限数据并实现资源管理接口
- 新增初始化系统权限的SQL脚本,包含菜单权限、按钮权限及角色权限分配 - 实现资源管理RestController,支持资源的增删改查操作 - 资源接口支持分页查询、按ID查询以及状态和数量更新 - 增加资源预算汇总、即将到位资源和待审批资源查询接口 - 新增资源更新请求DTO,支持详细的资源属性修改及负责人自动匹配功能 - 权限检查基于注解实现,保障接口安全性与权限控制有效性
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
package cn.yinlihupo.controller.project;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.yinlihupo.common.core.BaseResponse;
|
||||
import cn.yinlihupo.common.util.ResultUtils;
|
||||
import cn.yinlihupo.domain.dto.ResourceUpdateRequest;
|
||||
import cn.yinlihupo.domain.entity.Resource;
|
||||
import cn.yinlihupo.domain.entity.SysUser;
|
||||
import cn.yinlihupo.mapper.ResourceMapper;
|
||||
import cn.yinlihupo.mapper.SysUserMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 资源管理控制器
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/resource")
|
||||
@RequiredArgsConstructor
|
||||
public class ResourceController {
|
||||
|
||||
private final ResourceMapper resourceMapper;
|
||||
private final SysUserMapper sysUserMapper;
|
||||
|
||||
/**
|
||||
* 分页查询资源列表
|
||||
*/
|
||||
@SaCheckPermission("project:resource:list")
|
||||
@GetMapping("/list")
|
||||
public BaseResponse<Page<Map<String, Object>>> list(
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) Long projectId,
|
||||
@RequestParam(required = false) String resourceType,
|
||||
@RequestParam(required = false) String status,
|
||||
@RequestParam(required = false) String keyword) {
|
||||
|
||||
Page<Map<String, Object>> page = new Page<>(pageNum, pageSize);
|
||||
List<Map<String, Object>> records = resourceMapper.selectResourcePageWithResponsible(
|
||||
projectId, resourceType, status, keyword);
|
||||
|
||||
page.setRecords(records);
|
||||
page.setTotal(records.size());
|
||||
|
||||
return ResultUtils.success("查询成功", page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询资源详情
|
||||
*/
|
||||
@SaCheckPermission("project:resource:view")
|
||||
@GetMapping("/{id}")
|
||||
public BaseResponse<Resource> getById(@PathVariable Long id) {
|
||||
Resource resource = resourceMapper.selectById(id);
|
||||
if (resource == null || resource.getDeleted() == 1) {
|
||||
return ResultUtils.error("资源不存在");
|
||||
}
|
||||
return ResultUtils.success("查询成功", resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增资源
|
||||
*/
|
||||
@SaCheckPermission("project:resource:create")
|
||||
@PostMapping
|
||||
public BaseResponse<Long> create(@RequestBody Resource resource) {
|
||||
if (resource.getProjectId() == null) {
|
||||
return ResultUtils.error("项目ID不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(resource.getResourceName())) {
|
||||
return ResultUtils.error("资源名称不能为空");
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (resource.getStatus() == null) {
|
||||
resource.setStatus("planned");
|
||||
}
|
||||
if (resource.getCurrency() == null) {
|
||||
resource.setCurrency("CNY");
|
||||
}
|
||||
|
||||
resourceMapper.insert(resource);
|
||||
log.info("新增资源成功, id: {}, resourceName: {}", resource.getId(), resource.getResourceName());
|
||||
return ResultUtils.success("新增成功", resource.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改资源
|
||||
*/
|
||||
@SaCheckPermission("project:resource:update")
|
||||
@PutMapping
|
||||
public BaseResponse<Void> update(@RequestBody ResourceUpdateRequest request) {
|
||||
if (request.getId() == null) {
|
||||
return ResultUtils.error("资源ID不能为空");
|
||||
}
|
||||
|
||||
Resource exist = resourceMapper.selectById(request.getId());
|
||||
if (exist == null || exist.getDeleted() == 1) {
|
||||
return ResultUtils.error("资源不存在");
|
||||
}
|
||||
|
||||
// 将DTO转换为实体
|
||||
Resource resource = new Resource();
|
||||
BeanUtils.copyProperties(request, resource);
|
||||
|
||||
// 如果传递了responsibleName,根据姓名查询用户ID
|
||||
if (StringUtils.hasText(request.getResponsibleName())) {
|
||||
SysUser user = sysUserMapper.selectByRealName(request.getResponsibleName());
|
||||
if (user != null) {
|
||||
resource.setResponsibleId(user.getId());
|
||||
log.debug("资源负责人 '{}' 匹配到用户 ID: {}", request.getResponsibleName(), user.getId());
|
||||
} else {
|
||||
log.warn("资源负责人 '{}' 未在系统中找到匹配的用户", request.getResponsibleName());
|
||||
}
|
||||
}
|
||||
|
||||
// 不更新敏感字段
|
||||
resource.setCreateTime(null);
|
||||
resource.setDeleted(null);
|
||||
resource.setResourceCode(null);
|
||||
|
||||
resourceMapper.updateById(resource);
|
||||
log.info("修改资源成功, id: {}", resource.getId());
|
||||
return ResultUtils.success("修改成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除资源
|
||||
*/
|
||||
@SaCheckPermission("project:resource:delete")
|
||||
@DeleteMapping("/{id}")
|
||||
public BaseResponse<Void> delete(@PathVariable Long id) {
|
||||
Resource resource = resourceMapper.selectById(id);
|
||||
if (resource == null || resource.getDeleted() == 1) {
|
||||
return ResultUtils.error("资源不存在");
|
||||
}
|
||||
|
||||
resourceMapper.deleteById(id);
|
||||
log.info("删除资源成功, id: {}", id);
|
||||
return ResultUtils.success("删除成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新资源状态
|
||||
*/
|
||||
@SaCheckPermission("project:resource:update")
|
||||
@PutMapping("/{id}/status")
|
||||
public BaseResponse<Void> updateStatus(@PathVariable Long id, @RequestParam String status) {
|
||||
Resource resource = resourceMapper.selectById(id);
|
||||
if (resource == null || resource.getDeleted() == 1) {
|
||||
return ResultUtils.error("资源不存在");
|
||||
}
|
||||
|
||||
resource.setStatus(status);
|
||||
|
||||
// 如果状态变为已到货,设置实际到位日期
|
||||
if ("arrived".equals(status) || "in_use".equals(status) || "completed".equals(status)) {
|
||||
if (resource.getActualArriveDate() == null) {
|
||||
resource.setActualArriveDate(java.time.LocalDate.now());
|
||||
}
|
||||
}
|
||||
|
||||
resourceMapper.updateById(resource);
|
||||
log.info("更新资源状态成功, id: {}, status: {}", id, status);
|
||||
return ResultUtils.success("更新成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新资源数量
|
||||
*/
|
||||
@SaCheckPermission("project:resource:update")
|
||||
@PutMapping("/{id}/quantity")
|
||||
public BaseResponse<Void> updateQuantity(@PathVariable Long id,
|
||||
@RequestParam BigDecimal actualQuantity) {
|
||||
if (actualQuantity == null || actualQuantity.compareTo(BigDecimal.ZERO) < 0) {
|
||||
return ResultUtils.error("实际数量不能为负数");
|
||||
}
|
||||
|
||||
Resource resource = resourceMapper.selectById(id);
|
||||
if (resource == null || resource.getDeleted() == 1) {
|
||||
return ResultUtils.error("资源不存在");
|
||||
}
|
||||
|
||||
resource.setActualQuantity(actualQuantity);
|
||||
resourceMapper.updateById(resource);
|
||||
log.info("更新资源数量成功, id: {}, actualQuantity: {}", id, actualQuantity);
|
||||
return ResultUtils.success("更新成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询资源预算汇总
|
||||
*/
|
||||
@SaCheckPermission("project:resource:stats")
|
||||
@GetMapping("/stats/budget")
|
||||
public BaseResponse<List<Map<String, Object>>> getBudgetSummary(@RequestParam Long projectId) {
|
||||
List<Map<String, Object>> stats = resourceMapper.selectResourceBudgetSummary(projectId);
|
||||
return ResultUtils.success("查询成功", stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询即将到位的资源
|
||||
*/
|
||||
@SaCheckPermission("project:resource:view")
|
||||
@GetMapping("/pending-arrival")
|
||||
public BaseResponse<List<Resource>> getPendingArrivalResources(
|
||||
@RequestParam Long projectId,
|
||||
@RequestParam(defaultValue = "7") int days) {
|
||||
List<Resource> resources = resourceMapper.selectPendingArrivalResources(projectId, days);
|
||||
return ResultUtils.success("查询成功", resources);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询待审批的资源申请
|
||||
*/
|
||||
@SaCheckPermission("project:resource:view")
|
||||
@GetMapping("/pending-approval")
|
||||
public BaseResponse<List<Map<String, Object>>> getPendingApprovalResources(
|
||||
@RequestParam(required = false) Long projectId) {
|
||||
List<Map<String, Object>> resources = resourceMapper.selectPendingApprovalResources(projectId);
|
||||
return ResultUtils.success("查询成功", resources);
|
||||
}
|
||||
}
|
||||
109
src/main/java/cn/yinlihupo/domain/dto/ResourceUpdateRequest.java
Normal file
109
src/main/java/cn/yinlihupo/domain/dto/ResourceUpdateRequest.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package cn.yinlihupo.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源更新请求DTO
|
||||
*/
|
||||
@Data
|
||||
public class ResourceUpdateRequest {
|
||||
|
||||
/**
|
||||
* 资源ID(必填)
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 资源类型: human-人力, material-物料, equipment-设备, software-软件, finance-资金, other-其他
|
||||
*/
|
||||
private String resourceType;
|
||||
|
||||
/**
|
||||
* 资源名称
|
||||
*/
|
||||
private String resourceName;
|
||||
|
||||
/**
|
||||
* 资源描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
private String specification;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 计划数量
|
||||
*/
|
||||
private BigDecimal planQuantity;
|
||||
|
||||
/**
|
||||
* 实际数量
|
||||
*/
|
||||
private BigDecimal actualQuantity;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 币种
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 供应商/来源
|
||||
*/
|
||||
private String supplier;
|
||||
|
||||
/**
|
||||
* 状态: planned-计划中, requested-已申请, approved-已批准, procuring-采购中, arrived-已到货, in_use-使用中, completed-已完成
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 计划到位日期
|
||||
*/
|
||||
private LocalDate planArriveDate;
|
||||
|
||||
/**
|
||||
* 实际到位日期
|
||||
*/
|
||||
private LocalDate actualArriveDate;
|
||||
|
||||
/**
|
||||
* 负责人ID(直接传递ID时使用)
|
||||
*/
|
||||
private Long responsibleId;
|
||||
|
||||
/**
|
||||
* 负责人姓名(根据姓名自动匹配用户ID)
|
||||
*/
|
||||
private String responsibleName;
|
||||
|
||||
/**
|
||||
* 存放位置
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
/**
|
||||
* 扩展数据
|
||||
*/
|
||||
private Object extraData;
|
||||
}
|
||||
Reference in New Issue
Block a user