Files
backend_jupiter/domain/utilsDomain.go
2026-05-25 11:45:56 +05:30

728 lines
17 KiB
Go

package domain
import (
"context"
"errors"
"nearle/db"
"nearle/models"
"nearle/utils"
"net/http"
"strconv"
firebase "firebase.google.com/go"
"firebase.google.com/go/messaging"
"google.golang.org/api/option"
"gorm.io/gorm"
)
var (
firebaseApp *firebase.App
fcmClient *messaging.Client
)
func getFCMClient() (*messaging.Client, error) {
if fcmClient != nil {
return fcmClient, nil
}
opt := option.WithCredentialsFile("nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json")
app, err := firebase.NewApp(context.Background(), nil, opt)
if err != nil {
return nil, errors.New("error initializing firebase app: " + err.Error())
}
firebaseApp = app
client, err := app.Messaging(context.Background())
if err != nil {
return nil, errors.New("error getting messaging client: " + err.Error())
}
fcmClient = client
return fcmClient, nil
}
func GetApplocations(aid int) []models.Applocations {
var data []models.Applocations
var q1 string
if aid != 0 {
q1 = "Select * from app_location where status='Active' and applocationid=?"
db.DB.Raw(q1, aid).Find(&data)
} else {
q1 = "Select * from app_location where status='Active'"
db.DB.Raw(q1).Find(&data)
}
utils.Logger.Debugf("Query executed for aid: %d", aid)
return data
}
func GetApplocationsv2(userid int) []models.Applocations {
var data []models.Applocations
var q1 string
if userid != 0 {
q1 = `
SELECT b.*
FROM app_locationconfig a
INNER JOIN app_location b
ON a.applocationid = b.applocationid
WHERE b.status = 'Active'
AND a.userid = ?`
db.DB.Raw(q1, userid).Find(&data)
} else {
q1 = `
SELECT *
FROM app_location
WHERE status = 'Active'
`
db.DB.Raw(q1).Find(&data)
}
utils.Logger.Debugf("Query executed for userid: %d", userid)
return data
}
func GetApplocationConfig(aid int) models.Applocations {
var data models.Applocations
var q1, q2 string
if aid != 0 {
q1 = `Select * from app_location where status='Active' and applocationid=` + strconv.Itoa(aid)
q2 = `SELECT distinct a.userid,a.userfcmtoken,b.notify,b.applocationid,c.opentime,c.closetime
FROM app_users a
INNER JOIN app_locationconfig b ON a.userid=b.userid
INNER JOiN app_location c on a.applocationid= c.applocationid
WHERE b.notify='true' AND b.applocationid=` + strconv.Itoa(aid)
} else {
q1 = `Select * from app_location where status='Active'`
}
// print(q1)
// db.DB.Raw(q1).Preload("Applocationadmins").Find(&data)
db.DB.Raw(q1).Preload("Applocationadmins", func(db *gorm.DB) *gorm.DB {
return db.Raw(q2)
}).Find(&data)
return data
}
func GetAppPricing(aid, cid, pid int) []models.Apppricing {
var data []models.Apppricing
var q1 string
if aid != 0 {
q1 = `SELECT a.* FROM app_pricing a
JOIN (
SELECT pricingtypeid, MAX(pricingdate) AS maxpricingdate
FROM app_pricing
WHERE applocationid = ?
GROUP BY pricingtypeid
) AS maxpricing ON a.pricingtypeid = maxpricing.pricingtypeid AND a.pricingdate = maxpricing.maxpricingdate WHERE a.applocationid = ?`
db.DB.Raw(q1, aid, aid).Find(&data)
} else if cid != 0 {
q1 = `SELECT * FROM app_pricing WHERE pricingdate = (SELECT MAX(pricingdate) FROM app_pricing where configid= ?)`
db.DB.Raw(q1, cid).Find(&data)
}
// print(q1)
db.DB.Raw(q1).Find(&data)
return data
}
func CreateAppProcing(input models.Apppricing) bool {
err := db.DB.Table("app_pricing").Create(&input).Error
return err == nil
}
func GetAllAppPricing(aid int) []models.Apppricing {
var data []models.Apppricing
var q1 string
if aid != 0 {
q1 = `SELECT a.*,b.locationname as applocation, d.appname FROM app_pricing a
inner join app_location b on a.applocationid=b.applocationid
Inner Join app_types c on a.pricingtypeid=c.apptypeid
INNER JOIN app_config d ON a.configid=d.configid
where a.applocationid=? ORDER BY b.locationname ASC`
db.DB.Raw(q1, aid).Find(&data)
} else {
q1 = `SELECT a.*,b.locationname as applocation, d.appname FROM app_pricing a
inner join app_location b on a.applocationid=b.applocationid
Inner Join app_types c on a.pricingtypeid=c.apptypeid
INNER JOIN app_config d ON a.configid=d.configid ORDER BY b.locationname ASC`
db.DB.Raw(q1).Find(&data)
}
utils.Logger.Debugf("Query executed for aid: %d", aid)
return data
}
func GetApplocationadmins(aid int) []models.Applocationadmins {
var data []models.Applocationadmins
var q1 string
if aid != 0 {
q1 = `SELECT distinct a.userid,a.userfcmtoken,b.notify,b.applocationid,c.opentime,c.closetime
FROM app_users a
INNER JOIN app_locationconfig b ON a.userid=b.userid
INNER JOiN app_location c on a.applocationid= c.applocationid
WHERE b.notify='true' AND b.applocationid=?`
db.DB.Raw(q1, aid).Find(&data)
}
return data
}
func GetAppconfig(cid int) models.Appconfig {
var data models.Appconfig
var q1 string
if cid != 0 {
q1 = `SELECT a.configid,a.Appname,a.paymentdevkey,a.paymentlivekey,a.fcmkey,a.googleapikey,a.applocationradius,
b.providerid,b.providerapi,b.providerkey
FROM app_config a
LEFT JOIN smsproviders b ON a.smsproviderid=b.providerid
WHERE a.configid=?`
db.DB.Raw(q1, cid).Find(&data)
} else {
q1 = `SELECT a.configid,a.Appname,a.paymentdevkey,a.paymentlivekey,a.fcmkey,a.googleapikey,a.applocationradius,
b.providerid,b.providerapi,b.providerkey FROM app_config a
LEFT JOIN smsproviders b ON a.smsproviderid=b.providerid order by configid asc`
db.DB.Raw(q1).Find(&data)
}
utils.Logger.Debugf("Query executed for cid: %d", cid)
return data
}
func GetAllAppconfig() []models.Appconfig {
var data []models.Appconfig
q1 := `SELECT a.configid,a.Appname,a.paymentdevkey,a.paymentlivekey,a.fcmkey,a.googleapikey,a.applocationradius,
b.providerid,b.providerapi,b.providerkey FROM app_config a
LEFT JOIN smsproviders b ON a.smsproviderid=b.providerid order by configid asc`
db.DB.Raw(q1).Find(&data)
return data
}
func GetAppModule() []models.AppModule {
var data []models.AppModule
q1 := `SELECT * FROM app_module where status='Active'`
db.DB.Raw(q1).Find(&data)
return data
}
func GetApptypes(tag string) []models.Apptypes {
var data []models.Apptypes
q1 := "Select * from app_types where status ='Active' and tag=?"
db.DB.Raw(q1, tag).Find(&data)
return data
}
func GetSubcategories(moduleid int, categoryid int) []models.Appsubcategories {
var data []models.Appsubcategories
query := `
SELECT a.subcategoryid,a.categoryid,a.subcategoryname,b.categoryname,a.status,c.moduleid
FROM app_subcategory a
INNER JOIN app_category b ON a.categoryid = b.categoryid
INNER JOIN app_module c ON a.categoryid = c.categoryid
WHERE 1=1`
var params []interface{}
if moduleid != 0 {
query += " AND c.moduleid = ?"
params = append(params, moduleid)
}
if categoryid != 0 {
query += " AND a.categoryid = ?"
params = append(params, categoryid)
}
db.DB.Raw(query, params...).Scan(&data)
return data
}
func GetCategories(mid int) []models.AppCategory {
var data []models.AppCategory
if mid == 0 {
// No moduleid filter → return all categories
q := `
SELECT a.*, b.moduleid
FROM app_category a
INNER JOIN app_module b ON a.categoryid = b.categoryid
`
db.DB.Raw(q).Scan(&data)
} else {
// Filter by moduleid
q := `
SELECT a.*, b.moduleid
FROM app_category a
INNER JOIN app_module b ON a.categoryid = b.categoryid
WHERE b.moduleid = ?
`
db.DB.Raw(q, mid).Scan(&data)
}
return data
}
func Insertnotification(input models.Data) bool {
db.DB.Table("tenantnotifications").Create(&input)
return true
}
func SendLoginNotification(regid, accessid string, pin int) error {
if regid == "" {
return errors.New("no FCM token provided")
}
client, err := getFCMClient()
if err != nil {
return err
}
// Construct the notification payload
body := "Your passcode to Nearle app is: " + strconv.Itoa(pin) + "."
title := "Nearle Code"
// Prepare FCM message
message := &messaging.Message{
Notification: &messaging.Notification{
Title: title,
Body: body,
},
Token: regid,
Android: &messaging.AndroidConfig{
Priority: "high",
Notification: &messaging.AndroidNotification{
Sound: "ring",
},
},
}
// Send the FCM notification
response, err := client.Send(context.Background(), message)
if err != nil {
utils.Logger.Errorf("FCM send error: %v", err)
return errors.New("failed to send FCM: " + err.Error())
}
utils.Logger.Infof("Successfully sent message: %v", response)
return nil
}
func SendSingleNotification(regid, accessid string, Partner string) bool {
client, err := getFCMClient()
if err != nil {
utils.Logger.Errorf("getFCMClient error: %v", err)
return false
}
title := "Nearle Admin"
body := "Orders had been placed for delivery by " + Partner
message := &messaging.Message{
Notification: &messaging.Notification{
Title: title,
Body: body,
},
Token: regid,
Android: &messaging.AndroidConfig{
Priority: "high",
Notification: &messaging.AndroidNotification{
Sound: "ring",
},
},
}
response, err := client.Send(context.Background(), message)
if err != nil {
utils.Logger.Errorf("Error sending single notification: %v", err)
return false
}
utils.Logger.Infof("Successfully sent single message: %v", response)
return true
}
func NotifyUser(fcm models.NotifyUser) bool {
client, err := getFCMClient()
if err != nil {
utils.Logger.Errorf("getFCMClient error: %v", err)
return false
}
message := &messaging.Message{
Notification: &messaging.Notification{
Title: fcm.Notification.Notify.Title,
Body: fcm.Notification.Notify.Body,
},
Token: fcm.Notification.To,
Android: &messaging.AndroidConfig{
Priority: fcm.Notification.Priority,
Notification: &messaging.AndroidNotification{
Sound: fcm.Notification.Notify.Sound,
},
},
}
response, err := client.Send(context.Background(), message)
if err != nil {
utils.Logger.Errorf("Error notifying user: %v", err)
return false
}
utils.Logger.Infof("Successfully notified user: %v", response)
return true
}
func SendNotifications(fcm models.Notifications) bool {
client, err := getFCMClient()
if err != nil {
utils.Logger.Errorf("getFCMClient error: %v", err)
return false
}
successCount := 0
for _, token := range fcm.Registrationids {
if token == "" {
continue
}
message := &messaging.Message{
Notification: &messaging.Notification{
Title: fcm.Notify.Title,
Body: fcm.Notify.Body,
},
Token: token,
Android: &messaging.AndroidConfig{
Priority: fcm.Priority,
Notification: &messaging.AndroidNotification{
Sound: fcm.Notify.Sound,
},
},
}
_, err := client.Send(context.Background(), message)
if err != nil {
utils.Logger.Errorf("Error sending notification to token %s: %v", token, err)
continue
}
successCount++
}
utils.Logger.Infof("Successfully sent %d notifications out of %d", successCount, len(fcm.Registrationids))
return successCount > 0
}
func SendNotification(fcm models.Notifications, accessid string) models.Result {
var result models.Result
client, err := getFCMClient()
if err != nil {
utils.Logger.Errorf("getFCMClient error: %v", err)
result.Code = http.StatusInternalServerError
result.Message = "Error initializing FCM client"
result.Status = false
return result
}
// Assuming we send to the first registration ID if multiple provided
if len(fcm.Registrationids) == 0 {
result.Code = http.StatusBadRequest
result.Message = "No registration IDs provided"
result.Status = false
return result
}
message := &messaging.Message{
Notification: &messaging.Notification{
Title: fcm.Notify.Title,
Body: fcm.Notify.Body,
},
Token: fcm.Registrationids[0],
Android: &messaging.AndroidConfig{
Priority: fcm.Priority,
Notification: &messaging.AndroidNotification{
Sound: fcm.Notify.Sound,
},
},
}
response, err := client.Send(context.Background(), message)
if err != nil {
utils.Logger.Errorf("Error sending single notification: %v", err)
result.Code = http.StatusInternalServerError
result.Message = "Error sending notification: " + err.Error()
result.Status = false
return result
}
utils.Logger.Infof("Successfully sent notification: %v", response)
status := Insertnotification(fcm.Data)
if !status {
result.Code = http.StatusConflict
result.Message = "Notification sent but Insert UnSuccessfully"
result.Status = false
return result
}
result.Code = http.StatusCreated
result.Message = "Notification Sent and Inserted Successfully"
result.Status = true
return result
}
func Getconfigs(categoryid int) models.Appconfig {
var q1 string
var data models.Appconfig
q1 = `SELECT a.configid,a.appname,a.smsproviderid,COALESCE(a.fcmkey,'') AS fcmkey,COALESCE(a.clientid,'') AS clientid,COALESCE(a.googleapikey,'') AS googleapikey,COALESCE(a.paymentdevkey,'') AS paymentdevkey,COALESCE(a.paymentlivekey,'') AS paymentlivekey,a.applocationradius,COALESCE(b.providername,'') AS providername,COALESCE(b.providerapi,'') AS providerapi,COALESCE(b.providerkey,'') AS providerkey, COALESCE(b.username,'') AS username,COALESCE(b.passcode,'') AS passcode,COALESCE(b.defaultprovider,false) AS defaultprovider
FROM app_config a LEFT OUTER JOIN smsproviders b ON a.smsproviderid = b.providerid AND b.status='Active' WHERE a.configid=?`
db.DB.Raw(q1, categoryid).Find(&data)
return data
}
func UpdateSeqno(tid int, prefix string) error {
var field string
if prefix == "ORD" {
field = "orderseqno"
} else if prefix == "INV" {
field = "invoiceseqno"
} else {
return errors.New("invalid prefix: " + prefix)
}
result := db.DB.
Table("ordersequences").
Where("tenantid = ?", tid).
Update(field, gorm.Expr(field+" + 1"))
if result.Error != nil {
utils.Logger.Errorf("UpdateSeqno failed for tenantid %d, prefix %s: %v", tid, prefix, result.Error)
return result.Error
}
if result.RowsAffected == 0 {
utils.Logger.Infof("No rows updated for tenantid %d with prefix %s", tid, prefix)
return errors.New("no rows updated for tenantid " + strconv.Itoa(tid))
}
return nil
}
func GetSequenceno(tid int, prefix string) string {
type SeqResult struct {
Orderseqno string
}
var q1 string
if prefix == "ORD" {
q1 = `
SELECT COALESCE(CONCAT(tenantid, '-', subprefix, COALESCE(MAX(orderseqno) + 1, 1)), '') AS orderseqno
FROM ordersequences
WHERE tenantid = ?
GROUP BY tenantid, subprefix
`
} else if prefix == "INV" {
q1 = `
SELECT COALESCE(CONCAT(tenantid, '-', subprefix, COALESCE(MAX(invoiceseqno) + 1, 1)), '') AS orderseqno
FROM ordersequences
WHERE tenantid = ?
GROUP BY tenantid, subprefix
`
}
var result SeqResult
db.DB.Raw(q1, tid).Scan(&result)
return result.Orderseqno
}
func GetTenantNotifications(tenantid, locationid, customerid, moduleid, pageno, pagesize int) ([]models.TenantNotification, int) {
var data []models.TenantNotification
var total int
offset := (pageno - 1) * pagesize
baseQuery := db.DB.Table("tenantnotifications").
Select("*").
Where("tenantid = ?", tenantid)
if locationid != 0 {
baseQuery = baseQuery.Where("locationid = ?", locationid)
}
if customerid != 0 {
baseQuery = baseQuery.Where("customerid = ?", customerid)
}
if moduleid != 0 {
baseQuery = baseQuery.Where("moduleid = ?", moduleid)
}
err := baseQuery.
Order("notificationdate DESC").
Limit(pagesize).
Offset(offset).
Find(&data).Error
if err != nil {
utils.Logger.Errorf("DB Error GetTenantNotifications: %v", err)
}
return data, total
}
func GetUserBonusSummary(userid int) (models.Riderinfo, error) {
var user models.Riderinfo
query := `
SELECT COALESCE(SUM(a.bonuspts), 0) AS bonuspts,b.*
FROM deliveries a
LEFT JOIN app_users b ON a.userid = b.userid
WHERE a.userid = ?
GROUP BY b.userid
`
err := db.DB.Raw(query, userid).Scan(&user).Error
if err != nil {
return user, err
}
return user, nil
}
func CreateAppLocationConfig(input models.AppLocationConfigRequest) bool {
if input.Notify == "" {
input.Notify = "true"
}
if input.Status == "" {
input.Status = "Active"
}
for _, locID := range input.Applocationids {
data := models.AppLocationConfig{
Applocationid: locID,
Configid: input.Configid,
Userid: input.Userid,
Partnerid: input.Partnerid,
Notify: input.Notify,
Status: input.Status,
}
if err := db.DB.Table("app_locationconfig").Create(&data).Error; err != nil {
return false
}
}
return true
}
func UpdateAppLocationConfig(input models.AppLocationConfigRequest) bool {
if input.Status == "" {
input.Status = "Active"
}
for _, locID := range input.Applocationids {
if err := db.DB.Table("app_locationconfig").
Where("userid = ? AND applocationid = ?", input.Userid, locID).
Update("status", input.Status).Error; err != nil {
utils.Logger.Errorf("Error updating app_locationconfig: %v", err)
return false
}
}
return true
}
func GetUserRoles() ([]models.UserRoles, error) {
var roles []models.UserRoles
query := `SELECT * FROM app_roles
`
err := db.DB.Raw(query).Scan(&roles).Error
if err != nil {
return roles, err
}
return roles, nil
}