intial commit

This commit is contained in:
2026-05-25 11:45:56 +05:30
commit 6ab508560f
73 changed files with 23713 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,448 @@
package controllers
import (
"nearle/db"
"nearle/domain"
"nearle/models"
"nearle/utils"
"net/http"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
)
func CreateCustomer(c *fiber.Ctx) error {
var data models.Customers
var id int
if err := c.BodyParser(&data); err != nil {
utils.Error("CreateCustomer body parse error", "error", err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": err.Error(),
"status": false,
})
}
// return c.JSON(fiber.Map{
// "status": false,
// "code": http.StatusConflict,
// "message": "Customer Already available",
// })
cid := domain.CheckCustomer(data.Contactno)
if cid != 0 {
data.Customerid = cid
tcid := domain.CheckTenantCustomer(data.Customerid, data.Tenantid)
if tcid == 0 {
id = domain.CreateTenantCustomer(data)
} else {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "Customer Already available",
})
}
} else {
id = domain.CreateCustomer(data)
}
if id != 0 {
result := domain.GetCustomer(id, "")
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusCreated,
"message": "Successful",
"details": result,
})
} else {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "Failed",
})
}
}
func UpdateCustomer(c *fiber.Ctx) error {
var data models.Customers
if err := c.BodyParser(&data); err != nil {
utils.Error("UpdateCustomer body parse error", "error", err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": err.Error(),
"status": false,
})
}
result := domain.UpdateCustomer(data)
if !result.Status {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "Failed",
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "Customer update successful",
})
}
func GetCustomer(c *fiber.Ctx) error {
cid, _ := strconv.Atoi(c.Query("customerid"))
cno := c.Query("contactno")
result := domain.GetCustomer(cid, cno)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetTenantCustomers(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
lid, _ := strconv.Atoi(c.Query("locationid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
keyword := c.Query("keyword")
result := domain.GetTenantCustomers(tid, lid, aid, pageno, pagesize, keyword)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetCustomersbytenent(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
lid, _ := strconv.Atoi(c.Query("locationid"))
//aid, _ := strconv.Atoi(c.Query("applocationid"))
result := domain.GetCustomerbytenant(tid, lid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetCustomersbyapplocation(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("applocationid"))
result := domain.GetCustomerbyApplocation(tid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetallCustomers(c *fiber.Ctx) error {
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
keyword := c.Query("keyword") // <-- new param
result := domain.GetallCustomers(aid, pageno, pagesize, keyword)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func SearchCustomer(c *fiber.Ctx) error {
keyword := c.Query("keyword")
tid, _ := strconv.Atoi(c.Query("tenantid"))
result := domain.SearchCustomer(keyword, tid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func DeleteCustomer(c *fiber.Ctx) error {
cid, _ := strconv.Atoi(c.Query("customerid"))
count := GetCustomerOrderCount(cid)
if count == 0 {
tx := db.DB.Begin()
t1 := tx.Table("customers").Where("customerid = ?", cid).Delete(&models.Customers{})
if t1.Error != nil {
utils.Error("DeleteCustomer t1 delete error", "error", t1.Error)
tx.Rollback()
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Error deleting customer",
"status": false,
})
}
t2 := tx.Table("customerlocations").Where("customerid = ?", cid).Delete(&models.Customerlocations{})
if t2.Error != nil {
utils.Error("DeleteCustomer t2 delete error", "error", t2.Error)
tx.Rollback()
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Error deleting customer",
"status": false,
})
}
t3 := tx.Table("tenantcustomers").Where("customerid = ?", cid).Delete(&models.Tenantcustomers{})
if t3.Error != nil {
utils.Error("DeleteCustomer t3 delete error", "error", t3.Error)
tx.Rollback()
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Error deleting customer",
"status": false,
})
}
tx.Commit()
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": "Orders available for customers",
"status": false,
})
}
func CreateCustomerLocation(c *fiber.Ctx) error {
var data models.Customerlocations
if err := c.BodyParser(&data); err != nil {
utils.Error("CreateCustomerLocation body parse error", "error", err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": err.Error(),
"status": false,
})
}
id := domain.CreateCustomerLocation(data)
if id != 0 {
result := domain.GetCustomerLocation(id)
return c.JSON(result)
} else {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "Failed",
})
}
}
func GetCustomerLocations(c *fiber.Ctx) error {
cid, _ := strconv.Atoi(c.Query("customerid"))
result := domain.GetCustomerLocation(cid)
return c.JSON(result)
}
func CreateCustomerRequest(c *fiber.Ctx) error {
var req models.CustomerRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Invalid request body",
"status": false,
})
}
now := time.Now()
req.Created = now
req.Updated = now
// Insert into database
if err := db.DB.Table("customerrequest").Create(&req).Error; err != nil {
utils.Error("CreateCustomerRequest DB error", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to create customer request",
"status": false,
})
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
"code": 201,
"message": "Customer request created successfully",
"status": true,
"data": req,
})
}
func GetCustomerRequests(c *fiber.Ctx) error {
customerIDStr := c.Query("customerid")
pageNoStr := c.Query("pageno", "1")
pageSizeStr := c.Query("pagesize", "10")
pageNo, _ := strconv.Atoi(pageNoStr)
pageSize, _ := strconv.Atoi(pageSizeStr)
if pageNo < 1 {
pageNo = 1
}
if pageSize < 1 {
pageSize = 10
}
offset := (pageNo - 1) * pageSize
var requests []models.CustomerRequest
query := db.DB.Table("customerrequest")
// Optional filter by customerid
if customerIDStr != "" {
customerID, err := strconv.Atoi(customerIDStr)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Invalid customerid",
"status": false,
})
}
if customerID != 0 {
query = query.Where("customerid = ?", customerID)
}
}
var total int64
query.Count(&total)
if err := query.Order("created desc").Offset(offset).Limit(pageSize).Find(&requests).Error; err != nil {
utils.Error("GetCustomerRequests DB error", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch customer requests",
"status": false,
})
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 200,
"message": "Customer requests fetched successfully",
"status": true,
"data": requests,
})
}
func GetCustomerSummary(c *fiber.Ctx) error {
aid, _ := strconv.Atoi(c.Query("applocationid", "0"))
tid, _ := strconv.Atoi(c.Query("tenantid", "0"))
// Initialize query builder
query := db.DB.Table("customers as a").
Joins("INNER JOIN customerlocations b ON a.customerid = b.customerid").
Where("b.primaryaddress = 1")
if aid != 0 {
query = query.Where("a.applocationid = ?", aid)
}
if tid != 0 {
query = query.Joins("INNER JOIN tenantcustomers ct ON a.customerid = ct.customerid").
Where("ct.tenantid = ?", tid)
}
type Summary struct {
Total int64
Active int64
Inactive int64
}
var summary Summary
// Execute consolidated summary counts
err := query.Select(`
COUNT(DISTINCT a.customerid) AS total,
COUNT(DISTINCT CASE WHEN a.status = 0 THEN a.customerid END) AS active,
COUNT(DISTINCT CASE WHEN a.status = 1 THEN a.customerid END) AS inactive`).
Scan(&summary).Error
if err != nil {
utils.Error("GetCustomerSummary DB error", "error", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Failed to fetch customer summary",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Customer summary fetched successfully",
"status": true,
"summary": summary,
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
package controllers
import (
"nearle/domain"
"nearle/models"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
)
func InvoiceSeqno(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
seqno := domain.GetSequenceno(tid, "INV")
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"Details": seqno,
})
}
func CreateInvoice(c *fiber.Ctx) error {
var data models.Tenantsales
if err := c.BodyParser(&data); err != nil {
return err
}
err := domain.CreateInvoice(data)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
func GetallInvoice(c *fiber.Ctx) error {
status, _ := strconv.Atoi(c.Query("billstatus"))
tid, _ := strconv.Atoi(c.Query("tenantid"))
result := domain.GetAllInvoice(status, tid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetInvoiceOrders(c *fiber.Ctx) error {
fdate := c.Query("fromdate")
tdate := c.Query("todate")
tid, _ := strconv.Atoi(c.Query("tenantid"))
result := domain.GetInvoiceOrders(tid, fdate, tdate)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetInvoiceInsight(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
result := domain.GetInvoiceInsight(tid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func UpdateInvoice(c *fiber.Ctx) error {
var data models.Tenantsales
if err := c.BodyParser(&data); err != nil {
return err
}
err := domain.UpdateInvoice(data)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
func UpdateInvoiceStatus(c *fiber.Ctx) error {
var data models.InvoiceStatus
if err := c.BodyParser(&data); err != nil {
return err
}
err := domain.UpdateInvoiceStatus(data)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}

View File

@@ -0,0 +1,141 @@
package controllers
import (
"context"
"nearle/domain"
"nearle/models"
"nearle/utils"
"net/http"
"sync"
firebase "firebase.google.com/go"
"firebase.google.com/go/messaging"
"github.com/gofiber/fiber/v2"
"google.golang.org/api/option"
)
var (
fcmApp *firebase.App
fcmClient *messaging.Client
fcmOnce sync.Once
fcmInitErr error
)
// getFCMClient handles the singleton initialization of Firebase
func getFCMClient() (*messaging.Client, error) {
fcmOnce.Do(func() {
ctx := context.Background()
opt := option.WithCredentialsFile("nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json")
app, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
fcmInitErr = err
return
}
fcmApp = app
client, err := app.Messaging(ctx)
if err != nil {
fcmInitErr = err
return
}
fcmClient = client
})
return fcmClient, fcmInitErr
}
func NotifyUser(c *fiber.Ctx) error {
// Parse the request body
var body struct {
Token string `json:"token"`
Notification models.FcmNotification `json:"notification"`
Data map[string]string `json:"data"`
}
if err := c.BodyParser(&body); err != nil {
utils.Error("NotifyUser parsing body error", "error", err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": err.Error(),
"status": false,
})
}
// Use shared client instead of initializing on every request
client, err := getFCMClient()
if err != nil {
utils.Error("NotifyUser Firebase initialization error", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "FCM Initialization error: " + err.Error(),
"status": false,
})
}
// Construct the message
message := &messaging.Message{
Token: body.Token,
Notification: &messaging.Notification{
Title: body.Notification.Title,
Body: body.Notification.Body,
},
Android: &messaging.AndroidConfig{
Priority: "high",
Notification: &messaging.AndroidNotification{
Sound: "ring",
},
},
Data: body.Data,
}
// Send the message
_, err = client.Send(context.Background(), message)
if err != nil {
utils.Error("NotifyUser FCM send error", "error", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
// Return structured response
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "FCM message sent successfully!",
"status": true,
})
}
func NotifyUsers(c *fiber.Ctx) error {
var data models.Notifications
if err := c.BodyParser(&data); err != nil {
utils.Error("NotifyUsers parsing body error", "error", err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": err.Error(),
"status": false,
})
}
result := domain.SendNotifications(data)
if !result {
utils.Error("NotifyUsers bulk send failed")
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Failed to send notifications",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
package controllers
import (
"nearle/db"
"nearle/models"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
)
func CreatePaymentRequest(c *fiber.Ctx) error {
var data models.Paymentrequests
if err := c.BodyParser(&data); err != nil {
return err
}
err := db.DB.Create(&data).Error
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Success",
"status": true,
})
}
func GetPaymentRequests(c *fiber.Ctx) error {
var data []models.RequestInfo
pid, _ := strconv.Atoi(c.Query("partnerid"))
status, _ := strconv.Atoi(c.Query("status"))
q1 := "select * from paymentrequests where partnerid=? and status=?"
db.DB.Raw(q1, pid, status).Find(&data)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}

37
controllers/platform.go Normal file
View File

@@ -0,0 +1,37 @@
package controllers
import (
"nearle/domain"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
)
func GetModules(c *fiber.Ctx) error {
mid, _ := strconv.Atoi(c.Query("moduleid"))
result := domain.GetModules(mid)
return c.JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Success",
"status": true,
"details": result,
})
}
func GetSmsProvider(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("templatetypeid"))
result := domain.GetSmsprovider(tid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}

View File

@@ -0,0 +1,868 @@
package controllers
import (
"nearle/db"
"nearle/domain"
"nearle/models"
"nearle/utils"
"net/http"
"strconv"
"strings"
"time"
"github.com/gofiber/fiber/v2"
)
func GetProductInfo(c *fiber.Ctx) error {
pid, _ := strconv.Atoi(c.Query("productid"))
utils.Logger.Debugf("productid: %d", pid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
func GetProducts(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
func GetProductCategory(c *fiber.Ctx) error {
data := domain.GetProductCategory()
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func GetProductSubCategory(c *fiber.Ctx) error {
categoryID, _ := strconv.Atoi(c.Query("categoryid"))
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
data := domain.GetProductSubCategory(categoryID, tenantID)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func CreateProductVariant(c *fiber.Ctx) error {
var input models.Productvariant
if err := c.BodyParser(&input); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := domain.CreateProductVariant(input); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": "Failed",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
func CreateProduct(c *fiber.Ctx) error {
var product models.Products
if err := c.BodyParser(&product); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := domain.CreateProduct(&product); err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Failed to create product",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Product created successfully",
"status": true,
})
}
func GetAllProducts(c *fiber.Ctx) error {
categoryID, _ := strconv.Atoi(c.Query("categoryid"))
subcategoryID, _ := strconv.Atoi(c.Query("subcategoryid"))
productID, _ := strconv.Atoi(c.Query("productid"))
applocationID, _ := strconv.Atoi(c.Query("applocationid"))
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
locationID, _ := strconv.Atoi(c.Query("locationid"))
keyword := c.Query("keyword", "")
productStatus := c.Query("productstatus", "")
approve := c.Query("approve", "")
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
details, err := domain.FetchFilteredProducts(
categoryID, subcategoryID, productID, applocationID, tenantID,
locationID, keyword, productStatus, approve, pageno, pagesize,
)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": "Failed",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"data": details,
})
}
func UpdateProduct(c *fiber.Ctx) error {
var data models.Products
if err := c.BodyParser(&data); err != nil {
return err
}
err := domain.UpdateProduct(data)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err,
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "Product update successful",
})
}
func DeleteProduct(c *fiber.Ctx) error {
// Get product ID from query
pidStr := c.Query("productid")
pid, err := strconv.Atoi(pidStr)
if err != nil || pid <= 0 {
return c.JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid product ID",
"status": false,
})
}
// Start transaction
tx := db.DB.Begin()
if tx.Error != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Failed to start transaction",
"status": false,
})
}
// Delete product
if err := tx.Table("products").Where("productid = ?", pid).Delete(&models.Products{}).Error; err != nil {
tx.Rollback()
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Error deleting product",
"status": false,
})
}
// Commit transaction
if err := tx.Commit().Error; err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Failed to commit transaction",
"status": false,
})
}
// Success response
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}
func GetProductsBySubcategory(c *fiber.Ctx) error {
// log.Println("Handler: GetProductsBySubcategory called")
// Required query param: categoryid
categoryIDStr := c.Query("categoryid")
if categoryIDStr == "" {
utils.Error("Error: categoryid is missing")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "categoryid is required",
"data": fiber.Map{},
})
}
categoryID, err := strconv.Atoi(categoryIDStr)
if err != nil {
utils.Logger.Errorf("Error: Invalid categoryid: %s", categoryIDStr)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid categoryid",
"data": fiber.Map{},
})
}
// Optional tenantid
tenantIDStr := c.Query("tenantid")
tenantID := 0
if tenantIDStr != "" {
tenantID, err = strconv.Atoi(tenantIDStr)
if err != nil {
utils.Logger.Errorf("Error: Invalid tenantid: %s", tenantIDStr)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid tenantid",
"data": fiber.Map{},
})
}
}
// Optional query params
applocationIDStr := c.Query("applocationid", "0")
applocationID, _ := strconv.Atoi(applocationIDStr)
productIDStr := c.Query("productid")
keyword := c.Query("keyword")
locationIDStr := c.Query("locationid")
locationID := 0
if locationIDStr != "" {
locationID, _ = strconv.Atoi(locationIDStr)
}
productID := 0
if productIDStr != "" {
productID, err = strconv.Atoi(productIDStr)
if err != nil {
utils.Logger.Errorf("Error: Invalid productid: %s", productIDStr)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid productid",
"data": fiber.Map{},
})
}
}
// Fetch subcategories
var subcategories []models.Subcategory
utils.Logger.Infof("Fetching subcategories for categoryid: %d", categoryID)
if err := db.DB.Table("productsubcategories").
Where("categoryid = ?", categoryID).
Find(&subcategories).Error; err != nil {
utils.Logger.Errorf("Error fetching subcategories: %v", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"status": false,
"message": "Error fetching subcategories",
"data": fiber.Map{},
})
}
// Build product query
var allProducts []models.Products
query := db.DB.
Table("products a").
Joins("LEFT JOIN productlocations pl ON pl.productid = a.productid").
Where("a.categoryid = ?", categoryID)
if tenantID > 0 {
query = query.Where("a.tenantid = ?", tenantID)
}
if locationID > 0 {
utils.Logger.Infof("Filtering by locationid: %d", locationID)
query = query.Where("pl.locationid = ?", locationID)
} else {
utils.Info("No locationid provided or value is 0 — showing all locations")
}
if applocationID > 0 {
query = query.Where("a.applocationid = ?", applocationID)
}
if productID > 0 {
query = query.Where("a.productid = ?", productID)
}
if keyword != "" {
utils.Info("Applying keyword filter")
like := "%" + strings.ToLower(keyword) + "%"
query = query.Where(
db.DB.Where("LOWER(a.productname) LIKE ?", like).
Or("LOWER(a.unitvalue) LIKE ?", like).
Or("LOWER(CAST(a.productcost AS CHAR)) LIKE ?", like),
)
}
if err := query.Select("a.*").Find(&allProducts).Error; err != nil {
utils.Logger.Errorf("Error fetching products: %v", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"status": false,
"message": "Error fetching products",
"data": fiber.Map{},
})
}
// Group products under subcategories
var details []models.SubcategoryProductResponse
var uncategorizedProducts []models.Products
for _, subcat := range subcategories {
var subcatProducts []models.Products
for _, prod := range allProducts {
if prod.Subcategoryid != nil && *prod.Subcategoryid == subcat.Subcategoryid {
subcatProducts = append(subcatProducts, prod)
}
}
if len(subcatProducts) > 0 {
details = append(details, models.SubcategoryProductResponse{
SubcategoryID: subcat.Subcategoryid,
SubcategoryName: subcat.Subcategoryname,
Products: subcatProducts,
})
}
}
for _, prod := range allProducts {
if prod.Subcategoryid == nil {
uncategorizedProducts = append(uncategorizedProducts, prod)
}
}
if len(uncategorizedProducts) > 0 {
details = append(details, models.SubcategoryProductResponse{
SubcategoryID: 0,
SubcategoryName: "Uncategorized",
Products: uncategorizedProducts,
})
}
// Tenant info block only if tenantID is passed
if tenantID > 0 {
var tenantInfo = fiber.Map{}
var tenantFound bool
for _, p := range allProducts {
if p.Tenantid != nil {
var tenant struct {
Tenantname string
Address string
Licenseno string
Primaryemail string
Primarycontact string
Locationname string
Pickuplocationid int
Suburb string
City string
Latitude string
Longitude string
Postcode string
}
err := db.DB.Raw(`
SELECT
t.tenantname,
t.address,
t.licenseno,
t.primaryemail,
t.primarycontact,
l.locationid AS pickuplocationid,
l.suburb,
l.city,
l.latitude,
l.longitude,
l.postcode,
a.locationname
FROM tenants t
LEFT JOIN tenantlocations l ON t.tenantid = l.tenantid
LEFT JOIN app_location a ON l.applocationid = a.applocationid
WHERE t.tenantid = ? AND t.applocationid = ?
LIMIT 1
`, *p.Tenantid, applocationID).Scan(&tenant).Error
if err == nil {
tenantInfo = fiber.Map{
"tenantname": tenant.Tenantname,
"address": tenant.Address,
"licenseno": tenant.Licenseno,
"primaryemail": tenant.Primaryemail,
"primarycontact": tenant.Primarycontact,
"locationname": tenant.Locationname,
"pickuplocationid": tenant.Pickuplocationid,
"suburb": tenant.Suburb,
"city": tenant.City,
"pickuplat": tenant.Latitude,
"pickuplong": tenant.Longitude,
"postcode": tenant.Postcode,
"details": details,
}
tenantFound = true
}
break
}
}
if tenantFound {
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 200,
"status": true,
"message": "Success",
"data": tenantInfo,
})
}
}
// Return only details if tenantid is not provided
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 200,
"status": true,
"message": "Success",
"data": fiber.Map{
"details": details,
},
})
}
func GetProductCount(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
categoryID, _ := strconv.Atoi(c.Query("categoryid"))
subcategoryID, _ := strconv.Atoi(c.Query("subcategoryid"))
approve := c.Query("approve", "") // New line
result, err := domain.Getproductcount(tenantID, categoryID, subcategoryID, approve)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": "failed",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetProductByVariant(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
variantid, _ := strconv.Atoi(c.Query("variantid"))
result, err := domain.GetproductbyVariant(tenantID, variantid)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": "failed",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func GetCatalougeProducts(c *fiber.Ctx) error {
tenantId, _ := strconv.Atoi(c.Query("tenantid"))
locationid, _ := strconv.Atoi(c.Query("locationid"))
subcategoryid, _ := strconv.Atoi(c.Query("subcategoryid"))
keyword := c.Query("keyword")
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
data := domain.GetCatalougeProducts(tenantId, locationid, subcategoryid, pageno, pagesize, keyword)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func GetStockstatement(c *fiber.Ctx) error {
tenantId, _ := strconv.Atoi(c.Query("tenantid"))
locationid, _ := strconv.Atoi(c.Query("locationid"))
subcategoryid, _ := strconv.Atoi(c.Query("subcategoryid"))
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
keyword := c.Query("keyword")
data := domain.GetStockStatement(tenantId, locationid, subcategoryid, pageno, pagesize, keyword)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func GetProductVariants(c *fiber.Ctx) error {
tenantId, _ := strconv.Atoi(c.Query("tenantid"))
subcategoryId, _ := strconv.Atoi(c.Query("subcategoryid"))
data := domain.GetProductVariants(tenantId, subcategoryId)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func CreateProductLocation(c *fiber.Ctx) error {
var data []models.Productlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Invalid request body",
"status": false,
})
}
err := domain.CreateProductLocation(data)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err,
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusCreated,
"message": "Success",
})
}
func UpdateProductLocation(c *fiber.Ctx) error {
var data models.Productlocations
if err := c.BodyParser(&data); err != nil {
return err
}
err := domain.UpdateProductLocation(data)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err,
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "Product update successful",
})
}
func CreateProductStock(c *fiber.Ctx) error {
var stocks []models.Productstock
if err := c.BodyParser(&stocks); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Invalid request body",
"status": false,
})
}
for i := range stocks {
stocks[i].Stockdate = time.Now()
}
// Insert all stock records
if err := db.DB.Table("productstocks").Create(&stocks).Error; err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to create product stocks",
"status": false,
})
}
// Collect and dedupe product IDs to update their status
idMap := make(map[int]struct{})
var productIDs []int
for _, s := range stocks {
if s.Productid <= 0 {
continue
}
if _, ok := idMap[s.Productid]; !ok {
idMap[s.Productid] = struct{}{}
productIDs = append(productIDs, s.Productid)
}
}
// Only update if we have product ids
if len(productIDs) > 0 {
if err := db.DB.Table("products").
Where("productid IN ?", productIDs).
Update("productstatus", "available").Error; err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to update product status",
"status": false,
})
}
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
"code": 201,
"message": "Product stocks created successfully",
"status": true,
"details": stocks,
})
}
func UpdateProductStock(c *fiber.Ctx) error {
var stock models.Productstock
// Parse body
if err := c.BodyParser(&stock); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Invalid request body",
"status": false,
})
}
// Validate required ID
if stock.Productstockid == 0 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Missing productstockid",
"status": false,
})
}
// Attempt update
if err := domain.UpdateProductStock(&stock); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to update product stock",
"status": false,
})
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 200,
"message": "Product stock updated successfully",
"status": true,
})
}
func GetProductStocks(c *fiber.Ctx) error {
tenantID := c.Query("tenantid")
locationID := c.Query("locationid")
stocks, err := domain.GetProductStocks(tenantID, locationID)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch product stocks",
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": 200,
"message": "Product stocks fetched successfully",
"status": true,
"data": stocks,
})
}
func GetLocationProducts(c *fiber.Ctx) error {
tenantid, _ := strconv.Atoi(c.Query("tenantid"))
locationid, _ := strconv.Atoi(c.Query("locationid"))
subcategoryid, _ := strconv.Atoi(c.Query("subcategoryid"))
keyword := c.Query("keyword")
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
result := domain.GetLocationProducts(tenantid, locationid, subcategoryid, pageno, pagesize, keyword)
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Success",
"details": result,
})
}
func GetSubCategoryWiseSummary(c *fiber.Ctx) error {
tenantId, _ := strconv.Atoi(c.Query("tenantid"))
locationid, _ := strconv.Atoi(c.Query("locationid"))
subcategoryid, _ := strconv.Atoi(c.Query("subcategoryid"))
data, err := domain.GetSubCategoryWiseSummary(tenantId, locationid, subcategoryid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"status": false,
"message": "Failed to fetch subcategory-wise summary",
})
}
if data == nil {
data = []models.SubCategorySummary{}
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Subcategory-wise summary fetched successfully",
"status": true,
"details": data,
})
}
func GetLocationProductSummary(c *fiber.Ctx) error {
tenantid, _ := strconv.Atoi(c.Query("tenantid"))
locationid, _ := strconv.Atoi(c.Query("locationid"))
result := domain.GetLocationProductSummary(tenantid, locationid)
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Success",
"details": result,
})
}
func GetStockStatementSummary(c *fiber.Ctx) error {
tenantId, _ := strconv.Atoi(c.Query("tenantid"))
locationid, _ := strconv.Atoi(c.Query("locationid"))
data := domain.GetStockStatementSummary(tenantId, locationid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func CreateProductDiscount(c *fiber.Ctx) error {
var data models.ProductDiscount
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid JSON body",
})
}
if len(data.Locationid) > 0 {
data.LocationidStr = strings.Join(data.Locationid, ",")
}
data.Status = "Active"
if err := domain.CreateProductDiscount(&data); err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"status": true,
"code": http.StatusCreated,
"message": "Product discount created successfully",
"data": data,
})
}
func GetProductDiscounts(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
lid := c.Query("locationid")
data := domain.GetProductDiscounts(tid, lid)
return c.JSON(fiber.Map{
"status": true,
"code": 200,
"message": "Success",
"details": data,
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
package controllers
import (
"net/http"
"github.com/gofiber/fiber/v2"
)
func PublishLogs(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusConflict,
"message": "Heloo",
})
}

File diff suppressed because it is too large Load Diff