feat: Implementar reglas de negocio específicas de la empresa para la composición de plantillas de prueba

This commit is contained in:
2026-04-02 14:15:16 -03:00
parent 2b01d5d3f4
commit 4afccb89ef
3 changed files with 37 additions and 30 deletions
+15 -5
View File
@@ -9,6 +9,14 @@ use serde_json::json;
use sqlx::PgPool;
use uuid::Uuid;
const COMPANY_SPECIFIC_RULES_ORG_ID: &str = "00000000-0000-0000-0000-000000000001";
fn uses_company_specific_template_rules(org_id: Uuid) -> bool {
Uuid::parse_str(COMPANY_SPECIFIC_RULES_ORG_ID)
.map(|id| id == org_id)
.unwrap_or(false)
}
async fn validate_api_key(headers: &HeaderMap, pool: &PgPool) -> Result<Uuid, StatusCode> {
let api_key = headers
.get("X-API-Key")
@@ -218,12 +226,14 @@ async fn create_course_lesson_and_apply_template(
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
if template.2 == "CA" && template_questions.len() < 4 {
return Err(StatusCode::BAD_REQUEST);
}
if uses_company_specific_template_rules(org_id) {
if template.2 == "CA" && template_questions.len() < 4 {
return Err(StatusCode::BAD_REQUEST);
}
if template.2 != "CA" && template_questions.len() != 1 {
return Err(StatusCode::BAD_REQUEST);
if template.2 != "CA" && template_questions.len() != 1 {
return Err(StatusCode::BAD_REQUEST);
}
}
let questions_json: Vec<serde_json::Value> = template_questions
@@ -13,6 +13,14 @@ use sqlx::PgPool;
use std::time::Duration;
use uuid::Uuid;
const COMPANY_SPECIFIC_RULES_ORG_ID: &str = "00000000-0000-0000-0000-000000000001";
fn uses_company_specific_template_rules(org_id: Uuid) -> bool {
Uuid::parse_str(COMPANY_SPECIFIC_RULES_ORG_ID)
.map(|id| id == org_id)
.unwrap_or(false)
}
// ==================== Query Parameters ====================
#[derive(Debug, Deserialize)]
@@ -555,19 +563,21 @@ pub async fn apply_template_to_lesson(
return Err((StatusCode::BAD_REQUEST, "Template has no questions".to_string()));
}
// Business rules for template composition.
if matches!(template.test_type, TestType::CA) && template_questions.len() < 4 {
return Err((
StatusCode::BAD_REQUEST,
"Las plantillas CA deben tener minimo 4 preguntas".to_string(),
));
}
// Company-specific business rules for template composition.
if uses_company_specific_template_rules(org_ctx.id) {
if matches!(template.test_type, TestType::CA) && template_questions.len() < 4 {
return Err((
StatusCode::BAD_REQUEST,
"Las plantillas CA deben tener minimo 4 preguntas".to_string(),
));
}
if !matches!(template.test_type, TestType::CA) && template_questions.len() != 1 {
return Err((
StatusCode::BAD_REQUEST,
"Las plantillas MWT, MOT, FOT y FWT deben tener exactamente 1 pregunta".to_string(),
));
if !matches!(template.test_type, TestType::CA) && template_questions.len() != 1 {
return Err((
StatusCode::BAD_REQUEST,
"Las plantillas MWT, MOT, FOT y FWT deben tener exactamente 1 pregunta".to_string(),
));
}
}
// Build quiz_data JSON from template questions
@@ -205,19 +205,6 @@ export default function TestTemplateForm({ templateId, onSuccess, onCancel }: Te
return;
}
// Business rules by test type:
// - CA must have at least 4 questions.
// - MWT/MOT/FOT/FWT must have exactly 1 question.
if (formData.test_type === 'CA' && questions.length < 4) {
alert('Las plantillas CA deben tener minimo 4 preguntas.');
return;
}
if (formData.test_type !== 'CA' && questions.length !== 1) {
alert('Las plantillas MWT, MOT, FOT y FWT deben tener exactamente 1 pregunta.');
return;
}
// Validate: either mysql_course_id OR level+course_type must be provided
if (!formData.mysql_course_id && (!formData.level || !formData.course_type)) {
alert('Debes seleccionar un curso de MySQL o especificar nivel y tipo de curso manualmente');