新增监管端和机构端首页数据

dev
huwei 2026-07-31 15:28:09 +08:00
parent 06f271df83
commit dec6a6d5af
6 changed files with 287 additions and 1308 deletions

View File

@ -0,0 +1,287 @@
package org.qinan.safetyeval.app.executor.institution;
import org.qinan.safetyeval.app.executor.support.EvalProjectNodeOverviewAssembler;
import org.qinan.safetyeval.client.api.institution.InstitutionDashboardApi;
import org.qinan.safetyeval.client.co.institution.EvalProjectNodeItemCO;
import org.qinan.safetyeval.client.co.institution.EvalProjectNodeOverviewCO;
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardEvalTypeRatioCO;
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardIndustryStatCO;
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardNoticeCO;
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectExecutionCO;
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectNodeStatsCO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.domain.constant.EvalTypeEnum;
import org.qinan.safetyeval.domain.constant.IndustryEnum;
import org.qinan.safetyeval.domain.entity.EvalCustomerEntity;
import org.qinan.safetyeval.domain.entity.EvalProjectEntity;
import org.qinan.safetyeval.domain.gateway.EvalCustomerGateway;
import org.qinan.safetyeval.domain.gateway.EvalProjectGateway;
import org.qinan.safetyeval.domain.gateway.SafetyMessageGateway;
import org.qinan.safetyeval.domain.query.EvalProjectQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.domain.query.SafetyMessageQuery;
import org.qinan.safetyeval.infrastructure.adapter.ThreadLocalUserInfoAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
*
* <p><b></b> Gateway / </p>
* <p>orgId {@link ThreadLocalUserInfoAdapter}</p>
*/
@Component
public class InstitutionDashboardExecutor implements InstitutionDashboardApi {
@Resource
private EvalProjectGateway evalProjectGateway;
@Resource
private EvalProjectNodeOverviewAssembler evalProjectNodeOverviewAssembler;
@Resource
private SafetyMessageGateway safetyMessageGateway;
@Resource
private EvalCustomerGateway evalCustomerGateway;
/** 节点编码 → 大屏展示名称待X */
private static final LinkedHashMap<String, String> NODE_DISPLAY = new LinkedHashMap<>();
static {
NODE_DISPLAY.put("NODE_01", "待风险分析");
NODE_DISPLAY.put("NODE_02", "待合同录入");
NODE_DISPLAY.put("NODE_03", "待项目组成立");
NODE_DISPLAY.put("NODE_04", "待现场踏勘");
NODE_DISPLAY.put("NODE_05", "待报告编制");
NODE_DISPLAY.put("NODE_06", "待内部审核");
NODE_DISPLAY.put("NODE_07", "待技术审核");
NODE_DISPLAY.put("NODE_08", "待过程控制审核");
}
private static final int PAGE_SIZE = 1000;
/** SafetyMessage 已读状态值MessageSendStateEnum.SENT.code */
private static final int SENT_CODE = 1;
// ============================ 1. 当前项目节点统计 ============================
@Override
public SingleResponse<InstitutionDashboardProjectNodeStatsCO> projectNodeStats() {
Long orgId = ThreadLocalUserInfoAdapter.get();
if (orgId == null) {
return SingleResponse.success(new InstitutionDashboardProjectNodeStatsCO());
}
List<EvalProjectEntity> projects = listOrgProjects(orgId);
int total = projects.size();
int statutory = (int) projects.stream().filter(p -> Boolean.TRUE.equals(p.getIsStatutory())).count();
// 节点待办数(待办=节点状态为「未开始」)
LinkedHashMap<String, Integer> pending = new LinkedHashMap<>();
for (String code : NODE_DISPLAY.keySet()) {
pending.put(code, 0);
}
for (EvalProjectEntity p : projects) {
try {
EvalProjectNodeOverviewCO ov = evalProjectNodeOverviewAssembler.buildForInstitution(p.getId());
if (ov == null || ov.getNodes() == null) {
continue;
}
for (EvalProjectNodeItemCO n : ov.getNodes()) {
String code = n.getNodeCode();
if (code != null && pending.containsKey(code) && "未开始".equals(n.getStatusName())) {
pending.put(code, pending.get(code) + 1);
}
}
} catch (Exception e) {
// 单项目装配异常忽略,保证其余节点统计可用
}
}
List<InstitutionDashboardProjectNodeStatsCO.NodeStat> nodeStats = new ArrayList<>();
for (Map.Entry<String, String> entry : NODE_DISPLAY.entrySet()) {
InstitutionDashboardProjectNodeStatsCO.NodeStat ns = new InstitutionDashboardProjectNodeStatsCO.NodeStat();
ns.setNodeCode(entry.getKey());
ns.setNodeName(entry.getValue());
ns.setPendingCount(pending.getOrDefault(entry.getKey(), 0));
nodeStats.add(ns);
}
int archived = (int) projects.stream().filter(p -> Boolean.TRUE.equals(p.getArchiveFlag())).count();
int delayed = evalProjectGateway.countByOrgIdAndProgressStatus(orgId, "DELAY");
InstitutionDashboardProjectNodeStatsCO co = new InstitutionDashboardProjectNodeStatsCO();
co.setTotalProjects(total);
co.setStatutoryProjects(statutory);
co.setNodeStats(nodeStats);
co.setArchivedProjectCount(archived);
co.setDelayedProjectCount(delayed);
return SingleResponse.success(co);
}
// ============================ 2. 通知提醒 ============================
@Override
public SingleResponse<InstitutionDashboardNoticeCO> notices() {
Long orgId = ThreadLocalUserInfoAdapter.get();
if (orgId == null) {
return SingleResponse.success(new InstitutionDashboardNoticeCO());
}
InstitutionDashboardNoticeCO co = new InstitutionDashboardNoticeCO();
co.setQualOnSiteReviewCount(countMessages(orgId, "ON_SITE_REVIEW_NOTICE"));
co.setInspectionCount(countMessages(orgId, "INSP_NOTICE_ORG"));
co.setUnreadRegulatoryCount(countUnread(orgId));
return SingleResponse.success(co);
}
// ============================ 3. 服务行业项目统计 ============================
@Override
public SingleResponse<InstitutionDashboardIndustryStatCO> industryStat() {
Long orgId = ThreadLocalUserInfoAdapter.get();
if (orgId == null) {
return SingleResponse.success(new InstitutionDashboardIndustryStatCO());
}
List<EvalProjectEntity> projects = listOrgProjects(orgId);
Map<String, List<EvalProjectEntity>> grouped = projects.stream()
.collect(Collectors.groupingBy(EvalProjectEntity::getIndustryCode, LinkedHashMap::new, Collectors.toList()));
List<InstitutionDashboardIndustryStatCO.IndustryStat> list = new ArrayList<>();
for (Map.Entry<String, List<EvalProjectEntity>> entry : grouped.entrySet()) {
String code = entry.getKey();
List<EvalProjectEntity> ps = entry.getValue();
InstitutionDashboardIndustryStatCO.IndustryStat is = new InstitutionDashboardIndustryStatCO.IndustryStat();
is.setIndustryCode(code);
IndustryEnum ie = IndustryEnum.ofCode(code);
is.setIndustryName(ie != null ? ie.getValue() : code);
is.setProjectCount(ps.size());
is.setStatutoryProjectCount((int) ps.stream().filter(p -> Boolean.TRUE.equals(p.getIsStatutory())).count());
list.add(is);
}
InstitutionDashboardIndustryStatCO co = new InstitutionDashboardIndustryStatCO();
co.setList(list);
return SingleResponse.success(co);
}
// ============================ 4. 评价类别占比 ============================
@Override
public SingleResponse<InstitutionDashboardEvalTypeRatioCO> evalTypeRatio() {
Long orgId = ThreadLocalUserInfoAdapter.get();
if (orgId == null) {
return SingleResponse.success(new InstitutionDashboardEvalTypeRatioCO());
}
List<EvalProjectEntity> projects = listOrgProjects(orgId);
Map<String, List<EvalProjectEntity>> grouped = projects.stream()
.collect(Collectors.groupingBy(EvalProjectEntity::getEvalTypeCode, LinkedHashMap::new, Collectors.toList()));
List<InstitutionDashboardEvalTypeRatioCO.EvalTypeRatio> items = new ArrayList<>();
for (Map.Entry<String, List<EvalProjectEntity>> entry : grouped.entrySet()) {
String code = entry.getKey();
InstitutionDashboardEvalTypeRatioCO.EvalTypeRatio ratio = new InstitutionDashboardEvalTypeRatioCO.EvalTypeRatio();
ratio.setEvalTypeCode(code);
EvalTypeEnum ee = EvalTypeEnum.ofCode(code);
ratio.setEvalTypeName(ee != null ? ee.getValue() : code);
ratio.setCount(entry.getValue().size());
items.add(ratio);
}
InstitutionDashboardEvalTypeRatioCO co = new InstitutionDashboardEvalTypeRatioCO();
co.setTotalProjectCount(projects.size());
co.setItems(items);
return SingleResponse.success(co);
}
// ============================ 5. 项目执行情况 ============================
@Override
public SingleResponse<InstitutionDashboardProjectExecutionCO> projectExecution(Integer limit) {
Long orgId = ThreadLocalUserInfoAdapter.get();
if (orgId == null) {
return SingleResponse.success(new InstitutionDashboardProjectExecutionCO());
}
List<EvalProjectEntity> projects = listOrgProjects(orgId);
int lim = limit == null ? 10 : Math.max(1, Math.min(50, limit));
// 按项目结束日期升序(最近到期在前),空日期置尾
projects.sort(Comparator.comparing(
(EvalProjectEntity p) -> p.getPlanEndDate() != null ? p.getPlanEndDate().toString() : "9999-12-31"));
List<InstitutionDashboardProjectExecutionCO.ProjectExecutionItem> list = new ArrayList<>();
for (int i = 0; i < Math.min(lim, projects.size()); i++) {
EvalProjectEntity p = projects.get(i);
InstitutionDashboardProjectExecutionCO.ProjectExecutionItem item =
new InstitutionDashboardProjectExecutionCO.ProjectExecutionItem();
item.setProjectId(p.getId());
item.setProjectNo(p.getProjectNo());
item.setProjectName(p.getProjectName());
item.setCustomerName(resolveCustomerName(p.getCustomerId()));
item.setEvalTypeCode(p.getEvalTypeCode());
EvalTypeEnum ee = EvalTypeEnum.ofCode(p.getEvalTypeCode());
item.setEvalTypeName(ee != null ? ee.getValue() : p.getEvalTypeCode());
item.setProjectLeaderName(p.getProjectLeaderName());
item.setPlanEndDate(p.getPlanEndDate() != null ? p.getPlanEndDate().toString() : null);
list.add(item);
}
InstitutionDashboardProjectExecutionCO co = new InstitutionDashboardProjectExecutionCO();
co.setList(list);
return SingleResponse.success(co);
}
// ============================ 通用方法 ============================
private List<EvalProjectEntity> listOrgProjects(Long orgId) {
EvalProjectQuery q = new EvalProjectQuery();
q.setOrgId(orgId);
q.setPageNum(1L);
q.setPageSize((long) PAGE_SIZE);
PageResult<EvalProjectEntity> p = evalProjectGateway.page(q);
return p != null && p.getRecords() != null ? p.getRecords() : new ArrayList<>();
}
private int countMessages(Long orgId, String sendType) {
SafetyMessageQuery q = new SafetyMessageQuery();
q.setOrgId(orgId);
q.setSendType(sendType);
q.setPageNum(1L);
q.setPageSize(1L);
PageResult<?> p = safetyMessageGateway.page(q);
return p != null && p.getTotal() != null ? p.getTotal().intValue() : 0;
}
private int countUnread(Long orgId) {
SafetyMessageQuery q = new SafetyMessageQuery();
q.setOrgId(orgId);
q.setPageNum(1L);
q.setPageSize((long) PAGE_SIZE);
PageResult<org.qinan.safetyeval.domain.entity.SafetyMessageEntity> p = safetyMessageGateway.page(q);
if (p == null || p.getRecords() == null) {
return 0;
}
return (int) p.getRecords().stream()
.filter(m -> m.getSendState() == null || m.getSendState() != SENT_CODE)
.count();
}
private String resolveCustomerName(Long customerId) {
if (customerId == null) {
return null;
}
try {
EvalCustomerEntity c = evalCustomerGateway.get(customerId);
return c != null ? c.getCustomerName() : null;
} catch (Exception e) {
return null;
}
}
}

View File

@ -1,235 +0,0 @@
package org.qinan.safetyeval.app.executor.institution
import org.qinan.safetyeval.client.api.institution.InstitutionDashboardApi
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardEvalTypeRatioCO
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardEvalTypeRatioCO.EvalTypeRatio
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardIndustryStatCO
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardIndustryStatCO.IndustryStat
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardNoticeCO
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectExecutionCO
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectExecutionCO.ProjectExecutionItem
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectNodeStatsCO
import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectNodeStatsCO.NodeStat
import org.qinan.safetyeval.client.dto.SingleResponse
import org.qinan.safetyeval.domain.constant.EvalTypeEnum
import org.qinan.safetyeval.domain.constant.IndustryEnum
import org.qinan.safetyeval.domain.entity.EvalProjectEntity
import org.qinan.safetyeval.domain.gateway.EvalCustomerGateway
import org.qinan.safetyeval.domain.gateway.EvalProjectGateway
import org.qinan.safetyeval.domain.gateway.SafetyMessageGateway
import org.qinan.safetyeval.domain.query.EvalProjectQuery
import org.qinan.safetyeval.domain.query.SafetyMessageQuery
import org.qinan.safetyeval.infrastructure.adapter.ThreadLocalUserInfoAdapter
import org.springframework.stereotype.Component
import javax.annotation.Resource
/**
* 机构端首页驾驶舱聚合执行器
*
* <p>全部为<b>新增</b>接口实现复用既有 Gateway / 节点聚合装配器不做任何写操作不改动既有功能</p>
* <p>orgId 取自 [ThreadLocalUserInfoAdapter]机构端请求上下文</p>
*/
@Component
class InstitutionDashboardExecutor : InstitutionDashboardApi {
@Resource
private lateinit var evalProjectGateway: EvalProjectGateway
@Resource
private lateinit var evalProjectNodeOverviewAssembler: EvalProjectNodeOverviewAssembler
@Resource
private lateinit var safetyMessageGateway: SafetyMessageGateway
@Resource
private lateinit var evalCustomerGateway: EvalCustomerGateway
/** 节点编码 → 大屏展示名称待X */
private val NODE_DISPLAY = linkedMapOf(
"NODE_01" to "待风险分析",
"NODE_02" to "待合同录入",
"NODE_03" to "待项目组成立",
"NODE_04" to "待现场踏勘",
"NODE_05" to "待报告编制",
"NODE_06" to "待内部审核",
"NODE_07" to "待技术审核",
"NODE_08" to "待过程控制审核"
)
private val PAGE_SIZE = 1000
/** SafetyMessage 已读状态值MessageSendStateEnum.SENT.code */
private val SENT_CODE = 1
// ============================ 1. 当前项目节点统计 ============================
override fun projectNodeStats(): SingleResponse<InstitutionDashboardProjectNodeStatsCO> {
val orgId = ThreadLocalUserInfoAdapter.get() ?: return SingleResponse.success(InstitutionDashboardProjectNodeStatsCO())
val projects = listOrgProjects(orgId)
val total = projects.size
val statutory = projects.count { it.isStatutory == true }
// 节点待办数(待办=节点状态为「未开始」)
val pending = NODE_DISPLAY.keys.associateWith { 0 }.toLinkedMap()
for (p in projects) {
try {
val ov = evalProjectNodeOverviewAssembler.buildForInstitution(p.id!!) ?: continue
ov.nodes?.forEach { n ->
val code = n.nodeCode
if (code != null && pending.containsKey(code) && "未开始" == n.statusName) {
pending[code] = pending[code]!! + 1
}
}
} catch (e: Exception) {
// 单项目装配异常忽略,保证其余节点统计可用
}
}
val nodeStats = NODE_DISPLAY.map { (code, name) ->
NodeStat().also {
it.nodeCode = code
it.nodeName = name
it.pendingCount = pending[code] ?: 0
}
}
val archived = projects.count { it.archiveFlag == true }
val delayed = evalProjectGateway.countByOrgIdAndProgressStatus(orgId, "DELAY")
val co = InstitutionDashboardProjectNodeStatsCO()
co.totalProjects = total
co.statutoryProjects = statutory
co.nodeStats = nodeStats
co.archivedProjectCount = archived
co.delayedProjectCount = delayed
return SingleResponse.success(co)
}
// ============================ 2. 通知提醒 ============================
override fun notices(): SingleResponse<InstitutionDashboardNoticeCO> {
val orgId = ThreadLocalUserInfoAdapter.get() ?: return SingleResponse.success(InstitutionDashboardNoticeCO())
val co = InstitutionDashboardNoticeCO()
co.qualOnSiteReviewCount = countMessages(orgId, "ON_SITE_REVIEW_NOTICE")
co.inspectionCount = countMessages(orgId, "INSP_NOTICE_ORG")
co.unreadRegulatoryCount = countUnread(orgId)
return SingleResponse.success(co)
}
// ============================ 3. 服务行业项目统计 ============================
override fun industryStat(): SingleResponse<InstitutionDashboardIndustryStatCO> {
val orgId = ThreadLocalUserInfoAdapter.get() ?: return SingleResponse.success(InstitutionDashboardIndustryStatCO())
val projects = listOrgProjects(orgId)
val grouped = projects.groupBy { it.industryCode }
val list = grouped.map { (code, ps) ->
IndustryStat().also {
it.industryCode = code
it.industryName = IndustryEnum.ofCode(code)?.value ?: code
it.projectCount = ps.size
it.statutoryProjectCount = ps.count { p -> p.isStatutory == true }
}
}
val co = InstitutionDashboardIndustryStatCO()
co.list = list
return SingleResponse.success(co)
}
// ============================ 4. 评价类别占比 ============================
override fun evalTypeRatio(): SingleResponse<InstitutionDashboardEvalTypeRatioCO> {
val orgId = ThreadLocalUserInfoAdapter.get() ?: return SingleResponse.success(InstitutionDashboardEvalTypeRatioCO())
val projects = listOrgProjects(orgId)
val grouped = projects.groupBy { it.evalTypeCode }
val items = grouped.map { (code, ps) ->
EvalTypeRatio().also {
it.evalTypeCode = code
it.evalTypeName = EvalTypeEnum.ofCode(code)?.value ?: code
it.count = ps.size
}
}
val co = InstitutionDashboardEvalTypeRatioCO()
co.totalProjectCount = projects.size
co.items = items
return SingleResponse.success(co)
}
// ============================ 5. 项目执行情况 ============================
override fun projectExecution(limit: Int?): SingleResponse<InstitutionDashboardProjectExecutionCO> {
val orgId = ThreadLocalUserInfoAdapter.get() ?: return SingleResponse.success(InstitutionDashboardProjectExecutionCO())
val projects = listOrgProjects(orgId)
val lim = (limit ?: 10).coerceAtLeast(1).coerceAtMost(50)
// 按项目结束日期升序(最近到期在前),空日期置尾
val sorted = projects.sortedBy { it.planEndDate?.toString() ?: "9999-12-31" }
val top = sorted.take(lim)
val list = top.map { p ->
ProjectExecutionItem().also {
it.projectId = p.id
it.projectNo = p.projectNo
it.projectName = p.projectName
it.customerName = resolveCustomerName(p.customerId)
it.evalTypeCode = p.evalTypeCode
it.evalTypeName = EvalTypeEnum.ofCode(p.evalTypeCode)?.value ?: p.evalTypeCode
it.projectLeaderName = p.projectLeaderName
it.planEndDate = p.planEndDate?.toString()
}
}
val co = InstitutionDashboardProjectExecutionCO()
co.list = list
return SingleResponse.success(co)
}
// ============================ 通用方法 ============================
private fun listOrgProjects(orgId: Long): List<EvalProjectEntity> {
val q = EvalProjectQuery()
q.orgId = orgId
q.pageNum = 1L
q.pageSize = PAGE_SIZE.toLong()
val p = evalProjectGateway.page(q)
return p?.records ?: emptyList()
}
private fun countMessages(orgId: Long, sendType: String): Int {
val q = SafetyMessageQuery()
q.orgId = orgId
q.sendType = sendType
q.pageNum = 1L
q.pageSize = 1L
val p = safetyMessageGateway.page(q)
return (p?.total ?: 0L).toInt()
}
private fun countUnread(orgId: Long): Int {
val q = SafetyMessageQuery()
q.orgId = orgId
q.pageNum = 1L
q.pageSize = PAGE_SIZE.toLong()
val p = safetyMessageGateway.page(q) ?: return 0
return p.records?.count { it.sendState == null || it.sendState != SENT_CODE } ?: 0
}
private fun resolveCustomerName(customerId: Long?): String? {
if (customerId == null) return null
return try {
evalCustomerGateway.get(customerId)?.customerName
} catch (e: Exception) {
null
}
}
/** 保持插入顺序的可变 Map */
private fun <K, V> Map<K, V>.toLinkedMap(): LinkedHashMap<K, V> {
val m = LinkedHashMap<K, V>()
forEach { (k, v) -> m[k] = v }
return m
}
}

View File

@ -1,183 +0,0 @@
#!/usr/bin/env python3
import os
ROOT = os.path.join(os.path.dirname(__file__), "..")
def w(rel, c):
p = os.path.join(ROOT, rel.replace('/', os.sep))
os.makedirs(os.path.dirname(p), exist_ok=True)
open(p, 'w', encoding='utf-8', newline='\n').write(c)
# Save cmd - generic with all fields as optional for copy from client
def gen_save_cmd(name):
w(f"safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/institution/{name}SaveCmd.java", f"""package org.qinan.safetyeval.client.dto.institution;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class {name}SaveCmd {{
private String id;
private String projectId;
private String riskId;
private String surveyId;
private String signTaskId;
private LocalDate analysisDate;
private String evalTypeCode;
private String evalTypeName;
private String industryCode;
private String industryName;
private String evalScope;
private Integer inBizScopeFlag;
private String unitOverview;
private String industryRiskDesc;
private Integer staffMatchCode;
private Integer needExpertCode;
private Integer capabilityCode;
private Integer feasibleCode;
private Integer economicCode;
private Integer riskLevelCode;
private String riskLevelName;
private Integer signContractCode;
private String conclusionContent;
private String approverName;
private Integer approvalOpinionCode;
private String approvalOpinionName;
private LocalDate approvalDate;
private Integer statusCode;
private String personnelId;
private String personnelName;
private String deptName;
private Integer signStatusCode;
private String signFileUrl;
private Integer sortOrder;
private String orgName;
private String contractNo;
private String projectName;
private String projectIntro;
private Long amountFen;
private String projectTypeCode;
private String projectTypeName;
private String riskSummary;
private String projectRegion;
private String projectAddress;
private LocalDate contractStartDate;
private LocalDate contractEndDate;
private Integer toxicFlag;
private Integer precursorFlag;
private Integer crossProvinceFlag;
private String businessScope;
private String enterpriseName;
private String industryCategory;
private String officeAddress;
private String creditCode;
private String postCode;
private String enterprisePhone;
private String fax;
private String legalPerson;
private String contactName;
private Integer staffCount;
private String scanFileUrl;
private String leaderPersonnelId;
private String leaderName;
private String controlPersonnelId;
private String controlName;
private Integer memberCount;
private LocalDate planSurveyDate;
private String surveyPlace;
private Integer noticeDoneFlag;
private Integer inspectDoneFlag;
private Integer rectifyDoneFlag;
private Integer enterpriseDoneFlag;
private Integer reviewDoneFlag;
private String noticeContent;
private String memberSnapshot;
private String stampFileUrl;
private Integer taskStatusCode;
private LocalDateTime planTime;
private Integer checkinTypeCode;
private String checkinTypeName;
private LocalDateTime checkinTime;
private java.math.BigDecimal longitude;
private java.math.BigDecimal latitude;
private String address;
private Integer facePassFlag;
private String photoUrls;
private String signImageUrl;
private String attachTypeCode;
private String attachTypeName;
private String fileName;
private String fileUrl;
private Integer reviewResultCode;
private String reviewResultName;
private String reviewContent;
private String templateCode;
private String templateName;
private String contentUrl;
private String hintContent;
private String draftId;
private String reviewerPersonnelId;
private String reviewerName;
private Integer resultCode;
private String resultName;
private String opinionContent;
private LocalDateTime reviewTime;
private String controllerPersonnelId;
private String controllerName;
private Integer precheckPassFlag;
private Integer archiveFlag;
private LocalDateTime controlTime;
private String nodeCode;
private String nodeName;
private String bizTypeCode;
private String bizTypeName;
private String bizRefId;
private String signerPersonnelId;
private String signerName;
private String taskTitle;
private LocalDateTime expireTime;
private LocalDateTime signTime;
private Integer clientTypeCode;
private String clientTypeName;
private String remarks;
}}
""")
def gen_page_query(name):
w(f"safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/institution/{name}PageQuery.java", f"""package org.qinan.safetyeval.client.dto.institution;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.qinan.safetyeval.client.dto.BasePageQuery;
@Data
@EqualsAndHashCode(callSuper = true)
public class {name}PageQuery extends BasePageQuery {{
private String projectId;
}}
""")
def gen_archive_cmd():
w("safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/institution/EvalProcessArchiveCmd.java", """package org.qinan.safetyeval.client.dto.institution;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class EvalProcessArchiveCmd {
@NotBlank
private String projectId;
}
""")
# Generate save cmds for all
for n in ["EvalRiskAnalysis","EvalRiskParticipant","EvalContract","EvalTeam","EvalSurvey","EvalSurveyNotice",
"EvalSurveyCheckin","EvalSurveyAttach","EvalReportDraft","EvalInternalReview","EvalTechReview",
"EvalProcessControl","EvalSignTask","EvalSignRecord"]:
gen_save_cmd(n)
gen_page_query("EvalReportDraft")
gen_page_query("EvalSignTask")
gen_archive_cmd()
print("cmds done")

View File

@ -1,465 +0,0 @@
#!/usr/bin/env python3
"""Generate P2 gateway impl, query, domain service, client and adapter layers."""
import os
import re
ROOT = os.path.join(os.path.dirname(__file__), "..")
ENTITIES = [
("EvalRiskAnalysis", "NODE_01", True, None),
("EvalRiskParticipant", "NODE_01", False, "risk"),
("EvalContract", "NODE_02", True, None),
("EvalTeam", "NODE_03", True, None),
("EvalSurvey", "NODE_04", True, None),
("EvalSurveyNotice", "NODE_04", False, "survey_unique"),
("EvalSurveyCheckin", "NODE_04", False, "survey"),
("EvalSurveyAttach", "NODE_04", False, "survey"),
("EvalReportDraft", "NODE_05", False, None),
("EvalInternalReview", "NODE_06", True, None),
("EvalTechReview", "NODE_07", True, None),
("EvalProcessControl", "NODE_08", True, None),
("EvalSignTask", "SIGN", False, None),
("EvalSignRecord", "SIGN", False, "task"),
("EvalReport", "NODE_08", False, None),
]
def kebab(name):
s = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1-\2', s).lower().replace('eval-', 'eval-')
def resource_path(name):
mapping = {
"EvalRiskAnalysis": "eval-risk-analysis",
"EvalRiskParticipant": "eval-risk-participant",
"EvalContract": "eval-contract",
"EvalTeam": "eval-team",
"EvalSurvey": "eval-survey",
"EvalSurveyNotice": "eval-survey-notice",
"EvalSurveyCheckin": "eval-survey-checkin",
"EvalSurveyAttach": "eval-survey-attach",
"EvalReportDraft": "eval-report-draft",
"EvalInternalReview": "eval-internal-review",
"EvalTechReview": "eval-tech-review",
"EvalProcessControl": "eval-process-control",
"EvalSignTask": "eval-sign-task",
"EvalSignRecord": "eval-sign-record",
"EvalReport": "eval-report",
}
return mapping[name]
def write(rel, content):
full = os.path.join(ROOT, rel.replace("/", os.sep))
os.makedirs(os.path.dirname(full), exist_ok=True)
with open(full, "w", encoding="utf-8", newline="\n") as f:
f.write(content)
def gen_query(name):
content = f"""package org.qinan.safetyeval.domain.query;
import lombok.Data;
@Data
public class {name}Query {{
private Long pageNum;
private Long pageSize;
private Long orgId;
private Long projectId;
private Long riskId;
private Long surveyId;
private Long signTaskId;
}}
"""
write(f"safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/query/{name}Query.java", content)
def gen_gateway(name, by_project, list_by):
methods = [f" {name}Entity save({name}Entity entity);",
f" {name}Entity get(Long id);",
f" {name}Entity modify({name}Entity entity);",
" void delete(Long id);"]
if by_project:
methods.append(f" {name}Entity getByProjectId(Long projectId, Long orgId);")
if list_by == "risk":
methods.append(f" java.util.List<{name}Entity> listByRiskId(Long riskId, Long orgId);")
elif list_by == "survey":
methods.append(f" java.util.List<{name}Entity> listBySurveyId(Long surveyId, Long orgId);")
elif list_by == "task":
methods.append(f" java.util.List<{name}Entity> listBySignTaskId(Long signTaskId, Long orgId);")
if name == "EvalSurveyNotice":
methods.append(f" {name}Entity getBySurveyId(Long surveyId, Long orgId);")
if name in ("EvalReportDraft", "EvalSignTask"):
methods.append(f" PageResult<{name}Entity> page({name}Query query);")
if name == "EvalReportDraft":
methods.append(" int nextDraftVersionNo(Long projectId, Long orgId);")
if name == "EvalReport":
methods.append(f" {name}Entity saveInternal({name}Entity entity);")
body = "\n".join(methods)
content = f"""package org.qinan.safetyeval.domain.gateway;
import org.qinan.safetyeval.domain.entity.{name}Entity;
import org.qinan.safetyeval.domain.query.{name}Query;
import org.qinan.safetyeval.domain.query.PageResult;
import java.util.List;
public interface {name}Gateway {{
{body}
}}
"""
write(f"safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/gateway/{name}Gateway.java", content)
def gen_gateway_impl(name, by_project, list_by, has_delete_list):
mapper_var = name[0].lower() + name[1:] + "Mapper"
extra_methods = ""
if by_project:
extra_methods += f"""
@Override
public {name}Entity getByProjectId(Long projectId, Long orgId) {{
LambdaQueryWrapper<{name}DO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq({name}DO::getDeleteEnum, "false");
wrapper.eq({name}DO::getProjectId, projectId);
if (orgId != null) {{
wrapper.eq({name}DO::getOrgId, orgId);
}}
return toEntity({mapper_var}.selectOne(wrapper));
}}
"""
if name == "EvalSurveyNotice":
extra_methods += f"""
@Override
public {name}Entity getBySurveyId(Long surveyId, Long orgId) {{
LambdaQueryWrapper<{name}DO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq({name}DO::getDeleteEnum, "false");
wrapper.eq({name}DO::getSurveyId, surveyId);
if (orgId != null) {{
wrapper.eq({name}DO::getOrgId, orgId);
}}
return toEntity({mapper_var}.selectOne(wrapper));
}}
"""
if list_by == "risk":
extra_methods += f"""
@Override
public List<{name}Entity> listByRiskId(Long riskId, Long orgId) {{
LambdaQueryWrapper<{name}DO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq({name}DO::getDeleteEnum, "false");
wrapper.eq({name}DO::getRiskId, riskId);
if (orgId != null) {{
wrapper.eq({name}DO::getOrgId, orgId);
}}
wrapper.orderByAsc({name}DO::getSortOrder);
return {mapper_var}.selectList(wrapper).stream().map(this::toEntity).collect(Collectors.toList());
}}
"""
elif list_by == "survey":
extra_methods += f"""
@Override
public List<{name}Entity> listBySurveyId(Long surveyId, Long orgId) {{
LambdaQueryWrapper<{name}DO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq({name}DO::getDeleteEnum, "false");
wrapper.eq({name}DO::getSurveyId, surveyId);
if (orgId != null) {{
wrapper.eq({name}DO::getOrgId, orgId);
}}
wrapper.orderByDesc({name}DO::getCreateTime);
return {mapper_var}.selectList(wrapper).stream().map(this::toEntity).collect(Collectors.toList());
}}
"""
elif list_by == "task":
extra_methods += f"""
@Override
public List<{name}Entity> listBySignTaskId(Long signTaskId, Long orgId) {{
LambdaQueryWrapper<{name}DO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq({name}DO::getDeleteEnum, "false");
wrapper.eq({name}DO::getSignTaskId, signTaskId);
if (orgId != null) {{
wrapper.eq({name}DO::getOrgId, orgId);
}}
wrapper.orderByDesc({name}DO::getCreateTime);
return {mapper_var}.selectList(wrapper).stream().map(this::toEntity).collect(Collectors.toList());
}}
"""
page_method = ""
if name in ("EvalReportDraft", "EvalSignTask"):
page_method = f"""
@Override
public PageResult<{name}Entity> page({name}Query query) {{
Page<{name}DO> page = new Page<>(query.getPageNum(), query.getPageSize());
LambdaQueryWrapper<{name}DO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq({name}DO::getDeleteEnum, "false");
if (query.getOrgId() != null) {{
wrapper.eq({name}DO::getOrgId, query.getOrgId());
}}
if (query.getProjectId() != null) {{
wrapper.eq({name}DO::getProjectId, query.getProjectId());
}}
wrapper.orderByDesc({name}DO::getCreateTime);
IPage<{name}DO> result = {mapper_var}.selectPage(page, wrapper);
List<{name}Entity> records = result.getRecords().stream().map(this::toEntity).collect(Collectors.toList());
return PageResult.of(records, result.getTotal(), result.getCurrent(), result.getSize());
}}
"""
version_method = ""
if name == "EvalReportDraft":
version_method = """
@Override
public int nextDraftVersionNo(Long projectId, Long orgId) {
LambdaQueryWrapper<EvalReportDraftDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EvalReportDraftDO::getDeleteEnum, "false");
wrapper.eq(EvalReportDraftDO::getProjectId, projectId);
if (orgId != null) {
wrapper.eq(EvalReportDraftDO::getOrgId, orgId);
}
wrapper.orderByDesc(EvalReportDraftDO::getDraftVersionNo);
wrapper.last("LIMIT 1");
EvalReportDraftDO latest = evalReportDraftMapper.selectOne(wrapper);
return latest == null || latest.getDraftVersionNo() == null ? 1 : latest.getDraftVersionNo() + 1;
}
"""
internal_save = ""
if name == "EvalReport":
internal_save = f"""
@Override
public {name}Entity saveInternal({name}Entity entity) {{
return save(entity);
}}
"""
content = f"""package org.qinan.safetyeval.infrastructure.gatewayimpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.qinan.safetyeval.domain.entity.{name}Entity;
import org.qinan.safetyeval.domain.gateway.{name}Gateway;
import org.qinan.safetyeval.domain.query.{name}Query;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.infrastructure.dataobject.{name}DO;
import org.qinan.safetyeval.infrastructure.mapper.{name}Mapper;
import org.qinan.safetyeval.infrastructure.support.EvalBeanCopy;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.qinan.safetyeval.infrastructure.support.OrgContextResolver;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class {name}GatewayImpl implements {name}Gateway {{
@Resource
private {name}Mapper {mapper_var};
@Resource
private OrgContextResolver orgContextResolver;
@Override
public {name}Entity save({name}Entity entity) {{
{name}DO dataObject = toDO(entity);
InsertFieldDefaults.apply(dataObject);
{mapper_var}.insert(dataObject);
entity.setId(dataObject.getId());
return entity;
}}
@Override
public {name}Entity get(Long id) {{
{name}DO dataObject = {mapper_var}.selectById(id);
if (dataObject == null || !"false".equals(dataObject.getDeleteEnum())) {{
return null;
}}
return toEntity(dataObject);
}}
@Override
public {name}Entity modify({name}Entity entity) {{
{name}DO dataObject = toDO(entity);
dataObject.setId(entity.getId());
InsertFieldDefaults.applyForUpdate(dataObject);
{mapper_var}.updateById(dataObject);
return get(entity.getId());
}}
@Override
public void delete(Long id) {{
{mapper_var}.deleteById(id);
}}
{extra_methods}{page_method}{version_method}{internal_save}
private {name}DO toDO({name}Entity entity) {{
{name}DO dataObject = EvalBeanCopy.toNew(entity, {name}DO.class);
dataObject.setOrgId(orgContextResolver.resolveOrgId(entity.getOrgId()));
return dataObject;
}}
private {name}Entity toEntity({name}DO dataObject) {{
if (dataObject == null) {{
return null;
}}
return EvalBeanCopy.toNew(dataObject, {name}Entity.class);
}}
}}
"""
write(f"safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/gatewayimpl/{name}GatewayImpl.java", content)
def gen_co(name):
content = f"""package org.qinan.safetyeval.client.co.institution;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class {name}CO {{
private String id;
private String orgId;
private String projectId;
private String riskId;
private String surveyId;
private String signTaskId;
private LocalDate analysisDate;
private String evalTypeCode;
private String evalTypeName;
private String industryCode;
private String industryName;
private String evalScope;
private Integer inBizScopeFlag;
private String unitOverview;
private String industryRiskDesc;
private Integer staffMatchCode;
private Integer needExpertCode;
private Integer capabilityCode;
private Integer feasibleCode;
private Integer economicCode;
private Integer riskLevelCode;
private String riskLevelName;
private Integer signContractCode;
private String conclusionContent;
private String approverName;
private Integer approvalOpinionCode;
private String approvalOpinionName;
private LocalDate approvalDate;
private Integer statusCode;
private String statusName;
private String personnelId;
private String personnelName;
private String deptName;
private Integer signStatusCode;
private String signStatusName;
private String signFileUrl;
private Integer sortOrder;
private String orgName;
private String contractNo;
private String projectName;
private String projectIntro;
private Long amountFen;
private String projectTypeCode;
private String projectTypeName;
private String riskSummary;
private String projectRegion;
private String projectAddress;
private LocalDate contractStartDate;
private LocalDate contractEndDate;
private Integer toxicFlag;
private Integer precursorFlag;
private Integer crossProvinceFlag;
private String businessScope;
private String enterpriseName;
private String industryCategory;
private String officeAddress;
private String creditCode;
private String postCode;
private String enterprisePhone;
private String fax;
private String legalPerson;
private String contactName;
private Integer staffCount;
private String scanFileUrl;
private String leaderPersonnelId;
private String leaderName;
private String controlPersonnelId;
private String controlName;
private Integer memberCount;
private LocalDateTime finishTime;
private LocalDate planSurveyDate;
private String surveyPlace;
private Integer noticeDoneFlag;
private Integer inspectDoneFlag;
private Integer rectifyDoneFlag;
private Integer enterpriseDoneFlag;
private Integer reviewDoneFlag;
private String noticeContent;
private String memberSnapshot;
private String stampFileUrl;
private Integer taskStatusCode;
private String taskStatusName;
private LocalDateTime planTime;
private Integer checkinTypeCode;
private String checkinTypeName;
private LocalDateTime checkinTime;
private java.math.BigDecimal longitude;
private java.math.BigDecimal latitude;
private String address;
private Integer facePassFlag;
private String photoUrls;
private String signImageUrl;
private String attachTypeCode;
private String attachTypeName;
private String fileName;
private String fileUrl;
private Integer reviewResultCode;
private String reviewResultName;
private String reviewContent;
private Integer draftVersionNo;
private String templateCode;
private String templateName;
private String contentUrl;
private String hintContent;
private String draftId;
private String reviewerPersonnelId;
private String reviewerName;
private Integer resultCode;
private String resultName;
private String opinionContent;
private LocalDateTime reviewTime;
private String controllerPersonnelId;
private String controllerName;
private Integer precheckPassFlag;
private Integer archiveFlag;
private LocalDateTime controlTime;
private String nodeCode;
private String nodeName;
private String bizTypeCode;
private String bizTypeName;
private String bizRefId;
private String signerPersonnelId;
private String signerName;
private String taskTitle;
private LocalDateTime expireTime;
private LocalDateTime signTime;
private Integer clientTypeCode;
private String clientTypeName;
private String customerId;
private String reportNo;
private String reportName;
private Integer reportYear;
private Integer publicFlag;
private Integer completeFlag;
private Integer reportStatusCode;
private String reportStatusName;
private LocalDateTime archiveTime;
}}
"""
write(f"safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/institution/{name}CO.java", content)
for e in ENTITIES:
name, node, by_project, list_by = e
gen_query(name)
gen_gateway(name, by_project, list_by)
gen_gateway_impl(name, by_project, list_by if list_by not in ("survey_unique",) else "survey", False)
gen_co(name)
print(name)
print("done")

View File

@ -1,295 +0,0 @@
#!/usr/bin/env python3
"""Generate P2 eight-node COLA boilerplate files."""
import os
ROOT = os.path.join(os.path.dirname(__file__), "..")
TABLES = {
"EvalRiskAnalysis": {
"table": "eval_risk_analysis",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("LocalDate", "analysisDate"),
("String", "evalTypeCode"), ("String", "evalTypeName"), ("String", "industryCode"),
("String", "industryName"), ("String", "evalScope"), ("Integer", "inBizScopeFlag"),
("String", "unitOverview"), ("String", "industryRiskDesc"), ("Integer", "staffMatchCode"),
("Integer", "needExpertCode"), ("Integer", "capabilityCode"), ("Integer", "feasibleCode"),
("Integer", "economicCode"), ("Integer", "riskLevelCode"), ("String", "riskLevelName"),
("Integer", "signContractCode"), ("String", "conclusionContent"), ("String", "approverName"),
("Integer", "approvalOpinionCode"), ("String", "approvalOpinionName"), ("LocalDate", "approvalDate"),
("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_RISK_NOT_FOUND",
"node": "NODE_01",
},
"EvalRiskParticipant": {
"table": "eval_risk_participant",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "riskId"),
("Long", "personnelId"), ("String", "personnelName"), ("String", "deptName"),
("Integer", "signStatusCode"), ("String", "signStatusName"), ("String", "signFileUrl"),
("Integer", "sortOrder"),
],
"not_found": "EVAL_RISK_NOT_FOUND",
"node": "NODE_01",
"list_by": "riskId",
},
"EvalContract": {
"table": "eval_contract",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("String", "orgName"), ("String", "contractNo"),
("String", "projectName"), ("String", "projectIntro"), ("Long", "amountFen"),
("String", "projectTypeCode"), ("String", "projectTypeName"), ("String", "riskSummary"),
("String", "projectRegion"), ("String", "projectAddress"), ("LocalDate", "contractStartDate"),
("LocalDate", "contractEndDate"), ("String", "evalTypeCode"), ("String", "evalTypeName"),
("Integer", "toxicFlag"), ("Integer", "precursorFlag"), ("Integer", "crossProvinceFlag"),
("String", "businessScope"), ("String", "enterpriseName"), ("String", "industryCategory"),
("String", "officeAddress"), ("String", "creditCode"), ("String", "postCode"),
("String", "enterprisePhone"), ("String", "fax"), ("String", "legalPerson"),
("String", "contactName"), ("Integer", "staffCount"), ("String", "scanFileUrl"),
("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_CONTRACT_NOT_FOUND",
"node": "NODE_02",
},
"EvalTeam": {
"table": "eval_team",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "leaderPersonnelId"),
("String", "leaderName"), ("Long", "controlPersonnelId"), ("String", "controlName"),
("Integer", "memberCount"), ("Integer", "statusCode"), ("String", "statusName"),
("LocalDateTime", "finishTime"),
],
"not_found": "EVAL_TEAM_NOT_FOUND",
"node": "NODE_03",
},
"EvalSurvey": {
"table": "eval_survey",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("LocalDate", "planSurveyDate"),
("String", "surveyPlace"), ("Integer", "noticeDoneFlag"), ("Integer", "inspectDoneFlag"),
("Integer", "rectifyDoneFlag"), ("Integer", "enterpriseDoneFlag"), ("Integer", "reviewDoneFlag"),
("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_SURVEY_NOT_FOUND",
"node": "NODE_04",
},
"EvalSurveyNotice": {
"table": "eval_survey_notice",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "surveyId"),
("String", "noticeContent"), ("String", "memberSnapshot"), ("String", "stampFileUrl"),
("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_SURVEY_NOT_FOUND",
"node": "NODE_04",
"unique_by": "surveyId",
},
"EvalSurveyCheckin": {
"table": "eval_survey_checkin",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "surveyId"),
("Long", "personnelId"), ("String", "personnelName"),
("Integer", "taskStatusCode"), ("String", "taskStatusName"), ("LocalDateTime", "planTime"),
("Integer", "checkinTypeCode"), ("String", "checkinTypeName"), ("LocalDateTime", "checkinTime"),
("java.math.BigDecimal", "longitude"), ("java.math.BigDecimal", "latitude"),
("String", "address"), ("Integer", "facePassFlag"), ("String", "photoUrls"),
("String", "signImageUrl"),
],
"not_found": "EVAL_SURVEY_NOT_FOUND",
"node": "NODE_04",
"list_by": "surveyId",
},
"EvalSurveyAttach": {
"table": "eval_survey_attach",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "surveyId"),
("String", "attachTypeCode"), ("String", "attachTypeName"), ("String", "fileName"),
("String", "fileUrl"), ("Integer", "reviewResultCode"), ("String", "reviewResultName"),
("String", "reviewContent"),
],
"not_found": "EVAL_SURVEY_NOT_FOUND",
"node": "NODE_04",
"list_by": "surveyId",
},
"EvalReportDraft": {
"table": "eval_report_draft",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Integer", "draftVersionNo"),
("String", "templateCode"), ("String", "templateName"), ("String", "contentUrl"),
("String", "hintContent"), ("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_DRAFT_NOT_FOUND",
"node": "NODE_05",
},
"EvalInternalReview": {
"table": "eval_internal_review",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "draftId"),
("Long", "reviewerPersonnelId"), ("String", "reviewerName"),
("Integer", "resultCode"), ("String", "resultName"), ("String", "opinionContent"),
("LocalDateTime", "reviewTime"), ("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_INTERNAL_REVIEW_NOT_FOUND",
"node": "NODE_06",
},
"EvalTechReview": {
"table": "eval_tech_review",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "draftId"),
("Long", "reviewerPersonnelId"), ("String", "reviewerName"),
("Integer", "resultCode"), ("String", "resultName"), ("String", "opinionContent"),
("LocalDateTime", "reviewTime"), ("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_TECH_REVIEW_NOT_FOUND",
"node": "NODE_07",
},
"EvalProcessControl": {
"table": "eval_process_control",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "controllerPersonnelId"),
("String", "controllerName"), ("Integer", "precheckPassFlag"),
("Integer", "resultCode"), ("String", "resultName"), ("String", "opinionContent"),
("Integer", "archiveFlag"), ("LocalDateTime", "controlTime"),
("Integer", "statusCode"), ("String", "statusName"),
],
"not_found": "EVAL_PROCESS_NOT_FOUND",
"node": "NODE_08",
},
"EvalSignTask": {
"table": "eval_sign_task",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("String", "nodeCode"), ("String", "nodeName"),
("String", "bizTypeCode"), ("String", "bizTypeName"), ("Long", "bizRefId"),
("Long", "signerPersonnelId"), ("String", "signerName"), ("String", "taskTitle"),
("Integer", "taskStatusCode"), ("String", "taskStatusName"), ("LocalDateTime", "expireTime"),
],
"not_found": "EVAL_SIGN_TASK_NOT_FOUND",
"node": "SIGN",
},
"EvalSignRecord": {
"table": "eval_sign_record",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "signTaskId"),
("Long", "signerPersonnelId"), ("String", "signerName"), ("String", "signImageUrl"),
("LocalDateTime", "signTime"), ("Integer", "clientTypeCode"), ("String", "clientTypeName"),
],
"not_found": "EVAL_SIGN_RECORD_NOT_FOUND",
"node": "SIGN",
"list_by": "signTaskId",
},
"EvalReport": {
"table": "eval_report",
"fields": [
("Long", "orgId"), ("Long", "projectId"), ("Long", "customerId"),
("String", "reportNo"), ("String", "reportName"), ("Integer", "reportYear"),
("String", "evalTypeCode"), ("String", "evalTypeName"), ("String", "businessScope"),
("String", "fileUrl"), ("String", "fileName"), ("Integer", "publicFlag"),
("Integer", "completeFlag"), ("Integer", "reportStatusCode"), ("String", "reportStatusName"),
("LocalDateTime", "archiveTime"),
],
"not_found": "EVAL_PROJECT_NOT_FOUND",
"internal": True,
},
}
COMMON_DO_FIELDS = [
("String", "deleteEnum"), ("String", "remarks"), ("String", "createName"), ("String", "updateName"),
("Long", "tenantId"), ("Integer", "version"), ("LocalDateTime", "createTime"),
("LocalDateTime", "updateTime"), ("Long", "createId"), ("Long", "updateId"), ("String", "env"),
]
def camel_to_snake(name):
import re
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def write(path, content):
full = os.path.join(ROOT, path.replace("/", os.sep))
os.makedirs(os.path.dirname(full), exist_ok=True)
with open(full, "w", encoding="utf-8", newline="\n") as f:
f.write(content)
def gen_entity(name, fields):
imports = set()
for t, _ in fields + COMMON_DO_FIELDS:
if t.startswith("java."):
imports.add(f"import {t};")
elif t == "LocalDate":
imports.add("import java.time.LocalDate;")
elif t == "LocalDateTime":
imports.add("import java.time.LocalDateTime;")
imp = "\n".join(sorted(imports))
lines = [f"package org.qinan.safetyeval.domain.entity;\n", imp, "\n\n@Data\n", f"public class {name}Entity {{\n\n", " private Long id;\n"]
for t, f in fields:
lines.append(f" private {t.replace('java.math.', '')} {f};\n")
for t, f in COMMON_DO_FIELDS:
lines.append(f" private {t.replace('java.math.', '')} {f};\n")
lines.append("}\n")
write(f"safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/entity/{name}Entity.java",
"".join(["import lombok.Data;\n\n"] + lines[1:]))
def gen_do(name, table, fields):
imports = ["import com.baomidou.mybatisplus.annotation.TableName;", "import lombok.Data;"]
for t, _ in fields + COMMON_DO_FIELDS:
if t.startswith("java."):
imports.append(f"import {t};")
elif t in ("LocalDate", "LocalDateTime"):
imports.append(f"import java.time.{t};")
body = "\n".join(imports) + f"\n\n@Data\n@TableName(\"{table}\")\npublic class {name}DO {{\n\n private Long id;\n"
for t, f in fields + COMMON_DO_FIELDS:
body += f" private {t.replace('java.math.', '')} {f};\n"
body += "}\n"
write(f"safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/dataobject/{name}DO.java", body)
def gen_mapper(name):
content = f"""package org.qinan.safetyeval.infrastructure.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.qinan.safetyeval.infrastructure.dataobject.{name}DO;
@Mapper
public interface {name}Mapper extends BaseMapper<{name}DO> {{
}}
"""
write(f"safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/mapper/{name}Mapper.java", content)
def gen_gateway(name):
content = f"""package org.qinan.safetyeval.domain.gateway;
import org.qinan.safetyeval.domain.entity.{name}Entity;
import org.qinan.safetyeval.domain.query.{name}Query;
import org.qinan.safetyeval.domain.query.PageResult;
import java.util.List;
public interface {name}Gateway {{
{name}Entity save({name}Entity entity);
{name}Entity get(Long id);
{name}Entity modify({name}Entity entity);
void delete(Long id);
{name}Entity getByProjectId(Long projectId, Long orgId);
List<{name}Entity> list({name}Query query);
PageResult<{name}Entity> page({name}Query query);
int nextDraftVersionNo(Long projectId, Long orgId);
}}
"""
# simplify gateway - not all need all methods; we'll trim in gateway impl
write(f"safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/gateway/{name}Gateway.java", content)
print("Generator scaffold - run manual implementation for business logic")
for n in TABLES:
cfg = TABLES[n]
gen_entity(n, cfg["fields"])
gen_do(n, cfg["table"], cfg["fields"])
gen_mapper(n)
gen_gateway(n)
print(f"Generated {n}")

View File

@ -1,130 +0,0 @@
#!/usr/bin/env python3
"""Generate remaining P2 Api/Executor/Controller triples."""
import os
ROOT = os.path.join(os.path.dirname(__file__), "..")
def w(rel, c):
p = os.path.join(ROOT, rel.replace('/', os.sep))
os.makedirs(os.path.dirname(p), exist_ok=True)
open(p, 'w', encoding='utf-8', newline='\n').write(c)
GET_OR_SAVE = [
("EvalContract", "EvalContract", "NODE_02", "EVAL_CONTRACT_NOT_FOUND", "业务合同", "eval-contract", "toContractCO"),
("EvalTeam", "EvalTeam", "NODE_03", "EVAL_TEAM_NOT_FOUND", "项目组成立", "eval-team", "toTeamCO"),
("EvalSurvey", "EvalSurvey", "NODE_04", "EVAL_SURVEY_NOT_FOUND", "现场踏勘", "eval-survey", "toSurveyCO"),
("EvalInternalReview", "EvalInternalReview", "NODE_06", "EVAL_INTERNAL_REVIEW_NOT_FOUND", "内部审核", "eval-internal-review", "toInternalCO"),
("EvalTechReview", "EvalTechReview", "NODE_07", "EVAL_TECH_REVIEW_NOT_FOUND", "技术审核", "eval-tech-review", "toTechCO"),
("EvalProcessControl", "EvalProcessControl", "NODE_08", "EVAL_PROCESS_NOT_FOUND", "过程控制", "eval-process-control", "toProcessCO"),
]
for entity, name, node, err, tag, path, conv in GET_OR_SAVE:
w(f"safety-eval-client/src/main/java/org/qinan/safetyeval/client/api/institution/{name}Api.java", f"""package org.qinan.safetyeval.client.api.institution;
import org.qinan.safetyeval.client.co.institution.{name}CO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.{name}SaveCmd;
public interface {name}Api {{
SingleResponse<{name}CO> getOrSave({name}SaveCmd cmd);
SingleResponse<{name}CO> getByProject(String projectId);
}}
""")
w(f"safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/institution/{name}Executor.java", f"""package org.qinan.safetyeval.app.executor.institution;
import org.qinan.safetyeval.app.executor.institution.support.EvalCmdCopy;
import org.qinan.safetyeval.app.executor.institution.support.EvalNodeCoConverter;
import org.qinan.safetyeval.app.executor.institution.support.EvalProjectNodeSupport;
import org.qinan.safetyeval.client.api.institution.{name}Api;
import org.qinan.safetyeval.client.co.institution.{name}CO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.{name}SaveCmd;
import org.qinan.safetyeval.domain.entity.EvalProjectEntity;
import org.qinan.safetyeval.domain.entity.{entity}Entity;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.gateway.{entity}Gateway;
import org.qinan.safetyeval.domain.support.EvalNodeCodes;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class {name}Executor implements {name}Api {{
@Resource
private {entity}Gateway {entity[0].lower() + entity[1:]}Gateway;
@Resource
private EvalProjectNodeSupport evalProjectNodeSupport;
@Override
public SingleResponse<{name}CO> getOrSave({name}SaveCmd cmd) {{
Long projectId = Long.parseLong(cmd.getProjectId());
EvalProjectEntity project = evalProjectNodeSupport.requireProject(projectId);
evalProjectNodeSupport.assertWrite(projectId, EvalNodeCodes.{node});
{entity}Entity entity = {entity[0].lower() + entity[1:]}Gateway.getByProjectId(projectId, project.getOrgId());
if (entity == null) {{
entity = new {entity}Entity();
entity.setOrgId(project.getOrgId());
entity.setProjectId(projectId);
entity.setStatusCode(1);
evalProjectNodeSupport.fillNodeStatus(1, entity);
entity = {entity[0].lower() + entity[1:]}Gateway.save(entity);
}}
EvalCmdCopy.apply(cmd, entity);
evalProjectNodeSupport.fillNodeStatus(entity.getStatusCode(), entity);
entity = {entity[0].lower() + entity[1:]}Gateway.modify(entity);
evalProjectNodeSupport.afterNodeSaved(projectId, EvalNodeCodes.{node}, entity.getStatusCode());
return SingleResponse.success(EvalNodeCoConverter.{conv}(entity));
}}
@Override
public SingleResponse<{name}CO> getByProject(String projectId) {{
Long pid = Long.parseLong(projectId);
evalProjectNodeSupport.assertRead(pid);
EvalProjectEntity project = evalProjectNodeSupport.requireProject(pid);
{entity}Entity entity = {entity[0].lower() + entity[1:]}Gateway.getByProjectId(pid, project.getOrgId());
if (entity == null) {{
throw new BizException(ErrorCode.{err});
}}
return SingleResponse.success(EvalNodeCoConverter.{conv}(entity));
}}
}}
""")
w(f"safety-eval-adapter/src/main/java/org/qinan/safetyeval/adapter/web/institution/{name}Controller.java", f"""package org.qinan.safetyeval.adapter.web.institution;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.qinan.safetyeval.client.api.institution.{name}Api;
import org.qinan.safetyeval.client.co.institution.{name}CO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.{name}SaveCmd;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Api(tags = "机构端-{tag}")
@RestController
@RequestMapping("/safetyEval/institution/{path}")
public class {name}Controller {{
@Resource
private {name}Api {name[0].lower() + name[1:]}Api;
@ApiOperation("按项目获取或保存")
@PostMapping("/get-or-save")
public SingleResponse<{name}CO> getOrSave(@Validated @RequestBody {name}SaveCmd cmd) {{
return {name[0].lower() + name[1:]}Api.getOrSave(cmd);
}}
@ApiOperation("按项目查询")
@GetMapping("/get")
public SingleResponse<{name}CO> get(@ApiParam("项目ID") @RequestParam String projectId) {{
return {name[0].lower() + name[1:]}Api.getByProject(projectId);
}}
}}
""")
print(name)
print("get-or-save done")