feat: zjazd (meeting) on readings and materials

The Pulpit hero lists what to read for the current or next zjazd, so
readings and materials get a nullable meeting_id (FK to jz_bm_meetings,
ON DELETE SET NULL, indexed). The reading admin form gets a "Na zjazd"
picker, the student reading JSON carries meeting_id, and the management
/readings records filter and validate it.
This commit is contained in:
Jakub Zych
2026-10-27 01:41:48 +01:00
parent 8843e73f98
commit 3241cc9894
15 changed files with 94 additions and 15 deletions

View File

@@ -173,6 +173,7 @@ type readingJSON struct {
ID uint `json:"id"`
CourseID uint `json:"course_id"`
Course *courseRef `json:"course"`
MeetingID *uint `json:"meeting_id"`
Title string `json:"title"`
Author *string `json:"author"`
Source *string `json:"source"`

View File

@@ -0,0 +1,28 @@
package api
import (
"encoding/json"
"strings"
"testing"
)
// TestReadingJSONCarriesMeetingID checks that meeting_id is always present
// in a reading, as a number or as null.
func TestReadingJSONCarriesMeetingID(t *testing.T) {
id := uint(4)
for _, tc := range []struct {
meeting *uint
want string
}{
{&id, `"meeting_id":4`},
{nil, `"meeting_id":null`},
} {
b, err := json.Marshal(readingJSON{ID: 1, Title: "Lektura", MeetingID: tc.meeting})
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(b), tc.want) {
t.Errorf("reading JSON %s does not contain %s", b, tc.want)
}
}
}

View File

@@ -42,6 +42,7 @@ func listReadings(db *gorm.DB, userID, courseID uint) ([]readingJSON, error) {
ID: row.ID,
CourseID: idOf(row.CourseID),
Course: newCourseRef(courses[idOf(row.CourseID)]),
MeetingID: row.MeetingID,
Title: row.Title,
Author: row.Author,
Source: row.Source,