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`. ...@@ -54,7 +54,7 @@ All endpoints prefixed with `/api/v1`.
## Postgres source contract ## 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)`. 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 { ...@@ -20,6 +20,7 @@ type Student struct {
PeriodID int `bson:"student_period_id"` PeriodID int `bson:"student_period_id"`
CicleID int `bson:"student_cicle_id"` CicleID int `bson:"student_cicle_id"`
EnrollmentID int `bson:"enrollment_id"` EnrollmentID int `bson:"enrollment_id"`
EnrollmentPhotoURL *string `bson:"student_enrollment_photo_url"`
CreatedAt time.Time `bson:"created_at"` CreatedAt time.Time `bson:"created_at"`
UpdatedAt time.Time `bson:"updated_at"` UpdatedAt time.Time `bson:"updated_at"`
RowHash string `bson:"row_hash,omitempty" json:"-"` RowHash string `bson:"row_hash,omitempty" json:"-"`
......
package postgres package postgres
// StudentQuery es el SQL crudo de la tubería de estudiantes: junta estudiante + persona + matrícula + apertura (sede/nivel/grado). // 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. // Los planes de pago son una tubería aparte (payment_plans) — no se anidan en el documento de estudiante.
const StudentQuery = ` const StudentQuery = `
SELECT e.estudiante_id as student_id, SELECT e.estudiante_id as student_id,
...@@ -19,7 +20,8 @@ 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, ma.aula_id_asiste as student_classroom_attendance_id,
14 as student_period_id, 14 as student_period_id,
28 as student_cicle_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 FROM matricula.ma_estudiante e
INNER JOIN persona.pe_persona pp ON e.persona_id = pp.persona_id 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 INNER JOIN general.gn_catalogo_siiaa sexo on pp.sexo_id = sexo.catalogo_siiaa_id
...@@ -28,6 +30,14 @@ FROM matricula.ma_estudiante e ...@@ -28,6 +30,14 @@ FROM matricula.ma_estudiante e
INNER JOIN administracion.ad_sede se on ac.sede_id = se.sede_id 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 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 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 WHERE ac.periodo_academico_id = 14
and ac.ciclo_id = 28 and ac.ciclo_id = 28
and ma.matricula_retirado = false and ma.matricula_retirado = false
......
...@@ -59,10 +59,11 @@ func FetchStudentBasics(ctx context.Context, pool *Pool, query string) (map[int] ...@@ -59,10 +59,11 @@ func FetchStudentBasics(ctx context.Context, pool *Pool, query string) (map[int]
periodID int periodID int
cicleID int cicleID int
enrollmentID int enrollmentID int
enrollmentPhotoURL *string
) )
if err := rows.Scan(&studentID, &studentCode, &studentInternalCode, &paternalLastName, &maternalLastName, if err := rows.Scan(&studentID, &studentCode, &studentInternalCode, &paternalLastName, &maternalLastName,
&name, &dni, &birthday, &email, &genre, &branch, &level, &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) 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] ...@@ -84,6 +85,7 @@ func FetchStudentBasics(ctx context.Context, pool *Pool, query string) (map[int]
PeriodID: periodID, PeriodID: periodID,
CicleID: cicleID, CicleID: cicleID,
EnrollmentID: enrollmentID, EnrollmentID: enrollmentID,
EnrollmentPhotoURL: enrollmentPhotoURL,
} }
order = append(order, studentID) 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