@@ -191,6 +191,11 @@ | |||
<artifactId>nd-basic</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.ningdatech</groupId> | |||
<artifactId>nd-yxt-starter</artifactId> | |||
<version>1.0.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>easyexcel-core</artifactId> | |||
</dependency> | |||
@@ -3,15 +3,10 @@ package com.ningdatech.pmapi.common.config; | |||
import com.alibaba.fastjson.serializer.SerializerFeature; | |||
import com.alibaba.fastjson.support.config.FastJsonConfig; | |||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.http.MediaType; | |||
import org.springframework.http.converter.HttpMessageConverter; | |||
import org.springframework.web.cors.CorsConfiguration; | |||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | |||
import org.springframework.web.filter.CorsFilter; | |||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | |||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||
import java.nio.charset.StandardCharsets; | |||
@@ -1,6 +1,5 @@ | |||
package com.ningdatech.pmapi.common.handler; | |||
import cn.hutool.json.JSONUtil; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import org.springframework.core.MethodParameter; | |||
import org.springframework.http.MediaType; | |||
@@ -24,7 +23,9 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; | |||
"com.ningdatech.pmapi.sys.controller", | |||
"com.ningdatech.pmapi.todocenter.controller", | |||
"com.ningdatech.pmapi.user.controller", | |||
"com.ningdatech.pmapi.expert.controller" | |||
"com.ningdatech.pmapi.meeting.controller", | |||
"com.ningdatech.pmapi.expert.controller", | |||
"com.ningdatech.pmapi.sms.controller" | |||
}) | |||
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | |||
@@ -44,9 +45,9 @@ public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | |||
// ConverterType是StringHttpMessageConverter这个类型转换, | |||
// 由于将结果封装成了自定义的ApiResponse类型,所以有ApiResponse转换成String报错 | |||
// 所以需要对String类型的返回值单独进行处理 | |||
if (o instanceof String) { | |||
return JSONUtil.toJsonStr(apiResponse); | |||
} | |||
// if (o instanceof String) { | |||
// return JSONUtil.toJsonStr(apiResponse); | |||
// } | |||
return ApiResponse.ofSuccess(o); | |||
// return o; | |||
} | |||
@@ -17,8 +17,8 @@ import java.time.LocalDateTime; | |||
* @author Liuxinxin | |||
* @since 2023-02-22 | |||
*/ | |||
@TableName("nd_expert_user_full_info") | |||
@Data | |||
@TableName("nd_expert_user_full_info") | |||
@ApiModel(value = "NdExpertUserFullInfo对象", description = "") | |||
public class ExpertUserFullInfo implements Serializable { | |||
@@ -1,5 +1,8 @@ | |||
package com.ningdatech.pmapi.expert.helper; | |||
import com.ningdatech.pmapi.user.entity.enumeration.RoleEnum; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
@@ -13,8 +16,8 @@ import org.springframework.stereotype.Component; | |||
public class PermissionCheckHelper { | |||
public boolean isSuperAdmin() { | |||
// TODO | |||
return false; | |||
UserInfoDetails details = LoginUserUtil.loginUserDetail(); | |||
return details.getUserRoleList().stream().anyMatch(w -> w.getCode().equals(RoleEnum.SUPER_ADMIN.name())); | |||
} | |||
} |
@@ -22,11 +22,16 @@ import com.ningdatech.pmapi.expert.service.ExpertInfoService; | |||
import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService; | |||
import com.ningdatech.pmapi.meta.constant.DictExpertInfoTypeEnum; | |||
import com.ningdatech.pmapi.meta.model.ExpertRegionInfo; | |||
import com.ningdatech.pmapi.user.constant.UserAvailableEnum; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import lombok.RequiredArgsConstructor; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.time.LocalDateTime; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Objects; | |||
@@ -47,6 +52,7 @@ public class ExpertManage { | |||
private final ExpertInfoCommonHelper expertInfoCommonHelper; | |||
private final FileService fileService; | |||
private final ExpertUserInfoAssembler expertUserInfoAssembler; | |||
private final IUserInfoService iUserInfoService; | |||
/** | |||
@@ -54,10 +60,12 @@ public class ExpertManage { | |||
* | |||
* @param request | |||
*/ | |||
@Transactional(rollbackFor = Exception.class) | |||
public void expertBasicInfoSubmit(ExpertUserBasicInfoSubmitRequest request) { | |||
// 用户id | |||
Long userId = LoginUserUtil.getUserId(); | |||
ExpertBasicInfo basicInfo = request.getBasicInfo(); | |||
Long userId = generateOrGetUserId(basicInfo); | |||
// 校验区域编码合法性 校验履职意向编码合法性 | |||
ExpertRegionInfo expertRegionInfo = basicInfo.getExpertRegionInfo(); | |||
expertManageHelper.expertRegionInfoCheck(expertRegionInfo); | |||
@@ -90,13 +98,13 @@ public class ExpertManage { | |||
List<DictionaryFieldInfo> recommendedWay = recommendInfo.getRecommendedWay(); | |||
// 推荐方式 | |||
List<FileBasicInfo> recommendProofFile = recommendInfo.getRecommendationProofFile(); | |||
expertRecommendProofSubmit(recommendedWay, recommendProofFile); | |||
expertRecommendProofSubmit(recommendedWay, recommendProofFile, userId); | |||
} | |||
public void expertRecommendProofSubmit(List<DictionaryFieldInfo> recommendedWay, List<FileBasicInfo> recommendProofFile) { | |||
@Transactional(rollbackFor = Exception.class) | |||
public void expertRecommendProofSubmit(List<DictionaryFieldInfo> recommendedWay, List<FileBasicInfo> recommendProofFile, Long expertUserId) { | |||
// 用户id | |||
Long expertUserId = LoginUserUtil.getUserId(); | |||
ExpertUserFullInfo expertUserFullInfo = iExpertUserFullInfoService.getByUserId(expertUserId); | |||
// 判断专家状态,是否可以进行证明材料提交 | |||
if (Objects.isNull(expertUserFullInfo) | |||
@@ -137,4 +145,26 @@ public class ExpertManage { | |||
List<AttachFileVo> attachFiles = fileService.getByIds(fileIdList); | |||
return expertUserInfoAssembler.buildExpertFullInfoVO(attachFiles, expertUserFullInfoAll); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public Long generateOrGetUserId(ExpertBasicInfo basicInfo) { | |||
String phoneNo = basicInfo.getPhoneNo(); | |||
UserInfo userInfo = iUserInfoService.getUserInfoByPhoneNo(phoneNo); | |||
if (Objects.isNull(userInfo)) { | |||
userInfo = UserInfo.builder() | |||
// .accountId(dingEmployeeInfo.getAccountId()) | |||
.username(basicInfo.getName()) | |||
.realName(basicInfo.getName()) | |||
// .employeeCode(dingEmployeeInfo.getEmployeeCode()) | |||
.available(UserAvailableEnum.DISABLE.name()) | |||
.mobile(phoneNo) | |||
.createBy(LoginUserUtil.getUserId()) | |||
.updateBy(LoginUserUtil.getUserId()) | |||
.createOn(LocalDateTime.now()) | |||
.updateOn(LocalDateTime.now()) | |||
.build(); | |||
iUserInfoService.save(userInfo); | |||
} | |||
return userInfo.getId(); | |||
} | |||
} |
@@ -79,6 +79,7 @@ public class ExpertReviewManage { | |||
review.setContent(JSONUtil.toJsonStr(req.getReviewTemplateOptions())); | |||
review.setProjectId(req.getProjectId()); | |||
review.setTemplateId(req.getTemplateId()); | |||
review.setMeetingId(req.getMeetingId()); | |||
review.setOtherAdvice(req.getOtherAdvice()); | |||
review.setAttachFileId(req.getAttachFileId()); | |||
review.setIsFinal(req.getIsFinal()); | |||
@@ -30,6 +30,9 @@ public class ExpertReview implements Serializable { | |||
@ApiModelProperty("项目ID") | |||
private Long projectId; | |||
@ApiModelProperty("会议ID") | |||
private Long meetingId; | |||
@ApiModelProperty("评审模版配置ID") | |||
private Long templateId; | |||
@@ -21,7 +21,9 @@ public enum ReviewTemplateTypeEnum { | |||
CONSTRUCTION_SCHEME_REVIEW("建设方案评审", 2), | |||
ACCEPTANCE_SCHEME_REVIEW("验收方案评审", 3); | |||
ACCEPTANCE_SCHEME_REVIEW("验收方案评审", 3), | |||
DEPT_JOIN_REVIEW("部门联审", 4); | |||
private final String value; | |||
@@ -28,6 +28,10 @@ public class ExpertReviewDetailReq { | |||
@NotNull(message = "项目ID不能为空") | |||
private Long projectId; | |||
@ApiModelProperty("会议ID") | |||
@NotNull(message = "会议ID不能为空") | |||
private Long meetingId; | |||
@Valid | |||
@ApiModelProperty("配置模版") | |||
@NotEmpty(message = "配置不能为空") | |||
@@ -0,0 +1,50 @@ | |||
package com.ningdatech.pmapi.irs.config; | |||
import lombok.Data; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @author liuxinxin | |||
* @date 2023/3/16 下午6:03 | |||
*/ | |||
@Component | |||
@Data | |||
public class IrsSealPlatformProperties { | |||
public static String projectId; | |||
public static String projectSecret; | |||
public static String accessKey; | |||
public static String secretKey; | |||
public static String apiUrl; | |||
@Value("${irs.seal-platform.project-id}") | |||
public void setProjectId(String projectId) { | |||
IrsSealPlatformProperties.projectId = projectId; | |||
} | |||
@Value("${irs.seal-platform.project-secret}") | |||
public void setProjectSecret(String projectSecret) { | |||
IrsSealPlatformProperties.projectSecret = projectSecret; | |||
} | |||
@Value("${irs.seal-platform.access-key}") | |||
public void setAccessKey(String accessKey) { | |||
IrsSealPlatformProperties.accessKey = accessKey; | |||
} | |||
@Value("${irs.seal-platform.secret-key}") | |||
public void setSecretKey(String secretKey) { | |||
IrsSealPlatformProperties.secretKey = secretKey; | |||
} | |||
@Value("${irs.seal-platform.api-url}") | |||
public void setApiUrl(String apiUrl) { | |||
IrsSealPlatformProperties.apiUrl = apiUrl; | |||
} | |||
} |
@@ -8,6 +8,7 @@ import com.ningdatech.pmapi.meeting.entity.dto.ReviewProjectDTO; | |||
import com.ningdatech.pmapi.meeting.entity.req.*; | |||
import com.ningdatech.pmapi.meeting.entity.vo.*; | |||
import com.ningdatech.pmapi.meeting.manage.MeetingManage; | |||
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO; | |||
import io.swagger.annotations.Api; | |||
import io.swagger.annotations.ApiOperation; | |||
import lombok.AllArgsConstructor; | |||
@@ -168,8 +169,14 @@ public class MeetingController { | |||
@GetMapping("/listReviewProject") | |||
@ApiOperation("评审会议列表") | |||
public PageVo<ReviewProjectDTO> listReviewProject(ReviewProjectListReq req){ | |||
public PageVo<ReviewProjectDTO> listReviewProject(ReviewProjectListReq req) { | |||
return meetingManage.pageReviewProject(req); | |||
} | |||
@GetMapping("/option/project") | |||
@ApiOperation("项目列表(创建会议添加项目)") | |||
public PageVo<ProjectLibListItemVO> projectList(MeetingOptionProjectReq req) { | |||
return meetingManage.optionProject(req); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
package com.ningdatech.pmapi.meeting.entity.enumeration; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
/** | |||
* <p> | |||
* MeetingReviewTypeEnum | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 16:32 2023/3/15 | |||
*/ | |||
@Getter | |||
@AllArgsConstructor | |||
public enum MeetingReviewTypeEnum { | |||
/** | |||
* 会议评审类型 | |||
*/ | |||
PRELIMINARY_SCHEME_REVIEW("初步方案评审", "1"), | |||
CONSTRUCTION_SCHEME_REVIEW("建设方案评审", "2"), | |||
ACCEPTANCE_SCHEME_REVIEW("验收方案评审", "3"), | |||
DEPT_JOIN_REVIEW("部门联审", "4"); | |||
private final String value; | |||
private final String code; | |||
public boolean eq(String code) { | |||
return this.getCode().equals(code); | |||
} | |||
public static MeetingReviewTypeEnum getByCode(String code) { | |||
return Arrays.stream(values()) | |||
.filter(w -> w.getCode().equals(code)) | |||
.findFirst() | |||
.orElseThrow(() -> new IllegalArgumentException("无效的会议评审类型编码")); | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
package com.ningdatech.pmapi.meeting.entity.req; | |||
import com.ningdatech.basic.model.PagePo; | |||
import lombok.Data; | |||
import lombok.EqualsAndHashCode; | |||
/** | |||
* <p> | |||
* MeetingOptionProjectReq | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:50 2023/3/16 | |||
*/ | |||
@Data | |||
@EqualsAndHashCode | |||
public class MeetingOptionProjectReq extends PagePo { | |||
private String meetingType; | |||
} |
@@ -61,4 +61,7 @@ public class MeetingByManagerVO { | |||
@ApiModelProperty("专家状态") | |||
private Integer expertStatus; | |||
@ApiModelProperty("创建时间") | |||
private LocalDateTime createOn; | |||
} |
@@ -118,6 +118,7 @@ public class MeetingManageHelper { | |||
.confirmedRoster(meeting.getConfirmedRoster()) | |||
.inviteStatus(meeting.getInviteStatus()) | |||
.status(meeting.getStatus()) | |||
.createOn(meeting.getCreateOn()) | |||
.build(); | |||
} | |||
@@ -77,6 +77,7 @@ public class ExpertInviteManage { | |||
.select(ExpertUserFullInfo::getUserId, | |||
ExpertUserFullInfo::getId, | |||
ExpertUserFullInfo::getCompany, | |||
ExpertUserFullInfo::getExpertName, | |||
ExpertUserFullInfo::getPhoneNo) | |||
.eq(ExpertUserFullInfo::getExpertAccountStatus, ExpertAccountStatusEnum.AVAILABLE.getKey()); | |||
} | |||
@@ -281,7 +282,7 @@ public class ExpertInviteManage { | |||
LambdaQueryWrapper<ExpertUserFullInfo> query = buildBaseExpertQuery(); | |||
query.notIn(!tmpAvoidCompany.isEmpty(), ExpertUserFullInfo::getCompany, tmpAvoidCompany); | |||
if (avoidCompany) { | |||
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" + | |||
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" + | |||
" and company_name in ({0})", CollUtils.joinByComma(avoidRule.getAvoidUnitIdList())); | |||
} | |||
// 处理专家层级 | |||
@@ -357,7 +358,7 @@ public class ExpertInviteManage { | |||
} | |||
LambdaQueryWrapper<ExpertUserFullInfo> query = buildBaseExpertQuery(); | |||
query.notIn(ExpertUserFullInfo::getCompany, avoidRule.getAvoidUnitIdList()); | |||
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" + | |||
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" + | |||
" and company_name in ({0})", CollUtils.joinByComma(avoidRule.getAvoidOrgIdList())); | |||
// 处理专家层级 | |||
@@ -25,6 +25,7 @@ import com.ningdatech.pmapi.meeting.entity.domain.*; | |||
import com.ningdatech.pmapi.meeting.entity.dto.*; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingReviewTypeEnum; | |||
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum; | |||
import com.ningdatech.pmapi.meeting.entity.req.*; | |||
import com.ningdatech.pmapi.meeting.entity.vo.*; | |||
@@ -35,7 +36,9 @@ import com.ningdatech.pmapi.meeting.service.*; | |||
import com.ningdatech.pmapi.meeting.task.ExpertInviteTask; | |||
import com.ningdatech.pmapi.meta.helper.DictionaryCache; | |||
import com.ningdatech.pmapi.meta.helper.TagCache; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||
@@ -702,4 +705,49 @@ public class MeetingManage { | |||
return PageVo.of(page.getRecords(), page.getTotal()); | |||
} | |||
public PageVo<ProjectLibListItemVO> optionProject(MeetingOptionProjectReq req) { | |||
String meetingType = req.getMeetingType(); | |||
LambdaQueryWrapper<Project> query = Wrappers.lambdaQuery(Project.class); | |||
switch (MeetingReviewTypeEnum.getByCode(meetingType)) { | |||
case PRELIMINARY_SCHEME_REVIEW: | |||
buildOptionProjectQuery(query, meetingType, ProjectStatusEnum.PRE_APPLYING); | |||
break; | |||
case CONSTRUCTION_SCHEME_REVIEW: | |||
buildOptionProjectQuery(query, meetingType, ProjectStatusEnum.SCHEME_UNDER_REVIEW); | |||
break; | |||
case ACCEPTANCE_SCHEME_REVIEW: | |||
query.eq(Project::getStatus, ProjectStatusEnum.FINAL_ACCEPTANCE_IS_UNDER_REVIEW); | |||
break; | |||
case DEPT_JOIN_REVIEW: | |||
query.eq(Project::getStatus, ProjectStatusEnum.DEPARTMENT_JOINT_REVIEW); | |||
break; | |||
default: | |||
return PageVo.empty(); | |||
} | |||
Page<Project> page = projectService.page(req.page(), query); | |||
PageVo<ProjectLibListItemVO> result = PageVo.of(null, page.getTotal()); | |||
if (result.getTotal() > 0) { | |||
List<ProjectLibListItemVO> projects = CollUtils.convert(page.getRecords(), | |||
w -> ProjectLibListItemVO | |||
.builder() | |||
.id(w.getId()) | |||
.projectName(w.getProjectName()) | |||
.declaredAmount(w.getDeclareAmount()) | |||
.projectType(w.getProjectType()) | |||
.projectYear(w.getProjectYear()) | |||
.buildOrg(w.getBuildOrgName()) | |||
.build()); | |||
result.setRecords(projects); | |||
} | |||
return result; | |||
} | |||
private void buildOptionProjectQuery(LambdaQueryWrapper<Project> query, String meetingType, ProjectStatusEnum status) { | |||
String sql = String.format("select 1 from meeting m inner join meeting_inner_project mip on" + | |||
" m.is_inner_project = true and m.id = mip.meeting_id and m.type = %s and m.status != 3", meetingType); | |||
query.eq(Project::getStatus, status.getCode()); | |||
query.and(q1 -> q1.notExists(sql)).or(q2 -> q2.exists(sql + " inner join nd_expert_review ner " + | |||
"on ner.meeting_id = m.id and ner.is_final = true and review_result in (2, 3)")); | |||
} | |||
} |
@@ -87,7 +87,8 @@ public class ExpertInviteTask { | |||
} | |||
private CacheHashKey getCacheKey(Long meetingId) { | |||
return new CacheHashKey(MEETING_ID_INVITE_RANDOM, meetingId, EXPIRE_TIME); | |||
String meetingIdStr = meetingId == null ? null : meetingId.toString(); | |||
return new CacheHashKey(MEETING_ID_INVITE_RANDOM, meetingIdStr, EXPIRE_TIME); | |||
} | |||
@PostConstruct | |||
@@ -1,20 +1,44 @@ | |||
package com.ningdatech.pmapi.organization.controller; | |||
import com.ningdatech.pmapi.organization.manage.GovBusinessStripManage; | |||
import com.ningdatech.pmapi.organization.model.vo.GovBusinessStripTreeVO; | |||
import io.swagger.annotations.Api; | |||
import io.swagger.annotations.ApiOperation; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.stereotype.Controller; | |||
import org.springframework.validation.annotation.Validated; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RequestParam; | |||
import org.springframework.web.bind.annotation.RestController; | |||
import org.springframework.stereotype.Controller; | |||
import java.util.List; | |||
/** | |||
* <p> | |||
* 前端控制器 | |||
* 前端控制器 | |||
* </p> | |||
* | |||
* @author Liuxinxin | |||
* @since 2023-03-08 | |||
*/ | |||
@Controller | |||
@RequestMapping("/pmapi.organization/gov-business-strip") | |||
@Slf4j | |||
@Validated | |||
@RestController | |||
@RequiredArgsConstructor | |||
@Api(value = "GovBusinessStripController", tags = "条线管理") | |||
@RequestMapping("/api/v1/gov-business-strip") | |||
public class GovBusinessStripController { | |||
private final GovBusinessStripManage govBusinessStripManage; | |||
@GetMapping("/get-child-list") | |||
@ApiOperation("获取条线标签的的树状结构") | |||
public List<GovBusinessStripTreeVO> getChildOrganizationList(@RequestParam(value = "parentCode", required = false) String parentCode) { | |||
return govBusinessStripManage.getChildOrganizationList(parentCode); | |||
} | |||
} |
@@ -5,7 +5,6 @@ import io.swagger.annotations.ApiModel; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.time.LocalDateTime; | |||
/** | |||
* <p> | |||
@@ -24,14 +23,6 @@ public class GovBusinessStrip implements Serializable { | |||
private Long id; | |||
private LocalDateTime createOn; | |||
private LocalDateTime updateOn; | |||
private Long createBy; | |||
private Long updateBy; | |||
/** | |||
* 条线code | |||
*/ | |||
@@ -41,4 +32,14 @@ public class GovBusinessStrip implements Serializable { | |||
* 条线名称 | |||
*/ | |||
private String businessStripName; | |||
/** | |||
* 父级条线code | |||
*/ | |||
private String parentCode; | |||
/** | |||
* 父级条线名称 | |||
*/ | |||
private String parentName; | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.ningdatech.pmapi.organization.manage; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.pmapi.organization.entity.GovBusinessStrip; | |||
import com.ningdatech.pmapi.organization.model.vo.GovBusinessStripTreeVO; | |||
import com.ningdatech.pmapi.organization.service.IGovBusinessStripService; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @author liuxinxin | |||
* @date 2023/3/14 下午4:48 | |||
*/ | |||
@Component | |||
@RequiredArgsConstructor | |||
public class GovBusinessStripManage { | |||
private final IGovBusinessStripService iGovBusinessStripService; | |||
public List<GovBusinessStripTreeVO> getChildOrganizationList(String parentCode) { | |||
if (Objects.isNull(parentCode)) { | |||
parentCode = "-1"; | |||
} | |||
List<GovBusinessStrip> govBusinessStripList = iGovBusinessStripService.list(Wrappers.lambdaQuery(GovBusinessStrip.class) | |||
.eq(GovBusinessStrip::getParentCode, parentCode)); | |||
return govBusinessStripList.stream().map(r -> { | |||
GovBusinessStripTreeVO govBusinessStripTreeVO = new GovBusinessStripTreeVO(); | |||
govBusinessStripTreeVO.setBusinessStripCode(r.getBusinessStripCode()); | |||
govBusinessStripTreeVO.setBusinessStripName(r.getBusinessStripName()); | |||
govBusinessStripTreeVO.setParentCode(r.getParentCode()); | |||
govBusinessStripTreeVO.setParentName(r.getParentName()); | |||
return govBusinessStripTreeVO; | |||
}).collect(Collectors.toList()); | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.ningdatech.pmapi.organization.model.vo; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
/** | |||
* @author Liuxinxin | |||
* @since 2023-03-08 | |||
*/ | |||
@Data | |||
@ApiModel(value = "条线树形 responseVO", description = "") | |||
public class GovBusinessStripTreeVO { | |||
private Long id; | |||
@ApiModelProperty("条线code") | |||
private String businessStripCode; | |||
@ApiModelProperty("条线名称") | |||
private String businessStripName; | |||
@ApiModelProperty("父级条线code") | |||
private String parentCode; | |||
@ApiModelProperty("父级条线名称") | |||
private String parentName; | |||
} |
@@ -0,0 +1,113 @@ | |||
package com.ningdatech.pmapi.projectdeclared.converter; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.model.entity.ProjectApplication; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialApplicationDTO; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import org.assertj.core.util.Lists; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @Classname ApplicationConverter | |||
* @Description | |||
* @Date 2023/3/13 17:38 | |||
* @Author PoffyZhang | |||
*/ | |||
public class ApplicationConverter { | |||
public static ProvincialProjectDTO convertProject(Project projectInfo,List<ProjectApplication> applications) { | |||
return ProvincialProjectDTO.builder() | |||
.regionCode(projectInfo.getAreaCode()) | |||
.regionName(projectInfo.getArea()) | |||
.projectName(projectInfo.getProjectName()) | |||
.projectId(String.valueOf(projectInfo.getId())) | |||
.projectType(projectInfo.getProjectType()) | |||
.totalMoney(projectInfo.getDeclareAmount()) | |||
.yearBudget(projectInfo.getAnnualPlanAmount()) | |||
.budgetFrom(projectInfo.getDeclareHaveAmount() + "," + | |||
projectInfo.getDeclareGovOwnFinanceAmount() + "," | |||
+ projectInfo.getDeclareGovSuperiorFinanceAmount()) | |||
.year(String.valueOf(projectInfo.getProjectYear())) | |||
.financialCode(projectInfo.getFinancialCode()) | |||
.developCode(projectInfo.getDevelopCode()) | |||
.beginTime(projectInfo.getBeginTime()) | |||
.endTime(projectInfo.getEndTime()) | |||
.buildBasis("立项依据") | |||
.buildBasisFile(projectInfo.getBuildBasis()) | |||
.projectSummary(projectInfo.getProjectIntroduction()) | |||
.responsibleMan(projectInfo.getResponsibleMan()) | |||
.responsibleManPhone(projectInfo.getResponsibleManMobile()) | |||
.contactName(projectInfo.getContactName()) | |||
.contactPhone(projectInfo.getContactPhone()) | |||
.buildUnit(projectInfo.getBuildOrgName()) | |||
.buildUnitCode(projectInfo.getBuildOrgCode()) | |||
.superUnit(projectInfo.getSuperOrg()) | |||
.superUnitCode(projectInfo.getSuperOrgCode()) | |||
.projectApplyFile(projectInfo.getProjectPdf()) | |||
.projectEstimateFile(projectInfo.getCalculationTotalInvestmentFile()) | |||
.unitThreePlan(projectInfo.getMainResponsibilitiesApplicantFile()) | |||
.otherFile(projectInfo.getPreliminaryPlanFile()) | |||
.projectRemark(projectInfo.getProjectRemarks()) | |||
.includeApplication(projectInfo.getIncludeApplication()) | |||
.applicationInfo(convertApplications(applications)) | |||
.build(); | |||
} | |||
//放入项目 app | |||
private static List<ProvincialApplicationDTO> convertApplications(List<ProjectApplication> applications) { | |||
if(CollUtil.isEmpty(applications)){ | |||
Collections.emptyList(); | |||
} | |||
return applications.stream().map(ApplicationConverter::convertApp).collect(Collectors.toList()); | |||
} | |||
private static ProvincialApplicationDTO convertApp(ProjectApplication projectApplication) { | |||
return ProvincialApplicationDTO.builder() | |||
.clouds(convertCloud(projectApplication)) | |||
.isFirst(projectApplication.getIsFirst()) | |||
.applicationName(projectApplication.getApplicationName()) | |||
.applicationCode(projectApplication.getRelatedExistsApplicationCode()) | |||
.relatedExistsApplication(projectApplication.getRelatedExistsApplication()) | |||
.applicationType(2) | |||
.buildLevel(projectApplication.getBuildLevel()) | |||
.isUniteBuild(projectApplication.getIsUniteBuild()) | |||
.unionBuildKind(projectApplication.getUnionBuildKind()) | |||
.applicationSummary(projectApplication.getApplicationSummary()) | |||
.applicationRemark(projectApplication.getApplicationRemark()) | |||
.applicationEstimateFile(projectApplication.getApplicationEstimateFile()) | |||
.isFiveDomain(projectApplication.getIsDigitalModification()) | |||
.fiveDomain(projectApplication.getDigitalModification()) | |||
.bizDomain(projectApplication.getBizDomain()) | |||
.isBizCooperate(projectApplication.getIsBizCooperate()) | |||
.userRange(projectApplication.getUsesRangeRemark()) | |||
.useGovCloud(projectApplication.getUseGovCloud()) | |||
.nationalITSpec(projectApplication.getNationalItSpec()) | |||
.netEnv(String.valueOf(projectApplication.getNetEnv())) | |||
.secrecyGrade(projectApplication.getSecrecyGrade()) | |||
.passwordGrade(projectApplication.getPasswordGrade()) | |||
.accountAppName(projectApplication.getAccountAppName()) | |||
.brainAccountAppName(projectApplication.getDomainBrainAccount()) | |||
.useCommonData(projectApplication.getUseCommonData()) | |||
.dataName(projectApplication.getDataName()) | |||
.commonComponents(projectApplication.getCommonComponents()) | |||
.useCommonComponent(projectApplication.getUseCommonComponent()) | |||
.isProduceCommonComponent(projectApplication.getProduceCommonComponent()) | |||
.produceCommonComponent(projectApplication.getProduceCommonComponents()) | |||
.publishSide(projectApplication.getPublishSide()) | |||
.build(); | |||
} | |||
private static List<ProvincialApplicationDTO.Cloud> convertCloud(ProjectApplication projectApplication) { | |||
return Lists.newArrayList(ProvincialApplicationDTO.Cloud.builder() | |||
.cloudType(projectApplication.getCloudsType()) | |||
.cloudNums(projectApplication.getCloudsNumber()) | |||
.cloudBasicSpec(projectApplication.getCloudsFoundationSpecifications()) | |||
.cloudUseDescription(projectApplication.getCloudsDescription()) | |||
.build()); | |||
} | |||
} |
@@ -102,7 +102,7 @@ public class ConstructionPlanManage { | |||
VUtils.isTrue(Objects.isNull(projectDto.getId())).throwMessage("提交失败 缺少项目ID!"); | |||
Project projectInfo = projectService.getById(projectDto.getId()); | |||
VUtils.isTrue(Objects.isNull(projectInfo)).throwMessage("提交失败 此项目不存在!"); | |||
VUtils.isTrue(StringUtils.isBlank(projectInfo.getConstructionPlanFile())).throwMessage("提交失败 请提交建设方案!"); | |||
VUtils.isTrue(StringUtils.isBlank(projectDto.getConstructionPlanFile())).throwMessage("提交失败 请提交建设方案!"); | |||
String regionCode = projectInfo.getAreaCode(); | |||
@@ -133,7 +133,7 @@ public class ConstructionPlanManage { | |||
); | |||
params.setFormData(dto.getFormData()); | |||
// 获取发起单位、发起单位主管单位、发起单位上级条线主管单位信息 | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId,projectInfo); | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.buildOrgModelMap(userId,projectInfo); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("建设方案项目申报成功 【{}】", instanceId); | |||
@@ -53,6 +53,8 @@ import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.vo.ProcessStartParamsVo; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
import com.wflow.workflow.service.ProcessModelService; | |||
import lombok.AllArgsConstructor; | |||
import lombok.NoArgsConstructor; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.StringUtils; | |||
@@ -64,6 +66,7 @@ import javax.servlet.http.HttpServletResponse; | |||
import java.io.IOException; | |||
import java.time.LocalDateTime; | |||
import java.util.*; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.stream.Collectors; | |||
/** | |||
@@ -107,8 +110,7 @@ public class DeclaredProjectManage { | |||
public String startTheProcess(DefaultDeclaredDTO dto) { | |||
UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); | |||
Long userId = userInfoDetails.getUserId(); | |||
VUtils.isTrue(Objects.isNull(userInfoDetails) ||Objects.isNull(userInfoDetails.getUserId())) | |||
.throwMessage("获取登录用户失败!"); | |||
VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!"); | |||
ProjectDTO projectInfo = dto.getProjectInfo(); | |||
projectInfo.setAreaCode(userInfoDetails.getRegionCode()); | |||
@@ -116,6 +118,11 @@ public class DeclaredProjectManage { | |||
projectInfo.setBuildOrgCode(userInfoDetails.getOrganizationCode()); | |||
projectInfo.setBuildOrgName(userInfoDetails.getOrganizationName()); | |||
//项目名称去重 | |||
defaultDeclaredProjectManage.checkDuplication(projectInfo); | |||
//判断申报金额 是否等于总的 判断年度支付金额 是否等于总金额 | |||
defaultDeclaredProjectManage.checkAmount(projectInfo); | |||
//如果主管单位没有 那么主管单位就是自己 | |||
if(CommonEnum.NO.getCode().equals(projectInfo.getIsSuperOrg())){ | |||
projectInfo.setSuperOrgCode(userInfoDetails.getOrganizationCode()); | |||
@@ -147,9 +154,6 @@ public class DeclaredProjectManage { | |||
throw new BusinessException(String.format("此 【%s】区域找不到单位流程配置", regionCode)); | |||
} | |||
//项目名称去重 | |||
defaultDeclaredProjectManage.checkDuplication(projectInfo); | |||
ProcessStartParamsVo params = new ProcessStartParamsVo(); | |||
params.setUser(defaultDeclaredProjectManage.buildUser(userId)); | |||
params.setProcessUsers(Collections.emptyMap()); | |||
@@ -165,7 +169,7 @@ public class DeclaredProjectManage { | |||
// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息 | |||
Project project = new Project(); | |||
BeanUtils.copyProperties(projectInfo,project); | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId,project); | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.buildOrgModelMap(userId,project); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("申报项目成功 【{}】", instanceId); | |||
@@ -201,6 +205,11 @@ public class DeclaredProjectManage { | |||
Project projectInfo = projectService.getById(projectDto.getId()); | |||
VUtils.isTrue(Objects.isNull(projectInfo)).throwMessage("提交失败 此项目不存在!"); | |||
//项目名称去重 | |||
defaultDeclaredProjectManage.checkDuplication(projectDto); | |||
//判断申报金额 是否等于总的 判断年度支付金额 是否等于总金额 | |||
defaultDeclaredProjectManage.checkAmount(projectDto); | |||
String regionCode = projectInfo.getAreaCode(); | |||
WflowModels model = processModelService.getOne(Wrappers.lambdaQuery(WflowModels.class) | |||
.eq(WflowModels::getRegionCode, regionCode) | |||
@@ -231,7 +240,7 @@ public class DeclaredProjectManage { | |||
// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息 | |||
Project project = new Project(); | |||
BeanUtils.copyProperties(projectInfo,project); | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId,project); | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.buildOrgModelMap(userId,project); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("重新申报项目成功 【{}】", instanceId); | |||
@@ -375,19 +384,15 @@ public class DeclaredProjectManage { | |||
} | |||
public void exportList(HttpServletResponse response, ProjectListReq param) { | |||
Long userId = LoginUserUtil.getUserId(); | |||
UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); | |||
Long userId = userInfoDetails.getUserId(); | |||
VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!"); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
//放入用户的单位 | |||
param.setBuildOrgCode(userFullInfo.getOrganizationCode()); | |||
param.setPageNumber(CommonConst.EXPORT_PAGE_NUMBER); | |||
param.setPageSize(CommonConst.EXPORT_PAGE_SIZE); | |||
param.setBuildOrgCode(userInfoDetails.getOrganizationCode()); | |||
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param); | |||
Page<Project> page = projectService.page(param.page(), query); | |||
List<Project> records = page.getRecords(); | |||
List<Project> records = projectService.list(query); | |||
AtomicInteger serialNumber = new AtomicInteger(0); | |||
List<DeclaredProjectExportDTO> collect = records.stream().map(r -> { | |||
DeclaredProjectExportDTO exportDTO = new DeclaredProjectExportDTO(); | |||
BeanUtils.copyProperties(r, exportDTO); | |||
@@ -395,11 +400,9 @@ public class DeclaredProjectManage { | |||
exportDTO.setStatusName(ProjectStatusEnum.getDesc(r.getStatus())); | |||
String createOnStr = NdDateUtils.format(r.getCreateOn(), "yyyy-MM-dd HH:mm"); | |||
exportDTO.setCreateOn(createOnStr); | |||
exportDTO.setSerialNumber(serialNumber.incrementAndGet()); | |||
return exportDTO; | |||
}).collect(Collectors.toList()); | |||
for (int i = 0; i < collect.size(); i++) { | |||
collect.get(i).setSerialNumber(i + 1); | |||
} | |||
String fileName = "项目申报列表"; | |||
ExcelDownUtil.setFileName(fileName,response); | |||
//数据导出处理函数 | |||
@@ -34,6 +34,7 @@ import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.BeanUtils; | |||
import org.springframework.stereotype.Component; | |||
import java.math.BigDecimal; | |||
import java.time.LocalDateTime; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
@@ -73,6 +74,30 @@ public class DefaultDeclaredProjectManage { | |||
.throwMessage(String.format("修改失败 此项目名 【%s】 已存在!",project.getProjectName())); | |||
} | |||
public void checkAmount(ProjectDTO projectInfo) { | |||
BigDecimal declareAmount = projectInfo.getDeclareAmount(); | |||
BigDecimal govSuperFinanceAmount = projectInfo.getDeclareGovSuperiorFinanceAmount(); | |||
BigDecimal govOwnFinanceAmount = projectInfo.getDeclareGovOwnFinanceAmount(); | |||
BigDecimal bankLendingAmount = projectInfo.getDeclareBankLendingAmount(); | |||
BigDecimal haveAmount = projectInfo.getDeclareHaveAmount(); | |||
BigDecimal otherAmount = projectInfo.getDeclareOtherAmount(); | |||
BigDecimal totalAmount = govSuperFinanceAmount | |||
.add(govOwnFinanceAmount).add(bankLendingAmount).add(haveAmount).add(otherAmount); | |||
VUtils.isTrue(declareAmount.compareTo(totalAmount) != 0) | |||
.throwMessage(String.format("申报失败! 申报总金额【{}】 不等于其它申报金额 【{}】",declareAmount,totalAmount)); | |||
BigDecimal annualPlanAmount = projectInfo.getAnnualPlanAmount(); | |||
BigDecimal annualGovSuperAmount = projectInfo.getAnnualPlanGovSuperiorFinanceAmount(); | |||
BigDecimal annualOwnSuperAmount = projectInfo.getAnnualPlanGovOwnFinanceAmount(); | |||
BigDecimal annualBankLendingAmount = projectInfo.getAnnualPlanBankLendingAmount(); | |||
BigDecimal annualHaveAmount = projectInfo.getAnnualPlanHaveAmount(); | |||
BigDecimal anualOtherAmount = projectInfo.getAnnualPlanOtherAmount(); | |||
BigDecimal totalAnnual = annualGovSuperAmount | |||
.add(annualOwnSuperAmount).add(annualBankLendingAmount).add(annualHaveAmount).add(anualOtherAmount); | |||
VUtils.isTrue(annualPlanAmount.compareTo(totalAnnual) != 0) | |||
.throwMessage(String.format("申报失败! 年度支付总金额【{}】 不等于其它年度支付金额 【{}】",annualPlanAmount,totalAnnual)); | |||
} | |||
public ProcessInstanceUserDto buildUser(Long userId){ | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
@@ -87,7 +112,7 @@ public class DefaultDeclaredProjectManage { | |||
.build(); | |||
} | |||
public Map<String, OrgInfoDTO> getOrgModelInfo(Long userId,Project project) { | |||
public Map<String, OrgInfoDTO> buildOrgModelMap(Long userId,Project project) { | |||
Map<String, OrgInfoDTO> orgMap = new HashMap<>(); | |||
// 查出所有的单位流程配置 | |||
@@ -168,7 +193,7 @@ public class DefaultDeclaredProjectManage { | |||
} | |||
// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息 | |||
Map<String, OrgInfoDTO> orgModelMap = getOrgModelInfo(userId,projectInfo); | |||
Map<String, OrgInfoDTO> orgModelMap = buildOrgModelMap(userId,projectInfo); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("提交预审项目成功 【{}】", instanceId); | |||
@@ -43,6 +43,7 @@ import java.time.LocalDateTime; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.function.Function; | |||
import java.util.stream.Collectors; | |||
@@ -163,13 +164,9 @@ public class ProjectAdjustmentManage { | |||
req.setBuildOrgCode(userFullInfo.getOrganizationCode()); | |||
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(req); | |||
Page<Project> page = projectService.page(req.page(), query); | |||
req.setPageNumber(CommonConst.EXPORT_PAGE_NUMBER); | |||
req.setPageSize(CommonConst.EXPORT_PAGE_SIZE); | |||
List<Project> records = page.getRecords(); | |||
List<Project> records = projectService.list(query); | |||
AtomicInteger serialNumber = new AtomicInteger(0); | |||
List<ProjectAdjustmentExportDTO> collect = records.stream().map(r -> { | |||
ProjectAdjustmentExportDTO exportDTO = new ProjectAdjustmentExportDTO(); | |||
BeanUtils.copyProperties(r, exportDTO); | |||
@@ -177,11 +174,9 @@ public class ProjectAdjustmentManage { | |||
exportDTO.setStatusName(ProjectStatusEnum.getDesc(r.getStatus())); | |||
String createOnStr = NdDateUtils.format(r.getCreateOn(), "yyyy-MM-dd HH:mm"); | |||
exportDTO.setCreateOn(createOnStr); | |||
exportDTO.setSerialNumber(serialNumber.incrementAndGet()); | |||
return exportDTO; | |||
}).collect(Collectors.toList()); | |||
for (int i = 0; i < collect.size(); i++) { | |||
collect.get(i).setSerialNumber(i + 1); | |||
} | |||
String fileName = "项目内容调整列表"; | |||
ExcelDownUtil.setFileName(fileName,response); | |||
//数据导出处理函数 | |||
@@ -103,7 +103,7 @@ public class ReviewByDeptJointManage { | |||
params.setFormData(formData); | |||
// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息 | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId,project); | |||
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.buildOrgModelMap(userId,project); | |||
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap); | |||
log.info("部门联审申报成功 【{}】", instanceId); | |||
@@ -1,18 +1,30 @@ | |||
package com.ningdatech.pmapi.projectdeclared.manage; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils; | |||
import com.ningdatech.pmapi.projectdeclared.converter.ApplicationConverter; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
import com.ningdatech.pmapi.projectlib.model.dto.ProjectDTO; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.model.entity.ProjectApplication; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectApplicationService; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialApplicationDTO; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @Classname ReviewByProvincialDeptManage | |||
@@ -31,6 +43,10 @@ public class ReviewByProvincialDeptManage { | |||
private final DefaultDeclaredProjectManage defaultProjectManage; | |||
private final IJoinReviewProvincialBureauService joinReviewProvincialBureauService; | |||
private final IProjectApplicationService applicationService; | |||
/** | |||
* 省级部门联审 | |||
* @param project | |||
@@ -47,17 +63,21 @@ public class ReviewByProvincialDeptManage { | |||
VUtils.isTrue(!ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS.getCode().equals(projectInfo.getStatus()) || | |||
!ProjectStatusEnum.NOT_APPROVED.getCode().equals(projectInfo.getStage())) | |||
.throwMessage("提交失败 该项目不是 省级部门联审状态状态或者未立项阶段"); | |||
// TODO 对接省级联审的接口 | |||
Boolean sucessProvince = Boolean.TRUE; | |||
if(sucessProvince){ | |||
//测试先成功 | |||
stateMachineUtils.pass(project); | |||
projectService.updateById(project); | |||
//直接去预审 | |||
if(StringUtils.isNotBlank(defaultProjectManage | |||
.directStartProcess(project,project.getPreStartUserId()))){ | |||
return Boolean.TRUE; | |||
} | |||
// 对接省级联审的接口 | |||
List<ProjectApplication> applications = applicationService.list(Wrappers.lambdaQuery(ProjectApplication.class) | |||
.eq(ProjectApplication::getProjectId, projectInfo.getId())); | |||
if(joinReviewProvincialBureauService.pushImportProject( | |||
ApplicationConverter.convertProject(projectInfo,applications))){ | |||
return Boolean.TRUE; | |||
// //测试先成功 | |||
// stateMachineUtils.pass(project); | |||
// projectService.updateById(project); | |||
// //直接去预审 | |||
// if(StringUtils.isNotBlank(defaultProjectManage | |||
// .directStartProcess(project,project.getPreStartUserId()))){ | |||
// return Boolean.TRUE; | |||
// } | |||
} | |||
return Boolean.FALSE; | |||
@@ -67,7 +67,7 @@ public class ProjectApplication implements Serializable { | |||
@ApiModelProperty("是否数改系统 0:否 1:是") | |||
private Integer isDigitalModification; | |||
@ApiModelProperty("数改系统") | |||
@ApiModelProperty("数改系统 1: '党政机关整体智治',2: '数字政府',3: '数字经济',4: '数字社会',7: '数字文化',5: '数字法治',6: '一体化智能化公共数据平台', 8: '基层智治' 多个用英文,分隔") | |||
private String digitalModification; | |||
@ApiModelProperty("业务领域") | |||
@@ -4,7 +4,9 @@ import com.fasterxml.jackson.annotation.JsonFormat; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectTypeEnum; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.experimental.Tolerate; | |||
import java.math.BigDecimal; | |||
import java.time.LocalDateTime; | |||
@@ -20,9 +22,14 @@ import java.util.Optional; | |||
* @since 15:13 2023/2/1 | |||
*/ | |||
@Data | |||
@Builder | |||
@ApiModel("项目库列表视图") | |||
public class ProjectLibListItemVO { | |||
@Tolerate | |||
public ProjectLibListItemVO() { | |||
} | |||
@ApiModelProperty("项目ID") | |||
private Long id; | |||
@@ -67,8 +74,8 @@ public class ProjectLibListItemVO { | |||
private String projectTypeName; | |||
public String getProjectTypeName(){ | |||
if(Objects.nonNull(this.projectType)){ | |||
public String getProjectTypeName() { | |||
if (Objects.nonNull(this.projectType)) { | |||
Optional.ofNullable(ProjectTypeEnum.getDesc(this.projectType)) | |||
.ifPresent(desc -> this.projectTypeName = desc); | |||
} | |||
@@ -1,5 +1,8 @@ | |||
package com.ningdatech.pmapi.provincial.controller; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import com.ningdatech.pmapi.projectdeclared.manage.ReviewByProvincialDeptManage; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import io.swagger.annotations.Api; | |||
@@ -24,15 +27,20 @@ public class TestController { | |||
@Autowired | |||
private IJoinReviewProvincialBureauService joinReviewProvincialBureauService; | |||
@PostMapping("/push") | |||
@Autowired | |||
private ReviewByProvincialDeptManage provincialDeptManage; | |||
@GetMapping("/push") | |||
@ApiOperation("测试推送") | |||
private String push(@Valid @RequestBody ProvincialProjectDTO project){ | |||
return joinReviewProvincialBureauService.pushImportProject(project); | |||
private Boolean push(@Valid @RequestParam Long projectId){ | |||
Project project = new Project(); | |||
project.setId(projectId); | |||
return provincialDeptManage.startTheProcess(project); | |||
} | |||
@GetMapping("/detail") | |||
@ApiOperation("测试推送") | |||
private String detail(@RequestParam String projectId){ | |||
@ApiOperation("测试获取详情") | |||
private ApiResponse detail(@RequestParam String projectId){ | |||
return joinReviewProvincialBureauService.processInfo(projectId); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package com.ningdatech.pmapi.provincial.enumeration; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
import lombok.Getter; | |||
import lombok.NoArgsConstructor; | |||
/** | |||
* @Classname ProjectProvincialAuditStatusEnum | |||
* @Description | |||
* @Date 2023/3/16 11:04 | |||
* @Author PoffyZhang | |||
*/ | |||
@Getter | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public enum ProjectProvincialAuditStatusEnum { | |||
/** | |||
* 省级联审的状态 | |||
*/ | |||
AUDITING(1,"审核中"), | |||
SUCCESS(2,"审核通过"), | |||
FAIL(3,"审核不通过"); | |||
private Integer code; | |||
private String desc; | |||
} |
@@ -1,11 +1,13 @@ | |||
package com.ningdatech.pmapi.provincial.model.dto; | |||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
@@ -17,7 +19,9 @@ import java.util.List; | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProvincialApplicationDTO", description = "") | |||
public class ProvincialApplicationDTO { | |||
public class ProvincialApplicationDTO implements Serializable { | |||
//云 信息 | |||
private List<Cloud> clouds; | |||
//是否初次建设 1是 2不是 | |||
@@ -85,7 +89,9 @@ public class ProvincialApplicationDTO { | |||
//发布端 '浙里办','浙政钉','数字化改革门户','支付宝','微信','网页','PC客户端','APP端' | |||
private String publishSide; | |||
public static class Cloud { | |||
@Builder | |||
@JsonIgnoreProperties(value = { "handler"}) | |||
public static class Cloud implements Serializable { | |||
//云资源台数 11 | |||
private Integer cloudNums; | |||
//云资源类型 云服务器(ECS) | |||
@@ -7,6 +7,7 @@ import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.math.BigDecimal; | |||
import java.util.List; | |||
@@ -21,7 +22,7 @@ import java.util.List; | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@ApiModel(value = "ProvincialProjectDTO", description = "") | |||
public class ProvincialProjectDTO { | |||
public class ProvincialProjectDTO implements Serializable { | |||
@ApiModelProperty("区域code") | |||
private String regionCode; | |||
@@ -114,10 +115,10 @@ public class ProvincialProjectDTO { | |||
private String projectRemark; | |||
@ApiModelProperty("是否有效 1有效 2无效 3撤回") | |||
private String isEffective; | |||
private Integer isEffective; | |||
@ApiModelProperty("是否包含应用 1包含") | |||
private String includeApplication; | |||
private Integer includeApplication; | |||
@ApiModelProperty("app信息") | |||
private List<ProvincialApplicationDTO> applicationInfo; | |||
@@ -0,0 +1,36 @@ | |||
package com.ningdatech.pmapi.provincial.model.res; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
/** | |||
* @Classname ProcessCommentDTO | |||
* @Description | |||
* @Date 2023/3/2 15:25 | |||
* @Author PoffyZhang | |||
*/ | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProcessCommentRes", description = "省局返回流程审核详情") | |||
public class ProcessCommentRes { | |||
@ApiModelProperty("任务id") | |||
private String taskId; | |||
@ApiModelProperty("comment") | |||
private String comment; | |||
@ApiModelProperty("流程步骤") | |||
private String stepName; | |||
@ApiModelProperty("审批状态") | |||
private String status; | |||
@ApiModelProperty("审批人") | |||
private String label; | |||
@ApiModelProperty("时间") | |||
private String approverTime; | |||
} |
@@ -0,0 +1,102 @@ | |||
package com.ningdatech.pmapi.provincial.model.res; | |||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* @Classname ProvincialApplicationDTO | |||
* @Description | |||
* @Date 2023/3/2 10:06 | |||
* @Author PoffyZhang | |||
*/ | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProvincialApplicationRes", description = "") | |||
public class ProvincialApplicationRes implements Serializable { | |||
//云 信息 | |||
private List<Cloud> clouds; | |||
//是否初次建设 1是 2不是 | |||
private Integer isFirst; | |||
//应用名称 | |||
private String applicationName; | |||
//关联 关联的IRS应用code | |||
private String applicationCode; | |||
//关联的IRS应用name | |||
private String relatedExistsApplication; | |||
//1: '办公类系统',2: '业务应用类系统',3: '门户网站',4: '宣传微博/微信公众号',5: '硬件类系统',6: '工具类系统',99: '其他' | |||
private Integer applicationType; | |||
//建设层级 1:国家 2:省级 3:市级 4:县(市、区) | |||
private Integer buildLevel; | |||
//是否统建 0:否 1:是 | |||
private Integer isUniteBuild; | |||
//统建类型 1:全省统建 2:全市统建 | |||
private Integer unionBuildKind; | |||
//应用简介 | |||
private String applicationSummary; | |||
//应用备注 | |||
private String applicationRemark; | |||
//应用总投资测算明细 | |||
private String applicationEstimateFile; | |||
//是否数改系统 0:否 1:是 | |||
private Integer isFiveDomain; | |||
//1: '党政机关整体智治',2: '数字政府',3: '数字经济',4: '数字社会',7: '数字文化',5: '数字法治',6: '一体化智能化公共数据平台', 8: '基层智治' 多个用英文,分隔 | |||
private String fiveDomain; | |||
//业务领域 | |||
private String bizDomain; | |||
//否涉及业务协同 0:否 1:是 | |||
private Integer isBizCooperate; | |||
//协同单位111111 | |||
private String cooperativeUnit; | |||
//用户范围 0: '机关事业单位人员','0-1': '跨部门跨系统','0-2': '系统内地方各级','0-3': '本部门本级','0-4': '处室内部','0-6': '主管处室内部','0-5': '其他',1: '企业', 2: '社会公众',3: '其他' 多个用英文,分隔 | |||
private String userRange; | |||
//是否使用政务云资源 1使用 | |||
private Integer useGovCloud; | |||
//是否符合国家信息技术应用创新相关规范 0:否 1:是 | |||
private Integer nationalITSpec; | |||
//网络环境 1:政务内网 2:政务外网 3:互联网 4:业务专网 5:单机 | |||
private String netEnv; | |||
//等保级别 1:一级 2:二级 3:三级 4:四级 5:五级 | |||
private Integer secrecyGrade; | |||
//密码测评级别 1:一级 2:二级 3:三级 4:四级 5:五级 | |||
private Integer passwordGrade; | |||
//是否是S2 0:否 1:是 | |||
private Integer isS2; | |||
//一本账应用名称 | |||
private String accountAppName; | |||
//领域”大脑”一本帐名称 | |||
private String brainAccountAppName; | |||
//是否使用公共数据 | |||
private Integer useCommonData; | |||
//使用的公共数据名称 | |||
private String dataName; | |||
//使用公共组件的名称 | |||
private String commonComponents; | |||
//是否使用公共组件 | |||
private Integer useCommonComponent; | |||
//是否产生公共组件 | |||
private Integer isProduceCommonComponent; | |||
//产生的组件名称 | |||
private String produceCommonComponent; | |||
//发布端 '浙里办','浙政钉','数字化改革门户','支付宝','微信','网页','PC客户端','APP端' | |||
private String publishSide; | |||
@Builder | |||
@JsonIgnoreProperties(value = { "handler"}) | |||
public static class Cloud implements Serializable { | |||
//云资源台数 11 | |||
private Integer cloudNums; | |||
//云资源类型 云服务器(ECS) | |||
private String cloudType; | |||
//云资源规格 1核8G | |||
private String cloudBasicSpec; | |||
//云资源描述 | |||
private String cloudUseDescription; | |||
} | |||
} |
@@ -0,0 +1,132 @@ | |||
package com.ningdatech.pmapi.provincial.model.res; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialApplicationDTO; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.math.BigDecimal; | |||
import java.util.List; | |||
/** | |||
* @Classname ProvincialProjectDTO | |||
* @Description | |||
* @Date 2023/3/2 10:06 | |||
* @Author PoffyZhang | |||
*/ | |||
@Data | |||
@Builder | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@ApiModel(value = "ProvincialProjectDTO", description = "") | |||
public class ProvincialProjectRes implements Serializable { | |||
@ApiModelProperty("项目审核结果 1审核中 2审核通过 3审核不通过") | |||
private Integer projectStatus; | |||
@ApiModelProperty("区域code") | |||
private String regionCode; | |||
@ApiModelProperty("区域名称") | |||
private String regionName; | |||
@ApiModelProperty("重大项目名称") | |||
private String projectName; | |||
@ApiModelProperty("重大项目code 21位") | |||
private String projectId; | |||
@ApiModelProperty("项目类型 1新建 2续建") | |||
private Integer projectType; | |||
@ApiModelProperty("项目总投资(万元)") | |||
private BigDecimal totalMoney; | |||
@ApiModelProperty("项目年度预算(万元)") | |||
private BigDecimal yearBudget; | |||
@ApiModelProperty("自有资金,政府投资-本级财政资金,政府投资-上级补助资金") | |||
private String budgetFrom; | |||
@ApiModelProperty("预算年度 2023") | |||
private String year; | |||
@ApiModelProperty("财政code 32") | |||
private String financialCode; | |||
@ApiModelProperty("发改code 23") | |||
private String developCode; | |||
@ApiModelProperty("开始时间 比如2022-11-18") | |||
private String beginTime; | |||
@ApiModelProperty("结束时间 比如2022-12-13") | |||
private String endTime; | |||
@ApiModelProperty("立项依据1111") | |||
private String buildBasis; | |||
@ApiModelProperty("立项依据材料 [{\"fileId\":\"\"}]") | |||
private String buildBasisFile; | |||
@ApiModelProperty("项目概述") | |||
private String projectSummary; | |||
@ApiModelProperty("负责人") | |||
private String responsibleMan; | |||
@ApiModelProperty("联系人联系方式") | |||
private String responsibleManPhone; | |||
@ApiModelProperty("联系人") | |||
private String contactName; | |||
@ApiModelProperty("联系人联系方式") | |||
private String contactPhone; | |||
@ApiModelProperty("建设单位 比如财政局") | |||
private String buildUnit; | |||
@ApiModelProperty("建设单位浙政钉code") | |||
private String buildUnitCode; | |||
@ApiModelProperty("主管单位") | |||
private String superUnit; | |||
@ApiModelProperty("主管单位浙政钉code") | |||
private String superUnitCode; | |||
@ApiModelProperty("可研报告文件") | |||
private String researchReport; | |||
@ApiModelProperty("项目申报书") | |||
private String projectApplyFile; | |||
@ApiModelProperty("项目总投资测算明细") | |||
private String projectEstimateFile; | |||
@ApiModelProperty("申报单位主要职责") | |||
private String unitThreePlan; | |||
@ApiModelProperty("其他附件") | |||
private String otherFile; | |||
@ApiModelProperty("项目备注111") | |||
private String projectRemark; | |||
@ApiModelProperty("是否有效 1有效 2无效 3撤回") | |||
private Integer isEffective; | |||
@ApiModelProperty("是否包含应用 1包含") | |||
private Integer includeApplication; | |||
@ApiModelProperty("app信息") | |||
private List<ProvincialApplicationRes> applicationInfo; | |||
@ApiModelProperty("审核信息") | |||
private List<ProcessCommentRes> processComment; | |||
} |
@@ -1,5 +1,6 @@ | |||
package com.ningdatech.pmapi.provincial.service; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
/** | |||
@@ -14,12 +15,12 @@ public interface IJoinReviewProvincialBureauService { | |||
* 推送/保存 重大接口到 省局联审 | |||
* @return | |||
*/ | |||
String pushImportProject(ProvincialProjectDTO project); | |||
Boolean pushImportProject(ProvincialProjectDTO project); | |||
/** | |||
* 查看 本区域 省局联审 的项目审核详情 | |||
* @return | |||
*/ | |||
String processInfo(String projectId); | |||
ApiResponse processInfo(String projectId); | |||
} |
@@ -2,8 +2,12 @@ package com.ningdatech.pmapi.provincial.service.impl; | |||
import cn.hutool.core.util.StrUtil; | |||
import cn.hutool.crypto.SecureUtil; | |||
import com.alibaba.fastjson.JSON; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import com.ningdatech.pmapi.common.config.ProvincialProperties; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.model.res.ProvincialProjectRes; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
@@ -35,12 +39,12 @@ public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvinc | |||
* @return | |||
*/ | |||
@Override | |||
public String pushImportProject(ProvincialProjectDTO project){ | |||
public Boolean pushImportProject(ProvincialProjectDTO project){ | |||
Long timeStamp = System.currentTimeMillis()/1000; | |||
String url = provincialProperties.getHost() + provincialProperties.getPushUrl() | |||
+ "?timestamp=" + timeStamp; | |||
log.info("省局推送联审url {}",url); | |||
ResponseEntity<String> responseEntity = null; | |||
ResponseEntity<ApiResponse> responseEntity = null; | |||
String signature = getSha256(timeStamp,provincialProperties.getPushUrl(), | |||
HttpMethod.POST.name()); | |||
@@ -55,14 +59,19 @@ public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvinc | |||
.accept(MediaType.APPLICATION_JSON) | |||
.body(project); | |||
log.info("省局联审 提交 :{}", requestEntity); | |||
log.info("省局联审 提交body :{}", JSON.toJSONString(requestEntity.getBody())); | |||
try { | |||
responseEntity = restTemplate.exchange(requestEntity,String.class); | |||
responseEntity = restTemplate.exchange(requestEntity, ApiResponse.class); | |||
log.info("省局联审 响应 :{}",responseEntity); | |||
if(responseEntity.getBody().getCode().equals(200)){ | |||
return Boolean.TRUE; | |||
} | |||
} catch (Exception e) { | |||
log.error("[省局联审] http request error", e); | |||
} | |||
return responseEntity.getBody(); | |||
return Boolean.FALSE; | |||
} | |||
/** | |||
@@ -71,29 +80,31 @@ public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvinc | |||
* @return | |||
*/ | |||
@Override | |||
public String processInfo(String projectId) { | |||
public ApiResponse processInfo(String projectId) { | |||
Long timeStamp = System.currentTimeMillis()/1000; | |||
String url = provincialProperties.getHost() + provincialProperties.getDetailUrl() | |||
+ "?timestamp=" + timeStamp; | |||
log.info("省局获取审核详情 url {}",url); | |||
ResponseEntity<String> responseEntity = null; | |||
ResponseEntity<ApiResponse> responseEntity = null; | |||
String signature = getSha256(timeStamp,provincialProperties.getDetailUrl(), | |||
HttpMethod.POST.name()); | |||
JSONObject jsonBaby = new JSONObject(); | |||
jsonBaby.put("projectId",projectId); | |||
//发送post请求 | |||
RequestEntity<String> requestEntity = RequestEntity | |||
RequestEntity<JSONObject> requestEntity = RequestEntity | |||
.post(url) | |||
.header("Accept", MediaType.APPLICATION_JSON.toString()) | |||
.header("X-Hmac-Auth-Key",provincialProperties.getKey()) | |||
.header("X-Hmac-Auth-Signature",signature) | |||
.contentType(MediaType.APPLICATION_JSON) | |||
.accept(MediaType.APPLICATION_JSON) | |||
.body(projectId); //也可以是DTO | |||
.body(jsonBaby); //也可以是DTO | |||
try { | |||
responseEntity = restTemplate.exchange(requestEntity,String.class); | |||
responseEntity = restTemplate.exchange(requestEntity,ApiResponse.class); | |||
log.info("获取审批详情 响应 :{}",responseEntity); | |||
} catch (Exception e) { | |||
log.error("[省局获取审核详情] http request error", e); | |||
@@ -0,0 +1,91 @@ | |||
package com.ningdatech.pmapi.scheduler.task; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.http.HttpStatus; | |||
import com.alibaba.fastjson.JSON; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.provincial.enumeration.ProjectProvincialAuditStatusEnum; | |||
import com.ningdatech.pmapi.provincial.model.res.ProvincialProjectRes; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import com.ningdatech.pmapi.scheduler.contants.TaskContant; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.scheduling.annotation.Scheduled; | |||
import org.springframework.stereotype.Component; | |||
import java.net.InetAddress; | |||
import java.net.UnknownHostException; | |||
import java.time.LocalDateTime; | |||
import java.util.List; | |||
import java.util.Objects; | |||
/** | |||
* @Classname CheckProvincialReviewResultTask | |||
* @Description 去获取省级联审结果任务 | |||
* @Date 2023/3/16 10:12 | |||
* @Author PoffyZhang | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class CheckProvincialReviewResultTask { | |||
private final IJoinReviewProvincialBureauService reviewProvincialBureauService; | |||
private final IProjectService projectService; | |||
private final StateMachineUtils stateMachineUtils; | |||
@Scheduled(cron = "0 */5 * * * ?") | |||
public void statusFlow() throws UnknownHostException { | |||
//测试暂时用自己电脑HOST | |||
if (TaskContant.Host.HOST_ZPF.equals(InetAddress.getLocalHost().getHostName())) { | |||
//1. 定时取 省级部门联审中的项目 去取项目 | |||
List<Project> projectList = projectService.list(Wrappers.lambdaQuery(Project.class) | |||
.eq(Project::getStage, ProjectStatusEnum.NOT_APPROVED) | |||
.eq(Project::getStatus, ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS) | |||
.orderByAsc(Project::getCreateOn)); | |||
log.info("需要去查询省级联审结果的项目 size:{}",projectList.size()); | |||
if(CollUtil.isEmpty(projectList)){ | |||
log.info("没有正在省级联审中的项目!"); | |||
return; | |||
} | |||
//遍历 | |||
for(Project project: projectList){ | |||
try{ | |||
ApiResponse apiResponse = reviewProvincialBureauService.processInfo(String.valueOf(project.getId())); | |||
log.info("项目 【{}】 去获取省局联审结果 :{}",project.getId(),apiResponse); | |||
if(Objects.isNull(apiResponse) || !Integer.valueOf(HttpStatus.HTTP_OK).equals(apiResponse.getCode())){ | |||
log.info("项目 【{}】 去获取省局联审结果失败",project.getId()); | |||
continue; | |||
} | |||
ProvincialProjectRes projectRes = JSON.parseObject(JSON.toJSONString(apiResponse.getData()), | |||
ProvincialProjectRes.class); | |||
if(ProjectProvincialAuditStatusEnum.AUDITING.getCode().equals(projectRes.getProjectStatus())){ | |||
log.info("此项目 【{}】 还在审核中",projectRes.getProjectId()); | |||
}else if(ProjectProvincialAuditStatusEnum.SUCCESS.getCode().equals(projectRes.getProjectStatus())){ | |||
log.info("此项目 【{}】 审核通过",projectRes.getProjectId()); | |||
stateMachineUtils.pass(project); | |||
project.setUpdateOn(LocalDateTime.now()); | |||
projectService.updateById(project); | |||
}else if(ProjectProvincialAuditStatusEnum.SUCCESS.getCode().equals(projectRes.getProjectStatus())){ | |||
log.info("此项目 【{}】 审核不通过",projectRes.getProjectId()); | |||
stateMachineUtils.reject(project); | |||
project.setUpdateOn(LocalDateTime.now()); | |||
projectService.updateById(project); | |||
}else{ | |||
log.info("此项目 【{}】 审核结果错误",projectRes.getProjectId()); | |||
} | |||
}catch (Exception e){ | |||
log.error("项目审核信息获取异常 projectId:【" + project.getId() + "】 异常内容:" + e.getMessage()); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -42,8 +42,8 @@ public class ProjectStatusFlowTask { | |||
@Scheduled(cron = "0 */1 * * * ?") | |||
public void statusFlow() throws UnknownHostException { | |||
//测试暂时用自己电脑HOST | |||
if (TaskContant.Host.HOST_ZPF.equals(InetAddress.getLocalHost().getHostName())) { | |||
//测试暂时用自己207 | |||
if (TaskContant.Host.HOST_207.equals(InetAddress.getLocalHost().getHostName())) { | |||
//1. 定时取 项目暂存表的数据 去进行状态继续流转 | |||
List<ProjectStaging> stagingList = projectStagingService.list(Wrappers.lambdaQuery(ProjectStaging.class) | |||
.eq(ProjectStaging::getDead,Boolean.FALSE) | |||
@@ -46,10 +46,10 @@ public class WorkNoticeFlowTask { | |||
private final INdWorkNoticeStagingService workNoticeStagingService; | |||
private final ZwddClient zwddClient; | |||
// @Scheduled(cron = "0 */1 * * * ?") | |||
@Scheduled(cron = "0 */1 * * * ?") | |||
public void statusFlow() throws UnknownHostException { | |||
//测试暂时用自己电脑HOST | |||
if (TaskContant.Host.HOST_CMM.equals(InetAddress.getLocalHost().getHostName())) { | |||
if (TaskContant.Host.HOST_207.equals(InetAddress.getLocalHost().getHostName())) { | |||
//1. 定时取 工作通知暂存表的数据进行发送 | |||
List<WorkNoticeStaging> stagingList = workNoticeStagingService.list(Wrappers.lambdaQuery(WorkNoticeStaging.class) | |||
.eq(WorkNoticeStaging::getDead, Boolean.FALSE) | |||
@@ -35,7 +35,7 @@ public class VerificationCodeController { | |||
@ApiOperation(value = "发送验证码", notes = "发送验证码") | |||
@PostMapping(value = "/send") | |||
public void send(@Validated @RequestBody ReqVerificationCodePO request) { | |||
// smsManage.sendVerificationCode(request); | |||
smsManage.sendVerificationCode(request); | |||
} | |||
} |
@@ -11,6 +11,9 @@ import com.ningdatech.pmapi.sms.model.dto.VerifyCodeCacheDTO; | |||
import com.ningdatech.pmapi.sms.model.po.ReqVerificationCodePO; | |||
import com.ningdatech.pmapi.sms.utils.DateUtil; | |||
import com.ningdatech.pmapi.sms.utils.SmsRedisKeyUtils; | |||
import com.ningdatech.yxt.client.YxtClient; | |||
import com.ningdatech.yxt.constants.YxtSmsSignEnum; | |||
import com.ningdatech.yxt.model.cmd.SendSmsCmd; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.StringUtils; | |||
@@ -20,6 +23,7 @@ import org.springframework.util.Assert; | |||
import java.time.Duration; | |||
import java.time.LocalDateTime; | |||
import java.util.Collections; | |||
import java.util.Objects; | |||
/** | |||
* @author liuxinxin | |||
@@ -29,65 +33,66 @@ import java.util.Collections; | |||
@Component | |||
@RequiredArgsConstructor | |||
public class SmsManage { | |||
// | |||
// private final YxtClient yxtClient; | |||
// private final CachePlusOps cachePlusOps; | |||
// | |||
// public void sendVerificationCode(ReqVerificationCodePO request) { | |||
// Assert.isTrue(PhoneUtil.isMobile(request.getMobile()), "手机号码格式不正确"); | |||
// String verificationType = request.getVerificationType(); | |||
// VerificationCodeType verificationCodeTypeEnum = VerificationCodeType.of(verificationType); | |||
// | |||
// // 验证是否被锁定 | |||
// String lockKey = SmsRedisKeyUtils.smsSendLockKey(verificationCodeTypeEnum, request.getMobile()); | |||
// if (StringUtils.isNotBlank(cachePlusOps.get(lockKey))) { | |||
// throw BizException.wrap("今日" + verificationCodeTypeEnum.getDesc() + "的验证码发送次数过多,已被锁定"); | |||
// } | |||
// // 验证发送间隔 | |||
// String cacheKey = SmsRedisKeyUtils.smsCodeVerifyKey(verificationCodeTypeEnum, request.getMobile()); | |||
// VerifyCodeCacheDTO preCache = (VerifyCodeCacheDTO) cachePlusOps.get(cacheKey); | |||
// if (preCache != null) { | |||
// if (LocalDateTime.now().minusMinutes(verificationCodeTypeEnum.getSendInterval()) | |||
// .isBefore(preCache.getSendTime())) { | |||
// throw BizException.wrap(verificationCodeTypeEnum.getSendInterval() + "分钟之内已发送过验证码,请稍后重试"); | |||
// } | |||
// } | |||
// String code = RandomUtil.randomNumbers(6); | |||
// VerifyCodeCacheDTO cache = VerifyCodeCacheDTO.builder() | |||
// .code(code) | |||
// .sendTime(LocalDateTime.now()) | |||
// .mobile(request.getMobile()) | |||
// .build(); | |||
// | |||
// // 创建短信内容 | |||
// SendSmsCmd sendSmsCmd = new SendSmsCmd(); | |||
// switch (verificationCodeTypeEnum) { | |||
// case LOGIN: | |||
// SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext(); | |||
// sendSmsContext.setReceiveNumber(request.getMobile()); | |||
// sendSmsContext.setContent(String.format(YxtSmsTemplateConst.SMS_LOGIN_TEMPLATE, code, verificationCodeTypeEnum.getExpireTime())); | |||
// sendSmsCmd.setContextList(Collections.singletonList(sendSmsContext)); | |||
// sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | |||
// break; | |||
// default: | |||
// throw new IllegalArgumentException("非法的短信发送类型"); | |||
// } | |||
// // 发送 短信 | |||
// yxtClient.submitSmsTask(sendSmsCmd); | |||
// log.info("send verificationCode mobile = {},code = {}", request.getMobile(), code); | |||
// | |||
// cachePlusOps.set(new CacheKey(cacheKey, Duration.ofMinutes(verificationCodeTypeEnum.getExpireTime())), cache); | |||
// String limitKey = SmsRedisKeyUtils.smsSendLimitKey(verificationCodeTypeEnum, request.getMobile()); | |||
// if (StringUtils.isNotBlank(cachePlusOps.get(limitKey))) { | |||
// long limitCount = cachePlusOps.incr(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon()))); | |||
// // 超出单日发送次数之后直接锁定 | |||
// if (limitCount >= verificationCodeTypeEnum.getSendTimesByDay().longValue()) { | |||
// cachePlusOps.set(new CacheKey(lockKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), request.getMobile()); | |||
// } | |||
// } else { | |||
// cachePlusOps.set(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), 1); | |||
// } | |||
// } | |||
private final YxtClient yxtClient; | |||
private final CachePlusOps cachePlusOps; | |||
public void sendVerificationCode(ReqVerificationCodePO request) { | |||
Assert.isTrue(PhoneUtil.isMobile(request.getMobile()), "手机号码格式不正确"); | |||
String verificationType = request.getVerificationType(); | |||
VerificationCodeType verificationCodeTypeEnum = VerificationCodeType.of(verificationType); | |||
// 验证是否被锁定 | |||
String lockKey = SmsRedisKeyUtils.smsSendLockKey(verificationCodeTypeEnum, request.getMobile()); | |||
if (StringUtils.isNotBlank(cachePlusOps.get(lockKey))) { | |||
throw BizException.wrap("今日" + verificationCodeTypeEnum.getDesc() + "的验证码发送次数过多,已被锁定"); | |||
} | |||
// 验证发送间隔 | |||
String cacheKey = SmsRedisKeyUtils.smsCodeVerifyKey(verificationCodeTypeEnum, request.getMobile()); | |||
VerifyCodeCacheDTO preCache = (VerifyCodeCacheDTO) cachePlusOps.get(cacheKey); | |||
if (preCache != null) { | |||
if (LocalDateTime.now().minusMinutes(verificationCodeTypeEnum.getSendInterval()) | |||
.isBefore(preCache.getSendTime())) { | |||
throw BizException.wrap(verificationCodeTypeEnum.getSendInterval() + "分钟之内已发送过验证码,请稍后重试"); | |||
} | |||
} | |||
String code = RandomUtil.randomNumbers(6); | |||
VerifyCodeCacheDTO cache = VerifyCodeCacheDTO.builder() | |||
.code(code) | |||
.sendTime(LocalDateTime.now()) | |||
.mobile(request.getMobile()) | |||
.build(); | |||
// 创建短信内容 | |||
SendSmsCmd sendSmsCmd = new SendSmsCmd(); | |||
switch (verificationCodeTypeEnum) { | |||
case LOGIN: | |||
SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext(); | |||
sendSmsContext.setReceiveNumber(request.getMobile()); | |||
sendSmsContext.setContent(String.format(YxtSmsTemplateConst.SMS_LOGIN_TEMPLATE, code, verificationCodeTypeEnum.getExpireTime())); | |||
sendSmsCmd.setContextList(Collections.singletonList(sendSmsContext)); | |||
sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | |||
break; | |||
default: | |||
throw new IllegalArgumentException("非法的短信发送类型"); | |||
} | |||
// 发送 短信 | |||
yxtClient.submitSmsTask(sendSmsCmd); | |||
log.info("send verificationCode mobile = {},code = {}", request.getMobile(), code); | |||
cachePlusOps.set(new CacheKey(cacheKey, Duration.ofMinutes(verificationCodeTypeEnum.getExpireTime())), cache); | |||
String limitKey = SmsRedisKeyUtils.smsSendLimitKey(verificationCodeTypeEnum, request.getMobile()); | |||
if (Objects.nonNull(cachePlusOps.get(limitKey))) { | |||
Integer limitCount = cachePlusOps.get(limitKey); | |||
cachePlusOps.set(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), limitCount++); | |||
// 超出单日发送次数之后直接锁定 | |||
if (limitCount >= verificationCodeTypeEnum.getSendTimesByDay().longValue()) { | |||
cachePlusOps.set(new CacheKey(lockKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), request.getMobile()); | |||
} | |||
} else { | |||
cachePlusOps.set(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), 1); | |||
} | |||
} | |||
} |
@@ -19,8 +19,8 @@ public class ReqVerificationCodePO implements Serializable { | |||
@NotBlank(message = "手机号不能为空") | |||
private String mobile; | |||
@ApiModelProperty(value = "短信类型", allowableValues = "LOGIN,RECOMMENDATION_PROOF_FILE_SUBMIT") | |||
@ApiModelProperty(value = "短信类型", allowableValues = "LOGIN") | |||
@NotBlank(message = "短信类型不能为空") | |||
private String verificationType; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
package com.ningdatech.pmapi.sms.task; | |||
import com.ningdatech.yxt.client.YxtContext; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.scheduling.annotation.Scheduled; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @author liuxinxin | |||
* @date 2022/8/9 下午3:58 | |||
* 音信通定时检查电话结果 | |||
*/ | |||
@Component | |||
@RequiredArgsConstructor | |||
public class YxtPollingTask { | |||
private final YxtContext yxtContext; | |||
/** | |||
* 校验音信通结果数据 | |||
* 每5分钟执行一次 | |||
*/ | |||
@Scheduled(cron = "0 */1 * * * ?") | |||
// @Scheduled(cron = "${cron-expression.sms-msg-result-check-cron}") | |||
public void smsMsgResultCheck() { | |||
yxtContext.smsMsgResultCheck(); | |||
} | |||
} |
@@ -16,20 +16,22 @@ public class SmsRedisKeyUtils { | |||
private SmsRedisKeyUtils() { | |||
} | |||
private static final String PROJECT_NAME = "ls_pm:"; | |||
private static final String SMS_CODE_VERIFY_PREFIX = "sms:verify:"; | |||
private static final String SMS_SEND_LIMIT = "sms:limit:"; | |||
private static final String SMS_SEND_LOCK = "sms:lock:"; | |||
public static String smsCodeVerifyKey(VerificationCodeType type, String mobile) { | |||
return SMS_CODE_VERIFY_PREFIX + StrPool.COLON + type.name() + StrPool.COLON + mobile; | |||
return PROJECT_NAME + SMS_CODE_VERIFY_PREFIX + StrPool.COLON + type.name() + StrPool.COLON + mobile; | |||
} | |||
public static String smsSendLimitKey(VerificationCodeType type, String mobile) { | |||
return SMS_SEND_LIMIT + StrPool.COLON + type.name() + StrPool.COLON + mobile; | |||
return PROJECT_NAME + SMS_SEND_LIMIT + StrPool.COLON + type.name() + StrPool.COLON + mobile; | |||
} | |||
public static String smsSendLockKey(VerificationCodeType type, String mobile) { | |||
return SMS_SEND_LOCK + StrPool.COLON + type.name() + StrPool.COLON + mobile; | |||
return PROJECT_NAME + SMS_SEND_LOCK + StrPool.COLON + type.name() + StrPool.COLON + mobile; | |||
} | |||
} |
@@ -1,8 +1,8 @@ | |||
package com.ningdatech.pmapi.sys.service; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import java.util.List; | |||
@@ -52,9 +52,9 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme | |||
@Override | |||
public Long getRegionIdByParentIdWithSameRegionCode(Long parentId, String regionCode) { | |||
return baseMapper.selectOne(Wrappers.lambdaQuery(Region.class) | |||
.eq(Region::getParentId, parentId) | |||
.eq(Region::getRegionCode, regionCode) | |||
.eq(Region::getDeleted, false)) | |||
.eq(Region::getParentId, parentId) | |||
.eq(Region::getRegionCode, regionCode) | |||
.eq(Region::getDeleted, false)) | |||
.getId(); | |||
} | |||
@@ -81,4 +81,11 @@ public class UserAuthController { | |||
response.getWriter().write(objectMapper.writeValueAsString(BizConst.UNAUTHENTICATED)); | |||
} | |||
@PostMapping(value = "/agent-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||
@ApiOperation(value = "代登陆") | |||
@ApiImplicitParams({ | |||
@ApiImplicitParam(name = "userId", value = "账号", required = true, paramType = "form", dataType = "String")}) | |||
public void agentLogin(@RequestParam(value = "userId", required = true) String userId) { | |||
// 不实现任何内容,只是为了出api文档 | |||
} | |||
} |
@@ -59,10 +59,4 @@ public class UserInfoController { | |||
return userInfoManage.currentUserInfo(); | |||
} | |||
@ApiOperation(value = "代登陆", notes = "代登陆") | |||
@PostMapping("/generation-login") | |||
public void generationLogin(@Valid @RequestBody ReqGenerationLoginPO reqGenerationLoginPO, HttpServletRequest httpServletRequest) { | |||
userInfoManage.generationLogin(reqGenerationLoginPO); | |||
} | |||
} |
@@ -17,7 +17,10 @@ import com.ningdatech.pmapi.sys.service.IRoleService; | |||
import com.ningdatech.pmapi.sys.service.IUserRoleService; | |||
import com.ningdatech.pmapi.user.constant.UserAvailableEnum; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.ningdatech.pmapi.user.model.po.*; | |||
import com.ningdatech.pmapi.user.model.po.ReqUserDetailEditPO; | |||
import com.ningdatech.pmapi.user.model.po.ReqUserDetailPO; | |||
import com.ningdatech.pmapi.user.model.po.ReqUserDisableOrEnablePO; | |||
import com.ningdatech.pmapi.user.model.po.ReqUserInfoListPO; | |||
import com.ningdatech.pmapi.user.model.vo.ResUserDetailVO; | |||
import com.ningdatech.pmapi.user.model.vo.ResUserInfoListVO; | |||
import com.ningdatech.pmapi.user.model.vo.UserRoleVO; | |||
@@ -25,7 +28,6 @@ import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
@@ -250,7 +252,7 @@ public class UserInfoManage { | |||
} | |||
resUserDetailVO.setUserRoleInfoList(userRoleInfoList); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
if(Objects.nonNull(userFullInfo)){ | |||
if (Objects.nonNull(userFullInfo)) { | |||
resUserDetailVO.setOrgCode(userFullInfo.getOrganizationCode()); | |||
resUserDetailVO.setOrgName(userFullInfo.getOrganizationName()); | |||
resUserDetailVO.setRegionCode(userFullInfo.getRegionCode()); | |||
@@ -258,39 +260,4 @@ public class UserInfoManage { | |||
return resUserDetailVO; | |||
} | |||
public void generationLogin(ReqGenerationLoginPO reqGenerationLoginPO) { | |||
Long userId = reqGenerationLoginPO.getUserId(); | |||
UserInfo userInfo = iUserInfoService.getById(userId); | |||
if (Objects.isNull(userInfo)) { | |||
throw new BizException("该员工账号处于禁用状态中,无法使用"); | |||
} | |||
if (!UserAvailableEnum.ENABLE.name().equals(userInfo.getAvailable())) { | |||
throw new BizException("该员工账号处于禁用状态中,无法使用"); | |||
} | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
// ReqGenerationLoginPO reqGenerationLoginPO | |||
} | |||
// public void autoLogin(Long userId){ | |||
// userDetailsService.loadUserByUsername(userId + UserDeatilsServiceConstant.USER_DETAILS_SERVICE_SEPARATOR + LoginTypeEnum.USERNAME_PASSWORD_LOGIN.name()); | |||
// | |||
// CredentialAuthToken token = new CredentialAuthToken(email, password); | |||
// try { | |||
// token.setDetails(new WebAuthenticationDetails(httpServletRequest)); | |||
// UsernamePasswordAuthToken authenticatedUser = (UsernamePasswordAuthToken)usernamePasswordAuthSecurityConfig | |||
// .getAuthenticationManager().authenticate(token); | |||
// SecurityContextHolder.getContext().setAuthentication(authenticatedUser); | |||
// httpServletRequest.getSession().setAttribute( | |||
// HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); | |||
// String sessionId = httpServletRequest.getSession().getId(); | |||
// putSessionIdToCache(LoginUserUtil.getUserId(), sessionId); | |||
// } catch ( | |||
// AuthenticationException e) { | |||
// throw new RuntimeException("autoLogIn Authentication failed!", e); | |||
// } | |||
// } | |||
} |
@@ -29,6 +29,11 @@ public class AuthProperties { | |||
private String passwordLoginUrl; | |||
/** | |||
* 代登陆接口 | |||
*/ | |||
private String agentLoginUrl; | |||
private String logoutUrl; | |||
private List<String> ignoreAuthUrls; | |||
@@ -4,8 +4,9 @@ import com.ningdatech.basic.util.NdJsonUtil; | |||
import com.ningdatech.basic.util.StrPool; | |||
import com.ningdatech.pmapi.common.constant.BizConst; | |||
import com.ningdatech.pmapi.common.constant.CommonConst; | |||
import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy; | |||
import com.ningdatech.pmapi.user.security.auth.agent.AgentAuthSecurityConfig; | |||
import com.ningdatech.pmapi.user.security.auth.credential.CredentialAuthSecurityConfig; | |||
import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy; | |||
import org.springframework.beans.factory.annotation.Qualifier; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.http.HttpStatus; | |||
@@ -31,13 +32,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||
private final CredentialAuthSecurityConfig credentialAuthSecurityConfig; | |||
private final LogoutSuccessHandler logoutSuccessHandler; | |||
private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | |||
private final AgentAuthSecurityConfig agentAuthSecurityConfig; | |||
public WebSecurityConfig(AuthProperties authProperties, | |||
CredentialAuthSecurityConfig credentialAuthSecurityConfig, | |||
AgentAuthSecurityConfig agentAuthSecurityConfig, | |||
@Qualifier(value = "defaultLogoutSuccessHandler") LogoutSuccessHandler logoutSuccessHandler, | |||
DefaultExpiredSessionStrategy defaultExpiredSessionStrategy) { | |||
this.authProperties = authProperties; | |||
this.credentialAuthSecurityConfig = credentialAuthSecurityConfig; | |||
this.agentAuthSecurityConfig = agentAuthSecurityConfig; | |||
this.logoutSuccessHandler = logoutSuccessHandler; | |||
this.defaultExpiredSessionStrategy = defaultExpiredSessionStrategy; | |||
} | |||
@@ -47,7 +51,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||
assemblerPreAuthUrls(http); | |||
http.formLogin() | |||
.loginPage(authProperties.getAuthRequireUrl()) | |||
.and().apply(credentialAuthSecurityConfig) | |||
.and().apply(credentialAuthSecurityConfig).and().apply(agentAuthSecurityConfig) | |||
.and() | |||
.authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest() | |||
.authenticated().and() | |||
@@ -0,0 +1,74 @@ | |||
package com.ningdatech.pmapi.user.security.auth.agent; | |||
import com.ningdatech.basic.exception.BizException; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.http.HttpMethod; | |||
import org.springframework.security.authentication.AuthenticationServiceException; | |||
import org.springframework.security.authentication.BadCredentialsException; | |||
import org.springframework.security.authentication.InternalAuthenticationServiceException; | |||
import org.springframework.security.core.Authentication; | |||
import org.springframework.security.core.AuthenticationException; | |||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; | |||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
/** | |||
* @Author LiuXinXin | |||
* @Date 2020/8/3 8:46 下午 | |||
* @Version 1.0 | |||
**/ | |||
public class AgentAuthFilter extends AbstractAuthenticationProcessingFilter { | |||
private boolean postOnly = true; | |||
private static final String USER_ID_PARAMETER = "userId"; | |||
// ~ Constructors | |||
// =================================================================================================== | |||
public AgentAuthFilter(String processingUrl) { | |||
super(new AntPathRequestMatcher(processingUrl, HttpMethod.POST.name())); | |||
} | |||
// ~ Methods | |||
// ======================================================================================================== | |||
@Override | |||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) | |||
throws AuthenticationException { | |||
if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { | |||
throw new AuthenticationServiceException("请求方法错误"); | |||
} | |||
String userId = request.getParameter(USER_ID_PARAMETER); | |||
if (StringUtils.isBlank(userId)) { | |||
throw new BadCredentialsException("用户id 不能为空"); | |||
} | |||
userId = trim(userId); | |||
try { | |||
AgentAuthToken authRequest = new AgentAuthToken(userId, userId); | |||
// Allow subclasses to set the "details" property | |||
setDetails(request, authRequest); | |||
return this.getAuthenticationManager().authenticate(authRequest); | |||
} catch (AuthenticationException e) { | |||
throw new BadCredentialsException("账号或密码错误"); | |||
} catch (BizException e) { | |||
throw new BadCredentialsException(e.getMessage()); | |||
} catch (Exception e) { | |||
throw new InternalAuthenticationServiceException("授权失败:", e); | |||
} | |||
} | |||
protected void setDetails(HttpServletRequest request, AgentAuthToken authRequest) { | |||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); | |||
} | |||
private String trim(String trimStr) { | |||
if (StringUtils.isNotBlank(trimStr)) { | |||
return trimStr.trim(); | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
package com.ningdatech.pmapi.user.security.auth.agent; | |||
import org.springframework.security.authentication.AuthenticationProvider; | |||
import org.springframework.security.core.Authentication; | |||
import org.springframework.security.core.AuthenticationException; | |||
import org.springframework.security.core.userdetails.UserDetails; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
/** | |||
* @Author LiuXinXin | |||
* @Date 2020/8/3 8:55 下午 | |||
* @Version 1.0 | |||
**/ | |||
public class AgentAuthProvider implements AuthenticationProvider { | |||
private UserDetailsService userDetailsService; | |||
@Override | |||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { | |||
if (!(authentication instanceof AgentAuthToken)) { | |||
throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken"); | |||
} | |||
AgentAuthToken authenticationToken = (AgentAuthToken) authentication; | |||
String principal = (String) authenticationToken.getPrincipal(); | |||
UserDetails user = userDetailsService.loadUserByUsername(principal); | |||
// 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | |||
return new AgentAuthToken(user, user.getPassword(), user.getAuthorities()); | |||
} | |||
@Override | |||
public boolean supports(Class<?> authentication) { | |||
return AgentAuthToken.class.isAssignableFrom(authentication); | |||
} | |||
public void setUserDetailsService(UserDetailsService userDetailsService) { | |||
this.userDetailsService = userDetailsService; | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package com.ningdatech.pmapi.user.security.auth.agent; | |||
import com.ningdatech.pmapi.user.security.auth.AuthProperties; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.beans.factory.annotation.Qualifier; | |||
import org.springframework.security.authentication.AuthenticationManager; | |||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; | |||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
import org.springframework.security.web.DefaultSecurityFilterChain; | |||
import org.springframework.security.web.authentication.AuthenticationFailureHandler; | |||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | |||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* 账号密码登陆的认证配置 | |||
*/ | |||
@Component | |||
public class AgentAuthSecurityConfig | |||
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | |||
@Autowired | |||
@Qualifier(value = "defaultLoginSuccessHandler") | |||
protected AuthenticationSuccessHandler defaultLoginSuccessHandler; | |||
@Autowired | |||
@Qualifier(value = "defaultLoginFailureHandler") | |||
protected AuthenticationFailureHandler defaultLoginFailureHandler; | |||
@Autowired | |||
@Qualifier(value = "agentLoginUserDetailService") | |||
private UserDetailsService agentLoginUserDetailService; | |||
@Autowired | |||
private AuthProperties authProperties; | |||
private AuthenticationManager authenticationManager; | |||
@Override | |||
public void configure(HttpSecurity http) throws Exception { | |||
AgentAuthFilter agentAuthFilter = | |||
new AgentAuthFilter(authProperties.getAgentLoginUrl()); | |||
authenticationManager = http.getSharedObject(AuthenticationManager.class); | |||
agentAuthFilter.setAuthenticationManager(authenticationManager); | |||
agentAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); | |||
agentAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | |||
AgentAuthProvider authenticationProvider = new AgentAuthProvider(); | |||
authenticationProvider.setUserDetailsService(agentLoginUserDetailService); | |||
http.authenticationProvider(authenticationProvider).addFilterAfter(agentAuthFilter, | |||
UsernamePasswordAuthenticationFilter.class); | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
package com.ningdatech.pmapi.user.security.auth.agent; | |||
import com.ningdatech.pmapi.user.constant.LoginTypeEnum; | |||
import org.springframework.security.authentication.AbstractAuthenticationToken; | |||
import org.springframework.security.core.GrantedAuthority; | |||
import org.springframework.security.core.SpringSecurityCoreVersion; | |||
import java.util.Collection; | |||
/** | |||
* @Author LiuXinXin | |||
* @Date 2020/8/3 8:52 下午 | |||
* @Version 1.0 | |||
**/ | |||
public class AgentAuthToken extends AbstractAuthenticationToken { | |||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | |||
private final Object principal; | |||
private final Object credentials; | |||
/** | |||
* This constructor can be safely used by any code that wishes to create a | |||
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()} will return | |||
* <code>false</code>. | |||
*/ | |||
public AgentAuthToken(String principal, String credentials) { | |||
super(null); | |||
this.principal = principal; | |||
this.credentials = credentials; | |||
setAuthenticated(false); | |||
} | |||
/** | |||
* This constructor should only be used by <code>AuthenticationManager</code> or <code>AuthenticationProvider</code> | |||
* implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>) | |||
* authentication token. | |||
* | |||
* @param principal | |||
* @param authorities | |||
*/ | |||
public AgentAuthToken(Object principal, Object credentials, | |||
Collection<? extends GrantedAuthority> authorities) { | |||
super(authorities); | |||
this.principal = principal; | |||
this.credentials = credentials; | |||
// must use super, as we override | |||
super.setAuthenticated(true); | |||
} | |||
@Override | |||
public Object getCredentials() { | |||
return this.credentials; | |||
} | |||
@Override | |||
public Object getPrincipal() { | |||
return this.principal; | |||
} | |||
@Override | |||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { | |||
if (isAuthenticated) { | |||
throw new IllegalArgumentException( | |||
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); | |||
} | |||
super.setAuthenticated(false); | |||
} | |||
@Override | |||
public void eraseCredentials() { | |||
super.eraseCredentials(); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
package com.ningdatech.pmapi.user.security.auth.agent; | |||
import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||
import org.springframework.stereotype.Service; | |||
import java.util.Objects; | |||
/** | |||
* @author LiuXinXin | |||
* @date 2022/9/30 上午9:49 | |||
*/ | |||
@Service("agentLoginUserDetailService") | |||
@RequiredArgsConstructor | |||
public class AgentLoginUserDetailService implements UserDetailsService { | |||
private final UserAuthLoginManage userAuthLoginManage; | |||
@Override | |||
public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||
final Long userId = Long.parseLong(username); | |||
UserFullInfoDTO userFullInfoDTO = userAuthLoginManage.getUserFullInfo(userId); | |||
if (Objects.isNull(userFullInfoDTO)) { | |||
throw new UsernameNotFoundException(String.format("%s user not exist", username)); | |||
} | |||
UserInfoDetails userInfoDetails = new UserInfoDetails(); | |||
userInfoDetails.setUserId(userFullInfoDTO.getUserId()); | |||
userInfoDetails.setUsername(userFullInfoDTO.getUsername()); | |||
userInfoDetails.setRealName(userFullInfoDTO.getRealName()); | |||
userInfoDetails.setUserRoleList(userFullInfoDTO.getUserRoleList()); | |||
userInfoDetails.setRegionCode(userFullInfoDTO.getRegionCode()); | |||
userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier()); | |||
userInfoDetails.setPassword(userFullInfoDTO.getCredential()); | |||
userInfoDetails.setOrganizationCode(userFullInfoDTO.getOrganizationCode()); | |||
userInfoDetails.setOrganizationName(userFullInfoDTO.getOrganizationName()); | |||
return userInfoDetails; | |||
} | |||
} |
@@ -29,7 +29,7 @@ public class DefaultLoginSuccessHandler extends SavedRequestAwareAuthenticationS | |||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, | |||
Authentication authentication) throws IOException { | |||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); | |||
response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofSuccess())); | |||
response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofMessage(ApiResponse.SUCCESS_MSG))); | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
package com.ningdatech.pmapi.user.service; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import java.util.Map; | |||
@@ -9,7 +9,7 @@ import java.util.Set; | |||
/** | |||
* <p> | |||
* 服务类 | |||
* 服务类 | |||
* </p> | |||
* | |||
* @author Lierbao | |||
@@ -19,4 +19,7 @@ public interface IUserInfoService extends IService<UserInfo> { | |||
Map<String, ProcessInstanceUserDto> getUserMapByIds(Set<String> staterUsers); | |||
ProcessInstanceUserDto getUserInfo(String userId); | |||
UserInfo getUserInfoByPhoneNo(String phoneNo); | |||
} |
@@ -12,6 +12,7 @@ import com.ningdatech.pmapi.user.mapper.NdUserInfoMapper; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import lombok.RequiredArgsConstructor; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.stereotype.Service; | |||
import java.util.List; | |||
@@ -22,7 +23,7 @@ import java.util.stream.Collectors; | |||
/** | |||
* <p> | |||
* 服务实现类 | |||
* 服务实现类 | |||
* </p> | |||
* | |||
* @author Lierbao | |||
@@ -36,6 +37,7 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
private final IDingEmployeeInfoService dingEmployeeInfoService; | |||
private final IDingOrganizationService dingOrganizationService; | |||
@Override | |||
public Map<String, ProcessInstanceUserDto> getUserMapByIds(Set<String> staterUsers) { | |||
List<UserInfo> userInfos = userInfoMapper.selectBatchIds(staterUsers); | |||
@@ -44,13 +46,13 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
userInfo.setUserId(String.valueOf(u.getId())); | |||
userInfo.setUserName(u.getRealName()); | |||
Long accountId = u.getAccountId(); | |||
if (Objects.isNull(accountId)){ | |||
if (Objects.isNull(accountId)) { | |||
throw new BizException("该用户没有录入浙政钉用户信息!"); | |||
} | |||
// 根据浙政钉用户ID获取单位code | |||
DingEmployeeInfo employeeInfo = dingEmployeeInfoService.getOne(Wrappers.lambdaQuery(DingEmployeeInfo.class) | |||
.eq(DingEmployeeInfo::getAccountId, accountId) | |||
.eq(DingEmployeeInfo::getMainJob,String.valueOf(Boolean.TRUE)) | |||
.eq(DingEmployeeInfo::getMainJob, String.valueOf(Boolean.TRUE)) | |||
.last("limit 1")); | |||
String organizationCode = employeeInfo.getOrganizationCode(); | |||
// 根据 单位code获取单位名称 | |||
@@ -70,7 +72,7 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
processInstanceUserDto.setUserId(String.valueOf(userInfo.getId())); | |||
processInstanceUserDto.setUserName(userInfo.getRealName()); | |||
Long accountId = userInfo.getAccountId(); | |||
if (Objects.isNull(accountId)){ | |||
if (Objects.isNull(accountId)) { | |||
throw new BizException("该用户没有录入浙政钉用户信息!"); | |||
} | |||
// 根据浙政钉用户ID获取部门code | |||
@@ -85,4 +87,15 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
processInstanceUserDto.setOrgName(organizationName); | |||
return processInstanceUserDto; | |||
} | |||
@Override | |||
public UserInfo getUserInfoByPhoneNo(String phoneNo) { | |||
if (StringUtils.isEmpty(phoneNo)) { | |||
return null; | |||
} | |||
UserInfo userInfo = userInfoMapper | |||
.selectOne(Wrappers.lambdaQuery(UserInfo.class) | |||
.eq(UserInfo::getMobile, phoneNo)); | |||
return userInfo; | |||
} | |||
} |
@@ -193,3 +193,12 @@ provincial: | |||
detailUrl: /api/v1/foreign/importantProView | |||
key: 7196317343a64e67895dc0375c098fe7 | |||
secret: 75152a97f20e4c4c854dc6301cf72ad4 | |||
irs: | |||
seal-platform: | |||
project-id: 1 | |||
project-secret: 2 | |||
access-key: 3 | |||
secret-key: 4 | |||
api-url: https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220309000004/seal-platform/seal/v1/rest/sign/signPdf |
@@ -3,6 +3,7 @@ security: | |||
auth-require-url: /api/v1/user/auth/auth-require | |||
invalid-session-url: /api/v1/user/auth/invalid-session | |||
password-login-url: /api/v1/user/auth/login | |||
agent-login-url: /api/v1/user/auth/agent-login | |||
logout-url: /api/v1/user/auth/logout | |||
ignore-auth-urls: | |||
- /v2/api-docs | |||
@@ -21,6 +22,7 @@ security: | |||
- /oa/** | |||
- /wflow/** | |||
- /sys/** | |||
- /api/v1/verification/** | |||
ignore-csrf-urls: | |||
- /api/v1/user/auth/** | |||
- /v2/api-docs | |||
@@ -37,6 +39,7 @@ security: | |||
- /oa/** | |||
- /wflow/** | |||
- /sys/** | |||
- /api/v1/verification/** | |||
role-map: | |||
"engineer": | |||
"project_manager": | |||