@@ -14,7 +14,7 @@ import java.util.Collections; | |||||
public class GeneratorCodeKingbaseConfig { | public class GeneratorCodeKingbaseConfig { | ||||
private static final String PATH_LXX = "/Users/liuxinxin/IdeaProjects/project-management/pmapi/src/main/java"; | 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_LS = ""; | ||||
private static final String PATH_ZPF = "D:\\ningda\\project-management\\pmapi\\src\\main\\java"; | 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"; | 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) { | public static void main(String[] args) { | ||||
//generate("Liuxinxin", "expert", PATH_LXX, "expert_gov_business_strip"); | //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 meetingId; | ||||
private Long meetingExpertId; | |||||
private Long expertId; | |||||
private Integer status; | private Integer status; | ||||
private Boolean attended; | private Boolean attended; | ||||
@@ -0,0 +1,61 @@ | |||||
package com.ningdatech.pmapi.meeting.entity.req; | |||||
import com.alibaba.fastjson.annotation.JSONField; | |||||
import com.baomidou.mybatisplus.annotation.FieldFill; | |||||
import com.baomidou.mybatisplus.annotation.TableField; | |||||
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") | @ApiModelProperty("会议ID") | ||||
private Long meetingId; | private Long meetingId; | ||||
@ApiModelProperty("会议专家ID") | |||||
private Long meetingExpertId; | |||||
@ApiModelProperty("会议开始时间") | @ApiModelProperty("会议开始时间") | ||||
@JSONField(format = "yyyy-MM-dd HH:mm") | @JSONField(format = "yyyy-MM-dd HH:mm") | ||||
private LocalDateTime startTime; | private LocalDateTime startTime; | ||||
@@ -70,4 +73,7 @@ public class MeetingByManagerVO { | |||||
@ApiModelProperty("联系方式") | @ApiModelProperty("联系方式") | ||||
private String contact; | 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 ExpertInviteHelper expertInviteHelper; | ||||
private final MeetingCallOrMsgHelper meetingCallOrMsgHelper; | private final MeetingCallOrMsgHelper meetingCallOrMsgHelper; | ||||
private final MeetingDataScopeHelper meetingDataScopeHelper; | private final MeetingDataScopeHelper meetingDataScopeHelper; | ||||
private final IMeetingExpertJudgeService expertJudgeService; | |||||
private static final String INVITED_RULE_CREATE = "INVITED_RULE_CREATE:"; | private static final String INVITED_RULE_CREATE = "INVITED_RULE_CREATE:"; | ||||
private static final String MEETING_CREATE_KEY = "MEETING_CREATE:"; | private static final String MEETING_CREATE_KEY = "MEETING_CREATE:"; | ||||
@@ -324,7 +325,11 @@ public class MeetingManage { | |||||
return PageVo.empty(); | return PageVo.empty(); | ||||
} | } | ||||
Map<Long, MeetingAndAttendStatusDTO> mapByMeetingId = new HashMap<>(16); | 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>() | LambdaQueryWrapper<Meeting> query = new LambdaQueryWrapper<Meeting>() | ||||
.orderByDesc(Meeting::getCreateOn) | .orderByDesc(Meeting::getCreateOn) | ||||
.in(Meeting::getId, mapByMeetingId.keySet()) | .in(Meeting::getId, mapByMeetingId.keySet()) | ||||
@@ -337,11 +342,14 @@ public class MeetingManage { | |||||
if (page.getTotal() == 0) { | if (page.getTotal() == 0) { | ||||
return PageVo.empty(); | return PageVo.empty(); | ||||
} | } | ||||
List<Long> existsMeIds = expertJudgeService.listExistsMeetingExpertIds(meetingExpertIds); | |||||
PageVo<MeetingByManagerVO> result = new PageVo<>(new ArrayList<>(), page.getTotal()); | PageVo<MeetingByManagerVO> result = new PageVo<>(new ArrayList<>(), page.getTotal()); | ||||
page.getRecords().forEach(meeting -> { | page.getRecords().forEach(meeting -> { | ||||
MeetingByManagerVO item = meetingManageHelper.buildByMeeting(meeting); | MeetingByManagerVO item = meetingManageHelper.buildByMeeting(meeting); | ||||
MeetingAndAttendStatusDTO info = mapByMeetingId.get(meeting.getId()); | MeetingAndAttendStatusDTO info = mapByMeetingId.get(meeting.getId()); | ||||
item.setMeetingExpertId(info.getMeetingExpertId()); | |||||
item.setExpertStatus(info.getStatus()); | item.setExpertStatus(info.getStatus()); | ||||
item.setHasJudge(existsMeIds.contains(info.getMeetingExpertId())); | |||||
result.getRecords().add(item); | result.getRecords().add(item); | ||||
}); | }); | ||||
return result; | 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" | <select id="selectByExpertIdAndStatus" | ||||
resultType="com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO"> | 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, | FROM (SELECT ROW_NUMBER() OVER ( PARTITION BY meeting_id ORDER BY update_on DESC ) rowNumber, ID, expert_id, | ||||
status, meeting_id | status, meeting_id | ||||
FROM meeting_expert | 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 { | |||||
} |