UPDATE: Historian module
All checks were successful
Build and Release / release (push) Successful in 1m20s

This commit is contained in:
2026-04-12 00:35:14 +07:00
parent af76d2a26a
commit 03415782d1
38 changed files with 2759 additions and 231 deletions

View File

@@ -3,6 +3,7 @@ package constants
type StatusType int16
const (
StatusUnknown StatusType = 0
StatusPending StatusType = 1
StatusApproved StatusType = 2
StatusRejected StatusType = 3
@@ -21,6 +22,10 @@ func (t StatusType) String() string {
}
}
func (t StatusType) Int16() int16 {
return int16(t)
}
func ParseStatusType(v int16) StatusType {
switch v {
case 1:
@@ -30,6 +35,19 @@ func ParseStatusType(v int16) StatusType {
case 3:
return StatusRejected
default:
return 0
return StatusUnknown
}
}
func ParseStatusTypeText(v string) StatusType {
switch v {
case "PENDING":
return StatusPending
case "APPROVED":
return StatusApproved
case "REJECT":
return StatusRejected
default:
return StatusUnknown
}
}

View File

@@ -3,9 +3,10 @@ package constants
type TaskType string
const (
TaskTypeSendEmailOTP TaskType = "SEND_EMAIL_OTP"
TaskTypeDeleteMedia TaskType = "DELETE_MEDIA"
TaskTypeBulkDeleteMedia TaskType = "BULK_DELETE_MEDIA"
TaskTypeSendEmailOTP TaskType = "SEND_EMAIL_OTP"
TaskTypeNotifyHistorianReview TaskType = "NOTIFY_HISTORIAN_REVIEW"
TaskTypeDeleteMedia TaskType = "DELETE_MEDIA"
TaskTypeBulkDeleteMedia TaskType = "BULK_DELETE_MEDIA"
)
func (t TaskType) String() string {

View File

@@ -25,7 +25,26 @@ func (t VerifyType) String() string {
}
}
func ParseVerifyType(v string) VerifyType {
func (t VerifyType) Int16() int16 {
return int16(t)
}
func ParseVerifyType(v int16) VerifyType {
switch v {
case 1:
return VerifyIdCard
case 2:
return VerifyEducation
case 3:
return VerifyExpert
case 4:
return VerifyOther
default:
return VerifyUnknown
}
}
func ParseVerifyTypeText(v string) VerifyType {
switch v {
case "ID_CARD":
return VerifyIdCard

View File

@@ -45,7 +45,7 @@ func TimeToPtr(v pgtype.Timestamptz) *time.Time {
}
func PtrToText(s *string) pgtype.Text {
if s == nil {
if s == nil || *s == "" {
return pgtype.Text{Valid: false}
}
return pgtype.Text{

View File

@@ -3,6 +3,7 @@ package email
import (
"fmt"
"history-api/assets"
"history-api/internal/models"
"history-api/pkg/config"
"history-api/pkg/constants"
"strings"
@@ -10,7 +11,7 @@ import (
"github.com/wneessen/go-mail"
)
func SendMailOTP(toEmail, otpCode string, tokenType constants.TokenType) error {
func SendMail(toEmail, subject, templatePath string, data map[string]string) error {
userSmtp, err := config.GetConfig("SMTP_USER")
if err != nil {
return err
@@ -21,36 +22,27 @@ func SendMailOTP(toEmail, otpCode string, tokenType constants.TokenType) error {
return err
}
var subject string
var templatePath string
switch tokenType {
case constants.TokenPasswordReset:
subject = "Your Password Reset Code"
templatePath = "resources/password_reset.html"
case constants.TokenEmailVerify:
subject = "Verify your email address"
templatePath = "resources/email_verify.html"
default:
return fmt.Errorf("invalid token type: %v", tokenType)
}
htmlTemplate, err := assets.GetFileContent(templatePath)
if err != nil {
return fmt.Errorf("failed to read email template: %s", err)
}
message := mail.NewMsg()
if err := message.From(userSmtp); err != nil {
return fmt.Errorf("failed to set From email address: %s", err)
}
if err := message.To(toEmail); err != nil {
return fmt.Errorf("failed to set To email address: %s", err)
finalHTML := htmlTemplate
for k, v := range data {
finalHTML = strings.ReplaceAll(finalHTML, "{{"+k+"}}", v)
}
finalHTML := strings.ReplaceAll(htmlTemplate, "{{OTP_CODE}}", otpCode)
message := mail.NewMsg()
if err := message.From(userSmtp); err != nil {
return fmt.Errorf("failed to set From: %s", err)
}
if err := message.To(toEmail); err != nil {
return fmt.Errorf("failed to set To: %s", err)
}
message.Subject(subject)
message.SetBodyString(mail.TypeTextHTML, finalHTML)
client, err := mail.NewClient(
"smtp.gmail.com",
mail.WithSMTPAuth(mail.SMTPAuthAutoDiscover),
@@ -59,12 +51,56 @@ func SendMailOTP(toEmail, otpCode string, tokenType constants.TokenType) error {
mail.WithPassword(passSmtp),
)
if err != nil {
return fmt.Errorf("failed to create mail client: %s", err)
return fmt.Errorf("failed to create client: %s", err)
}
err = client.DialAndSend(message)
if err != nil {
if err := client.DialAndSend(message); err != nil {
return fmt.Errorf("failed to send mail: %s", err)
}
return nil
}
func SendMailOTP(dto *models.TokenEntity) error {
var subject string
var templatePath string
switch dto.TokenType {
case constants.TokenPasswordReset:
subject = "Your Password Reset Code"
templatePath = "resources/password_reset.html"
case constants.TokenEmailVerify:
subject = "Verify your email address"
templatePath = "resources/email_verify.html"
default:
return fmt.Errorf("invalid token type: %v", dto.TokenType)
}
return SendMail(dto.Email, subject, templatePath, map[string]string{
"OTP_CODE": dto.Token,
})
}
func SendHistorianReviewMail(dto *models.UserVerificationStorageEntity) error {
var subject string
var templatePath string
feUrl := config.GetConfigWithDefault("FRONTEND_URL", "http://localhost:3000")
switch dto.Status {
case constants.StatusApproved:
subject = "Your Historian Application is Approved"
templatePath = "resources/historian_approved.html"
case constants.StatusRejected:
subject = "Your Historian Application is Rejected"
templatePath = "resources/historian_rejected.html"
default:
return fmt.Errorf("invalid status: %v", dto.Status)
}
return SendMail(dto.Email, subject, templatePath, map[string]string{
"NAME": dto.Email,
"REASON": dto.ReviewNote,
"APP_URL": feUrl,
})
}