Skip to content

Commit

Permalink
Merge branch 'pvf' of https://github.com/AkshatGupta15/ras-backend in…
Browse files Browse the repository at this point in the history
…to pvf
  • Loading branch information
AkshatGupta15 committed Jul 5, 2024
2 parents c850a24 + 59f094f commit f5ee49c
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 14 deletions.
58 changes: 58 additions & 0 deletions application/db.student.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,64 @@ func createEventStudents(ctx *gin.Context, eventStudents *[]EventStudent) error
return tx.Error
}

func getCompanyRecruitmentStats(ctx *gin.Context, cid uint, stats *[]statsResponse) error {
tx := db.WithContext(ctx).Model(&EventStudent{}).
Joins("JOIN proforma_events ON proforma_events.name IN ? AND proforma_events.id = event_students.proforma_event_id", []EventType{Recruited, PIOPPOACCEPTED}).
Joins("JOIN proformas ON proformas.id = proforma_events.proforma_id AND proformas.company_recruitment_cycle_id = ?", cid).
Select("event_students.student_recruitment_cycle_id, proformas.company_name, proformas.profile ,proforma_events.name as type").
Order("event_students.student_recruitment_cycle_id").
Find(stats)
return tx.Error
}
func fetchCompanyRecruitCount(ctx *gin.Context, cids []uint) (map[uint]int, error) {
resultCounts := make(map[uint]int)

var stats []companyRecruitResponce
tx := db.WithContext(ctx).Model(&EventStudent{}).
Joins("JOIN proforma_events ON proforma_events.name IN ? AND proforma_events.id = event_students.proforma_event_id", []EventType{Recruited, PIOPPOACCEPTED}).
Joins("JOIN proformas ON proformas.id = proforma_events.proforma_id").
Where("proformas.company_recruitment_cycle_id IN ?", cids).
Select("proformas.company_recruitment_cycle_id, COUNT(*) as count").
Group("proformas.company_recruitment_cycle_id").
Order("proformas.company_recruitment_cycle_id").
Find(&stats)

if tx.Error != nil {
return nil, tx.Error
}

// Populate resultCounts map
for _, stat := range stats {
resultCounts[stat.CompanyRecruitmentCycleID] = stat.Count
}

return resultCounts, nil
}

func fetchCompanyPPOCount(ctx *gin.Context, cids []uint) (map[uint]int, error) {
resultCounts := make(map[uint]int)

var stats []companyRecruitResponce
tx := db.WithContext(ctx).Model(&EventStudent{}).
Joins("JOIN proforma_events ON proforma_events.name IN ? AND proforma_events.id = event_students.proforma_event_id", []EventType{PIOPPOACCEPTED}).
Joins("JOIN proformas ON proformas.id = proforma_events.proforma_id").
Where("proformas.company_recruitment_cycle_id IN ?", cids).
Select("proformas.company_recruitment_cycle_id, COUNT(*) as count").
Group("proformas.company_recruitment_cycle_id").
Order("proformas.company_recruitment_cycle_id").
Find(&stats)

if tx.Error != nil {
return nil, tx.Error
}

for _, stat := range stats {
resultCounts[stat.CompanyRecruitmentCycleID] = stat.Count
}

return resultCounts, nil
}

func getRecruitmentStats(ctx *gin.Context, rid uint, stats *[]statsResponse) error {
tx := db.WithContext(ctx).Model(&EventStudent{}).
Joins("JOIN proforma_events ON proforma_events.name IN ? AND proforma_events.id = event_students.proforma_event_id", []EventType{Recruited, PIOPPOACCEPTED}).
Expand Down
2 changes: 2 additions & 0 deletions application/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func AdminRouter(mail_channel chan mail.Mail, r *gin.Engine) {
admin.DELETE("pvf/:pid", deletePVFHandler)

admin.GET("/company/:cid/proforma", getProformaByCompanyHandler)
admin.GET("/company/:cid/stats", getCompanyRecruitStatsHandler)
admin.POST("/company/count", fetchCompanyRecruitCountHandler)

admin.GET("/proforma", getAllProformasHandler)
admin.POST("/proforma", postProformaHandler)
Expand Down
79 changes: 79 additions & 0 deletions application/stats.recruitment.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,85 @@ type statsRecruitmentResponse struct {
Type string `json:"type"`
}

type companyRecruitResponce struct {
CompanyRecruitmentCycleID uint `json:"company_recruitment_cycle_id"`
Count int `json:"count"`
}

func fetchCompanyRecruitCountHandler(c *gin.Context) {
var cids []uint

if err := c.ShouldBindJSON(&cids); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
return
}

recruitCounts, err := fetchCompanyRecruitCount(c, cids)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error"})
return
}
ppoCounts, err := fetchCompanyPPOCount(c, cids)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error"})
return
}

c.JSON(http.StatusOK, gin.H{"recruitCounts": recruitCounts, "ppoCount": ppoCounts})
}

func getCompanyRecruitStatsHandler(ctx *gin.Context) {
cid, err := util.ParseUint(ctx.Param("cid"))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var stats []statsResponse
err = getCompanyRecruitmentStats(ctx, cid, &stats)

if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var srids []uint
for _, stat := range stats {
srids = append(srids, stat.StudentRecruitmentCycleID)
}

var students []rc.StudentRecruitmentCycle
err = rc.FetchStudentBySRID(ctx, srids, &students)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var studentsMap = make(map[uint]*rc.StudentRecruitmentCycle)
for i := range students {
studentsMap[students[i].ID] = &students[i]
}

var studentResponse []statsRecruitmentResponse
for _, stat := range stats {
student := studentsMap[stat.StudentRecruitmentCycleID]
res := statsRecruitmentResponse{
ID: student.ID,
Name: student.Name,
Email: student.Email,
RollNo: student.RollNo,
ProgramDepartmentID: student.ProgramDepartmentID,
SecondaryProgramDepartmentID: student.SecondaryProgramDepartmentID,
CompanyName: stat.CompanyName,
Profile: stat.Profile,
Type: stat.Type,
}
studentResponse = append(studentResponse, res)
}

ctx.JSON(http.StatusOK, gin.H{"student": studentResponse})

}

func getStatsHandler(ctx *gin.Context) {
rid, err := util.ParseUint(ctx.Param("rid"))
if err != nil {
Expand Down
42 changes: 30 additions & 12 deletions mail/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net/smtp"
"strings"
"time"

"text/template"
"github.com/sirupsen/logrus"
)

Expand All @@ -16,23 +16,41 @@ type Mail struct {
}

func (mail *Mail) BuildMessage() []byte {
message := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\r\n"
message += fmt.Sprintf("From: Recruitment Automation System IITK<%s>\r\n", sender)
message += fmt.Sprintf("Subject: %s | Recruitment Automation System\r\n", mail.Subject)

type TemplateData struct {
To []string
Subject string
Body string
}

var message strings.Builder

msg := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\r\n"
msg += fmt.Sprintf("From: Recruitment Automation System IITK<%s>\r\n", sender)
msg += fmt.Sprintf("Subject: %s\r\n", mail.Subject)

// If mass mailing, BCC all the users
if len(mail.To) == 1 {
message += fmt.Sprintf("To: %s\r\n\r\n", mail.To[0])
msg += fmt.Sprintf("To: %s\r\n\r\n", mail.To[0])
} else {
message += fmt.Sprintf("To: Undisclosed Recipients<%s>\r\n\r\n", webteam)
msg += fmt.Sprintf("To: Undisclosed Recipients<%s>\r\n\r\n", webteam)
}

message += strings.Replace(mail.Body, "\n", "<br>", -1)
message += "<br><br>--<br>Recruitment Automation System<br>"
message += "Indian Institute of Technology Kanpur<br><br>"
message += "<small>This is an auto-generated email. Please do not reply.</small>"
message.WriteString(msg)

return []byte(message)
bodyWithLineBreaks := strings.ReplaceAll(mail.Body, "\n", "<br>")

tmpl := template.Must(template.New("Template").Parse(DefaultTemplate))
err := tmpl.Execute(&message, TemplateData{
Subject: mail.Subject,
Body: bodyWithLineBreaks,
})
if err != nil {
logrus.Errorf("Error executing email template: %v", err)
return nil
}

return []byte(message.String())
}

func batchEmails(to []string, batch int) [][]string {
Expand Down Expand Up @@ -66,4 +84,4 @@ func Service(mailQueue chan Mail) {
time.Sleep(1 * time.Second)
}
}
}
}
151 changes: 151 additions & 0 deletions mail/templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package mail

const (
DefaultTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<html dir="ltr" lang="en">
<head></head>
<body style="background-color:#ffffff;margin:0 auto;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif">
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="width:100%;margin:0 auto;padding:0px 20px">
<tbody>
<tr style="width:100%">
<td>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-top:10px;width:100%">
<tbody>
<tr>
<td><img alt="Recruitment Automation System &lt;br /&gt; Indian Institute of Technology, Kanpur" height="75" src="https://i.ibb.co/h7HMySr/Screenshot-from-2024-04-06-07-02-51.png" style="display:block;outline:none;border:none;text-decoration:none" width="475" /></td>
</tr>
</tbody>
</table>
<h1 style="color:#1d1c1d;font-size:24px;font-weight:700;margin:30px 0;padding:0;line-height:28px">{{.Subject}}</h1>
<p style="font-size:16px;line-height:20px;margin:16px 0;margin-bottom:30px;white-space:pre-wrap">{{.Body}}</p>
<p style="font-size:12px;line-height:16px;margin:16px 0;color:#000">This is an auto-generated email. Please do not reply.</p>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody>
<tr>
<td>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-bottom:32px;padding-left:8px;padding-right:8px;width:100%">
<tbody style="width:100%">
<tr style="width:100%">
<td data-id="__react-email-column" style="width:66%"><img alt="IIT Kanpur" height="48" src="https://upload.wikimedia.org/wikipedia/en/thumb/a/a3/IIT_Kanpur_Logo.svg/1200px-IIT_Kanpur_Logo.svg.png" style="display:block;outline:none;border:none;text-decoration:none" width="48" /></td>
<td data-id="__react-email-column">
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody>
<tr>
<td>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody style="width:100%">
<tr style="width:100%">
<td data-id="__react-email-column"><a href="https://twitter.com/IITKanpur" style="color:#067df7;text-decoration:none" target="_blank"><img alt="Twitter" height="32" src="https://th.bing.com/th/id/OIP.YGJYM4pqXxVMHzPYfdLumgHaHa?rs=1&amp;pid=ImgDetMain" style="display:inline;outline:none;border:none;text-decoration:none;margin-left:16px" width="32" /></a></td>
<td data-id="__react-email-column"><a href="https://www.facebook.com/spo.iitkanpur/" style="color:#067df7;text-decoration:none" target="_blank"><img alt="Facebook" height="32" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/2021_Facebook_icon.svg/2048px-2021_Facebook_icon.svg.png" style="display:inline;outline:none;border:none;text-decoration:none;margin-left:16px" width="32" /></a></td>
<td data-id="__react-email-column"><a href="https://www.linkedin.com/company/students-placement-office-iit-kanpur/" style="color:#067df7;text-decoration:none" target="_blank"><img alt="LinkedIn" height="32" src="https://static-00.iconduck.com/assets.00/linkedin-icon-1024x1024-net2o24e.png" style="display:inline;outline:none;border:none;text-decoration:none;margin-left:16px" width="32" /></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody>
<tr>
<td><a href="https://spo.iitk.ac.in/" rel="noopener noreferrer" style="color:#b7b7b7;text-decoration:underline;font-size:14px;" target="_blank">Website</a> | <a href="https://placement.iitk.ac.in/" rel="noopener noreferrer" style="color:#b7b7b7;text-decoration:underline;font-size:14px;" target="_blank">RAS Portal</a> | <a href="https://phdplacement.iitk.ac.in/" rel="noopener noreferrer" style="color:#b7b7b7;text-decoration:underline;font-size:14px;" target="_blank">PhD Portal</a>
<p style="font-size:12px;line-height:15px;margin:16px 0;color:#b7b7b7;text-align:left;margin-bottom:50px">©2024 Recruitment Automation System. <br />Students&#x27; Placement Office, IIT Kanpur <br /><br />All rights reserved.</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>
</html>`

// OTPTemplate and RecruitedTemplate are incomplete.

OTPTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<html dir="ltr" lang="en">
<!-- OTP email template content -->
</html>`

RecruitedTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<html dir="ltr" lang="en">
<head></head>
<body style="background-color:#ffffff;margin:0 auto;font-family:-apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif">
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="max-width:37.5em;margin:0 auto;padding:0px 20px">
<tbody>
<tr style="width:100%">
<td>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-top:10px">
<tbody>
<tr>
<td><img alt="Recruitment Automation System &lt;br /&gt; Indian Institute of Technology, Kanpur" height="75" src="https://i.ibb.co/YDvnbf5/Screenshot-2024-02-13-000009.png" style="display:block;outline:none;border:none;text-decoration:none" width="475" /></td>
</tr>
</tbody>
</table>
<h1 style="color:#1d1c1d;font-size:36px;font-weight:700;margin:30px 0;padding:0;line-height:42px">Congratualtions!</h1>
<p style="font-size:24px;line-height:28px;margin:16px 0;margin-bottom:30px">You have been recruited for the position of Software Developer at SPO IITK.<br /></p><img alt="IIT Kanpur" height="300" src="https://i.pinimg.com/originals/ee/cc/42/eecc42c92afa81900f655d4328d790c1.gif" style="display:block;outline:none;border:none;text-decoration:none" width="600" />
<p style="font-size:18px;line-height:24px;margin:16px 0;color:#000">This is an auto-generated email. Please do not reply.</p>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody>
<tr>
<td>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-bottom:32px;padding-left:8px;padding-right:8px;width:100%">
<tbody style="width:100%">
<tr style="width:100%">
<td data-id="__react-email-column" style="width:66%"><img alt="IIT Kanpur" height="48" src="https://upload.wikimedia.org/wikipedia/en/thumb/a/a3/IIT_Kanpur_Logo.svg/1200px-IIT_Kanpur_Logo.svg.png" style="display:block;outline:none;border:none;text-decoration:none" width="48" /></td>
<td data-id="__react-email-column">
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody>
<tr>
<td>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody style="width:100%">
<tr style="width:100%">
<td data-id="__react-email-column"><a href="https://twitter.com/IITKanpur" style="color:#067df7;text-decoration:none" target="_blank"><img alt="Twitter" height="32" src="https://th.bing.com/th/id/OIP.YGJYM4pqXxVMHzPYfdLumgHaHa?rs=1&amp;pid=ImgDetMain" style="display:inline;outline:none;border:none;text-decoration:none;margin-left:32px" width="32" /></a></td>
<td data-id="__react-email-column"><a href="https://www.facebook.com/spo.iitkanpur/" style="color:#067df7;text-decoration:none" target="_blank"><img alt="Facebook" height="32" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/2021_Facebook_icon.svg/2048px-2021_Facebook_icon.svg.png" style="display:inline;outline:none;border:none;text-decoration:none;margin-left:32px" width="32" /></a></td>
<td data-id="__react-email-column"><a href="https://www.linkedin.com/company/students-placement-office-iit-kanpur/" style="color:#067df7;text-decoration:none" target="_blank"><img alt="LinkedIn" height="32" src="https://static-00.iconduck.com/assets.00/linkedin-icon-1024x1024-net2o24e.png" style="display:inline;outline:none;border:none;text-decoration:none;margin-left:32px" width="32" /></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
<tbody>
<tr>
<td><a href="https://spo.iitk.ac.in/" rel="noopener noreferrer" style="color:#b7b7b7;text-decoration:underline" target="_blank">Website</a> | <a href="https://placement.iitk.ac.in/" rel="noopener noreferrer" style="color:#b7b7b7;text-decoration:underline" target="_blank">RAS Portal</a> | <a href="https://phdplacement.iitk.ac.in/" rel="noopener noreferrer" style="color:#b7b7b7;text-decoration:underline" target="_blank">PhD Portal</a>
<p style="font-size:12px;line-height:15px;margin:16px 0;color:#b7b7b7;text-align:left;margin-bottom:50px">©2024 Recruitment Automation System. <br />Students&#x27; Placement Office, IIT Kanpur <br /><br />All rights reserved.</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>
</html>`
)
4 changes: 2 additions & 2 deletions ras/hello.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func PlaceHolderController(c *gin.Context) {

func MailController(mail_channel chan mail.Mail) gin.HandlerFunc {
return func(c *gin.Context) {
mail_channel <- mail.GenerateMail("harshitr20@iitk.ac.in", "Test Mail", "Hello World!")
mail_channel <- mail.GenerateMails([]string{"[email protected]", "ias@iitk.ac.in"}, "Test Mail to multiple ppl", "Hello Worlds!")
mail_channel <- mail.GenerateMail("yashc22@iitk.ac.in", "Test Mail", "Hello World!")
mail_channel <- mail.GenerateMails([]string{"[email protected]", "bmerchant22@iitk.ac.in"}, "Test Mail to multiple ppl", "Hello Worlds!")
c.JSON(http.StatusOK, gin.H{"message": "Mail sent"})
}
}
Loading

0 comments on commit f5ee49c

Please sign in to comment.