feat(aihr): add position qualification schema contract
This commit is contained in:
+16
-2
@@ -81,7 +81,7 @@ check_pilot_samples() {
|
||||
[[ "$(pilot_sql_scalar "SELECT DATE('$pilot_end') IS NOT NULL")" == "1" ]] || fail "invalid AIHR_PILOT_END_DATE: $pilot_end"
|
||||
[[ "$pilot_start" > "$pilot_end" ]] && fail "pilot start date must not be after end date"
|
||||
|
||||
local catalog_schema_count scenario_count scenario_service_promotion_count scenario_daily_service_count rubric_expected_count rubric_five_dimension_count completed_people pilot_people org_active org_phone_linked org_hire_date_linked org_pilot_people org_pilot_projects org_completed_people audio_table_count audio_upload_table_count case_table_exists case_media_schema_count case_learning_schema_count practice_session_schema_count daily_drill_schema_count prompt_template_count prompt_version_schema_count requester_identity_schema_count hire_date_schema_count sop_document_count case_stored_count case_unmasked_count
|
||||
local catalog_schema_count scenario_count scenario_service_promotion_count scenario_daily_service_count rubric_expected_count rubric_five_dimension_count completed_people pilot_people org_active org_phone_linked org_hire_date_linked org_pilot_people org_pilot_projects org_completed_people audio_table_count audio_upload_table_count case_table_exists case_media_schema_count case_learning_schema_count practice_session_schema_count daily_drill_schema_count prompt_template_count prompt_version_schema_count requester_identity_schema_count hire_date_schema_count position_sop_schema_count formal_applicability_count onboard_task_count qualification_gate_count sop_document_count case_stored_count case_unmasked_count
|
||||
local calibration_stats calibration_count calibration_matched sop_total sop_usable sop_pending satisfaction_count satisfaction_average
|
||||
local org_identity_cte="
|
||||
WITH active_org AS (
|
||||
@@ -151,6 +151,15 @@ check_pilot_samples() {
|
||||
prompt_version_schema_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'aihr_sop_answer_review' AND column_name = 'prompt_version'")"
|
||||
requester_identity_schema_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'aihr_sop_answer_review' AND column_name = 'requester_ext_party_id'")"
|
||||
hire_date_schema_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'aihr_org_snapshot' AND column_name = 'hire_date'")"
|
||||
position_sop_schema_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name IN ('aihr_position_responsibility','aihr_sop_applicability','aihr_onboard_task','aihr_qualification_gate')")"
|
||||
formal_applicability_count=0
|
||||
onboard_task_count=0
|
||||
qualification_gate_count=0
|
||||
if (( position_sop_schema_count == 4 )); then
|
||||
formal_applicability_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_sop_applicability WHERE tenant_id = '$pilot_tenant' AND enabled = 1")"
|
||||
onboard_task_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_onboard_task WHERE tenant_id = '$pilot_tenant'")"
|
||||
qualification_gate_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_qualification_gate WHERE tenant_id = '$pilot_tenant'")"
|
||||
fi
|
||||
sop_document_count="$(pilot_sql_scalar "SELECT COUNT(*) FROM aihr_knowledge_attach WHERE tenant_id = '$pilot_tenant' AND type = 'sop' AND status = 2")"
|
||||
case_stored_count=0
|
||||
case_unmasked_count=0
|
||||
@@ -312,7 +321,7 @@ check_pilot_samples() {
|
||||
AND s.finished_time < DATE_ADD('${pilot_end}', INTERVAL 1 DAY)
|
||||
)
|
||||
SELECT COALESCE(ROUND(AVG(satisfaction_score), 1), 0) FROM formal_sessions WHERE satisfaction_score IS NOT NULL")"
|
||||
echo "OK: pilot gates window=${pilot_start}..${pilot_end} catalog_schema=${catalog_schema_count}/3 scenarios=${scenario_count}/12 rubric_five_dimensions=${rubric_five_dimension_count}/${rubric_expected_count} core_flow=service_promotion:${scenario_service_promotion_count} daily_service:${scenario_daily_service_count} sop_docs=${sop_document_count}/5 stored_cases=${case_stored_count}/20 case_unmasked=${case_unmasked_count} ten_sessions=${completed_people}/${pilot_people} org_identity=${org_phone_linked}/${org_active} org_hire_date=${org_hire_date_linked}/${org_active} org_pilot=${org_pilot_people}/20 projects=${org_pilot_projects}/1-2 org_ten_sessions=${org_completed_people}/${org_pilot_people} calibration=${calibration_count}/20 consistency=${calibration_matched}/${calibration_count} sop_usable=${sop_usable}/${sop_total} sop_pending=${sop_pending} satisfaction=${satisfaction_average}/5 responses=${satisfaction_count} audio_schema=${audio_table_count} audio_upload_schema=${audio_upload_table_count} case_media_schema=${case_media_schema_count}/2 case_learning_schema=${case_learning_schema_count}/2 practice_session_schema=${practice_session_schema_count}/8 daily_drill_schema=${daily_drill_schema_count}/6 prompt_templates=${prompt_template_count}/6 prompt_version_schema=${prompt_version_schema_count} requester_identity_schema=${requester_identity_schema_count} hire_date_schema=${hire_date_schema_count}"
|
||||
echo "OK: pilot gates window=${pilot_start}..${pilot_end} catalog_schema=${catalog_schema_count}/3 scenarios=${scenario_count}/12 rubric_five_dimensions=${rubric_five_dimension_count}/${rubric_expected_count} core_flow=service_promotion:${scenario_service_promotion_count} daily_service:${scenario_daily_service_count} sop_docs=${sop_document_count}/5 stored_cases=${case_stored_count}/20 case_unmasked=${case_unmasked_count} ten_sessions=${completed_people}/${pilot_people} org_identity=${org_phone_linked}/${org_active} org_hire_date=${org_hire_date_linked}/${org_active} org_pilot=${org_pilot_people}/20 projects=${org_pilot_projects}/1-2 org_ten_sessions=${org_completed_people}/${org_pilot_people} calibration=${calibration_count}/20 consistency=${calibration_matched}/${calibration_count} sop_usable=${sop_usable}/${sop_total} sop_pending=${sop_pending} satisfaction=${satisfaction_average}/5 responses=${satisfaction_count} audio_schema=${audio_table_count} audio_upload_schema=${audio_upload_table_count} case_media_schema=${case_media_schema_count}/2 case_learning_schema=${case_learning_schema_count}/2 practice_session_schema=${practice_session_schema_count}/8 daily_drill_schema=${daily_drill_schema_count}/6 prompt_templates=${prompt_template_count}/6 prompt_version_schema=${prompt_version_schema_count} requester_identity_schema=${requester_identity_schema_count} hire_date_schema=${hire_date_schema_count} position_sop_schema=${position_sop_schema_count}/4 formal_applicability=${formal_applicability_count} onboard_tasks=${onboard_task_count} qualification_gates=${qualification_gate_count}"
|
||||
|
||||
[[ "${AIHR_PILOT_STRICT:-false}" != "true" ]] || {
|
||||
(( catalog_schema_count == 3 )) || fail "pilot practice catalog schema incomplete (${catalog_schema_count}/3)"
|
||||
@@ -333,6 +342,7 @@ check_pilot_samples() {
|
||||
(( prompt_version_schema_count == 1 )) || fail "pilot RAG traceability schema unavailable (aihr_sop_answer_review.prompt_version missing)"
|
||||
(( requester_identity_schema_count == 1 )) || fail "pilot SOP requester identity schema unavailable (aihr_sop_answer_review.requester_ext_party_id missing)"
|
||||
(( hire_date_schema_count == 1 )) || fail "pilot org hire_date schema unavailable"
|
||||
(( position_sop_schema_count == 4 )) || fail "pilot position/SOP/onboard/qualification schema incomplete (${position_sop_schema_count}/4)"
|
||||
(( org_phone_linked >= 20 )) || fail "pilot mobile-login org members ${org_phone_linked}/20 (active org ${org_active})"
|
||||
(( org_hire_date_linked >= 20 )) || fail "pilot org hire_date identities ${org_hire_date_linked}/20"
|
||||
(( org_pilot_people >= 20 )) || fail "pilot activity matched to active org ${org_pilot_people}/20"
|
||||
@@ -604,6 +614,10 @@ contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/control
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/domain/AihrSopDto.java "String position"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrSopController.java "/position-sop"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrSopController.java "@SaCheckLogin"
|
||||
contains backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql "aihr_position_responsibility"
|
||||
contains backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql "aihr_sop_applicability"
|
||||
contains backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql "aihr_onboard_task"
|
||||
contains backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql "aihr_qualification_gate"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrDashboardController.java "@SaCheckLogin"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrDashboardController.java "@SaCheckRole"
|
||||
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java 'firstNonBlank(position, "生活顾问")'
|
||||
|
||||
@@ -150,6 +150,19 @@ mysql "$DB" < "$ROOT_DIR/backend/script/sql/update/aihr_20260714_org_hire_date_m
|
||||
org_columns="$(mysql "$DB" -N -B -e "SELECT GROUP_CONCAT(column_name ORDER BY ordinal_position) FROM information_schema.columns WHERE table_schema='$DB' AND table_name='aihr_org_snapshot' AND column_name='hire_date';")"
|
||||
test "$org_columns" = 'hire_date'
|
||||
|
||||
mysql "$DB" < "$ROOT_DIR/backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql"
|
||||
mysql "$DB" < "$ROOT_DIR/backend/script/sql/update/aihr_20260715_position_sop_qualification_mysql8.sql"
|
||||
position_sop_tables="$(mysql "$DB" -N -B -e "SELECT GROUP_CONCAT(table_name ORDER BY table_name) FROM information_schema.tables WHERE table_schema='$DB' AND table_name IN ('aihr_onboard_task','aihr_position_responsibility','aihr_qualification_gate','aihr_sop_applicability');")"
|
||||
test "$position_sop_tables" = 'aihr_onboard_task,aihr_position_responsibility,aihr_qualification_gate,aihr_sop_applicability'
|
||||
position_responsibility_columns="$(mysql "$DB" -N -B -e "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='$DB' AND table_name='aihr_position_responsibility' AND column_name IN ('position_code','responsibility_text','sop_id','sop_code');")"
|
||||
test "$position_responsibility_columns" = '4'
|
||||
sop_applicability_columns="$(mysql "$DB" -N -B -e "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='$DB' AND table_name='aihr_sop_applicability' AND column_name IN ('sop_id','sop_code','project_type','industry','org_scope');")"
|
||||
test "$sop_applicability_columns" = '5'
|
||||
onboard_task_columns="$(mysql "$DB" -N -B -e "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='$DB' AND table_name='aihr_onboard_task' AND column_name IN ('ext_party_id','position_code','task_type','status','assign_by');")"
|
||||
test "$onboard_task_columns" = '5'
|
||||
qualification_gate_columns="$(mysql "$DB" -N -B -e "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='$DB' AND table_name='aihr_qualification_gate' AND column_name IN ('ext_party_id','position_code','cert_id','passed','valid_thru');")"
|
||||
test "$qualification_gate_columns" = '5'
|
||||
|
||||
mysql -e "CREATE DATABASE \`$LEGACY_DB\` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;"
|
||||
mysql "$LEGACY_DB" <<'SQL'
|
||||
CREATE TABLE aihr_candidate_material (
|
||||
@@ -172,4 +185,4 @@ test "$candidate_interview_tables" = 'aihr_candidate_employee_link,aihr_candidat
|
||||
candidate_interview_columns="$(mysql "$LEGACY_DB" -N -B -e "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='$LEGACY_DB' AND ((table_name = 'aihr_candidate_material' AND column_name IN ('reviewer','reviewed_time')) OR (table_name = 'aihr_interview_result' AND column_name IN ('questions_json','reviewed_score','review_status','reviewer','review_note','reviewed_time')));")"
|
||||
test "$candidate_interview_columns" = '8'
|
||||
|
||||
echo "PASS: AIHR legacy schema migrations are idempotent, including practice evidence, knowledge feedback, and candidate interview review fields"
|
||||
echo "PASS: AIHR legacy schema migrations are idempotent, including practice evidence, knowledge feedback, candidate interview review, and position/SOP qualification contracts"
|
||||
|
||||
@@ -177,6 +177,7 @@ export AIHR_PILOT_DB="$TEST_DB"
|
||||
pilot_output="$(AIHR_PILOT_START_DATE=2026-07-07 AIHR_PILOT_END_DATE=2026-07-10 check_pilot_samples)"
|
||||
[[ "$pilot_output" == *'ten_sessions=1/5'* ]] || { echo "FAIL: 9/10 boundary or raw window count: $pilot_output" >&2; exit 1; }
|
||||
[[ "$pilot_output" == *'catalog_schema=1/3'* ]] || { echo "FAIL: missing catalog schema was not visible: $pilot_output" >&2; exit 1; }
|
||||
[[ "$pilot_output" == *'position_sop_schema=0/4'* ]] || { echo "FAIL: missing position/SOP qualification schema was not visible: $pilot_output" >&2; exit 1; }
|
||||
[[ "$pilot_output" == *'core_flow=service_promotion:1 daily_service:1'* ]] || { echo "FAIL: BRD core-flow coverage counts: $pilot_output" >&2; exit 1; }
|
||||
[[ "$pilot_output" == *'org_identity=2/6'* ]] || { echo "FAIL: unsafe org identities were not excluded: $pilot_output" >&2; exit 1; }
|
||||
[[ "$pilot_output" == *'org_pilot=2/20'* ]] || { echo "FAIL: collision or dual-key identity was miscounted: $pilot_output" >&2; exit 1; }
|
||||
|
||||
Reference in New Issue
Block a user