From 23c387a7e9a0c8a03772532d36eba79ef6f39f06 Mon Sep 17 00:00:00 2001 From: likdan Date: Wed, 1 Nov 2023 13:45:29 +0300 Subject: [PATCH] Update query --- cmd/studyum/main.go | 2 +- db/queries/StudyPlaceUsers.sql | 54 ++++ db/queries/getLessonInfo.sql | 81 ------ db/queries/getScheduleQuery.sql | 97 -------- db/queries/studentJournal.sql | 240 ------------------ db/queries/teacherJournal.sql | 207 ---------------- internal/schedule/entities/entities.go | 38 +-- internal/schedule/repositories/repository.go | 246 +++++++------------ internal/schedule/schedule.go | 3 +- 9 files changed, 172 insertions(+), 796 deletions(-) create mode 100644 db/queries/StudyPlaceUsers.sql delete mode 100755 db/queries/getLessonInfo.sql delete mode 100755 db/queries/getScheduleQuery.sql delete mode 100755 db/queries/studentJournal.sql delete mode 100755 db/queries/teacherJournal.sql diff --git a/cmd/studyum/main.go b/cmd/studyum/main.go index c2c8968..0336466 100755 --- a/cmd/studyum/main.go +++ b/cmd/studyum/main.go @@ -66,7 +66,7 @@ func main() { loadSwagger(engine.RouterGroup, "general", "auth", "user", "schedule", "journal") setupSSL(engine.RouterGroup) - db := client.Database("Studyum") + db := client.Database("StudyumKBP") redisClient := redis.NewClient(&redis.Options{ Addr: os.Getenv("REDIS_DB_URL"), diff --git a/db/queries/StudyPlaceUsers.sql b/db/queries/StudyPlaceUsers.sql new file mode 100644 index 0000000..266aa2d --- /dev/null +++ b/db/queries/StudyPlaceUsers.sql @@ -0,0 +1,54 @@ +db.createView('StudyPlaceUsers', 'Users', [ + { + "$addFields": { + "studyPlaceInfo.studyPlaceID": "$studyPlaceInfo._id", + "studyPlaceInfo._id": "$_id" + } + }, + { + "$replaceRoot": { + "newRoot": "$studyPlaceInfo" + } + }, + { + "$group": { + "_id": null, + "user": { + "$push": "$$ROOT" + } + } + }, + { + "$lookup": { + "from": "CodeUsers", + "pipeline": [], + "as": "codeUsers" + } + }, + { + "$project": { + "users": { + "$concatArrays": ["$codeUsers", "$user"] + } + } + }, + { + "$unwind": "$users" + }, + { + "$replaceRoot": { + "newRoot": "$users" + } + }, + { + "$project": { + "_id": 1, + "studyPlaceID": 1, + "name": 1, + "role": 1, + "roleName": 1, + "tuitionGroup": 1, + "permissions": 1 + } + } + ]) \ No newline at end of file diff --git a/db/queries/getLessonInfo.sql b/db/queries/getLessonInfo.sql deleted file mode 100755 index 501540a..0000000 --- a/db/queries/getLessonInfo.sql +++ /dev/null @@ -1,81 +0,0 @@ -db.Lessons.aggregate([ - { - "$match": {"_id": new ObjectId("63b5275b5c953b713cdc425e")}, - }, - { - "$lookup": { - "from": "Lessons", - "let": { - "date": { - "$dateToString": { - "date": "$startDate", - "format": "%Y-%m-%d", - } - }, - "subject": "$subject", - "teacher": "$teacher", - "group": "$group" - }, - "pipeline": [ - { - "$match": { - "$expr": { - "$and": [ - { - "$eq": [ - "$$date", { - "$dateToString": { - "date": "$startDate", - "format": "%Y-%m-%d", - } - }, - ] - }, - { - "$eq": ["$subject", "$$subject"] - }, - { - "$eq": ["$teacher", "$$teacher"] - }, - { - "$eq": ["$group", "$$group"] - } - ] - } - } - }, - { - "$addFields": { - "marks": { - "$filter": - { - "input": "$marks", - "cond": {"$eq": ["$$marks.studentID", new ObjectId("633322073d379e063d8ee8a4")]}, - "as": "marks", - } - } - } - } - ], - "as": "lessons", - }, - }, - { - "$project": { - "lessons": 1, - }, - }, - { - "$unwind": "$lessons", - }, - { - "$replaceRoot": { - "newRoot": "$lessons" - } - }, - { - "$sort": { - "startDate": 1 - } - } -]) \ No newline at end of file diff --git a/db/queries/getScheduleQuery.sql b/db/queries/getScheduleQuery.sql deleted file mode 100755 index 90ce7f5..0000000 --- a/db/queries/getScheduleQuery.sql +++ /dev/null @@ -1,97 +0,0 @@ -db.GeneralLessons.aggregate([ - {"$match": {group: "95Т"}}, - { - "$group": { - "_id": {"dayIndex": "$dayIndex", "weekIndex": "$weekIndex"}, - "lessons": {"$push": "$$ROOT"}, - } - }, - { - "$sort": { - "_id.weekIndex": 1, - "_id.dayIndex": 1, - } - }, - { - "$group": { - "_id": null, - "days": {"$push": "$$ROOT"}, - } - }, - { - "$addFields": { - "days": { - "$function": { - "body": `function(templates, start, end) { - const getWeekNumber = (date) => { - const yearStart = new Date(date.getFullYear(), 0, 1); - return Math.ceil((((date.getTime() - yearStart.getTime()) / 86400000) + yearStart.getDay() + 1) / 7); - } - - const weekAmount = Math.max(...templates.map(t => t._id.weekIndex)) + 1 - const currentDate = new Date(start.getTime()); - const lessons = []; - while (currentDate <= end) { - const day = currentDate.getUTCDay() === 0 ? 6 : currentDate.getUTCDay() - 1; - const week = getWeekNumber(currentDate) % weekAmount; - const template = templates.find(t => t._id.dayIndex === day && t._id.weekIndex === week) - if (!!template) { - template.lessons = template.lessons.map(t => { - const date = new Date(currentDate.getTime()) - const startDate = new Date(currentDate.toLocaleDateString() + ' ' + t.startTime) - const endDate = new Date(currentDate.toLocaleDateString() + ' ' + t.endTime) - return {...t, date: day, startDate, endDate, isGeneral: true} - }) - lessons.push({...template}); - } - currentDate.setDate(currentDate.getDate() + 1); - } - - return lessons - }`, - "args": ["$days", new Date(2023, 4, 17), new Date(2023, 4, 30)], - "lang": "js", - }, - }, - }, - }, - {"$unwind": "$days"}, - {"$replaceRoot": {"newRoot": "$days"}}, - {"$addFields": {"_id": {"$first": "$lessons.date"}}}, - {"$project": {"general": "$lessons"}}, - { - "$lookup": { - "from": "Lessons", - "let": {"from": "$_id.date", "till": {"$dateAdd": {"startDate": "$_id.date", "unit": "day", "amount": 1}}}, - "pipeline": [ - { - "$match": { - "$expr": { - "$and": [{"$eq": ["$group", "95Т"]}, {"$gte": ["$startDate", "$$from"]}, {"$lt": ["$startDate", "$$till"]}] - } - } - }, - ], - "as": "lessons" - } - }, - { - "$project": { - "lessons": { - "$cond": { - "if": {"$eq": ["$lessons", []]}, - "then": "$general", - "else": "$lessons" - } - } - } - }, - {"$unwind": "$lessons"}, - {"$replaceRoot": {"newRoot": "$lessons"}}, - { - "$group": { - "_id": null, - "lessons": {"$push": "$$ROOT"} - } - }, -]) \ No newline at end of file diff --git a/db/queries/studentJournal.sql b/db/queries/studentJournal.sql deleted file mode 100755 index 6766b65..0000000 --- a/db/queries/studentJournal.sql +++ /dev/null @@ -1,240 +0,0 @@ -db.Lessons.aggregate([ - {$match: {group: "95Т"}}, //TODO studyPlaceID - { - "$addFields": { - "marks": { - "$filter": { - "input": "$marks", - "as": "mark", - "cond": {"$eq": ["$$mark.studentID", new ObjectId("633322073d379e063d8ee8a4")]}, - } - } - } - }, - { - $lookup: { - "from": "StudyPlaces", - "pipeline": [], //TODO studyPlaceID - "as": "studyPlace", - } - }, - { - $addFields: { - journalCellColor: { - $function: { - // language=JavaScript - body: `function (studyPlace, lesson) { - if (!lesson?.marks) return ""; - - let color = studyPlace.journalColors.general - for (let mark of lesson.marks) { - let type = studyPlace.lessonTypes.find(v => v.type === lesson.type); - if (type === undefined) return studyPlace.journalColors.general; - - let markType = type.marks.find(m => m.mark === mark.mark); - if (markType === undefined || markType.workOutTime === undefined) return studyPlace.journalColors.general; - - lesson.startDate.setSeconds(lesson.startDate.getSeconds() + 604800); - - color = lesson.startDate.getTime() > new Date().getTime() ? studyPlace.journalColors.warning : studyPlace.journalColors.danger; - } - - return color; - }`, - args: [{$first: "$studyPlace"}, "$$ROOT"], - lang: "js", - } - }, - } - }, - { - $group: { - _id: null, - studyPlace: {$first: {$first: "$studyPlace"}}, - lessons: {$push: "$$ROOT"}, - dates: {$addToSet: {$toDate: {$dateToString: {date: "$startDate", format: "%m/%d/%Y"}}}} - } - }, - { - $addFields: { - "dates": { - $sortArray: { - input: "$dates", - sortBy: 1 - } - }, - } - }, - { - $project: { - "lessons.studyPlace": 0, - } - }, - { - $addFields: { - rows: { - $function: { - // language=JavaScript - body: `function (studyPlace, lessons, dates) { - const groupBy = function (xs, key) { - return xs.reduce(function (rv, x) { - //TODO sort - (rv[x[key]] = rv[x[key]] || []).push(x); - return rv; - }, {}); - }; - - let groupedLessons = groupBy(lessons, 'subject') - - for (const [key, value] of Object.entries(groupedLessons)) { - groupedLessons[key] = value.sort((a, b) => a.startDate - b.startDate) - } - - let rows = [] - for (const [key, value] of Object.entries(groupedLessons)) { - rows.unshift({title: key, lessons: [], info: {}}) - - let added = 0 - for (let i = 0; i < value.length; i++) { - let startTime = new Date(value[i].startDate.toDateString()).getTime() - if (i > 0 && new Date(value[i - 1].startDate.toDateString()).getTime() === startTime) { - let prevLesson = rows[0].lessons.at(-1) - - if (value[i].journalCellColor != studyPlace.journalColors.general && prevLesson.journalCellColor == studyPlace.journalColors.general) { - prevLesson.journalCellColor = value[i].journalCellColor - } - - prevLesson.marks = prevLesson.marks?.concat(value[i].marks ?? []) - added-- - continue - } - while (dates[i + added].getTime() !== startTime) { - rows[0].lessons.push(null) - added++ - } - rows[0].lessons.push(value[i]) - } - for (let i = added + value.length; i < dates.length; i++) { - rows[0].lessons.push(null) - } - - let marks = rows[0].lessons.flatMap(l => l?.marks ?? []).map(m => Number.parseInt(m.mark)).filter(m => m) - rows[0].numericMarksSum = marks.reduce((sum, a) => sum + a, 0) - rows[0].numericMarksAmount = marks.length - - let color = studyPlace.journalColors.general - for (let lesson of rows[0].lessons) { - if (lesson == null) continue - - if (lesson.journalCellColor == studyPlace.journalColors.warning) - color = studyPlace.journalColors.warning - - if (lesson.journalCellColor == studyPlace.journalColors.danger){ - color = studyPlace.journalColors.danger - break - } - } - - rows[0].color = color - } - - return rows.sort((a, b) => a.title > b.title) - }`, - args: ["$studyPlace", "$lessons", "$dates"], - lang: "js", - } - } - } - }, - { - "$addFields": { - "rows": { - "$map": { - "input": "$" + "rows", - "as": "rows", - "in": { - "$function": { - // language=JavaScript - body: `function(studyPlace, row) { - let marks = row.lessons.flatMap(l => l?.marks ?? []) - - let markList = studyPlace.lessonTypes - .flatMap(t => t.marks.concat(t.standaloneMarks ?? [])).map(m => m.mark) - .filter((v, i, a) => a.indexOf(v) === i) - - row.marks = marks - - let marksAmount = {} - for (let m of markList) { - marksAmount[m] = { - mark: m, - amount: 0 - } - } - for (let mark of marks) marksAmount[mark.mark].amount++ - row.marksAmount = Object.values(marksAmount) - - marks = marks.map(m => Number.parseInt(m.mark)).filter(m => m) - - row.numericMarksSum = marks.reduce((sum, a) => sum + a, 0) - row.numericMarksAmount = marks.length - - let absences = row.lessons.flatMap(l => l?.absences ?? []).map(a => a.time) - row.absencesAmount = absences.filter(v => !v).length - row.absencesTime = absences.filter(v => v).reduce((sum, a) => sum + a, 0) - - let color = studyPlace.journalColors.general - for (let lesson of row.lessons) { - if (lesson == null) continue - - if (lesson.journalCellColor == studyPlace.journalColors.warning) - color = studyPlace.journalColors.warning - - if (lesson.journalCellColor == studyPlace.journalColors.danger){ - color = studyPlace.journalColors.danger - break - } - } - - row.color = color - return row - }`, - "args": ["$studyPlace", "$$rows"], - "lang": "js", - } - }, - }, - } - }, - }, - { - $addFields: { - "info": { - "editable": false, - "studyPlace": "$studyPlace" - } - } - }, - { - $addFields: { - dates: { - $map: - { - input: "$dates", - as: "date", - in: { - startDate: "$$date", - endDate: "$$date" - } - } - } - } - }, - { - $project: { - lessons: 0, - studyPlace: 0 - } - }, -]) - diff --git a/db/queries/teacherJournal.sql b/db/queries/teacherJournal.sql deleted file mode 100755 index dff9659..0000000 --- a/db/queries/teacherJournal.sql +++ /dev/null @@ -1,207 +0,0 @@ -db.Users.aggregate([ - { - "$group": {"_id": null, "user": {"$push": "$$ROOT"}} - }, - { - "$project": { - "user._id": 1, - "user.name": 1, - "user.role": 1, - "user.roleName": 1 - } - }, - { - "$lookup": { - "from": "SignUpCodes", - "pipeline": [ - { - "$project": { - "name": 1, - "role": 1, - "roleName": 1 - } - }, - ], - "as": "codeUsers", - } - }, - { - "$project": { - "user": { - "$filter": { - "input": {"$concatArrays": ["$codeUsers", "$user"]}, - "as": "user", - "cond": {"$and": [{"$eq": ["$$user.role", "group"]}, {"$eq": ["$$user.roleName", "95Т"]}]} - } - } - } - }, - { - "$lookup": { - "from": "Lessons", - "let": {"userID": "$_id"}, - "pipeline": [ - { - "$match": { - "subject": "КПиЯП", - "group": "95Т" - } - }, - ], - "as": "lessons" - } - }, - { - "$lookup": { - "from": "StudyPlaces", - "pipeline": [], - "as": "studyPlace" - } - }, - { - "$addFields": { - "lessons": { - "$sortArray": { - "input": "$lessons", - "sortBy": {"startDate": 1}, - } - } - } - }, - { - "$unwind": "$user" - }, - { - "$unwind": "$lessons" - }, - { - "$lookup": { - "from": "Marks", - "localField": "lessons._id", - "foreignField": "lessonID", - "let": {"userID": "$user._id"}, - "pipeline": [ - { - "$match": { - "$expr": {"$and": [{"$eq": ["$studentID", "$$userID"]}]} - } - } - ], - "as": "lessons.marks" - } - }, - { - "$addFields": { - "lessons.journalCellColor": { - "$function": { - // language=JavaScript - "body": `function (studyPlace, lesson) { - if (lesson === undefined || lesson.marks === undefined) return ""; - - let color = studyPlace.journalColors.general - for (let mark of lesson.marks) { - let type = studyPlace.lessonTypes.find(v => v.type === lesson.type); - if (type === undefined) return studyPlace.journalColors.general; - - let markType = type.marks.find(m => m.mark === mark.mark); - if (markType === undefined || markType.workOutTime === undefined) return studyPlace.journalColors.general; - - lesson.startDate.setSeconds(lesson.startDate.getSeconds() + markType.workOutTime); - - color = lesson.startDate.getTime() > new Date().getTime() ? studyPlace.journalColors.warning : studyPlace.journalColors.danger; - } - - return color; - }`, - "args": [{"$first": "$studyPlace"}, "$lessons"], - "lang": "js", - }, - }, - } - }, - { - "$group": { - "_id": { - "_id": "$user._id", - "title": "$user.name", - }, - "lessons": {"$push": "$lessons"}, - "studyPlace": {"$first": {"$first": "$studyPlace"}} - } - }, - { - "$addFields": { - "info": { - "$function": { - "body": `function (studyPlace, lessons) { - let info = {} - - let marks = lessons.flatMap(l => l?.marks ?? []).map(m => Number.parseInt(m.mark)).filter(m => m) - info.numericMarksSum = marks.reduce((sum, a) => sum + a, 0) - info.numericMarksAmount = marks.length - - let color = studyPlace.journalColors.general - for (let lesson of lessons) { - if (lesson == null) continue - - if (lesson.journalCellColor == studyPlace.journalColors.warning) - color = studyPlace.journalColors.warning - - if (lesson.journalCellColor == studyPlace.journalColors.danger){ - color = studyPlace.journalColors.danger - break - } - } - - info.color = color - return info - }`, - "args": ["$studyPlace", "$lessons"], - "lang": "js", - } - } - } - }, - { - "$project": { - "row": { - "_id": "$_id._id", - "title": "$_id.title", - "numericMarksSum": "$info.numericMarksSum", - "numericMarksAmount": "$info.numericMarksAmount", - "color": "$info.color", - "lessons": "$lessons" - }, - "studyPlace": "$studyPlace", - } - }, - { - "$group": { - "_id": null, - "dates": {"$first": "$row.lessons"}, - "rows": {"$push": "$row"}, - "studyPlace": {"$first": "$studyPlace"} - } - }, - { - "$project": { - "dates.marks": 0, - "dates.journalCellColor": 0, - "dates.studyPlace": 0, - "rows.studyPlace": 0 - } - }, - { - "$addFields": { - "info": { - "editable": true, - "studyPlace": "$studyPlace", - } - } - }, - { - "$project": { - "studyPlace": 0 - } - } -]) diff --git a/internal/schedule/entities/entities.go b/internal/schedule/entities/entities.go index 839b49a..be3a1d4 100755 --- a/internal/schedule/entities/entities.go +++ b/internal/schedule/entities/entities.go @@ -42,24 +42,26 @@ type Lesson struct { } type GeneralLesson struct { - Id primitive.ObjectID `json:"id" bson:"_id"` - StudyPlaceId primitive.ObjectID `json:"studyPlaceId" bson:"studyPlaceId"` - PrimaryColor string `json:"primaryColor" bson:"primaryColor"` - SecondaryColor string `json:"secondaryColor" bson:"secondaryColor"` - EndTime string `json:"endTime" bson:"endTime"` - StartTime string `json:"startTime" bson:"startTime"` - Subject string `json:"subject" bson:"subject"` - Group string `json:"group" bson:"group"` - Teacher string `json:"teacher" bson:"teacher"` - Room string `json:"room" bson:"room"` - SubjectID primitive.ObjectID `json:"subjectID" bson:"subjectID"` - GroupID primitive.ObjectID `json:"groupID" bson:"groupID"` - TeacherID primitive.ObjectID `json:"teacherID§" bson:"teacherID"` - RoomID primitive.ObjectID `json:"roomID" bson:"roomID"` - Type string `json:"type" bson:"type"` - LessonIndex int `json:"lessonIndex" bson:"lessonIndex"` - DayIndex int `json:"dayIndex" bson:"dayIndex"` - WeekIndex int `json:"weekIndex" bson:"weekIndex"` + Id primitive.ObjectID `json:"id" bson:"_id"` + StudyPlaceId primitive.ObjectID `json:"studyPlaceId" bson:"studyPlaceId"` + PrimaryColor string `json:"primaryColor" bson:"primaryColor"` + SecondaryColor string `json:"secondaryColor" bson:"secondaryColor"` + EndTime string `json:"endTime" bson:"endTime"` + StartTime string `json:"startTime" bson:"startTime"` + Subject string `json:"subject" bson:"subject"` + Group string `json:"group" bson:"group"` + Teacher string `json:"teacher" bson:"teacher"` + Room string `json:"room" bson:"room"` + SubjectID primitive.ObjectID `json:"subjectID" bson:"subjectID"` + GroupID primitive.ObjectID `json:"groupID" bson:"groupID"` + TeacherID primitive.ObjectID `json:"teacherID§" bson:"teacherID"` + RoomID primitive.ObjectID `json:"roomID" bson:"roomID"` + Type string `json:"type" bson:"type"` + LessonIndex int `json:"lessonIndex" bson:"lessonIndex"` + DayIndex int `json:"dayIndex" bson:"dayIndex"` + WeekIndex int `json:"weekIndex" bson:"weekIndex"` + StartTimeMinutes int `json:"startTimeMinutes" bson:"startTimeMinutes"` + EndTimeMinutes int `json:"endTimeMinutes" bson:"endTimeMinutes"` } type Info struct { diff --git a/internal/schedule/repositories/repository.go b/internal/schedule/repositories/repository.go index 4f38cee..f8a8a5b 100755 --- a/internal/schedule/repositories/repository.go +++ b/internal/schedule/repositories/repository.go @@ -48,12 +48,13 @@ type repository struct { studyPlaces *mongo.Collection lessons *mongo.Collection generalLessons *mongo.Collection + schedule *mongo.Collection database *mongo.Database } -func NewScheduleRepository(studyPlaces *mongo.Collection, lessons *mongo.Collection, generalLessons *mongo.Collection, database *mongo.Database) Repository { - return &repository{studyPlaces: studyPlaces, lessons: lessons, generalLessons: generalLessons, database: database} +func NewScheduleRepository(studyPlaces *mongo.Collection, lessons *mongo.Collection, generalLessons *mongo.Collection, schedule *mongo.Collection, database *mongo.Database) Repository { + return &repository{studyPlaces: studyPlaces, lessons: lessons, generalLessons: generalLessons, schedule: schedule, database: database} } func (s *repository) GetTypeID(ctx context.Context, studyPlaceID primitive.ObjectID, type_, typeName string) (primitive.ObjectID, error) { @@ -101,184 +102,127 @@ func (s *repository) GetSchedule(ctx context.Context, studyPlaceID primitive.Obj type_ = "group" } - cursor, err := s.generalLessons.Aggregate(ctx, bson.A{ - bson.M{"$match": bson.M{"studyPlaceId": studyPlaceID, type_ + "ID": typeID}}, - bson.M{"$group": bson.M{ - "_id": bson.M{"dayIndex": "$dayIndex", "weekIndex": "$weekIndex"}, - "lessons": bson.M{"$push": "$$ROOT"}, - }}, + cursor, err := s.schedule.Aggregate(ctx, bson.A{ bson.M{ - "$sort": bson.M{ - "_id.weekIndex": 1, - "_id.dayIndex": 1, + "$match": bson.M{ + "date": bson.M{"$gte": startDate, "$lte": endDate}, + "status": bson.M{"$ne": "draft"}, }, }, - bson.M{"$group": bson.M{ - "_id": nil, - "days": bson.M{"$push": "$$ROOT"}, - }}, - bson.M{ - "$addFields": bson.M{ - "days": bson.M{ - "$function": bson.M{ - "body": `function(templates, start, end) { - const getWeekNumber = (date) => { - const yearStart = new Date(date.getFullYear(), 0, 1); - return Math.ceil((((date.getTime() - yearStart.getTime()) / 86400000) + yearStart.getDay() + 1) / 7); - } - - const weekAmount = Math.max(...templates.map(t => t._id.weekIndex)) + 1 - const currentDate = new Date(start.getTime()); - const lessons = []; - while (currentDate <= end) { - const day = currentDate.getUTCDay() === 0 ? 6 : currentDate.getUTCDay() - 1; - const week = getWeekNumber(currentDate) % weekAmount; - const template = templates.find(t => t._id.dayIndex === day && t._id.weekIndex === week) - if (!!template) { - template.lessons = template.lessons.map(t => { - const date = new Date(currentDate.getTime()) - const startDate = new Date(currentDate.toLocaleDateString() + ' ' + t.startTime) - const endDate = new Date(currentDate.toLocaleDateString() + ' ' + t.endTime) - return {...t, date, startDate, endDate, isGeneral: true} - }) - lessons.push({...template}); - } - currentDate.setDate(currentDate.getDate() + 1); - } - - return lessons - }`, - "args": bson.A{"$days", startDate, endDate}, - "lang": "js", - }, - }, - }, - }, - bson.M{"$unwind": "$days"}, - bson.M{"$replaceRoot": bson.M{"newRoot": "$days"}}, - bson.M{"$addFields": bson.M{"_id.date": bson.M{"$first": "$lessons.date"}}}, - bson.M{"$project": bson.M{"general": "$lessons"}}, bson.M{ "$lookup": bson.M{ "from": "Lessons", - "let": bson.M{"from": "$_id.date", "till": bson.M{"$dateAdd": bson.M{"startDate": "$_id.date", "unit": "day", "amount": 1}}}, + "let": bson.M{"date": "$date", "status": "$status"}, "pipeline": bson.A{ bson.M{ - "$match": bson.M{ - "$expr": bson.M{ - "$and": bson.A{ - bson.M{"$eq": bson.A{onlyGeneral, false}}, - bson.M{"$eq": bson.A{"$" + type_ + "ID", typeID}}, - bson.M{"$eq": bson.A{"$studyPlaceId", studyPlaceID}}, - //todo - bson.M{"$gte": bson.A{"$startDate", "$$from"}}, - //bson.M{"$lt": bson.A{"$startDate", "$$till"}}, - }, - }, - }, + "$match": bson.M{"$expr": bson.M{"$and": bson.A{ + bson.M{"$eq": bson.A{"$$date", bson.M{"$dateTrunc": bson.M{"date": "$startDate", "unit": "day"}}}}, + bson.M{"$eq": bson.A{"$" + type_ + "ID", typeID}}, + }}}, }, bson.M{ - "$sort": bson.M{ - "startDate": 1, - }, + "$addFields": bson.M{"status": "$$status"}, }, }, "as": "lessons", }, }, + bson.M{ + "$group": bson.M{ + "_id": nil, + "items": bson.M{"$push": "$$ROOT"}}, + }, bson.M{ "$project": bson.M{ - "lessons": bson.M{ - "$cond": bson.M{ - "if": bson.M{"$eq": bson.A{"$lessons", bson.A{}}}, - "then": "$general", - "else": "$lessons", + "items": bson.M{ + "$function": bson.M{ + "body": `function (items, start, end) { +const currentDate = new Date(start); +while (currentDate <= end) { + if (!items.some(item => item.date.getTime() === currentDate.getTime())) { + items.push({date: new Date(currentDate)}); + } + currentDate.setDate(currentDate.getDate() + 1); +} +return items; +}`, + "args": bson.A{"$items", startDate, endDate}, + "lang": "js", }, }, }, }, - bson.M{"$unwind": "$lessons"}, - bson.M{"$replaceRoot": bson.M{"newRoot": "$lessons"}}, - bson.M{ - "$lookup": bson.M{ - "from": "StudyPlaceUsers", - "localField": "teacherID", - "foreignField": "_id", - "as": "teacher", - }, - }, - bson.M{ - "$addFields": bson.M{ - "teacher": bson.M{"$first": "$teacher.roleName"}, - }, - }, - bson.M{ - "$lookup": bson.M{ - "from": "Groups", - "localField": "groupID", - "foreignField": "_id", - "as": "group", - }, - }, - bson.M{ - "$addFields": bson.M{ - "group": bson.M{"$first": "$group.group"}, - }, - }, - bson.M{ - "$lookup": bson.M{ - "from": "Subjects", - "localField": "subjectID", - "foreignField": "_id", - "as": "subject", - }, - }, - bson.M{ - "$addFields": bson.M{ - "subject": bson.M{"$first": "$subject.subject"}, - }, - }, - bson.M{ - "$lookup": bson.M{ - "from": "Rooms", - "localField": "roomID", - "foreignField": "_id", - "as": "room", - }, - }, - bson.M{ - "$addFields": bson.M{ - "room": bson.M{"$first": "$room.room"}, - }, - }, - bson.M{ - "$group": bson.M{ - "_id": nil, - "info": bson.M{"$first": bson.M{ - "studyPlaceInfo": bson.M{ - "_id": studyPlaceID, + bson.M{"$unwind": "$items"}, + bson.M{"$replaceRoot": bson.M{"newRoot": "$items"}}, + bson.M{"$lookup": bson.M{ + "from": "GeneralLessons", + "let": bson.M{"lessons": "$lessons", "date": "$date"}, + "pipeline": bson.A{ + bson.M{ + "$match": bson.M{"$expr": bson.M{"$and": bson.A{ + bson.M{"$ne": bson.A{bson.M{"$type": "$$lessons"}, "array"}}, + bson.M{"$eq": bson.A{"$" + type_ + "ID", typeID}}, + bson.M{"$eq": bson.A{"$dayIndex", bson.M{"$dayOfWeek": "$$date"}}}, + }}}, + }, + bson.M{ + "$addFields": bson.M{ + "startDate": bson.M{"$dateAdd": bson.M{"startDate": "$$date", "unit": "minute", "amount": "$startTimeMinutes"}}, + "endDate": bson.M{"$dateAdd": bson.M{"startDate": "$$date", "unit": "minute", "amount": "$endTimeMinutes"}}, + "status": "general", }, - "type": type_, - "typeName": typeName, - "startDate": startDate, - "endDate": endDate, - }}, - "lessons": bson.M{"$push": "$$ROOT"}, - }, + }, + }, "as": "generalLessons"}, }, bson.M{ - "$lookup": bson.M{ - "from": "StudyPlaces", - "localField": "info.studyPlaceInfo._id", - "foreignField": "_id", - "as": "info.studyPlaceInfo.title", - }, + "$project": bson.M{ + "lessons": bson.M{"$cond": bson.M{ + "if": bson.M{"$eq": bson.A{bson.M{"$type": "$lessons"}, "array"}}, + "then": "$lessons", + "else": "$generalLessons"}, + }}, }, + bson.M{"$unwind": "$lessons"}, + bson.M{"$replaceRoot": bson.M{"newRoot": "$lessons"}}, + bson.M{"$lookup": bson.M{"from": "StudyPlaceUsers", "localField": "teacherID", "foreignField": "_id", "as": "teacher"}}, + bson.M{"$lookup": bson.M{"from": "Groups", "localField": "groupID", "foreignField": "_id", "as": "group"}}, + bson.M{"$lookup": bson.M{"from": "Subjects", "localField": "subjectID", "foreignField": "_id", "as": "subject"}}, + bson.M{"$lookup": bson.M{"from": "Rooms", "localField": "roomID", "foreignField": "_id", "as": "room"}}, bson.M{ "$addFields": bson.M{ - "info.studyPlaceInfo.title": bson.M{"$first": "$info.studyPlaceInfo.title.name"}, + "subject": bson.M{"$first": "$subject.subject"}, + "room": bson.M{"$first": "$room.room"}, + "teacher": bson.M{"$first": "$teacher.roleName"}, + "group": bson.M{"$first": "$group.group"}, }, }, + bson.M{"$project": bson.M{ + "endDate": 1, + "startDate": 1, + "subjectID": 1, + "subject": 1, + "teacherID": 1, + "teacher": 1, + "groupID": 1, + "group": 1, + "roomID": 1, + "room": 1, + "lessonIndex": 1, + "primaryColor": 1, + "secondaryColor": 1, + "status": 1, + }}, + bson.M{"$group": bson.M{ + "_id": nil, + "lessons": bson.M{"$push": "$$ROOT"}, + "info": bson.M{"$first": bson.M{ + "studyPlaceInfo": bson.M{"_id": studyPlaceID}, + "type": type_, + "typeName": typeName, //todo remove + "startDate": startDate, + "endDate": endDate, + }}, + }}, }) if err != nil { return entities.Schedule{}, err diff --git a/internal/schedule/schedule.go b/internal/schedule/schedule.go index d8ea9f2..10ba3d7 100644 --- a/internal/schedule/schedule.go +++ b/internal/schedule/schedule.go @@ -23,8 +23,9 @@ func New(core *gin.RouterGroup, auth auth.Middleware, apps apps.Controller, gene studyPlaces := db.Collection("StudyPlaces") lessons := db.Collection("Lessons") generalLessons := db.Collection("GeneralLessons") + schedule := db.Collection("Schedule") - repository := repositories.NewScheduleRepository(studyPlaces, lessons, generalLessons, db) + repository := repositories.NewScheduleRepository(studyPlaces, lessons, generalLessons, schedule, db) validator := validators.NewSchedule(v.New()) controller := controllers.NewScheduleController(repository, general, apps, validator)