Commit b5d80dba by Denys Tito

feat: sincronizar foto de matrícula del alumno (requisito 2961)

parent b308fdea
......@@ -54,7 +54,7 @@ All endpoints prefixed with `/api/v1`.
## Postgres source contract
Students: `internal/infrastructure/database/postgres.StudentQuery`, a raw SQL query (not a function) joining `matricula.ma_estudiante`/`persona.pe_persona`/`matricula.ma_matricula`/`caja.ca_plan_de_pago`, grouped per student, `payment_plans`/`payment_plans_current_year` built via `JSON_AGG(...) FILTER (...)` split on `periodo_academico_id = 14`. Read directly by `postgres.StudentReader` (`pgx` row scan, no JSON envelope) — one Mongo doc per row, requires numeric `enrollment_id`.
Students: `internal/infrastructure/database/postgres.StudentQuery`, a raw SQL query (not a function) joining `matricula.ma_estudiante`/`persona.pe_persona`/`matricula.ma_matricula`/`caja.ca_plan_de_pago`, grouped per student, `payment_plans`/`payment_plans_current_year` built via `JSON_AGG(...) FILTER (...)` split on `periodo_academico_id = 14`. Read directly by `postgres.StudentReader` (`pgx` row scan, no JSON envelope) — one Mongo doc per row, requires numeric `enrollment_id`. `student_enrollment_photo_url` sale de un `LEFT JOIN LATERAL` sobre `matricula.ma_requisito` (requisito 2961, "Foto tamaño carné"): la URL pública de Drive más reciente entre todas las matrículas del alumno, `null` si no tiene. Suma ~5 s al ciclo porque `ma_requisito` está inflada y no tiene índice por `requisito_documento_id`.
Payment plans: `internal/infrastructure/database/postgres.PaymentPlanQuery`, one document per plan of payment. Read by `postgres.StudentReader (anida los planes de pago)`.
......
......@@ -20,6 +20,7 @@ type Student struct {
PeriodID int `bson:"student_period_id"`
CicleID int `bson:"student_cicle_id"`
EnrollmentID int `bson:"enrollment_id"`
EnrollmentPhotoURL *string `bson:"student_enrollment_photo_url"`
CreatedAt time.Time `bson:"created_at"`
UpdatedAt time.Time `bson:"updated_at"`
RowHash string `bson:"row_hash,omitempty" json:"-"`
......
package postgres
// StudentQuery es el SQL crudo de la tubería de estudiantes: junta estudiante + persona + matrícula + apertura (sede/nivel/grado).
// La foto de matrícula es el requisito 2961 ("Foto tamaño carné", URL de Drive) más reciente entre todas las matrículas del alumno.
// Los planes de pago son una tubería aparte (payment_plans) — no se anidan en el documento de estudiante.
const StudentQuery = `
SELECT e.estudiante_id as student_id,
......@@ -19,7 +20,8 @@ SELECT e.estudiante_id as student_id,
ma.aula_id_asiste as student_classroom_attendance_id,
14 as student_period_id,
28 as student_cicle_id,
ma.matricula_id as enrollment_id
ma.matricula_id as enrollment_id,
foto.requisito_url as student_enrollment_photo_url
FROM matricula.ma_estudiante e
INNER JOIN persona.pe_persona pp ON e.persona_id = pp.persona_id
INNER JOIN general.gn_catalogo_siiaa sexo on pp.sexo_id = sexo.catalogo_siiaa_id
......@@ -28,6 +30,14 @@ FROM matricula.ma_estudiante e
INNER JOIN administracion.ad_sede se on ac.sede_id = se.sede_id
INNER JOIN general.gn_catalogo_siiaa nivel on ac.nivel_id = nivel.catalogo_siiaa_id
INNER JOIN academico.ac_grado grado on ac.grado_id = grado.grado_id
LEFT JOIN LATERAL (SELECT fr.requisito_url
FROM matricula.ma_matricula fm
INNER JOIN matricula.ma_requisito fr ON fr.matricula_id = fm.matricula_id
WHERE fm.estudiante_id = e.estudiante_id
AND fr.requisito_documento_id = 2961
AND fr.requisito_url LIKE 'http%'
ORDER BY fm.matricula_id DESC, fr.requisito_id DESC
LIMIT 1) foto ON true
WHERE ac.periodo_academico_id = 14
and ac.ciclo_id = 28
and ma.matricula_retirado = false
......
......@@ -59,10 +59,11 @@ func FetchStudentBasics(ctx context.Context, pool *Pool, query string) (map[int]
periodID int
cicleID int
enrollmentID int
enrollmentPhotoURL *string
)
if err := rows.Scan(&studentID, &studentCode, &studentInternalCode, &paternalLastName, &maternalLastName,
&name, &dni, &birthday, &email, &genre, &branch, &level,
&grade, &classroomAttendanceID, &periodID, &cicleID, &enrollmentID); err != nil {
&grade, &classroomAttendanceID, &periodID, &cicleID, &enrollmentID, &enrollmentPhotoURL); err != nil {
return nil, nil, fmt.Errorf("scan student row: %w", err)
}
......@@ -84,6 +85,7 @@ func FetchStudentBasics(ctx context.Context, pool *Pool, query string) (map[int]
PeriodID: periodID,
CicleID: cicleID,
EnrollmentID: enrollmentID,
EnrollmentPhotoURL: enrollmentPhotoURL,
}
order = append(order, studentID)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment