152 lines
9.0 KiB
Java
152 lines
9.0 KiB
Java
package scripts.qa;
|
|||
|
|
|
||
|
|
import java.io.File;
|
||
|
|
import java.nio.file.Files;
|
||
|
|
import java.sql.*;
|
||
|
|
|
||
|
|
public class CheckPackageBInventory {
|
||
|
|
public static void main(String[] args) throws Exception {
|
||
|
|
Class.forName("com.kingbase8.Driver");
|
||
|
|
|
||
|
|
File envFile = new File(System.getProperty("user.home"), ".railwaysystem-qa.env");
|
||
|
|
String pass = "";
|
||
|
|
if (envFile.exists()) {
|
||
|
|
for (String line : Files.readAllLines(envFile.toPath())) {
|
||
|
|
line = line.trim();
|
||
|
|
if (line.startsWith("QA_DB_PASSWORD=")) {
|
||
|
|
pass = line.substring("QA_DB_PASSWORD=".length()).trim();
|
||
|
|
if (pass.startsWith("\"") && pass.endsWith("\"")) {
|
||
|
|
pass = pass.substring(1, pass.length() - 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (pass.isEmpty()) {
|
||
|
|
throw new IllegalStateException("QA_DB_PASSWORD is required in ~/.railwaysystem-qa.env");
|
||
|
|
}
|
||
|
|
|
||
|
|
String dbUrl = "jdbc:kingbase8://192.168.139.218:4321/railwaysystem_integrated_qa_20260916?useUnicode=true&characterEncoding=utf8";
|
||
|
|
try (Connection conn = DriverManager.getConnection(dbUrl, "kingbase", pass)) {
|
||
|
|
try (Statement st = conn.createStatement()) {
|
||
|
|
// 验证当前数据库
|
||
|
|
try (ResultSet rs = st.executeQuery("SELECT current_database(), current_user")) {
|
||
|
|
if (rs.next()) {
|
||
|
|
System.out.println("CURRENT_DATABASE=" + rs.getString(1));
|
||
|
|
System.out.println("CURRENT_USER=" + rs.getString(2));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// A. status = 1 但无 class_report
|
||
|
|
int reportedWithoutReport = 0;
|
||
|
|
String qA = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 1 AND NOT EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qA)) {
|
||
|
|
if (rs.next()) reportedWithoutReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("REPORTED_WITHOUT_REPORT_COUNT=" + reportedWithoutReport);
|
||
|
|
|
||
|
|
// B. status = 0 但已有 class_report
|
||
|
|
int waitingWithReport = 0;
|
||
|
|
String qB = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 0 AND EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qB)) {
|
||
|
|
if (rs.next()) waitingWithReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("WAITING_WITH_REPORT_COUNT=" + waitingWithReport);
|
||
|
|
|
||
|
|
// C. status = 4 但无 class_report
|
||
|
|
int completedWithoutReport = 0;
|
||
|
|
String qC = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 4 AND NOT EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qC)) {
|
||
|
|
if (rs.next()) completedWithoutReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("COMPLETED_WITHOUT_REPORT_COUNT=" + completedWithoutReport);
|
||
|
|
|
||
|
|
// D. status = 2 且有 report
|
||
|
|
int leaveAfterReport = 0;
|
||
|
|
String qD = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 2 AND EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qD)) {
|
||
|
|
if (rs.next()) leaveAfterReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("LEAVE_AFTER_REPORT_COUNT=" + leaveAfterReport);
|
||
|
|
|
||
|
|
// E. status = 2 且无 report
|
||
|
|
int leaveBeforeReport = 0;
|
||
|
|
String qE = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 2 AND NOT EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qE)) {
|
||
|
|
if (rs.next()) leaveBeforeReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("LEAVE_BEFORE_REPORT_COUNT=" + leaveBeforeReport);
|
||
|
|
|
||
|
|
// F. status = 3 且有 report
|
||
|
|
int abandonedAfterReport = 0;
|
||
|
|
String qF = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 3 AND EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qF)) {
|
||
|
|
if (rs.next()) abandonedAfterReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("ABANDONED_AFTER_REPORT_COUNT=" + abandonedAfterReport);
|
||
|
|
|
||
|
|
// G. status = 3 且无 report
|
||
|
|
int abandonedBeforeReport = 0;
|
||
|
|
String qG = "SELECT count(*) FROM train_enrollment e WHERE e.enrollment_status = 3 AND NOT EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id)";
|
||
|
|
try (ResultSet rs = st.executeQuery(qG)) {
|
||
|
|
if (rs.next()) abandonedBeforeReport = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("ABANDONED_BEFORE_REPORT_COUNT=" + abandonedBeforeReport);
|
||
|
|
|
||
|
|
// 考勤盘点: CHECKIN_WITHOUT_SIGNIN_COUNT
|
||
|
|
int checkinWithoutSignin = 0;
|
||
|
|
String qCheckinNoSignin = "SELECT count(*) FROM train_student_checkin WHERE sign_in_time IS NULL";
|
||
|
|
try (ResultSet rs = st.executeQuery(qCheckinNoSignin)) {
|
||
|
|
if (rs.next()) checkinWithoutSignin = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("CHECKIN_WITHOUT_SIGNIN_COUNT=" + checkinWithoutSignin);
|
||
|
|
|
||
|
|
// 考勤盘点: SIGNOUT_ONLY_NORMAL_COUNT
|
||
|
|
int signoutOnlyNormal = 0;
|
||
|
|
String qSignoutOnlyNormal = "SELECT count(*) FROM train_student_checkin WHERE sign_in_time IS NULL AND sign_out_time IS NOT NULL AND attendance_status = 1";
|
||
|
|
try (ResultSet rs = st.executeQuery(qSignoutOnlyNormal)) {
|
||
|
|
if (rs.next()) signoutOnlyNormal = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("SIGNOUT_ONLY_NORMAL_COUNT=" + signoutOnlyNormal);
|
||
|
|
|
||
|
|
// DRY RUN anomaly list (sign_in_time IS NULL)
|
||
|
|
System.out.println("--- DRY RUN ANOMALY LIST (CHECKIN WITHOUT SIGNIN) ---");
|
||
|
|
String qAnomalyRows = "SELECT checkin_id, enrollment_id, lesson_id, attendance_status, sign_in_time, sign_out_time FROM train_student_checkin WHERE sign_in_time IS NULL ORDER BY checkin_id";
|
||
|
|
try (ResultSet rs = st.executeQuery(qAnomalyRows)) {
|
||
|
|
while (rs.next()) {
|
||
|
|
System.out.println(String.format("ANOMALY_ROW: checkin_id=%d, enrollment_id=%d, lesson_id=%d, attendance_status=%d, sign_in_time=%s, sign_out_time=%s",
|
||
|
|
rs.getLong("checkin_id"),
|
||
|
|
rs.getLong("enrollment_id"),
|
||
|
|
rs.getLong("lesson_id"),
|
||
|
|
rs.getInt("attendance_status"),
|
||
|
|
String.valueOf(rs.getTimestamp("sign_in_time")),
|
||
|
|
String.valueOf(rs.getTimestamp("sign_out_time"))
|
||
|
|
));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// PLAN_COMPLETION_BLOCKING_SAMPLE_COUNT
|
||
|
|
// 统计处于进行中/未结训状态(plan_status != 2 AND plan_status != 3),但其参训人员中存在 status=0 或 status=2 或 (status=1但无report) 的计划数量
|
||
|
|
int blockingPlanCount = 0;
|
||
|
|
String qBlockingPlans = "SELECT count(DISTINCT p.plan_id) FROM train_class_plan p " +
|
||
|
|
"JOIN train_enrollment e ON e.plan_id = p.plan_id " +
|
||
|
|
"WHERE p.plan_status NOT IN (2, 3) AND (" +
|
||
|
|
" e.enrollment_status = 0 OR e.enrollment_status = 2 OR " +
|
||
|
|
" (e.enrollment_status = 1 AND NOT EXISTS (SELECT 1 FROM train_class_report r WHERE r.enrollment_id = e.enrollment_id))" +
|
||
|
|
")";
|
||
|
|
try (ResultSet rs = st.executeQuery(qBlockingPlans)) {
|
||
|
|
if (rs.next()) blockingPlanCount = rs.getInt(1);
|
||
|
|
}
|
||
|
|
System.out.println("PLAN_COMPLETION_BLOCKING_SAMPLE_COUNT=" + blockingPlanCount);
|
||
|
|
|
||
|
|
// 如果存在 A/B/C 异常,打印 DRY RUN 修复建议
|
||
|
|
System.out.println("--- DRY RUN REMEDIATION REPORT ---");
|
||
|
|
if (reportedWithoutReport == 0 && waitingWithReport == 0 && completedWithoutReport == 0) {
|
||
|
|
System.out.println("REMEDIATION_NEEDED=NONE (No enrollment/report inconsistency detected)");
|
||
|
|
} else {
|
||
|
|
System.out.println(String.format("REMEDIATION_NEEDED=YES (A=%d, B=%d, C=%d). DRY RUN ONLY, NO UPDATE PERFORMED.",
|
||
|
|
reportedWithoutReport, waitingWithReport, completedWithoutReport));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|