Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions controller/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,33 @@ import (
"go.mongodb.org/mongo-driver/bson"
)

func GetAllCompanies(mongikClient *mongikModels.Mongik, noCache bool) ([]model.Company, error) {
companies, err := db.Aggregate[model.Company](mongikClient, constants.DB, constants.COLLECTION_COMPANY, []bson.M{}, noCache)
func GetAllCompanies(mongikClient *mongikModels.Mongik, noCache bool, currentPage int, companiesPerPage int) ([]model.Company, int, error) {

return companies, err
var pipeline []bson.M

pipeline = []bson.M{
{"$sort": bson.M{"createdAt": -1}},
}

if currentPage != 0 {
skip := (currentPage - 1) * companiesPerPage
limit := companiesPerPage

pipeline = []bson.M{
{"$sort": bson.M{"createdAt": -1}},
{"$skip": skip},
{"$limit": limit},
}
}

totalCompaniesArray, err := db.Aggregate[map[string]int](mongikClient, constants.DB, constants.COLLECTION_COMPANY, []bson.M{{"$count": "total"}}, noCache)
if err != nil {
return nil, 0, err
}

totalCompanies := totalCompaniesArray[0]["total"]

companies, err := db.Aggregate[model.Company](mongikClient, constants.DB, constants.COLLECTION_COMPANY, pipeline, noCache)

return companies, totalCompanies, err
}
108 changes: 98 additions & 10 deletions controller/student.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controller

import (
"sort"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -138,18 +139,84 @@ func InvalidateVerifiedFieldsOnChange(updated *studentModel.Student, current *st
}
}

func GetAllStudents(mongikClient *models.Mongik, noCache bool) (*[]model.StudentPopulated, error) {
students, err := db.Aggregate[model.StudentPopulated](mongikClient, constants.DB, constants.COLLECTION_STUDENT, []bson.M{
{
"$lookup": bson.M{
"from": constants.COLLECTION_GROUP,
"localField": "groups",
"foreignField": "_id",
"as": "groups",
func GetAllStudents(mongikClient *models.Mongik, noCache bool, currentPage int, studentsPerPage int, search string) (*[]model.StudentPopulated, int, error) {
var pipeline []bson.M

// Add search functionality
if search != "" && len(search) > 0 {
var searchConditions []bson.M

if search[0] >= '0' && search[0] <= '9' {
// If search starts with a digit, search ONLY on rollNo
// Validate that the search string is a valid number
if _, err := strconv.Atoi(search); err != nil {
return nil, 0, err
}

// Create lower and upper bounds for roll number range search
lowerBound, upperBound := getRollNumberBounds(search)

searchConditions = []bson.M{
{
"rollNo": bson.M{
"$gte": lowerBound,
"$lte": upperBound,
},
},
}
} else {
// If search starts with a letter, search ONLY on firstName or lastName
searchConditions = []bson.M{
{"firstName": bson.M{"$regex": search, "$options": "i"}},
{"lastName": bson.M{"$regex": search, "$options": "i"}},
}
}

pipeline = append(pipeline, bson.M{
"$match": bson.M{
"$or": searchConditions,
},
})
}

// Count matching students before pagination
countPipeline := make([]bson.M, len(pipeline))
copy(countPipeline, pipeline)
countPipeline = append(countPipeline, bson.M{"$count": "total"})

countResult, err := db.Aggregate[map[string]int](mongikClient, constants.DB, constants.COLLECTION_STUDENT, countPipeline, noCache)
if err != nil {
return nil, 0, err
}

totalStudents := 0
if len(countResult) > 0 {
totalStudents = countResult[0]["total"]
}

pipeline = append(pipeline, bson.M{
"$lookup": bson.M{
"from": constants.COLLECTION_GROUP,
"localField": "groups",
"foreignField": "_id",
"as": "groups",
},
}, noCache)
return &students, err
})

if currentPage != 0 && studentsPerPage != 0 {
skip := (currentPage - 1) * studentsPerPage
pipeline = append(pipeline,
bson.M{"$skip": skip},
bson.M{"$limit": studentsPerPage},
)
}

students, err := db.Aggregate[model.StudentPopulated](mongikClient, constants.DB, constants.COLLECTION_STUDENT, pipeline, noCache)
if err != nil {
return nil, 0, err
}

return &students, totalStudents, nil
}

func GetStudentById(mongikClient *models.Mongik, _id primitive.ObjectID, noCache bool) (*model.StudentPopulated, error) {
Expand Down Expand Up @@ -196,3 +263,24 @@ func GetAllStudentsOfRole(mongikClient *models.Mongik, role string, noCache bool

return &roleStudents, err
}

func getRollNumberBounds(searchDigits string) (int, int) {
paddingLength := 8 - len(searchDigits)

if paddingLength <= 0 {
num, _ := strconv.Atoi(searchDigits[:8])
return num, num
}

// Create lower bound by padding with zeros
lowerStr := searchDigits + strings.Repeat("0", paddingLength)

// Create upper bound by padding with nines
upperStr := searchDigits + strings.Repeat("9", paddingLength)

// Convert to integers
lowerBound, _ := strconv.Atoi(lowerStr)
upperBound, _ := strconv.Atoi(upperStr)

return lowerBound, upperBound
}
10 changes: 8 additions & 2 deletions handler/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package handler

import (
"net/http"
"strconv"

"github.com/FrosTiK-SD/auth/constants"
"github.com/FrosTiK-SD/auth/controller"
Expand All @@ -11,8 +12,12 @@ import (

func (h *Handler) GetAllCompanies(ctx *gin.Context) {
noCache := util.GetNoCache(ctx)
currentPage := 0

companies, err := controller.GetAllCompanies(h.MongikClient, noCache)
currentPage, err := strconv.Atoi(ctx.Request.URL.Query().Get("page"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctx.DefaultQuery()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will refactor the companies pagination in another pr. Currently it works as expected.

companiesPerPage, err := strconv.Atoi(ctx.Request.URL.Query().Get("limit"))

companies, totalCompanies, err := controller.GetAllCompanies(h.MongikClient, noCache, currentPage, companiesPerPage)

if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
Expand All @@ -23,6 +28,7 @@ func (h *Handler) GetAllCompanies(ctx *gin.Context) {
}

ctx.JSON(http.StatusOK, gin.H{
"data": companies,
"data": companies,
"totalCompanies": totalCompanies,
})
}
25 changes: 18 additions & 7 deletions handler/student.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handler
import (
"net/http"
"os"
"strconv"
"time"

"github.com/FrosTiK-SD/auth/constants"
Expand All @@ -27,22 +28,32 @@ func GetStudentRoleObjectID() primitive.ObjectID {
}

func (h *Handler) GetAllStudents(ctx *gin.Context) {

noCache := util.GetNoCache(ctx)

students, err := controller.GetAllStudents(h.MongikClient, noCache)
search := ctx.Query("search")

currentPageStr := ctx.DefaultQuery("page", "0")
studentsPerPageStr := ctx.DefaultQuery("limit", "0")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to 50

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better if the value 50 is handled in the frontend, if some issue is there from the frontend in sending the params, then it defaults to 0 and returns all the students.


currentPage, err := strconv.Atoi(currentPageStr)

studentsPerPage, err := strconv.Atoi(studentsPerPageStr)

students, totalStudents, err := controller.GetAllStudents(h.MongikClient, noCache, currentPage, studentsPerPage, search)

if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"data": nil,
"error": err,
})
return
}
ctx.JSON(http.StatusOK,
gin.H{
"data": students,
"error": nil,
})

ctx.JSON(http.StatusOK, gin.H{
"data": students,
"totalStudents": totalStudents,
"error": nil,
})
}

func (h *Handler) GetStudentById(ctx *gin.Context) {
Expand Down
Loading