fix(aihr): scope practice data to tenant

This commit is contained in:
2026-07-14 06:44:13 +08:00
parent a287551c0e
commit 7eb787995d
2 changed files with 83 additions and 77 deletions
@@ -46,6 +46,7 @@ import org.dromara.aihr.domain.AihrPracticeDto.TurnResponse;
import org.dromara.aihr.domain.AihrPracticeDto.TeamMemberResponse;
import org.dromara.aihr.service.AihrPracticeLlmService.PracticeTurn;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -255,7 +256,7 @@ public class AihrPracticeSeedService {
AND (? = '' OR position = ?)
AND (? = '' OR scenario_type = ?)
ORDER BY sort_order ASC, id ASC
""", this::mapScenarioResponse, TENANT_ID, safePosition, safePosition, safeType, safeType);
""", this::mapScenarioResponse, tenantId(), safePosition, safePosition, safeType, safeType);
return rows.isEmpty() ? fallbackScenarios() : rows;
} catch (DataAccessException e) {
return fallbackScenarios();
@@ -274,7 +275,7 @@ public class AihrPracticeSeedService {
FROM aihr_practice_scenario
WHERE tenant_id = ? AND scenario_code = ?
LIMIT 1
""", this::mapScenarioResponse, TENANT_ID, id.trim());
""", this::mapScenarioResponse, tenantId(), id.trim());
if (!rows.isEmpty()) {
return rows.get(0);
}
@@ -319,7 +320,7 @@ public class AihrPracticeSeedService {
enabled = VALUES(enabled),
update_time = VALUES(update_time)
""",
TENANT_ID,
tenantId(),
code,
name,
firstNonBlank(request == null ? null : request.position(), "生活顾问"),
@@ -355,7 +356,7 @@ public class AihrPracticeSeedService {
""",
request == null || request.enabled() == null || request.enabled(),
Timestamp.valueOf(LocalDateTime.now()),
TENANT_ID,
tenantId(),
id.trim()
);
return updated > 0;
@@ -388,7 +389,7 @@ public class AihrPracticeSeedService {
AND enabled = 1
AND (? = '' OR scenario_code = ?)
ORDER BY id ASC
""", this::mapRubric, TENANT_ID, safeScenario, safeScenario);
""", this::mapRubric, tenantId(), safeScenario, safeScenario);
if (!rows.isEmpty()) {
return rows;
}
@@ -417,7 +418,7 @@ public class AihrPracticeSeedService {
rs.getBoolean("enabled"),
rs.getString("description"),
rubricDimensions(rs.getString("rubric_code"))
), TENANT_ID);
), tenantId());
}
@Transactional(rollbackFor = Exception.class)
@@ -437,9 +438,9 @@ public class AihrPracticeSeedService {
scenario_code = VALUES(scenario_code), rubric_name = VALUES(rubric_name), version = VALUES(version),
enabled = VALUES(enabled), description = VALUES(description), update_time = VALUES(update_time)
""",
TENANT_ID, code, scenarioCode, name, version, enabled,
tenantId(), code, scenarioCode, name, version, enabled,
request == null ? null : request.description(), now, now);
jdbcTemplate.update("DELETE FROM aihr_practice_rubric_dimension WHERE tenant_id = ? AND rubric_code = ?", TENANT_ID, code);
jdbcTemplate.update("DELETE FROM aihr_practice_rubric_dimension WHERE tenant_id = ? AND rubric_code = ?", tenantId(), code);
List<RubricDimensionResponse> dimensions = request == null || request.dimensions() == null ? List.of() : request.dimensions();
int sort = 10;
for (RubricDimensionResponse dimension : dimensions) {
@@ -451,7 +452,7 @@ public class AihrPracticeSeedService {
INSERT INTO aihr_practice_rubric_dimension
(tenant_id, rubric_code, dimension_code, dimension_name, weight, description, sort_order, create_time, update_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""", TENANT_ID, code, dimension.code().trim(), dimension.name().trim(), weight,
""", tenantId(), code, dimension.code().trim(), dimension.name().trim(), weight,
dimension.description(), sort, now, now);
sort += 10;
}
@@ -468,7 +469,7 @@ public class AihrPracticeSeedService {
UPDATE aihr_practice_rubric SET enabled = ?, update_time = ?
WHERE tenant_id = ? AND rubric_code = ?
""", request == null || request.enabled() == null || request.enabled(),
Timestamp.valueOf(LocalDateTime.now()), TENANT_ID, code.trim()) > 0;
Timestamp.valueOf(LocalDateTime.now()), tenantId(), code.trim()) > 0;
}
public StartResponse start(StartRequest request) {
@@ -694,7 +695,7 @@ public class AihrPracticeSeedService {
FROM aihr_practice_assignment
WHERE tenant_id = ?
AND ((source <> 'daily' AND status = '待训练') OR (source = 'daily' AND DATE(create_time) = CURRENT_DATE()))
""", TENANT_ID);
""", tenantId());
}
public int mobileLowScoreCount() {
@@ -703,7 +704,7 @@ public class AihrPracticeSeedService {
SELECT COUNT(*)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND total_score < 80
""", TENANT_ID);
""", tenantId());
}
public int mobileAverageScore() {
@@ -712,7 +713,7 @@ public class AihrPracticeSeedService {
SELECT COALESCE(AVG(total_score), 0)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile'
""", Double.class, TENANT_ID);
""", Double.class, tenantId());
return value == null ? 0 : Math.round(value.floatValue());
}
@@ -726,7 +727,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND mode = 'mobile'
ORDER BY finished_time DESC, id DESC
LIMIT ?
""", this::mapRecord, TENANT_ID, safeLimit);
""", this::mapRecord, tenantId(), safeLimit);
}
return jdbcTemplate.query("""
SELECT id, session_id, finished_time, trainee_name, scenario_name, total_score, status, summary, ext_party_id
@@ -734,7 +735,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND mode = 'mobile' AND ext_party_id = ?
ORDER BY finished_time DESC, id DESC
LIMIT ?
""", this::mapRecord, TENANT_ID, extPartyId.trim(), safeLimit);
""", this::mapRecord, tenantId(), extPartyId.trim(), safeLimit);
}
public List<MistakeResponse> mobileMistakes(String extPartyId, int limit) {
@@ -793,7 +794,7 @@ public class AihrPracticeSeedService {
firstNonBlank(rs.getString("retry_status"), "未生成"),
rs.getTimestamp("finished_time") == null ? "" : rs.getTimestamp("finished_time").toLocalDateTime().format(TIME_FORMATTER),
firstNonBlank(rs.getString("summary"), "建议回看训练对话和导师改写")
), TENANT_ID, extPartyId.trim(), safeLimit);
), tenantId(), extPartyId.trim(), safeLimit);
}
public PracticeTeamResponse practiceTeamSnapshot(String supervisorExtPartyId, int limit) {
@@ -820,7 +821,7 @@ public class AihrPracticeSeedService {
? "COALESCE(NULLIF(person_phone, ''), ext_party_id)"
: "ext_party_id";
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
StringBuilder where = new StringBuilder("WHERE tenant_id = ? AND employment_status = 'active'");
if (scope.scoped()) {
where.append(" AND (ext_party_id IN (").append(inClause(scope.extPartyIds().size())).append(")");
@@ -848,14 +849,14 @@ public class AihrPracticeSeedService {
ensurePracticeTable();
ensureAssignmentTable();
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
String sessionScope = "";
String assignmentScope = "";
if (scope.scoped()) {
sessionScope = " AND ext_party_id IN (" + inClause(scope.extPartyIds().size()) + ")";
args.addAll(scope.extPartyIds());
}
args.add(TENANT_ID);
args.add(tenantId());
if (scope.scoped()) {
assignmentScope = " AND ext_party_id IN (" + inClause(scope.extPartyIds().size()) + ")";
args.addAll(scope.extPartyIds());
@@ -884,7 +885,7 @@ public class AihrPracticeSeedService {
private List<RecordResponse> practiceTeamRecords(TeamScope scope, int limit) {
ensurePracticeTable();
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
StringBuilder where = new StringBuilder("WHERE tenant_id = ? AND mode = 'mobile'");
if (scope.scoped()) {
where.append(" AND ext_party_id IN (").append(inClause(scope.extPartyIds().size())).append(")");
@@ -904,7 +905,7 @@ public class AihrPracticeSeedService {
private List<PracticeAssignmentResponse> practiceTeamAssignments(TeamScope scope, int limit) {
ensureAssignmentTable();
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
StringBuilder where = new StringBuilder("WHERE tenant_id = ? AND source <> 'daily'");
if (scope.scoped()) {
where.append(" AND ext_party_id IN (").append(inClause(scope.extPartyIds().size())).append(")");
@@ -925,7 +926,7 @@ public class AihrPracticeSeedService {
private List<MistakeAggregateResponse> practiceTeamMistakes(TeamScope scope, int limit) {
ensurePracticeTable();
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
StringBuilder where = new StringBuilder("WHERE tenant_id = ? AND mode = 'mobile' AND finished_time IS NOT NULL");
if (scope.scoped()) {
where.append(" AND ext_party_id IN (").append(inClause(scope.extPartyIds().size())).append(")");
@@ -992,7 +993,7 @@ public class AihrPracticeSeedService {
}
ensurePracticeTable();
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
StringBuilder where = new StringBuilder("WHERE tenant_id = ? AND mode = 'mobile' AND status = '待复盘'");
String party = isBlank(extPartyId) ? "" : extPartyId.trim();
if (!party.isEmpty()) {
@@ -1007,7 +1008,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND project_code = ? AND employment_status = 'active'
)
""");
args.add(TENANT_ID);
args.add(tenantId());
args.add(project);
}
if (scope.scoped()) {
@@ -1067,8 +1068,8 @@ public class AihrPracticeSeedService {
rs.getDouble("satisfaction_average"),
rs.getInt("calibration_count"),
rs.getInt("calibration_matched")
), TENANT_ID, startTime, endTime);
sessionRows = jdbcTemplate.queryForList(PILOT_SESSION_ROWS_SQL, TENANT_ID, startTime, endTime);
), tenantId(), startTime, endTime);
sessionRows = jdbcTemplate.queryForList(PILOT_SESSION_ROWS_SQL, tenantId(), startTime, endTime);
} catch (DataAccessException e) {
throw new ServiceException("正式试点数据不可用,请先完成组织快照和二期数据表初始化");
}
@@ -1175,7 +1176,7 @@ public class AihrPracticeSeedService {
GROUP BY ext_party_id
HAVING COUNT(*) >= 10
) completed_people
""", TENANT_ID);
""", tenantId());
}
private int countPilotPeople() {
@@ -1194,7 +1195,7 @@ public class AihrPracticeSeedService {
AND status = '待训练'
AND (source <> 'daily' OR DATE(create_time) = CURRENT_DATE())
) pilot_people
""", TENANT_ID, TENANT_ID);
""", tenantId(), tenantId());
}
public ReviewDetailResponse reviewDetail(Long id) {
@@ -1207,7 +1208,7 @@ public class AihrPracticeSeedService {
summary, mentor_rewrite, ai_comment, review_advice, incentive_point, dim_compliance, dim_emotion, dim_communication, dim_marketing, dialogue_json, annotations_json
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND id = ?
""", this::mapReviewDetail, TENANT_ID, id);
""", this::mapReviewDetail, tenantId(), id);
return rows.isEmpty() ? null : rows.get(0);
}
@@ -1232,7 +1233,7 @@ public class AihrPracticeSeedService {
JOIN aihr_practice_session s
ON s.tenant_id = a.tenant_id AND s.session_id = a.session_id
WHERE a.tenant_id = ? AND a.oss_id = ? AND s.mode = 'mobile'
""", (rs, rowNum) -> rs.getString("ext_party_id"), TENANT_ID, ossId);
""", (rs, rowNum) -> rs.getString("ext_party_id"), tenantId(), ossId);
String owner = identity.trim();
return sessionParties.stream().anyMatch(party -> owner.equals(party) || inTeamScope(owner, party));
}
@@ -1264,7 +1265,7 @@ public class AihrPracticeSeedService {
incentivePoint(request),
incentivePoint(request),
Timestamp.valueOf(LocalDateTime.now()),
TENANT_ID,
tenantId(),
id
);
if (updated == 0) {
@@ -1273,7 +1274,7 @@ public class AihrPracticeSeedService {
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND id = ?
FOR UPDATE
""", (rs, rowNum) -> rs.getString("status"), TENANT_ID, id);
""", (rs, rowNum) -> rs.getString("status"), tenantId(), id);
return !statuses.isEmpty() && "已复盘".equals(statuses.get(0));
}
if (request != null && !isBlank(request.nextScenarioId())) {
@@ -1317,7 +1318,7 @@ public class AihrPracticeSeedService {
SET satisfaction_score = ?, satisfaction_comment = ?, update_time = ?
WHERE tenant_id = ? AND mode = 'mobile' AND session_id = ? AND ext_party_id = ? AND finished_time IS NOT NULL
""",
request.score(), comment, submittedAt, TENANT_ID, request.sessionId().trim(), extPartyId.trim());
request.score(), comment, submittedAt, tenantId(), request.sessionId().trim(), extPartyId.trim());
if (updated == 0) {
return null;
}
@@ -1338,7 +1339,7 @@ public class AihrPracticeSeedService {
rs.getString("scenario_id"),
rs.getString("dialogue_json"),
rs.getString("annotations_json")
), TENANT_ID, sessionId.trim());
), tenantId(), sessionId.trim());
if (rows.isEmpty()) {
return List.of();
}
@@ -1352,7 +1353,7 @@ public class AihrPracticeSeedService {
UPDATE aihr_practice_session
SET annotations_json = ?, update_time = ?
WHERE tenant_id = ? AND session_id = ?
""", writeJson(annotations), Timestamp.valueOf(LocalDateTime.now()), TENANT_ID, sessionId.trim());
""", writeJson(annotations), Timestamp.valueOf(LocalDateTime.now()), tenantId(), sessionId.trim());
replaceAnnotationRows(sessionId.trim(), annotations);
return annotations;
}
@@ -1374,7 +1375,7 @@ public class AihrPracticeSeedService {
rs.getInt("dim_emotion"),
rs.getInt("dim_communication"),
rs.getInt("dim_marketing")
), TENANT_ID, sessionId.trim());
), tenantId(), sessionId.trim());
if (rows.isEmpty()) {
return null;
}
@@ -1388,7 +1389,7 @@ public class AihrPracticeSeedService {
(tenant_id, session_id, reviewer, original_score, corrected_score, corrected_dimensions_json, reason, status, create_time, update_time)
VALUES (?, ?, ?, ?, ?, ?, ?, '已记录', ?, ?)
""",
TENANT_ID,
tenantId(),
sessionId.trim(),
reviewer,
score.total(),
@@ -1422,7 +1423,7 @@ public class AihrPracticeSeedService {
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND id = ?
LIMIT 1
""", (rs, rowNum) -> rs.getString("ext_party_id"), TENANT_ID, id);
""", (rs, rowNum) -> rs.getString("ext_party_id"), tenantId(), id);
return rows.isEmpty() ? "" : rows.get(0);
}
@@ -1448,7 +1449,7 @@ public class AihrPracticeSeedService {
rs.getInt("communication"),
rs.getInt("emotion"),
rs.getInt("incentive_points")
), TENANT_ID, party, party);
), tenantId(), party, party);
CompetencySnapshot snapshot = rows.isEmpty() ? new CompetencySnapshot(0, 0, 0, 0, 0, 0, 0) : rows.get(0);
int trainingMinutes = snapshot.completed() * 8;
int contribution = snapshot.completed() == 0 && snapshot.incentivePoints() == 0
@@ -1546,7 +1547,7 @@ public class AihrPracticeSeedService {
SELECT COUNT(*)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND total_score < 80
""", TENANT_ID);
""", tenantId());
List<PracticeAlertResponse> result = new ArrayList<>();
if (pending > 0) {
result.add(new PracticeAlertResponse("pending_review", "待复盘积压", pending + " 条对练等待主管复盘", "medium", ""));
@@ -1598,7 +1599,7 @@ public class AihrPracticeSeedService {
create_time DESC,
id DESC
LIMIT ?
""", this::mapAssignment, TENANT_ID, party, party, normalizeLimit(limit));
""", this::mapAssignment, tenantId(), party, party, normalizeLimit(limit));
}
public List<PracticeAssignmentResponse> assignments(String extPartyId, String supervisorExtPartyId, int limit) {
@@ -1620,7 +1621,7 @@ public class AihrPracticeSeedService {
}
ensureAssignmentTable();
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
args.addAll(scope.extPartyIds());
args.add(normalizeLimit(limit));
return jdbcTemplate.query("""
@@ -1647,7 +1648,7 @@ public class AihrPracticeSeedService {
SELECT COUNT(*)
FROM aihr_practice_assignment
WHERE tenant_id = ? AND ext_party_id = ? AND source = 'daily' AND DATE(create_time) = CURRENT_DATE()
""", TENANT_ID, extPartyId);
""", tenantId(), extPartyId);
if (existingToday >= 3) {
return;
}
@@ -1662,7 +1663,7 @@ public class AihrPracticeSeedService {
(tenant_id, ext_party_id, trainee_name, scenario_id, scenario_name, source, reason, status, create_time, update_time)
VALUES (?, ?, ?, ?, ?, 'daily', ?, '待训练', ?, ?)
""",
TENANT_ID,
tenantId(),
extPartyId,
extPartyId.matches("\\d{11}") ? "手机用户" + extPartyId.substring(7) : extPartyId,
scenario.id(),
@@ -1691,7 +1692,7 @@ public class AihrPracticeSeedService {
INSERT INTO aihr_practice_assignment
(tenant_id, ext_party_id, trainee_name, scenario_id, scenario_name, source, reason, status, create_time, update_time)
VALUES (?, ?, ?, ?, ?, ?, ?, '待训练', ?, ?)
""", TENANT_ID, extPartyId, traineeName, scenario.id(), firstNonBlank(request == null ? null : request.scenarioName(), scenario.name()), source, reason, createdAt, createdAt);
""", tenantId(), extPartyId, traineeName, scenario.id(), firstNonBlank(request == null ? null : request.scenarioName(), scenario.name()), source, reason, createdAt, createdAt);
List<PracticeAssignmentResponse> rows = jdbcTemplate.query("""
SELECT id, ext_party_id, trainee_name, scenario_id, scenario_name, source, reason, status, create_time,
answer_text, answer_audio_url, answer_audio_oss_id, feedback, correct
@@ -1699,7 +1700,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND ext_party_id = ? AND scenario_id = ? AND source = ? AND reason = ?
ORDER BY id DESC
LIMIT 1
""", this::mapAssignment, TENANT_ID, extPartyId, scenario.id(), source, reason);
""", this::mapAssignment, tenantId(), extPartyId, scenario.id(), source, reason);
return rows.isEmpty() ? new PracticeAssignmentResponse(null, extPartyId, traineeName, scenario.id(), scenario.name(), source, reason, "待训练", now.format(TIME_FORMATTER), null, null, null, null, null, null, null) : rows.get(0);
}
@@ -1730,7 +1731,7 @@ public class AihrPracticeSeedService {
""",
Timestamp.valueOf(LocalDateTime.now()),
Timestamp.valueOf(LocalDateTime.now()),
TENANT_ID,
tenantId(),
assignmentId,
activeSession.extPartyId()
);
@@ -1752,7 +1753,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND id = ? AND source = 'daily'
AND (? = '' OR ext_party_id = ?)
LIMIT 1
""", TENANT_ID, id, party, party);
""", tenantId(), id, party, party);
if (rows.isEmpty()) {
return null;
}
@@ -1781,7 +1782,7 @@ public class AihrPracticeSeedService {
score.correct() ? 1 : 0,
Timestamp.valueOf(now),
Timestamp.valueOf(now),
TENANT_ID,
tenantId(),
id
);
return new DailyDrillAnswerResponse(id, "已完成", score.correct(), score.score(), score.feedback(), parts.referenceAnswer(), audioUrl, audioOssId);
@@ -1800,7 +1801,7 @@ public class AihrPracticeSeedService {
AND (? = '' OR code = ?)
AND (? = -1 OR enabled = ?)
ORDER BY category ASC, code ASC, version DESC, id DESC
""", this::mapPromptTemplate, TENANT_ID, safeCategory, safeCategory, safeCode, safeCode, enabledFilter, enabledFilter);
""", this::mapPromptTemplate, tenantId(), safeCategory, safeCategory, safeCode, safeCode, enabledFilter, enabledFilter);
}
public PromptTemplateResponse savePromptTemplate(PromptTemplateRequest request) {
@@ -1823,7 +1824,7 @@ public class AihrPracticeSeedService {
description = VALUES(description),
update_time = VALUES(update_time)
""",
TENANT_ID,
tenantId(),
code,
firstNonBlank(request == null ? null : request.name(), code),
firstNonBlank(request == null ? null : request.category(), "practice"),
@@ -1868,7 +1869,7 @@ public class AihrPracticeSeedService {
request == null || request.enabled() == null ? current.enabled() : request.enabled(),
request == null || request.description() == null ? current.description() : request.description(),
Timestamp.valueOf(now),
TENANT_ID,
tenantId(),
id
);
List<PromptTemplateResponse> updated = promptTemplateById(id);
@@ -1930,7 +1931,7 @@ public class AihrPracticeSeedService {
finished_time = VALUES(finished_time),
update_time = VALUES(update_time)
""",
TENANT_ID,
tenantId(),
id,
activeSession == null ? record.trainee() : activeSession.extPartyId(),
record.trainee(),
@@ -1968,7 +1969,7 @@ public class AihrPracticeSeedService {
SELECT COUNT(*)
FROM aihr_practice_assignment
WHERE tenant_id = ? AND ext_party_id = ? AND scenario_id = ? AND source = 'retry' AND status = '待训练'
""", TENANT_ID, extPartyId, scenario.id());
""", tenantId(), extPartyId, scenario.id());
if (exists > 0) {
return;
}
@@ -1978,7 +1979,7 @@ public class AihrPracticeSeedService {
(tenant_id, ext_party_id, trainee_name, scenario_id, scenario_name, source, reason, status, create_time, update_time)
VALUES (?, ?, ?, ?, ?, 'retry', ?, '待训练', ?, ?)
""",
TENANT_ID,
tenantId(),
extPartyId,
record.trainee(),
scenario.id(),
@@ -1996,13 +1997,13 @@ public class AihrPracticeSeedService {
SELECT COUNT(*)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile'
""", TENANT_ID);
""", tenantId());
}
return count("""
SELECT COUNT(*)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND ext_party_id = ?
""", TENANT_ID, extPartyId.trim());
""", tenantId(), extPartyId.trim());
}
private int countPendingReview(String extPartyId) {
@@ -2012,13 +2013,13 @@ public class AihrPracticeSeedService {
SELECT COUNT(*)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND status = '待复盘'
""", TENANT_ID);
""", tenantId());
}
return count("""
SELECT COUNT(*)
FROM aihr_practice_session
WHERE tenant_id = ? AND mode = 'mobile' AND status = '待复盘' AND ext_party_id = ?
""", TENANT_ID, extPartyId.trim());
""", tenantId(), extPartyId.trim());
}
private int countPendingReview(TeamScope scope) {
@@ -2026,7 +2027,7 @@ public class AihrPracticeSeedService {
return 0;
}
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
args.addAll(scope.extPartyIds());
return count("""
SELECT COUNT(*)
@@ -2041,7 +2042,7 @@ public class AihrPracticeSeedService {
return 0;
}
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
args.addAll(scope.extPartyIds());
return count("""
SELECT COUNT(*)
@@ -2066,7 +2067,7 @@ public class AihrPracticeSeedService {
}
boolean hasPhone = orgSnapshotColumnExists("person_phone");
List<Object> args = new ArrayList<>();
args.add(TENANT_ID);
args.add(tenantId());
args.add(identity);
String identityWhere = "ext_party_id = ?";
if (hasPhone) {
@@ -2096,7 +2097,7 @@ public class AihrPracticeSeedService {
}
boolean hasPhone = orgSnapshotColumnExists("person_phone");
List<Object> ownerArgs = new ArrayList<>();
ownerArgs.add(TENANT_ID);
ownerArgs.add(tenantId());
ownerArgs.add(owner);
String ownerWhere = "ext_party_id = ?";
if (hasPhone) {
@@ -2122,7 +2123,7 @@ public class AihrPracticeSeedService {
FROM aihr_org_snapshot
WHERE tenant_id = ? AND project_code = ? AND employment_status = 'active'
ORDER BY position_level, person_name, ext_party_id
""", (rs, rowNum) -> rs.getString("ext_party_id"), TENANT_ID, row.projectCode());
""", (rs, rowNum) -> rs.getString("ext_party_id"), tenantId(), row.projectCode());
if (hasPhone) {
ids = new ArrayList<>(new LinkedHashSet<>(ids));
ids.addAll(jdbcTemplate.query("""
@@ -2131,7 +2132,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND project_code = ? AND employment_status = 'active'
AND person_phone IS NOT NULL AND person_phone <> ''
ORDER BY position_level, person_name, ext_party_id
""", (rs, rowNum) -> rs.getString("person_phone"), TENANT_ID, row.projectCode()));
""", (rs, rowNum) -> rs.getString("person_phone"), tenantId(), row.projectCode()));
ids = new ArrayList<>(new LinkedHashSet<>(ids));
}
return TeamScope.scoped(ids);
@@ -2175,7 +2176,7 @@ public class AihrPracticeSeedService {
FROM aihr_practice_calibration
WHERE tenant_id = ? AND original_score IS NOT NULL AND corrected_score IS NOT NULL
ORDER BY id DESC
""", TENANT_ID).forEach(row -> {
""", tenantId()).forEach(row -> {
String sessionId = String.valueOf(row.get("session_id"));
latestBySession.putIfAbsent(sessionId, new CalibrationPair(
((Number) row.get("original_score")).intValue(),
@@ -2356,7 +2357,7 @@ public class AihrPracticeSeedService {
FROM aihr_prompt_template
WHERE tenant_id = ? AND code = ? AND output_format = ? AND version = ?
LIMIT 1
""", this::mapPromptTemplate, TENANT_ID, code, outputFormat, version);
""", this::mapPromptTemplate, tenantId(), code, outputFormat, version);
return rows.isEmpty() ? null : rows.get(0);
}
@@ -2366,7 +2367,7 @@ public class AihrPracticeSeedService {
FROM aihr_prompt_template
WHERE tenant_id = ? AND id = ?
LIMIT 1
""", this::mapPromptTemplate, TENANT_ID, id);
""", this::mapPromptTemplate, tenantId(), id);
}
private CalibrationResponse latestCalibration(String sessionId) {
@@ -2388,7 +2389,7 @@ public class AihrPracticeSeedService {
rs.getString("status"),
createTime == null ? "" : createTime.toLocalDateTime().format(TIME_FORMATTER)
);
}, TENANT_ID, sessionId);
}, tenantId(), sessionId);
return rows.isEmpty() ? null : rows.get(0);
}
@@ -2476,7 +2477,7 @@ public class AihrPracticeSeedService {
WHERE tenant_id = ? AND scenario_code = ? AND enabled = 1
ORDER BY id ASC
LIMIT 1
""", this::mapRubric, TENANT_ID, scenarioCode);
""", this::mapRubric, tenantId(), scenarioCode);
return rows.stream().findFirst();
} catch (DataAccessException e) {
return Optional.empty();
@@ -2498,7 +2499,7 @@ public class AihrPracticeSeedService {
rs.getString("dimension_name"),
rs.getDouble("weight"),
rs.getString("description")
), TENANT_ID, rubricCode);
), tenantId(), rubricCode);
return rows.isEmpty() ? defaultRubricDimensions(false) : rows;
} catch (DataAccessException e) {
return defaultRubricDimensions(false);
@@ -2733,7 +2734,7 @@ public class AihrPracticeSeedService {
rs.getString("scenario_id"),
rs.getString("dialogue_json"),
rs.getString("annotations_json")
), TENANT_ID, sessionId);
), tenantId(), sessionId);
if (rows.isEmpty()) {
return readAnnotations(fallbackJson, List.of(), scenario);
}
@@ -2750,7 +2751,7 @@ public class AihrPracticeSeedService {
ensureAnnotationTable();
String id = sessionId.trim();
LocalDateTime now = LocalDateTime.now();
jdbcTemplate.update("DELETE FROM aihr_practice_annotation WHERE tenant_id = ? AND session_id = ?", TENANT_ID, id);
jdbcTemplate.update("DELETE FROM aihr_practice_annotation WHERE tenant_id = ? AND session_id = ?", tenantId(), id);
for (AnnotationResponse annotation : annotations) {
if (annotation == null) {
continue;
@@ -2760,7 +2761,7 @@ public class AihrPracticeSeedService {
(tenant_id, session_id, turn_index, source_text, issue_text, rewrite_text, sop_point, create_time, update_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
TENANT_ID,
tenantId(),
id,
annotation.turnIndex(),
annotation.sourceText(),
@@ -2785,7 +2786,7 @@ public class AihrPracticeSeedService {
ensureAudioTable();
String id = sessionId.trim();
LocalDateTime now = LocalDateTime.now();
jdbcTemplate.update("DELETE FROM aihr_practice_audio WHERE tenant_id = ? AND session_id = ?", TENANT_ID, id);
jdbcTemplate.update("DELETE FROM aihr_practice_audio WHERE tenant_id = ? AND session_id = ?", tenantId(), id);
for (int i = 0; i < urls.size(); i++) {
String url = urls.get(i);
if (isBlank(url)) {
@@ -2796,7 +2797,7 @@ public class AihrPracticeSeedService {
(tenant_id, session_id, turn_index, role, oss_id, audio_url, create_time, update_time)
VALUES (?, ?, ?, 'trainee', ?, ?, ?, ?)
""",
TENANT_ID,
tenantId(),
id,
i + 1,
i < ossIds.size() ? ossIds.get(i) : null,
@@ -3321,6 +3322,10 @@ public class AihrPracticeSeedService {
return Math.max(0, Math.min(100, value));
}
private String tenantId() {
return firstNonBlank(LoginHelper.getTenantId(), TENANT_ID);
}
private String firstNonBlank(String first, String second) {
return isBlank(first) ? second : first.trim();
}
@@ -3373,7 +3378,7 @@ public class AihrPracticeSeedService {
FROM aihr_practice_scenario
WHERE tenant_id = ? AND scenario_code = ? AND enabled = 1
LIMIT 1
""", this::mapScenarioSeed, TENANT_ID, scenarioId.trim());
""", this::mapScenarioSeed, tenantId(), scenarioId.trim());
return rows.stream().findFirst();
} catch (DataAccessException e) {
return Optional.empty();