@@ -14,7 +14,7 @@ import java.util.Collections; | |||
public class GeneratorCodeKingbaseConfig { | |||
private static final String PATH_LXX = "/Users/liuxinxin/IdeaProjects/project-management/pmapi/src/main/java"; | |||
private static final String PATH_YYD = "/Users/wendy/code project/java/project-management/pmapi/src/main/java"; | |||
private static final String PATH_YYD = "/Users/wendy/coding/java/project-management/pmapi/src/main/java"; | |||
private static final String PATH_LS = ""; | |||
private static final String PATH_ZPF = "D:\\ningda\\project-management\\pmapi\\src\\main\\java"; | |||
private static final String PATH_CMM = "D:\\work\\project-management\\project-management\\pmapi\\src\\main\\java"; | |||
@@ -57,7 +57,7 @@ public class GeneratorCodeKingbaseConfig { | |||
public static void main(String[] args) { | |||
//generate("Liuxinxin", "expert", PATH_LXX, "expert_gov_business_strip"); | |||
generate("CMM", "test", PATH_CMM, "nd_performance_appraisal_app_indicator"); | |||
generate("CMM", "meeting", PATH_YYD, "meeting_expert_judge"); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
package com.ningdatech.pmapi.meeting.controller; | |||
import com.ningdatech.pmapi.meeting.entity.req.MeetingExpertJudgeReq; | |||
import com.ningdatech.pmapi.meeting.manage.MeetingExpertJudgeManage; | |||
import io.swagger.annotations.Api; | |||
import io.swagger.annotations.ApiOperation; | |||
import lombok.AllArgsConstructor; | |||
import org.springframework.web.bind.annotation.*; | |||
import javax.validation.Valid; | |||
/** | |||
* <p> | |||
* 前端控制器 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023-07-31 | |||
*/ | |||
@Api(tags = "履职评价管理") | |||
@AllArgsConstructor | |||
@RestController | |||
@RequestMapping("/api/v1/meeting/expert-judge") | |||
public class MeetingExpertJudgeController { | |||
private final MeetingExpertJudgeManage expertJudgeManage; | |||
@ApiOperation("保存履职评价") | |||
@PostMapping("/submit") | |||
public void saveExpertJudge(@Valid @RequestBody MeetingExpertJudgeReq req) { | |||
expertJudgeManage.saveExpertJudge(req); | |||
} | |||
@ApiOperation("查看履职评价") | |||
@GetMapping("/detail/{meetingExpertId}") | |||
public MeetingExpertJudgeReq expertJudgeDetail(@PathVariable Long meetingExpertId) { | |||
return expertJudgeManage.expertJudgeDetail(meetingExpertId); | |||
} | |||
} |
@@ -0,0 +1,63 @@ | |||
package com.ningdatech.pmapi.meeting.entity.domain; | |||
import com.baomidou.mybatisplus.annotation.*; | |||
import io.swagger.annotations.Api; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.time.LocalDateTime; | |||
/** | |||
* <p> | |||
* 会议专家履职评价表 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023-07-31 | |||
*/ | |||
@Data | |||
@TableName("meeting_expert_judge") | |||
@ApiModel(value = "MeetingExpertJudge对象") | |||
public class MeetingExpertJudge implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
@TableId(type = IdType.AUTO) | |||
private Long id; | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@ApiModelProperty("会议专家ID") | |||
private Long meetingExpertId; | |||
@ApiModelProperty("评分(1~10)") | |||
private Integer score; | |||
@ApiModelProperty("是否参加:1 准时、2 迟到、3 缺席") | |||
private Integer attended; | |||
@ApiModelProperty("参与程度:1 积极、2 消极") | |||
private Integer performance; | |||
@ApiModelProperty("是否提出建议:true 是、false 否") | |||
private Boolean advised; | |||
@ApiModelProperty("是否早退:true 早退、false 未早退") | |||
private Boolean leaveEarly; | |||
@ApiModelProperty("是否违规:true 是、false 否") | |||
private Boolean brokeRule; | |||
@ApiModelProperty("违规内容") | |||
private String brokeRuleContent; | |||
@TableField(fill = FieldFill.INSERT) | |||
private Long createBy; | |||
@TableField(fill = FieldFill.INSERT) | |||
private LocalDateTime createOn; | |||
} |
@@ -15,6 +15,10 @@ public class MeetingAndAttendStatusDTO { | |||
private Long meetingId; | |||
private Long meetingExpertId; | |||
private Long expertId; | |||
private Integer status; | |||
private Boolean attended; | |||
@@ -0,0 +1,59 @@ | |||
package com.ningdatech.pmapi.meeting.entity.req; | |||
import com.alibaba.fastjson.annotation.JSONField; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotNull; | |||
import java.time.LocalDateTime; | |||
/** | |||
* <p> | |||
* MeetingExpertJudgeReq | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023/7/31 | |||
**/ | |||
@Data | |||
public class MeetingExpertJudgeReq { | |||
private Long id; | |||
@NotNull(message = "会议ID不能为空") | |||
private Long meetingId; | |||
@NotNull(message = "会议专家ID不能为空") | |||
private Long meetingExpertId; | |||
@ApiModelProperty("评分(1~10)") | |||
@NotNull(message = "评分不能为空") | |||
private Integer score; | |||
@ApiModelProperty("是否参加:1 准时、2 迟到、3 缺席") | |||
@NotNull(message = "是否参加不能为空") | |||
private Integer attended; | |||
@ApiModelProperty("参与程度:1 积极、2 消极") | |||
@NotNull(message = "参与度不能为空") | |||
private Integer performance; | |||
@ApiModelProperty("是否提出建议:true 是、false 否") | |||
@NotNull(message = "是否提出建议不能为空") | |||
private Boolean advised; | |||
@ApiModelProperty("是否早退:true 早退、false 未早退") | |||
@NotNull(message = "是否早退不能为空") | |||
private Boolean leaveEarly; | |||
@ApiModelProperty("是否违规:true 是、false 否") | |||
@NotNull(message = "是否违规不能为空") | |||
private Boolean brokeRule; | |||
@ApiModelProperty("违规内容") | |||
private String brokeRuleContent; | |||
@JSONField(format = "yyyy-MM-dd HH:mm:ss") | |||
private LocalDateTime createOn; | |||
} |
@@ -29,6 +29,9 @@ public class MeetingByManagerVO { | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@ApiModelProperty("会议专家ID") | |||
private Long meetingExpertId; | |||
@ApiModelProperty("会议开始时间") | |||
@JSONField(format = "yyyy-MM-dd HH:mm") | |||
private LocalDateTime startTime; | |||
@@ -70,4 +73,7 @@ public class MeetingByManagerVO { | |||
@ApiModelProperty("联系方式") | |||
private String contact; | |||
@ApiModelProperty("是否评价") | |||
private Boolean hasJudge; | |||
} |
@@ -0,0 +1,80 @@ | |||
package com.ningdatech.pmapi.meeting.manage; | |||
import cn.hutool.core.bean.BeanUtil; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.cache.lock.DistributedLock; | |||
import com.ningdatech.pmapi.meeting.entity.domain.Meeting; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpertJudge; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.req.MeetingExpertJudgeReq; | |||
import com.ningdatech.pmapi.meeting.service.IMeetingExpertJudgeService; | |||
import com.ningdatech.pmapi.meeting.service.IMeetingExpertService; | |||
import com.ningdatech.pmapi.meeting.service.IMeetingService; | |||
import lombok.AllArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* <p> | |||
* MeetingExpertJudgeManage | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023/7/31 | |||
**/ | |||
@Component | |||
@AllArgsConstructor | |||
public class MeetingExpertJudgeManage { | |||
private final IMeetingExpertJudgeService expertJudgeService; | |||
private final IMeetingExpertService meetingExpertService; | |||
private final IMeetingService meetingService; | |||
private final DistributedLock distributedLock; | |||
private MeetingExpertJudge getMeetingExpertJudge(Long meetingExpertId) { | |||
LambdaQueryWrapper<MeetingExpertJudge> query = Wrappers.lambdaQuery(MeetingExpertJudge.class) | |||
.eq(MeetingExpertJudge::getMeetingExpertId, meetingExpertId); | |||
return expertJudgeService.getOne(query); | |||
} | |||
public void saveExpertJudge(MeetingExpertJudgeReq req) { | |||
String key = "lock_expert_judge:" + req.getMeetingExpertId(); | |||
if (!distributedLock.lock(key, 3)) { | |||
throw BizException.wrap("履职评价失败,请重试"); | |||
} | |||
try { | |||
// 会议状态校验 | |||
Meeting meeting = meetingService.getById(req.getMeetingId()); | |||
if (meeting == null || MeetingStatusEnum.CANCELED.eq(meeting.getStatus())) { | |||
throw BizException.wrap("会议不存在或已取消"); | |||
} | |||
// 专家抽取状态校验 | |||
MeetingExpert expert = meetingExpertService.getById(req.getMeetingExpertId()); | |||
if (expert == null || (ExpertAttendStatusEnum.AGREED.eq(expert.getStatus()) | |||
&& ExpertAttendStatusEnum.ON_LEAVE.eq(expert.getStatus()))) { | |||
throw BizException.wrap("未被抽中专家无法进行履职评价"); | |||
} | |||
// 智能履职评价一次 | |||
MeetingExpertJudge judge = getMeetingExpertJudge(req.getMeetingExpertId()); | |||
if (judge != null) { | |||
throw BizException.wrap("履职评价已提交"); | |||
} | |||
MeetingExpertJudge entity = BeanUtil.copyProperties(req, MeetingExpertJudge.class); | |||
expertJudgeService.save(entity); | |||
} finally { | |||
distributedLock.releaseLock(key); | |||
} | |||
} | |||
public MeetingExpertJudgeReq expertJudgeDetail(Long meetingExpertId) { | |||
MeetingExpertJudge judge = getMeetingExpertJudge(meetingExpertId); | |||
if (judge == null) { | |||
throw BizException.wrap("履职评价未提交"); | |||
} | |||
return BeanUtil.copyProperties(judge, MeetingExpertJudgeReq.class); | |||
} | |||
} |
@@ -97,6 +97,7 @@ public class MeetingManage { | |||
private final ExpertInviteHelper expertInviteHelper; | |||
private final MeetingCallOrMsgHelper meetingCallOrMsgHelper; | |||
private final MeetingDataScopeHelper meetingDataScopeHelper; | |||
private final IMeetingExpertJudgeService expertJudgeService; | |||
private static final String INVITED_RULE_CREATE = "INVITED_RULE_CREATE:"; | |||
private static final String MEETING_CREATE_KEY = "MEETING_CREATE:"; | |||
@@ -324,7 +325,11 @@ public class MeetingManage { | |||
return PageVo.empty(); | |||
} | |||
Map<Long, MeetingAndAttendStatusDTO> mapByMeetingId = new HashMap<>(16); | |||
meetings.forEach(w -> mapByMeetingId.put(w.getMeetingId(), w)); | |||
List<Long> meetingExpertIds = new ArrayList<>(); | |||
meetings.forEach(w -> { | |||
mapByMeetingId.put(w.getMeetingId(), w); | |||
meetingExpertIds.add(w.getMeetingExpertId()); | |||
}); | |||
LambdaQueryWrapper<Meeting> query = new LambdaQueryWrapper<Meeting>() | |||
.orderByDesc(Meeting::getCreateOn) | |||
.in(Meeting::getId, mapByMeetingId.keySet()) | |||
@@ -337,11 +342,14 @@ public class MeetingManage { | |||
if (page.getTotal() == 0) { | |||
return PageVo.empty(); | |||
} | |||
List<Long> existsMeIds = expertJudgeService.listExistsMeetingExpertIds(meetingExpertIds); | |||
PageVo<MeetingByManagerVO> result = new PageVo<>(new ArrayList<>(), page.getTotal()); | |||
page.getRecords().forEach(meeting -> { | |||
MeetingByManagerVO item = meetingManageHelper.buildByMeeting(meeting); | |||
MeetingAndAttendStatusDTO info = mapByMeetingId.get(meeting.getId()); | |||
item.setMeetingExpertId(info.getMeetingExpertId()); | |||
item.setExpertStatus(info.getStatus()); | |||
item.setHasJudge(existsMeIds.contains(info.getMeetingExpertId())); | |||
result.getRecords().add(item); | |||
}); | |||
return result; | |||
@@ -0,0 +1,16 @@ | |||
package com.ningdatech.pmapi.meeting.mapper; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpertJudge; | |||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||
/** | |||
* <p> | |||
* Mapper 接口 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-07-31 | |||
*/ | |||
public interface MeetingExpertJudgeMapper extends BaseMapper<MeetingExpertJudge> { | |||
} |
@@ -0,0 +1,5 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
<mapper namespace="com.ningdatech.pmapi.meeting.mapper.MeetingExpertJudgeMapper"> | |||
</mapper> |
@@ -4,7 +4,7 @@ | |||
<select id="selectByExpertIdAndStatus" | |||
resultType="com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO"> | |||
SELECT em.meeting_id meetingId, em.status | |||
SELECT em.meeting_id meetingId, em.status, em.ID meetingExpertId | |||
FROM (SELECT ROW_NUMBER() OVER ( PARTITION BY meeting_id ORDER BY update_on DESC ) rowNumber, ID, expert_id, | |||
status, meeting_id | |||
FROM meeting_expert | |||
@@ -0,0 +1,34 @@ | |||
package com.ningdatech.pmapi.meeting.service; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpertJudge; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
* <p> | |||
* 服务类 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-07-31 | |||
*/ | |||
public interface IMeetingExpertJudgeService extends IService<MeetingExpertJudge> { | |||
default List<Long> listExistsMeetingExpertIds(Collection<Long> meetingExpertIds) { | |||
if (CollUtil.isEmpty(meetingExpertIds)) { | |||
return Collections.emptyList(); | |||
} | |||
LambdaQueryWrapper<MeetingExpertJudge> query = Wrappers.lambdaQuery(MeetingExpertJudge.class) | |||
.select(MeetingExpertJudge::getMeetingExpertId) | |||
.in(MeetingExpertJudge::getMeetingExpertId, meetingExpertIds); | |||
return CollUtils.fieldList(list(query), MeetingExpertJudge::getMeetingExpertId); | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.ningdatech.pmapi.meeting.service.impl; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpertJudge; | |||
import com.ningdatech.pmapi.meeting.mapper.MeetingExpertJudgeMapper; | |||
import com.ningdatech.pmapi.meeting.service.IMeetingExpertJudgeService; | |||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | |||
import org.springframework.stereotype.Service; | |||
/** | |||
* <p> | |||
* 服务实现类 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-07-31 | |||
*/ | |||
@Service | |||
public class MeetingExpertJudgeServiceImpl extends ServiceImpl<MeetingExpertJudgeMapper, MeetingExpertJudge> implements IMeetingExpertJudgeService { | |||
} |