initial commit

This commit is contained in:
2026-05-25 11:52:26 +05:30
commit 0d42ac84e1
53 changed files with 11222 additions and 0 deletions

6
.env Normal file
View File

@@ -0,0 +1,6 @@
APP_PORT=1009
DB_HOST=66.116.207.225
DB_PORT=5433
DB_NAME=nearledb
DB_USER=admin
DB_PASSWORD="Package@123#"

50
.gitignore vendored Normal file
View File

@@ -0,0 +1,50 @@
# These are some examples of commonly ignored file patterns.
# You should customize this list as applicable to your project.
# Learn more about .gitignore:
# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
# Node artifact files
node_modules/
dist/
# Compiled Java class files
*.class
# Compiled Python bytecode
*.py[cod]
# Log files
*.log
# Package files
*.jar
# Maven
target/
dist/
# JetBrains IDE
.idea/
# Unit test reports
TEST*.xml
# Generated by MacOS
.DS_Store
# Generated by Windows
Thumbs.db
# Applications
*.app
*.exe
*.war
# Large media files
*.mp4
*.tiff
*.avi
*.flv
*.mov
*.wmv

19
Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
# ---------- Build Stage ----------
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server
# ---------- Runtime Stage ----------
FROM alpine:latest
RUN apk add --no-cache tzdata
WORKDIR /app
COPY --from=builder /app/server /app
COPY nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json .
EXPOSE 1009
CMD ["/app/server"]

49
config/config.go Normal file
View File

@@ -0,0 +1,49 @@
package config
import (
"log"
"os"
)
type Config struct {
Env string
Port string
DBName string
DBUser string
DBPassword string
DBPort string
DBHost string
UserContextKey string
JWTSecret string
}
func Load() *Config {
cfg := &Config{
Env: getEnv("ENV", "production"),
Port: getEnv("APP_PORT", "1009"),
// ✅ STANDARDIZED DB ENV KEYS
DBName: getEnv("DB_NAME", ""),
DBUser: getEnv("DB_USER", ""),
DBPassword: getEnv("DB_PASSWORD", ""),
DBPort: getEnv("DB_PORT", "5432"),
DBHost: getEnv("DB_HOST", "localhost"),
UserContextKey: getEnv("USER_CONTEXT_KEY", "nearle"),
JWTSecret: getEnv("JWT_SECRET_KEY", ""),
}
// ✅ Correct validation
if cfg.DBPassword == "" {
log.Println("Warning: DB_PASSWORD is not set")
}
return cfg
}
func getEnv(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}

View File

@@ -0,0 +1,271 @@
package controllers
import (
"nearle/models"
"nearle/services"
"net/http"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
)
type CustomerController struct {
customerService services.CustomerService
}
func NewCustomerController(customerService services.CustomerService) *CustomerController {
return &CustomerController{customerService: customerService}
}
func (ctl *CustomerController) GetCustomer(c *fiber.Ctx) error {
cid, _ := strconv.Atoi(c.Query("customerid"))
cno := c.Query("contactno")
result, err := ctl.customerService.GetCustomer(cid, cno)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": err.Error(),
"status": false,
"details": fiber.Map{},
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *CustomerController) UpdateCustomer(c *fiber.Ctx) error {
var data models.Customers
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
result := ctl.customerService.UpdateCustomer(data)
if !result.Status {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": result.Message,
})
}
return c.Status(http.StatusAccepted).JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": result.Message,
})
}
func (ctl *CustomerController) GetCustomerLocations(c *fiber.Ctx) error {
cid, err := strconv.Atoi(c.Query("customerid"))
if err != nil || cid == 0 {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"status": false,
"message": "Invalid customerid",
"details": []interface{}{},
})
}
result := ctl.customerService.GetCustomerLocations(cid)
return c.Status(result.Code).JSON(result)
}
func (ctl *CustomerController) CreateCustomerLocation(c *fiber.Ctx) error {
var data models.Customerlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
id, err := ctl.customerService.CreateCustomerLocation(data)
if id == -1 {
// Duplicate address
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "Address already exists",
})
}
if err != nil || id == 0 {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "Failed",
})
}
result := ctl.customerService.GetCustomerLocations(id)
return c.Status(result.Code).JSON(result)
}
func (ctl *CustomerController) CreateCustomerRequest(c *fiber.Ctx) error {
var req models.CustomerRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
now := time.Now()
req.Created = now
req.Updated = now
createdReq, err := ctl.customerService.CreateCustomerRequest(req)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Failed to create customer request",
"status": false,
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Customer request created successfully",
"status": true,
"data": createdReq,
})
}
func (ctl *CustomerController) 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)
requests, total, err := ctl.customerService.GetCustomerRequests(customerIDStr, pageNo, pageSize)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": 200,
"message": "Customer requests fetched successfully",
"status": true,
"data": requests,
"total": total,
})
}
func (ctl *CustomerController) GetTenantCustomers(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
lid, _ := strconv.Atoi(c.Query("locationid"))
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
keyword := c.Query("keyword")
result := ctl.customerService.GetTenantCustomers(tid, lid, pageno, pagesize, keyword)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *CustomerController) SearchCustomer(c *fiber.Ctx) error {
keyword := c.Query("keyword")
tid, _ := strconv.Atoi(c.Query("tenantid"))
result := ctl.customerService.SearchCustomer(keyword, tid)
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *CustomerController) CreateCustomer(c *fiber.Ctx) error {
var data models.Customers
if err := c.BodyParser(&data); err != nil {
return err
}
result, err := ctl.customerService.CreateCustomer(data)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusCreated,
"message": "Successful",
"details": result,
})
}
func (ctl *CustomerController) CustomerLogin(c *fiber.Ctx) error {
var body struct {
Contactno string `json:"contactno"`
}
if err := c.BodyParser(&body); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusBadRequest,
"status": false,
"message": "Invalid request",
"error": err.Error(),
})
}
customer, err := ctl.customerService.LoginCustomer(body.Contactno)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"message": "Failed to login",
"error": err.Error(),
})
}
if customer == nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"status": false,
"message": "Account not found",
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"status": true,
"message": "Success",
"details": customer,
})
}

View File

@@ -0,0 +1,261 @@
package controllers
import (
"net/http"
"strconv"
"nearle/models"
"nearle/services"
"github.com/gofiber/fiber/v2"
)
type DeliveriesController struct {
deliveriesService services.DeliveriesService
}
func NewDeliveriesController(deliveriesService services.DeliveriesService) *DeliveriesController {
return &DeliveriesController{deliveriesService: deliveriesService}
}
func (ctl *DeliveriesController) CreateDeliveries(c *fiber.Ctx) error {
var deliveries []models.Deliveries
if err := c.BodyParser(&deliveries); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid request body",
})
}
err := ctl.deliveriesService.CreateDeliveriesService(deliveries)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"status": false,
"message": err.Error(),
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": 200,
"status": true,
"message": "Deliveries created successfully",
})
}
func (ctl *DeliveriesController) UpdateDelivery(c *fiber.Ctx) error {
var data models.UpdateDeliveryStatus
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
err := ctl.deliveriesService.UpdateDeliveryService(data)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Success",
"status": true,
})
}
func (ctl *DeliveriesController) GetDeliverySummary(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
pid, _ := strconv.Atoi(c.Query("partnerid"))
uid, _ := strconv.Atoi(c.Query("userid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
lid, _ := strconv.Atoi(c.Query("locationid"))
fdate := c.Query("fromdate")
tdate := c.Query("todate")
data, err := ctl.deliveriesService.GetDeliverySummary(tid, pid, uid, aid, lid, fdate, tdate)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *DeliveriesController) GetDeliveryInsight(c *fiber.Ctx) error {
// Get tenantid from query param
tenantIDStr := c.Query("tenantid")
tenantID, _ := strconv.Atoi(tenantIDStr)
// Call service with tenantID
locations, err := ctl.deliveriesService.GetDeliveryInsightService(tenantID)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": locations,
})
}
func (ctl *DeliveriesController) GetLocationDeliverySummary(c *fiber.Ctx) error {
tenantIDStr := c.Query("tenantid")
tenantID, _ := strconv.Atoi(tenantIDStr)
data, err := ctl.deliveriesService.GetLocationDeliverySummary(tenantID)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *DeliveriesController) GetReportSummary(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
pid, _ := strconv.Atoi(c.Query("partnerid"))
uid, _ := strconv.Atoi(c.Query("userid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
fdate := c.Query("fromdate")
tdate := c.Query("todate")
data, err := ctl.deliveriesService.GetReportSummary(tid, pid, uid, aid, fdate, tdate)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *DeliveriesController) GetRiderSummary(c *fiber.Ctx) error {
aid, _ := strconv.Atoi(c.Query("applocationid"))
pid, _ := strconv.Atoi(c.Query("partnerid"))
tid, _ := strconv.Atoi(c.Query("tenantid"))
fdate := c.Query("fromdate")
tdate := c.Query("todate")
data, err := ctl.deliveriesService.GetRiderSummary(aid, pid, tid, fdate, tdate)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *DeliveriesController) GetDeliveries(c *fiber.Ctx) error {
pid, _ := strconv.Atoi(c.Query("partnerid"))
tid, _ := strconv.Atoi(c.Query("tenantid"))
uid, _ := strconv.Atoi(c.Query("userid"))
cid, _ := strconv.Atoi(c.Query("customerid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
aud, _ := strconv.Atoi(c.Query("appuserid"))
lid, _ := strconv.Atoi(c.Query("locationid")) // 👈 NEW
pageno, _ := strconv.Atoi(c.Query("pageno", "1"))
pagesize, _ := strconv.Atoi(c.Query("pagesize", ""))
fdate := c.Query("fromdate")
tdate := c.Query("todate")
stat := c.Query("status")
keyword := c.Query("keyword")
info := models.DeliveryQuery{
Partnerid: pid,
Tenantid: tid,
UserID: uid,
Customerid: cid,
Appuserid: aud,
Applocationid: aid,
Locationid: lid, // 👈 NEW
Fromdate: fdate,
ToDate: tdate,
Status: stat,
Pageno: pageno,
Pagesize: pagesize,
Keyword: keyword,
}
result := ctl.deliveriesService.GetDeliveries(info)
if result == nil {
result = []models.Deliveryinfo{}
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *DeliveriesController) GetDeliveryQueues(c *fiber.Ctx) error {
fdate := c.Query("fromdate")
tdate := c.Query("todate")
uid, _ := strconv.Atoi(c.Query("userid"))
result, err := ctl.deliveriesService.GetDeliveryQueues(uid, fdate, tdate)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}

View File

@@ -0,0 +1,356 @@
package controllers
import (
"log"
"nearle/models"
"net/http"
"strconv"
"strings"
"time"
"nearle/services"
"github.com/gofiber/fiber/v2"
)
type OrderController struct {
orderService services.OrderService
}
func NewOrderController(orderService services.OrderService) *OrderController {
return &OrderController{orderService: orderService}
}
func (ctl *OrderController) GetOrders(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
pid, _ := strconv.Atoi(c.Query("partnerid"))
cid, _ := strconv.Atoi(c.Query("customerid"))
mid, _ := strconv.Atoi(c.Query("moduleid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
uid, _ := strconv.Atoi(c.Query("appuserid"))
lid, _ := strconv.Atoi(c.Query("locationid"))
configid, _ := strconv.Atoi(c.Query("configid"))
stat := c.Query("status")
fdate := c.Query("fromdate")
tdate := c.Query("todate")
keyword := c.Query("keyword")
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
if pageno <= 0 {
pageno = 1
}
if pagesize <= 0 {
pagesize = 10
}
// Build dynamic query struct
query := models.DeliveryQuery{
Tenantid: tid,
Partnerid: pid,
Customerid: cid,
Moduleid: mid,
Applocationid: aid,
Locationid: lid,
UserID: uid,
Appuserid: uid,
Configid: configid,
Fromdate: fdate,
ToDate: tdate,
Status: stat,
Keyword: keyword,
Pageno: pageno,
Pagesize: pagesize,
}
var (
orders []models.OrderInfo
err error
)
// --------------------------
// 🔥 DYNAMIC ROUTING LOGIC
// --------------------------
if tid != 0 && lid != 0 {
// ⭐ Both tenant & location → special handler
orders, err = ctl.orderService.GetTenantLocationOrders(query)
} else if tid != 0 {
// Tenant only
orders, err = ctl.orderService.GetTenantOrders(query)
} else if pid != 0 {
// Partner
orders, err = ctl.orderService.GetPartnerOrders(stat, fdate, tdate, pid, pageno, pagesize, keyword)
} else if cid != 0 {
// Customer
orders, err = ctl.orderService.GetCustomerOrders(stat, fdate, tdate, cid, mid, pageno, pagesize, keyword)
} else if aid != 0 {
// App-location orders
orders, err = ctl.orderService.GetAdminOrders(stat, fdate, tdate, aid, pageno, pagesize, keyword)
} else if uid != 0 {
// User orders
orders, err = ctl.orderService.GetUserOrders(stat, fdate, tdate, uid, pageno, pagesize, keyword)
} else {
// All orders
orders, err = ctl.orderService.GetAllOrders(stat, fdate, tdate, pageno, pagesize, keyword)
}
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Success",
"details": orders,
})
}
func (ctl *OrderController) GetOrderSummary(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
pid, _ := strconv.Atoi(c.Query("partnerid"))
cid, _ := strconv.Atoi(c.Query("customerid"))
lid, _ := strconv.Atoi(c.Query("locationid"))
fdate := c.Query("fromdate")
tdate := c.Query("todate")
data, err := ctl.orderService.GetOrderSummary(tid, pid, cid, lid, fdate, tdate)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *OrderController) GetlocationOrderSummary(c *fiber.Ctx) error {
tenantIDStr := c.Query("tenantid")
tenantID, _ := strconv.Atoi(tenantIDStr)
data, err := ctl.orderService.GetLocationOrderSummary(tenantID)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *OrderController) GetOrderInsights(c *fiber.Ctx) error {
tenantIDStr := c.Query("tenantid")
tenantID, _ := strconv.Atoi(tenantIDStr)
insights, err := ctl.orderService.GetOrderInsights(tenantID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"message": "Failed to fetch order insights",
"error": err.Error(),
})
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"status": true,
"message": "Success",
"details": insights,
})
}
func (ctl *OrderController) GetOrderDetails(c *fiber.Ctx) error {
orderHeaderIDStr := c.Query("orderheaderid")
if orderHeaderIDStr == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "orderheaderid is required",
"status": false,
"details": []interface{}{},
})
}
orderHeaderID, err := strconv.Atoi(orderHeaderIDStr)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "invalid orderheaderid",
"status": false,
"details": []interface{}{},
})
}
details, err := ctl.orderService.GetOrderDetails(orderHeaderID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch order details",
"status": false,
"details": []interface{}{},
})
}
var orderAmount, totalTaxAmount float64
if len(details) > 0 {
orderAmount = details[0].Orderamount
totalTaxAmount = details[0].Totaltaxamount
}
return c.JSON(fiber.Map{
"code": 200,
"pricedetails": fiber.Map{
"orderamount": orderAmount,
"totaltaxamount": totalTaxAmount,
},
"details": details,
"message": "Success",
"status": true,
})
}
func (ctl *OrderController) UpdateOrder(c *fiber.Ctx) error {
var order models.Orders
if err := c.BodyParser(&order); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := ctl.orderService.UpdateOrder(&order); err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Error updating order",
"status": false,
})
}
return c.Status(http.StatusAccepted).JSON(fiber.Map{
"code": http.StatusAccepted,
"message": "Success",
"status": true,
})
}
func (ctl *OrderController) CreateOrderv3(c *fiber.Ctx) error {
var data models.Orders
// 🛠️ Strategy 1: Try parsing direct object (for Apidog)
if err := c.BodyParser(&data); err != nil {
log.Println("BodyParser strategy 1 error:", err)
}
// 🛠️ Strategy 2: If Strategy 1 didn't find a Tenantid, try parsing wrapped object (for Mobile App)
if data.Tenantid == 0 {
type OrderWrapper struct {
Orders models.Orders `json:"orders"`
}
var wrapper OrderWrapper
if err := c.BodyParser(&wrapper); err == nil && wrapper.Orders.Tenantid != 0 {
data = wrapper.Orders
}
}
// Double check we have the required ID
if data.Tenantid == 0 {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"message": "Tenant ID is required",
"status": false,
})
}
if strings.TrimSpace(data.Orderdate) == "" {
data.Orderdate = time.Now().Format("2006-01-02 15:04:05")
}
if strings.TrimSpace(data.Deliverytime) == "" {
data.Deliverytime = time.Now().Format("2006-01-02 15:04:05")
}
order, err := ctl.orderService.CreateOrder(data)
if err != nil {
log.Println("CreateOrder service error:", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Order created successfully",
"status": true,
"details": order,
})
}
func (ctl *OrderController) GetCustomerOrders(c *fiber.Ctx) error {
customerID := c.Query("customerid")
tenantID := c.Query("tenantid")
moduleID := c.Query("moduleid")
fromDate := c.Query("fromdate")
toDate := c.Query("todate")
orderStatus := c.Query("orderstatus")
keyword := c.Query("keyword")
pageNo, _ := strconv.Atoi(c.Query("pageno", "1"))
pageSize, _ := strconv.Atoi(c.Query("pagesize", "10"))
if pageNo < 1 {
pageNo = 1
}
if pageSize < 1 {
pageSize = 10
}
offset := (pageNo - 1) * pageSize
orders, err := ctl.orderService.GetCustomerOrdersv3(customerID, tenantID, moduleID, fromDate, toDate, orderStatus, keyword, pageSize, offset)
if err != nil {
log.Println("GetCustomerOrders error:", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"status": false,
"message": "Failed to fetch customer orders",
"error": err.Error(),
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"status": true,
"message": "Customer orders fetched successfully",
"data": orders,
})
}

View File

@@ -0,0 +1,156 @@
package controllers
import (
"nearle/services"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
)
type PartnerController struct {
partnerService services.PartnerService
}
func NewPartnerController(partnerService services.PartnerService) *PartnerController {
return &PartnerController{partnerService: partnerService}
}
func (ctl *PartnerController) GetActiveRiders(c *fiber.Ctx) error {
pid, _ := strconv.Atoi(c.Query("partnerid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
uid, _ := strconv.Atoi(c.Query("userid"))
tid,_ := strconv.Atoi(c.Query("tenantid"))
result, err := ctl.partnerService.GetActiveRiders(pid, aid, uid, tid)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}
func (ctl *PartnerController) GetPartners(c *fiber.Ctx) error {
pid, _ := strconv.Atoi(c.Query("partnerid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
uid, _ := strconv.Atoi(c.Query("userid"))
result, err := ctl.partnerService.GetPartners(aid, pid, uid)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}
func (ctl *PartnerController) GetRiderShifts(c *fiber.Ctx) error {
aid, _ := strconv.Atoi(c.Query("applocationid"))
result, err := ctl.partnerService.GetRiderShifts(aid)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}
func (ctl *PartnerController) GetLocationConfig(c *fiber.Ctx) error {
uid, _ := strconv.Atoi(c.Query("userid"))
cid, _ := strconv.Atoi(c.Query("configid"))
result, err := ctl.partnerService.GetLocationConfig(uid, cid)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}
func (ctl *PartnerController) GetRiderLogs(c *fiber.Ctx) error {
pid, _ := strconv.Atoi(c.Query("partnerid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
fdate := c.Query("fromdate")
tdate := c.Query("fromdate")
data, err := ctl.partnerService.GetRiderLogs(pid, aid, fdate, tdate)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": data,
})
}
func (ctl *PartnerController) GetRiderInfo(c *fiber.Ctx) error {
uid, _ := strconv.Atoi(c.Query("userid"))
result, err := ctl.partnerService.GetRiderInfo(uid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}

View File

@@ -0,0 +1,516 @@
package controllers
import (
"net/http"
"strconv"
"nearle/models"
"nearle/services"
"github.com/gofiber/fiber/v2"
)
type ProductController struct {
productService services.ProductService
}
func NewProductController(productService services.ProductService) *ProductController {
return &ProductController{productService: productService}
}
func (ctl *ProductController) GetProductSubCategory(c *fiber.Ctx) error {
categoryID, _ := strconv.Atoi(c.Query("categoryid", "0"))
tenantID, _ := strconv.Atoi(c.Query("tenantid", "0"))
data, err := ctl.productService.GetProductSubCategory(categoryID, tenantID)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": 200,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *ProductController) GetProductCount(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
categoryID, _ := strconv.Atoi(c.Query("categoryid"))
subcategoryID, _ := strconv.Atoi(c.Query("subcategoryid"))
// locationID, _ := strconv.Atoi(c.Query("locationid"))
approve := c.Query("approve", "")
data, err := ctl.productService.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": data,
})
}
func (ctl *ProductController) GetProductCategory(c *fiber.Ctx) error {
data, err := ctl.productService.GetProductCategory()
if err != nil {
return c.JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch categories",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *ProductController) GetProductVariants(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
subcategoryID, _ := strconv.Atoi(c.Query("subcategoryid"))
data, err := ctl.productService.GetProductVariants(tenantID, subcategoryID)
if err != nil {
return c.JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch Product varients",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *ProductController) 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, err := ctl.productService.GetCatalougeProducts(tenantID, locationID, subcategoryID, pageno, pagesize, keyword)
if err != nil {
return c.JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch Catalouge Product",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *ProductController) GetProductStocks(c *fiber.Ctx) error {
tenantID := c.Query("tenantid")
locationID := c.Query("locationid")
stocks, err := ctl.productService.GetProductStocks(tenantID, locationID)
if err != nil {
return c.JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch product stocks",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": 200,
"message": "Product stocks fetched successfully",
"status": true,
"data": stocks,
})
}
func (ctl *ProductController) 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,
})
}
if err := ctl.productService.CreateProductStock(stocks); err != nil {
return c.JSON(fiber.Map{
"code": 500,
"message": "Failed to create product stocks",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": 201,
"message": "Product stocks created successfully",
"status": true,
"details": stocks,
})
}
func (ctl *ProductController) CreateProduct(c *fiber.Ctx) error {
var product models.Products
if err := c.BodyParser(&product); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := ctl.productService.CreateProduct(product); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Failed to create product",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Product created successfully",
"status": true,
"data": product,
})
}
func (ctl *ProductController) UpdateProduct(c *fiber.Ctx) error {
var product models.Products
if err := c.BodyParser(&product); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := ctl.productService.UpdateProduct(product); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusAccepted,
"message": "Product updated successfully",
"status": true,
"data": product,
})
}
func (ctl *ProductController) DeleteProduct(c *fiber.Ctx) error {
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,
})
}
if err := ctl.productService.DeleteProduct(pid); err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Product deleted successfully",
"status": true,
})
}
func (ctl *ProductController) 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, err := ctl.productService.GetStockStatement(tenantID, locationID, subcategoryID, pageno, pagesize, keyword)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *ProductController) 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, err := ctl.productService.GetLocationProducts(tenantID, locationID, subcategoryID, pageno, pagesize, keyword)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Success",
"details": result,
})
}
func (ctl *ProductController) GetLocationProductSummary(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
locationID, _ := strconv.Atoi(c.Query("locationid"))
result, err := ctl.productService.GetLocationProductSummary(tenantID, locationID)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusInternalServerError,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Success",
"details": result,
})
}
func (ctl *ProductController) 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 := ctl.productService.FetchFilteredProducts(
categoryID, subcategoryID, productID, applocationID, tenantID,
locationID, keyword, productStatus, approve, pageno, pagesize,
)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Success",
"data": details,
})
}
func (ctl *ProductController) GetProductByVariant(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(c.Query("tenantid"))
variantid, _ := strconv.Atoi(c.Query("variantid"))
result, err := ctl.productService.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 (ctl *ProductController) GetProductsBySubcategory(c *fiber.Ctx) error {
categoryID, err := strconv.Atoi(c.Query("categoryid"))
if err != nil || categoryID == 0 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Valid categoryid is required",
"data": fiber.Map{},
})
}
params := models.ProductFilter{
CategoryID: categoryID,
TenantID: parseInt(c.Query("tenantid")),
AppLocationID: parseInt(c.Query("applocationid")),
ProductID: parseInt(c.Query("productid")),
Keyword: c.Query("keyword"),
LocationID: parseInt(c.Query("locationid")),
}
result, err := ctl.productService.GetProductsBySubcategory(params)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"status": false,
"message": err.Error(),
"data": fiber.Map{},
})
}
return c.JSON(fiber.Map{
"code": 200,
"status": true,
"message": "Success",
"data": result,
})
}
func parseInt(s string) int {
if s == "" {
return 0
}
val, _ := strconv.Atoi(s)
return val
}
func (ctl *ProductController) UpdateProductLocation(c *fiber.Ctx) error {
var data models.Productlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
if err := ctl.productService.UpdateProductLocation(data); err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.Status(http.StatusAccepted).JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "Product update successful",
})
}
func (ctl *ProductController) CreateProductLocation(c *fiber.Ctx) error {
var data []models.Productlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := ctl.productService.CreateProductLocation(data); err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"status": true,
"code": http.StatusCreated,
"message": "Success",
})
}
func (ctl *ProductController) CreateProductVariant(c *fiber.Ctx) error {
var input models.Productvariant
// Parse request body
if err := c.BodyParser(&input); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
// Call service layer
if err := ctl.productService.CreateProductVariant(input); err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
})
}

View File

@@ -0,0 +1,436 @@
package controllers
import (
"fmt"
"log"
"nearle/models"
"nearle/services"
"net/http"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
)
type TenantController struct {
tenantService services.TenantService
}
func NewTenantController(tenantService services.TenantService) *TenantController {
return &TenantController{tenantService: tenantService}
}
func (ctl *TenantController) SearchTenant(c *fiber.Ctx) error {
status := c.Query("status")
searchStr := c.Query("keyword")
data, err := ctl.tenantService.SearchTenant(status, searchStr)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": fmt.Sprintf("Error searching tenants: %v", err),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *TenantController) GetAllTenants(c *fiber.Ctx) error {
pageno, _ := strconv.Atoi(c.Query("pageno"))
pagesize, _ := strconv.Atoi(c.Query("pagesize"))
status := c.Query("status")
aid, _ := strconv.Atoi(c.Query("applocationid"))
tenanttype := c.Query("tenanttype")
keyword := c.Query("keyword")
details, err := ctl.tenantService.GetAllTenants(pageno, pagesize, aid, status, tenanttype, keyword)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": fmt.Sprintf("Error getting all tenants: %v", err),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": details,
})
}
func (ctl *TenantController) GetTenantLocations(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
data, err := ctl.tenantService.GetTenantLocations(tid)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": fmt.Sprintf("Error getting tenant locations: %v", err),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *TenantController) GetTenantSlot(c *fiber.Ctx) error {
data, err := ctl.tenantService.GetTenantSlot()
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": fmt.Sprintf("Error getting tenant slots: %v", err),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *TenantController) CreateTenantCustomer(c *fiber.Ctx) error {
var req models.CreateTenantCustomerRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid request body",
"data": fiber.Map{},
})
}
tenantCustomer, err := ctl.tenantService.CreateTenantCustomer(req)
if err != nil {
if strings.Contains(err.Error(), "already exists for this location") {
return c.JSON(fiber.Map{
"code": 409,
"status": false,
"message": "Customer already assigned to this location",
"data": fiber.Map{},
})
}
log.Println("Error inserting tenant customer:", err)
return c.JSON(fiber.Map{
"code": 500,
"status": false,
"message": "Failed to create tenant customer",
"data": fiber.Map{},
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": 200,
"status": true,
"message": "Tenant customer created successfully",
"data": tenantCustomer,
})
}
func (ctl *TenantController) GetCustomerTenants(c *fiber.Ctx) error {
customerID, err := strconv.Atoi(c.Query("customerid"))
if err != nil || customerID == 0 {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"message": "Invalid customerid",
"status": false,
"details": []interface{}{},
})
}
categoryID, _ := strconv.Atoi(c.Query("categoryid"))
tenantFlag, _ := strconv.Atoi(c.Query("tenant")) // 0 = all tenants, 1 = tenants with orders
data, err := ctl.tenantService.GetCustomerTenants(customerID, categoryID, tenantFlag)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": err.Error(),
"status": false,
"details": []interface{}{},
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data.Details,
})
}
func (ctl *TenantController) GetTenantPricing(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
aid, _ := strconv.Atoi(c.Query("applocationid"))
data, err := ctl.tenantService.GetTenantPricing(tid, aid)
if err != nil {
return c.JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *TenantController) UpdateLocation(c *fiber.Ctx) error {
var data models.Tenantlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
if err := ctl.tenantService.UpdateLocation(data); err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "Location update successful",
})
}
func (ctl *TenantController) CreateLocation(c *fiber.Ctx) error {
var data models.Tenantlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
err := ctl.tenantService.CreateLocation(data)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Location Successfully Created",
"status": true,
})
}
func (ctl *TenantController) GetStaffs(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(c.Query("tenantid"))
data, err := ctl.tenantService.GetStaffs(tid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *TenantController) CreateStaff(c *fiber.Ctx) error {
var data models.User
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
if err := ctl.tenantService.CreateStaff(data); err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusCreated,
"message": "Staff created successfully",
"status": true,
})
}
func (ctl *TenantController) UpdateStaff(c *fiber.Ctx) error {
var data models.User
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
if err := ctl.tenantService.UpdateStaff(data); err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "Staff updated successfully",
})
}
func (ctl *TenantController) CreateTenantLocation(c *fiber.Ctx) error {
var data models.Tenantlocations
if err := c.BodyParser(&data); err != nil {
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 400,
"message": "Invalid request body",
"status": false,
})
}
resp := ctl.tenantService.CreateTenantLocation(data)
return c.Status(fiber.StatusOK).JSON(resp)
}
func (ctl *TenantController) UpdateTenantLocation(c *fiber.Ctx) error {
var data models.Tenantlocations
// Parse JSON body
if err := c.BodyParser(&data); err != nil {
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"status": false,
"code": 400,
"message": "Invalid request body",
})
}
// Call service layer
resp := ctl.tenantService.UpdateTenantLocation(data)
// Always return HTTP 200 (as per your API pattern)
return c.Status(fiber.StatusOK).JSON(resp)
}
func (ctl *TenantController) CreateTenantUser(c *fiber.Ctx) error {
var data models.Tenants
if err := c.BodyParser(&data); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid request body",
})
}
result, err := ctl.tenantService.CreateTenantUser(data)
if err != nil {
if err.Error() == "Tenant Already Exists" {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": 409,
"status": false,
"message": err.Error(),
})
}
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"status": false,
"message": err.Error(),
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"code": 201,
"status": true,
"message": "Successfully Created",
"details": result,
})
}
func (ctl *TenantController) GetTenantInfo(c *fiber.Ctx) error {
tid, _ := strconv.Atoi(strings.TrimSpace(c.Query("tenantid")))
locationid, _ := strconv.Atoi(strings.TrimSpace(c.Query("locationid")))
data, err := ctl.tenantService.GetTenantByID(tid, locationid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": "Error fetching tenant info",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}
func (ctl *TenantController) GetTenantByKeyword(c *fiber.Ctx) error {
keyword := c.Query("keyword")
data, err := ctl.tenantService.GetTenantByKeyword(keyword)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Error searching tenants by keyword",
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": data,
})
}

View File

@@ -0,0 +1,230 @@
package controllers
import (
"net/http"
"strconv"
"nearle/models"
"nearle/services"
"github.com/gofiber/fiber/v2"
)
type UserController struct {
userService services.UserService
}
func NewUserController(userService services.UserService) *UserController {
return &UserController{userService: userService}
}
func (ctl *UserController) GetAllUsers(c *fiber.Ctx) error {
roleID, _ := strconv.Atoi(c.Query("roleid", "0"))
tenantID, _ := strconv.Atoi(c.Query("tenantid", "0"))
pageno, _ := strconv.Atoi(c.Query("pageno", "1"))
pagesize, _ := strconv.Atoi(c.Query("pagesize", "10"))
keyword := c.Query("keyword", "")
users, err := ctl.userService.GetAllUsers(roleID, tenantID, pageno, pagesize, keyword)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": users,
})
}
func (ctl *UserController) GetUserInfo(c *fiber.Ctx) error {
uid, err := strconv.Atoi(c.Query("userid"))
if err != nil || uid <= 0 {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid userid",
"status": false,
})
}
user, err := ctl.userService.GetUserByID(uid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": user,
})
}
func (ctl *UserController) Login(c *fiber.Ctx) error {
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid request body",
"status": false,
})
}
info, err := ctl.userService.Login(user)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": "User not found",
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": info,
})
}
func (ctl *UserController) TenantLogin(c *fiber.Ctx) error {
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
info, err := ctl.userService.TenantLogin(user)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": info,
})
}
func (ctl *UserController) UpdateStaff(c *fiber.Ctx) error {
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": http.StatusBadRequest,
"message": "Invalid request body",
})
}
if err := ctl.userService.UpdateStaff(user); err != nil {
return c.JSON(fiber.Map{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusAccepted,
"message": "User update successful",
})
}
func (ctl *UserController) AppLogin(c *fiber.Ctx) error {
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": 400,
"status": false,
"message": "Invalid request body",
})
}
_, resp, err := ctl.userService.AppLogin(user)
if err != nil {
// Use resp.Code if present, fallback to 409
code := http.StatusConflict
if v, ok := resp["code"].(int); ok {
code = v
}
return c.Status(code).JSON(resp)
}
// ✅ Always return resp
return c.Status(http.StatusOK).JSON(resp)
}
func (ctl *UserController) CreateUser(c *fiber.Ctx) error {
var user models.User
// Parse request body
if err := c.BodyParser(&user); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"status": false,
"message": "Invalid request body",
})
}
// Call service
info, err := ctl.userService.CreateUser(user)
if err != nil {
return c.Status(http.StatusConflict).JSON(fiber.Map{
"code": http.StatusConflict,
"status": false,
"message": "Failed",
})
}
return c.Status(http.StatusCreated).JSON(fiber.Map{
"code": http.StatusCreated,
"status": true,
"message": "Success",
"details": info,
})
}
func (ctl *UserController) TenantWebLogin(c *fiber.Ctx) error {
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"status": false,
"code": fiber.StatusBadRequest,
"message": "Invalid request body",
})
}
info, resp := ctl.userService.TenantWebLogin(user)
// Ensure the response map contains the correct status code
code, ok := resp["code"].(int)
if !ok {
code = fiber.StatusInternalServerError
}
// Include tenant user info if login successful (code 200)
if code == fiber.StatusOK {
resp["details"] = info
}
return c.Status(code).JSON(resp)
}

View File

@@ -0,0 +1,314 @@
package controllers
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"nearle/models"
"nearle/services"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
type UtilsController struct {
utilsService services.UtilsService
}
func NewUtilsController(utilsService services.UtilsService) *UtilsController {
return &UtilsController{utilsService: utilsService}
}
const (
fcmURL = "https://fcm.googleapis.com/v1/projects/nearle-gear/messages:send"
scope = "https://www.googleapis.com/auth/firebase.messaging"
serviceAcc = "nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json" // Path to your service account JSON
)
var client *http.Client
func (ctl *UtilsController) GetAppTypes(c *fiber.Ctx) error {
tag := c.Query("tag")
result, err := ctl.utilsService.GetApptypes(tag)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *UtilsController) NotifyUser(c *fiber.Ctx) error {
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 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": fmt.Sprintf("Error parsing request body: %v", err),
"status": false,
})
}
err := ctl.utilsService.SendNotification(body.Token, body.Notification, body.Data)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": fmt.Sprintf("Error sending notification: %v", err),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "FCM message sent successfully!",
"status": true,
})
}
func (ctl *UtilsController) GetSubcategories(c *fiber.Ctx) error {
mid, _ := strconv.Atoi(c.Query("moduleid"))
cid, _ := strconv.Atoi(c.Query("categoryid"))
result, err := ctl.utilsService.GetSubcategories(mid, cid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *UtilsController) GetApplocations(c *fiber.Ctx) error {
aid, err := strconv.Atoi(c.Query("applocationid"))
if err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid applocationid",
"status": false,
})
}
result, err := ctl.utilsService.GetApplocations(aid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}
func (ctl *UtilsController) GetApplocationConfig(c *fiber.Ctx) error {
aid, err := strconv.Atoi(c.Query("applocationid"))
if err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"code": http.StatusBadRequest,
"message": "Invalid applocationid",
"status": false,
})
}
result, err := ctl.utilsService.GetApplocationConfig(aid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": http.StatusInternalServerError,
"message": err.Error(),
"status": false,
})
}
return c.JSON(fiber.Map{
"status": true,
"code": http.StatusOK,
"message": "Successful",
"details": result,
})
}
type Notification struct {
Title string `json:"title"`
Body string `json:"body"`
}
type FCMRequestBody struct {
Message struct {
Notification Notification `json:"notification"`
Token string `json:"token"`
} `json:"message"`
}
func GetClientFromServiceAccount() (*http.Client, error) {
data, err := ioutil.ReadFile(serviceAcc)
if err != nil {
return nil, fmt.Errorf("failed to read service account file: %v", err)
}
config, err := google.JWTConfigFromJSON(data, scope)
if err != nil {
return nil, fmt.Errorf("failed to parse service account JSON: %v", err)
}
client := config.Client(oauth2.NoContext)
return client, nil
}
func sendFCMMessage(token, title, body string) error {
if client == nil {
var err error
client, err = GetClientFromServiceAccount()
if err != nil {
return fmt.Errorf("failed to get client: %v", err)
}
}
notification := Notification{
Title: title,
Body: body,
}
fcmRequest := FCMRequestBody{}
fcmRequest.Message.Notification = notification
fcmRequest.Message.Token = token
requestBody, err := json.Marshal(fcmRequest)
if err != nil {
return err
}
req, err := http.NewRequest("POST", fcmURL, bytes.NewBuffer(requestBody))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
bodyBytes, _ := ioutil.ReadAll(resp.Body)
return fmt.Errorf("failed to send message: %s", string(bodyBytes))
}
return nil
}
func (ctl *UtilsController) NotifyAdmin(c *fiber.Ctx) error {
body := new(struct {
Token []string `json:"token"`
Notification struct {
Title string `json:"title"`
Body string `json:"body"`
Sound string `json:"sound"`
Type string `json:"type"`
} `json:"notification"`
})
if err := c.BodyParser(body); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
}
if len(body.Token) == 0 {
return fiber.NewError(fiber.StatusBadRequest, "No tokens provided")
}
var successCount, failureCount int
for _, token := range body.Token {
err := sendFCMMessage(token, body.Notification.Title, body.Notification.Body)
if err != nil {
log.Printf("❌ Failed to send to %s: %v", token, err)
failureCount++
} else {
log.Printf("✅ Notification sent to %s", token)
successCount++
}
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Admin notifications sent",
"success": successCount,
"failure": failureCount,
})
}
func (ctl *UtilsController) GetAppConfig(c *fiber.Ctx) error {
cid, _ := strconv.Atoi(c.Query("configid"))
result, err := ctl.utilsService.GetAppConfig(cid)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch app config",
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}
func (ctl *UtilsController) GetAppCategory(c *fiber.Ctx) error {
result, err := ctl.utilsService.GetAppCategory()
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"message": "Failed to fetch app categories",
"status": false,
})
}
return c.Status(http.StatusOK).JSON(fiber.Map{
"code": http.StatusOK,
"message": "Success",
"status": true,
"details": result,
})
}

85
db/connect.go Normal file
View File

@@ -0,0 +1,85 @@
package db
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var (
DB *gorm.DB
)
// --------------------
// DATABASE CONNECTION
// --------------------
func Connect() {
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Kolkata",
mustEnv("DB_HOST"),
mustEnv("DB_USER"),
mustEnv("DB_PASSWORD"),
mustEnv("DB_NAME"),
getEnv("DB_PORT", "5433"),
)
var err error
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal("❌ Could not connect to database:", err)
}
setupDB(DB)
fmt.Println("✅ Database connected")
}
func setupDB(database *gorm.DB) {
sqlDB, err := database.DB()
if err != nil {
log.Fatal("❌ Failed to get DB from GORM:", err)
}
sqlDB.SetMaxIdleConns(100)
sqlDB.SetMaxOpenConns(1000)
sqlDB.SetConnMaxLifetime(time.Minute * 5)
}
// --------------------
// DATABASE SHUTDOWN
// --------------------
func CloseDB() {
if DB == nil {
return
}
sqlDB, err := DB.DB()
if err != nil {
log.Println("Error retrieving sql.DB:", err)
return
}
fmt.Println("Connection closed Successfully")
sqlDB.Close()
}
// --------------------
// ENV HELPERS
// --------------------
func mustEnv(key string) string {
val := os.Getenv(key)
if val == "" {
log.Fatalf("Missing required env variable: %s", key)
}
return val
}
func getEnv(key, fallback string) string {
if val := os.Getenv(key); val != "" {
return val
}
return fallback
}

74
facade/container.go Normal file
View File

@@ -0,0 +1,74 @@
package facade
import (
"nearle/controllers"
"nearle/repositories"
"nearle/services"
"gorm.io/gorm"
)
type Facade struct {
UserController *controllers.UserController
ProductController *controllers.ProductController
OrderController *controllers.OrderController
DeliveriesController *controllers.DeliveriesController
UtilsController *controllers.UtilsController
TenantController *controllers.TenantController
PartnerController *controllers.PartnerController
CustomerController *controllers.CustomerController
}
func NewFacade(db *gorm.DB) *Facade {
// User Module
userRepo := repositories.NewUserRepository(db)
userService := services.NewUserService(userRepo)
userController := controllers.NewUserController(userService)
// Product Module
productRepo := repositories.NewProductRepository(db)
productService := services.NewProductService(productRepo)
productController := controllers.NewProductController(productService)
// Order Module
orderRepo := repositories.NewOrderRepository(db)
orderService := services.NewOrderService(orderRepo)
orderController := controllers.NewOrderController(orderService)
// Deliveries Module
deliveriesRepo := repositories.NewDeliveriesRepository(db)
deliveriesService := services.NewDeliveriesService(deliveriesRepo)
deliveriesController := controllers.NewDeliveriesController(deliveriesService)
// Utils Module
utilsRepo := repositories.NewUtilsRepository(db)
utilsService := services.NewUtilsService(utilsRepo)
utilsController := controllers.NewUtilsController(utilsService)
//Tenant Module
tenantRepo := repositories.NewTenantRepository(db)
tenantService := services.NewTenantService(tenantRepo)
tenantController := controllers.NewTenantController(tenantService)
//Partner Module
partnerRepo := repositories.NewPartnerRepository(db)
partnerService := services.NewPartnerService(partnerRepo)
partnerController := controllers.NewPartnerController(partnerService)
//Customer Module
customerRepo := repositories.NewCustomerRepository(db)
customerService := services.NewCustomerService(customerRepo)
customerController := controllers.NewCustomerController(customerService)
return &Facade{
UserController: userController,
ProductController: productController,
OrderController: orderController,
DeliveriesController: deliveriesController,
UtilsController: utilsController,
TenantController: tenantController,
PartnerController: partnerController,
CustomerController: customerController,
}
}

83
go.mod Normal file
View File

@@ -0,0 +1,83 @@
module nearle
go 1.21
require gorm.io/gorm v1.25.10
require (
cloud.google.com/go v0.110.7 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/firestore v1.13.0 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
cloud.google.com/go/longrunning v0.5.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
firebase.google.com/go v3.13.0+incompatible // indirect
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/gofiber/fiber v1.14.6 // indirect
github.com/gofiber/utils v0.0.10 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gorilla/schema v1.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.6.0 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.50.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.143.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.58.2 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gorm.io/driver/postgres v1.6.0 // indirect
)
require (
github.com/gofiber/fiber/v2 v2.50.0
github.com/jinzhu/copier v0.4.0
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/spf13/viper v1.17.0
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.2
)

635
go.sum Normal file
View File

@@ -0,0 +1,635 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.13.0 h1:/3S4RssUV4GO/kvgJZB+tayjhOfyAHs+KcpJgRVu/Qk=
cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8=
cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o=
github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM=
github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw=
github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw=
github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U=
github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ=
github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA=
google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA=
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI=
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

94
main.go Normal file
View File

@@ -0,0 +1,94 @@
package main
import (
"fmt"
"log"
"nearle/db"
"nearle/facade"
"nearle/routes"
"os"
"os/signal"
"strings"
"syscall"
"time"
_ "time/tzdata"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/joho/godotenv"
"gorm.io/gorm"
)
func init() {
godotenv.Load()
}
func main() {
app := fiber.New()
app.Use(cors.New(cors.Config{
AllowHeaders: "Origin,Content-Type,Accept,Content-Length,Accept-Language,Accept-Encoding,Connection,Access-Control-Allow-Origin",
AllowOrigins: "*",
AllowCredentials: true,
AllowMethods: "GET,POST,HEAD,PUT,DELETE,PATCH,OPTIONS",
}))
fmt.Println("🌐 Connecting to databases...")
db.Connect()
fmt.Println("✅ Database connections established!")
f := facade.NewFacade(db.DB)
routes.RegisterRoutes(app, f)
// Start server
go func() {
if err := app.Listen(":1122"); err != nil {
log.Fatal("Server failed to start:", err)
}
}()
gracefulShutdown()
}
func selectDBMiddleware(c *fiber.Ctx) error {
path := c.Path()
result := strings.Split(path, "/")
var flavour string
if len(result) > 1 {
flavour = result[1]
}
var currentDB *gorm.DB
if flavour == "dev" {
currentDB = db.DB
} else if flavour == "live" {
currentDB = db.DB
}
if currentDB != nil {
c.Locals("DB", currentDB)
}
return c.Next()
}
func gracefulShutdown() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
fmt.Println("\nShutting down gracefully...")
// Normally: close db.DB_DEV and db.DB_LIVE
// Example:
// closeDB(db.DB_DEV)
// closeDB(db.DB_LIVE)
time.Sleep(2 * time.Second)
fmt.Println("Shutdown complete.")
os.Exit(0)
}

7
models/common.go Normal file
View File

@@ -0,0 +1,7 @@
package models
type Result struct {
Code int `json:"code"`
Status bool `json:"status"`
Message string `json:"message"`
}

123
models/customer.go Normal file
View File

@@ -0,0 +1,123 @@
package models
import "time"
type Customers struct {
Customerid int `json:"customerid" gorm:"Primary_Key"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Profileimage string `json:"profileimage"`
Gender string `json:"gender"`
Dob string `json:"dob"`
Dialcode string `json:"dialcode"`
Contactno string `json:"contactno"`
Email string `json:"email"`
Deviceid string `json:"deviceid"`
Devicetype string `json:"devicetype"`
Authmode int `json:"authmode"`
Configid int `json:"configid"`
Customertoken string `json:"customertoken"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Landmark string `json:"landmark"`
Doorno string `json:"doorno"`
Postcode string `json:"postcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Applocationid int `json:"applocationid"`
Locationid int `json:"locationid,omitempty" gorm:"-"`
Defaultaddress string `json:"defaultaddress,omitempty" gorm:"-"`
Primaryaddress int `json:"primaryaddress,omitempty" gorm:"-"`
Tenantid int `json:"tenantid,omitempty" gorm:"-"`
Status int `json:"status"`
Intro string `json:"intro"`
Qrmode int `json:"qrmode,omitempty" gorm:"-"`
}
type CustomerInfo struct {
Customerid int `json:"customerid"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Profileimage string `json:"profileimage"`
Gender string `json:"gender"`
Dob string `json:"dob"`
Dialcode string `json:"dialcode"`
Contactno string `json:"contactno"`
Email string `json:"email"`
Deviceid string `json:"deviceid"`
Devicetype string `json:"devicetype"`
Authmode int `json:"authmode"`
Configid int `json:"configid"`
Customertoken string `json:"customertoken"`
Deliverylocationid int `json:"deliverylocationid"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Landmark string `json:"landmark"`
Doorno string `json:"doorno"`
Postcode string `json:"postcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Applocationid int `json:"applocationid"`
Allocationid int `json:"allocationid"`
Primaryaddress int `json:"primaryaddress"`
Tenantlocationid int `json:"tenantlocationid"`
Tenantid int `json:"tenantid"`
Status int `json:"status"`
Intro string `json:"intro"`
Selectedlatitude string `json:"selectedlatitude"`
Selectedlongitude string `json:"selectedlongitude"`
Radius string `json:"radius"`
Qrmode int `json:"qrmode"`
}
type CustomerLocationResult struct {
Code int `json:"code"`
Status bool `json:"status"`
Message string `json:"message"`
Details []Customerlocations `json:"details"`
}
type Customerlocations struct {
Locationid int `json:"locationid" gorm:"Primary_Key"`
Customerid int `json:"customerid"`
Applocationid int `json:"applocationid" gorm:"-"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Landmark string `json:"landmark"`
Doorno string `json:"doorno"`
Postcode string `json:"postcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Primaryaddress int `json:"primaryaddress"`
Status int `json:"status"`
}
type CustomerRequest struct {
Customerrequestid int `json:"customerrequestid" gorm:"primaryKey;autoIncrement"`
Referencedate time.Time `json:"referencedate"`
Referencetype string `json:"referencetype"`
Customerid int `json:"customerid"`
Tenantid int `json:"tenantid"`
Apptypeid int `json:"apptypeid"`
Locationid int `json:"locationid"`
Subject string `json:"subject"`
Remarks string `json:"remarks"`
Status int `json:"status"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
type Tenantcustomers struct {
Tenantcustomerid int `json:"tenantcustomerid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid" `
Locationid int `json:"locationid"`
Customerid int `json:"customerid"`
Moduleid int `json:"moduleid"`
Status int `json:"status"`
}

243
models/deliveries.go Normal file
View File

@@ -0,0 +1,243 @@
package models
type Deliveries struct {
Deliveryid int `json:"deliveryid" gorm:"Primary_Key"`
Orderheaderid int `json:"orderheaderid"`
Applocationid int `json:"applocationid"`
Configid int `json:"configid"`
Partnerid int `json:"partnerid"`
Tenantid int `json:"tenantid"`
Moduleid int `json:"moduleid"`
Locationid int `json:"locationid"`
Categoryid int `json:"categoryid"`
Userid int `json:"userid"`
Subcategoryid int `json:"subcategoryid"`
Orderid string `json:"orderid"`
Deliverydate string `json:"deliverydate"`
Orderstatus string `json:"orderstatus"`
Assigntime string `json:"assigntime"`
Starttime string `json:"starttime"`
Arrivaltime string `json:"arrivaltime"`
Pickuptime string `json:"pickuptime"`
Deliverytime string `json:"deliverytime"`
Canceltime string `json:"canceltime"`
Itemcount int `json:"itemcount"`
Orderamount float32 `json:"orderamount"`
Customerid int `json:"customerid"`
Pickupcustomer string `json:"pickupcustomer"`
Pickupcontactno string `json:"pickupcontactno"`
Pickuplocationid int `json:"pickuplocationid"`
Pickupaddress string `json:"Pickupaddress"`
Pickuplocation string `json:"pickuplocation"`
Pickuplat string `json:"pickuplat"`
Pickuplon string `json:"pickuplon"`
Deliverycustomerid int `json:"deliverycustomerid"`
Deliverylocationid int `json:"deliverylocationid"`
Deliverycustomer string `json:"deliverycustomer"`
Deliverycontactno string `json:"deliverycontactno"`
Deliveryaddress string `json:"deliveryaddress"`
Deliverylocation string `json:"deliverylocation"`
Droplat string `json:"droplat"`
Droplon string `json:"droplon"`
Deliverylat string `json:"deliverylat"`
Deliverylong string `json:"deliverylong"`
Deliverycharges float32 `json:"deliverycharges"`
Deliveryamt float32 `json:"deliveryamt"`
Deliverytype string `json:"deliverytype"`
Notes string `json:"notes"`
Ordernotes string `json:"ordernotes"`
Riderslat string `json:"riderslat"`
Riderslon string `json:"riderslon"`
Firstmilekm float32 `json:"firstmilekm"`
Firstmilecharges float32 `json:"firstmilecharges"`
Lastmilecharges float32 `json:"lastmilecharges"`
Ridercharges float32 `json:"ridercharges"`
Kms string `json:"kms"`
Actualkms string `json:"actualkms"`
Smsdelivery int `json:"smsdelivery"`
Paymenttype int `json:"paymenttype"`
}
type Deliveryqueues struct {
Queueid int `json:"queueid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Orderheaderid int `json:"orderheaderid"`
Deliveryid int `json:"deliveryid"`
Userid int `json:"userid"`
Partnerid int `json:"partnerid"`
Orderid string `json:"orderid"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Accept int `json:"accept"`
Decline int `json:"decline"`
Queuestatus int `json:"queuestatus"`
}
type Updateorderstatus struct {
Orderheaderid int `json:"Orderheaderid"`
Orderstatus string `json:"Orderstatus"`
Pending string `json:"pending"`
Processing string `json:"processing"`
Cancelled string `json:"cancelled"`
Delivered string `json:"delivered"`
}
type UpdateDeliveryStatus struct {
Deliveryid int `json:"deliveryid"`
Deliverytype string `json:"deliverytype"`
Pickuplocationid int `json:"pickuplocationid"`
Deliverylocationid int `json:"deliverylocationid"`
Orderheaderid int `json:"orderheaderid"`
Userid int `json:"userid"`
Orderstatus string `json:"orderstatus"`
Assigntime string `json:"assigntime"`
Starttime string `json:"starttime"`
Arrivaltime string `json:"arrivaltime"`
Pickuptime string `json:"pickuptime"`
Deliverytime string `json:"deliverytime"`
Canceltime string `json:"canceltime"`
Pickuplat string `json:"pickuplat"`
Pickuplon string `json:"picklon"`
Riderslat string `json:"riderslat"`
Riderslon string `json:"riderslon"`
Deliverylat string `json:"deliverylat"`
Deliverylong string `json:"deliverylong"`
Address string `json:"address" gorm:"<-:false"`
Suburb string `json:"suburb" gorm:"<-:false"`
City string `json:"city" gorm:"<-:false"`
State string `json:"state" gorm:"<-:false"`
Postcode string `json:"postcode" gorm:"<-:false"`
Deliveryamt float32 `json:"deliveryamt"`
Kms string `json:"kms"`
Actualkms string `json:"actualkms"`
Riderkms string `json:"riderkms"`
Kmcal string `json:"kmcal"`
Notes string `json:"notes"`
Feedback string `json:"feedback"`
Smsdelivery int `json:"smsdelivery"`
}
type DeliverySummary struct {
Total int `json:"total"`
Created int `json:"created"`
Pending int `json:"pending"`
Accepted int `json:"accepted"`
Arrived int `json:"arrived"`
Picked int `json:"picked"`
Active int `json:"active"`
Delivered int `json:"delivered"`
Cancelled int `json:"cancelled"`
}
type ReportSummary struct {
Tenantid int `json:"tenantid"`
Tenantname string `json:"tenantname"`
Totalorders int `json:"totalorders"`
Orderscreated int `json:"orderscreated"`
Orderspending int `json:"Orderspending"`
Orderscompleted int `json:"orderscompleted"`
Orderscancelled int `json:"orderscancelled"`
Deliveriespending int `json:"deliveriespending"`
Deliveriescompleted int `json:"deliveriescompleted"`
Deliveriescancelled int `json:"deliveriescancelled"`
Paylater float32 `json:"paylater"`
Payondelivery float32 `json:"payondelivery"`
Kms float32 `json:"kms"`
Actualkms float32 `json:"actualkms"`
Charges float32 `json:"charges"`
}
type Ridersummary struct {
Userid int `json:"userid"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Deliveries int `json:"deliveries"`
Assigned int `json:"Assigened"`
Accepted int `json:"Accepted"`
Picked int `json:"Picked"`
Delivered int `json:"delivered"`
Kms float32 `json:"kms"`
Actualkms float32 `json:"actualkms"`
Payondelivery float32 `json:"payondelivery"`
Paylater float32 `json:"Paylater"`
Deliveryamt float32 `json:"Deliveryamt"`
Status string `json:"status"`
}
type Deliveryinfo struct {
Deliveryid int `json:"deliveryid"`
Orderheaderid int `json:"orderheaderid"`
Applocationid int `json:"applocationid"`
Applocation string `json:"applocation"`
Configid int `json:"configid"`
Partnerid int `json:"partnerid"`
Tenantid int `json:"tenantid"`
Moduleid int `json:"moduleid"`
Locationid int `json:"locationid"`
Categoryid int `json:"categoryid"`
Userid int `json:"userid"`
Subcategoryid int `json:"subcategoryid"`
Orderid string `json:"orderid"`
Deliverydate string `json:"deliverydate"`
Orderstatus string `json:"orderstatus"`
Assigntime string `json:"assigntime"`
Starttime string `json:"starttime"`
Arrivaltime string `json:"arrivaltime"`
Pickuptime string `json:"pickuptime"`
Deliverytime string `json:"deliverytime"`
Canceltime string `json:"canceltime"`
Itemcount int `json:"itemcount"`
Orderamount float32 `json:"orderamount"`
Customerid int `json:"customerid"`
Pickupcustomer string `json:"pickupcustomer"`
Pickupcontactno string `json:"pickupcontactno"`
Pickuplocationid int `json:"pickuplocationid"`
Pickupaddress string `json:"Pickupaddress"`
Pickuplocation string `json:"pickuplocation"`
Pickuplat string `json:"pickuplat"`
Pickuplon string `json:"pickuplon"`
Deliverycustomerid int `json:"deliverycustomerid"`
Deliverylocationid int `json:"deliverylocationid"`
Deliverycustomer string `json:"deliverycustomer"`
Deliverycontactno string `json:"deliverycontactno"`
Deliveryaddress string `json:"deliveryaddress"`
Deliverylocation string `json:"deliverylocation"`
Droplat string `json:"droplat"`
Droplon string `json:"droplon"`
Deliverylat string `json:"deliverylat"`
Deliverylong string `json:"deliverylong"`
Deliverycharges float32 `json:"deliverycharges"`
Deliveryamt float32 `json:"deliveryamt"`
Deliverytype string `json:"deliverytype"`
Notes string `json:"notes"`
Ordernotes string `json:"ordernotes"`
Riderslat string `json:"riderslat"`
Riderslon string `json:"riderslon"`
Firstmilekm float32 `json:"firstmilekm"`
Firstmilecharges float32 `json:"firstmilecharges"`
Lastmilecharges float32 `json:"lastmilecharges"`
Ridercharges float32 `json:"ridercharges"`
Kms string `json:"kms"`
Actualkms string `json:"actualkms"`
Riderkms string `json:"riderkms"`
Paymenttype int `json:"paymenttype"`
Tenantname string `json:"tenantname"`
Tenantcontactno string `json:"tenantcontactno"`
Tenanttoken string `json:"tenanttoken"`
Tenantsuburb string `json:"tenantsuburb"`
Tenantcity string `json:"tenantcity"`
Locationname string `json:"locationname"`
Locationcontactno string `json:"locationcontactno"`
Locationsuburb string `json:"locationsuburb"`
Ridername string `json:"ridername"`
Userfcmtoken string `json:"userfcmtoken"`
Queueid int `json:"queueid"`
Smsdelivery int `json:"smsdelivery"`
Customertoken string `json:"customertoken"`
Ridercontact string `json:"ridercontact"`
Expecteddeliverytime string `json:"expecteddeliverytime"`
Profit int `json:"profit"`
Transitminutes int `json:"transitminutes"`
Calculationdistancekm int `json:"calculationdistancekm"`
}

440
models/order.go Normal file
View File

@@ -0,0 +1,440 @@
package models
import (
"database/sql/driver"
"encoding/json"
"fmt"
"strconv"
"gorm.io/gorm"
)
// FlexibleString handles JSON that could be either a number or a string,
// and ensures it can be saved/read from the database as a string.
type FlexibleString string
func (fs *FlexibleString) UnmarshalJSON(b []byte) error {
if len(b) == 0 {
return nil
}
// If it's a string in JSON
if b[0] == '"' {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
*fs = FlexibleString(s)
return nil
}
// If it's a number in JSON
var f float64
if err := json.Unmarshal(b, &f); err != nil {
return err
}
*fs = FlexibleString(strconv.FormatFloat(f, 'f', -1, 64))
return nil
}
func (fs FlexibleString) MarshalJSON() ([]byte, error) {
return json.Marshal(string(fs))
}
// 🔥 Database Logic: Handle reading from DB
func (fs *FlexibleString) Scan(value interface{}) error {
if value == nil {
*fs = ""
return nil
}
switch v := value.(type) {
case []byte:
*fs = FlexibleString(v)
case string:
*fs = FlexibleString(v)
case float64:
*fs = FlexibleString(strconv.FormatFloat(v, 'f', -1, 64))
case int64:
*fs = FlexibleString(strconv.FormatInt(v, 10))
default:
*fs = FlexibleString(fmt.Sprintf("%v", v))
}
return nil
}
// 🔥 Database Logic: Handle writing to DB
func (fs FlexibleString) Value() (driver.Value, error) {
return string(fs), nil
}
func (fs FlexibleString) String() string {
return string(fs)
}
type OrderInfo struct {
Orderheaderid int `json:"orderheaderid"`
Applocationid int `json:"applocationid"`
Applocation string `json:"applocation"`
Tenantid int `json:"tenantid"`
Partnerid int `json:"partnerid"`
Locationid int `json:"locationid"`
Categoryid int `json:"categoryid"`
Subcategoryid int `json:"subcategoryid"`
Moduleid int `json:"moduleid"`
Configid int `json:"configid"`
Orderid string `json:"orderid"`
Orderdate string `json:"orderdate"`
Deliverydate string `json:"deliverydate"`
Orderstatus string `json:"orderstatus"`
Deliverystatus string `json:"deliverystatus"`
Deliveryamt float64 `json:"deliveryamt"`
Itemcount int `json:"itemcount"`
Ordernotes string `json:"ordernotes"`
Kms FlexibleString `json:"kms"`
Actualkms FlexibleString `json:"actualkms"`
Pending string `json:"Pending"`
Processing string `json:"processing"`
Ready string `json:"ready"`
Cancelled string `json:"cancelled"`
Delivered string `json:"delivered"`
Assigntime string `json:"assigntime"`
Starttime string `json:"starttime"`
Arrivaltime string `json:"arrivaltime"`
Pickuptime string `json:"pickuptime"`
Deliverytime string `json:"deliverytime"`
Canceltime string `json:"canceltime"`
Deliverycharge float32 `json:"deliverycharge"`
Orderamount float32 `json:"orderamount"`
Customerid int `json:"customerid"`
Pickupcustomer string `json:"pickupcustomer"`
Pickupcontactno string `json:"pickupcontactno"`
Pickuplocationid int `json:"pickuplocationid"`
Pickupaddress string `json:"pickupaddress"`
Pickupsuburb string `json:"pickupsuburb"`
Pickupcity string `json:"pickupcity"`
Pickuplat FlexibleString `json:"pickuplat"`
Pickuplong FlexibleString `json:"pickuplong"`
Deliveryid int `json:"deliveryid"`
Deliverycustomerid int `json:"deliverycustomerid"`
Deliverycustomer string `json:"deliverycustomer"`
Deliverycontactno string `json:"deliverycontactno"`
Deliverylocationid int `json:"deliverylocationid"`
Deliveryaddress string `json:"deliveryaddress"`
Deliverysuburb string `json:"deliverysuburb"`
Droplat FlexibleString `json:"droplat"`
Droplon FlexibleString `json:"droplon"`
Deliverylat FlexibleString `json:"deliverylat"`
Deliverylong FlexibleString `json:"deliverylong"`
Deliverytype string `json:"deliverytype"`
Paymenttype int `json:"paymenttype"`
Tenantname string `json:"tenantname"`
Tenanttoken string `json:"tenanttoken"`
Tenantsuburb string `json:"tenantsuburb"`
Tenantcity string `json:"tenantcity"`
Tenantcontactno string `json:"tenantcontactno"`
Tenantpostcode string `json:"tenantpostcode"`
Locationname string `json:"locationname"`
Locationsuburb string `json:"locationsuburb"`
Locationcity string `json:"locationcity"`
Locationcontactno string `json:"locationcontactno"`
Rider string `json:"rider"`
Ridercontactno string `json:"ridercontactno"`
Riderkms FlexibleString `json:"riderkms"`
Smsdelivery int `json:"smsdelivery"`
Customertoken string `json:"customertoken"`
Ridertoken string `json:"ridertoken"`
}
type DeliveryQuery struct {
Tenantid int
Customerid int
Partnerid int
UserID int
Appuserid int
Applocationid int
Moduleid int
Locationid int
Configid int
Fromdate string
ToDate string
Status string
Pageno int
Pagesize int
Conn *gorm.DB
Keyword string `json:"keyword"`
}
type Ordersummary struct {
Total int `json:"total"`
Created int `json:"created"`
Pending int `json:"pending"`
Processing int `json:"processing"`
Delivered int `json:"delivered"`
Cancelled int `json:"cancelled"`
// Locationid int `json:"locationid"`
Locationname string `json:"locationname"`
Applocationid string `json:"applocationid"`
}
type Ordersummarylocation struct {
Total int `json:"total"`
Created int `json:"created"`
Pending int `json:"pending"`
Processing int `json:"processing"`
Delivered int `json:"delivered"`
Cancelled int `json:"cancelled"`
Locationid int `json:"locationid"`
Locationname string `json:"locationname"`
}
type Ordersummarydaily struct {
Total int `json:"total"`
Created int `json:"created"`
Pending int `json:"pending"`
Processing int `json:"processing"`
Delivered int `json:"delivered"`
Cancelled int `json:"cancelled"`
Tenantid int `json:"tenantid"`
Tenantname string `json:"tenantname"`
Locationid int `json:"locationid"`
Locationname string `json:"locationname"`
}
type OrderInsight struct {
Applocationid int `json:"applocationid" gorm:"Primary_Key"`
Locationname string `json:"locationname"`
Ordermonths *Ordermonths `json:"ordermonths" gorm:"-"`
}
type OrderInsightv1 struct {
Locationid int `json:"locationid" gorm:"Primary_Key"`
Locationname string `json:"locationname"`
Ordermonths *Ordermonths `json:"ordermonths" gorm:"-"`
}
type Ordermonths struct {
Jan int `json:"jan"`
Feb int `json:"feb"`
Mar int `json:"mar"`
Apr int `json:"apr"`
May int `json:"may"`
Jun int `json:"jun"`
Jul int `json:"jul"`
Aug int `Json:"aug"`
Sep int `Json:"sep"`
Oct int `Json:"oct"`
Nov int `Json:"nov"`
Dece int `Json:"dece"`
// Applocationid int `json:"applocationid"`
}
type Orders struct {
Orderheaderid int `json:"orderheaderid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Applocationid int `json:"applocationid"`
Moduleid int `json:"moduleid"`
Partnerid int `json:"partnerid"`
Configid int `json:"configid"`
Categoryid int `json:"categoryid"`
Subcategoryid int `json:"subcategoryid"`
Orderid string `json:"orderid"`
Orderdate string `json:"orderdate,omitempty"`
Deliverytime string `json:"deliverytime"`
Deliverytype string `json:"deliverytype"`
Orderstatus string `json:"orderstatus"`
Pending string `json:"pending"`
Processing string `json:"processing"`
Ready string `json:"ready"`
Delivered string `json:"delivered"`
Cancelled string `json:"cancelled"`
Customerid int `json:"customerid"`
Pickupaddress string `json:"pickupaddress"`
Pickuplat FlexibleString `json:"pickuplat"`
Pickuplong FlexibleString `json:"pickuplong"`
Pickupcustomer string `json:"pickupcustomer"`
Pickupcontactno string `json:"pickupcontactno"`
Pickuplocation string `json:"pickupsuburb"` // alias
Pickupcity string `json:"pickupcity"`
Deliveryid int `json:"deliverycustomerid"` // alias
Deliverycustomer string `json:"deliverycustomer"`
Deliverycontactno string `json:"deliverycontactno"`
Deliveryaddress string `json:"deliveryaddress"`
Deliverylocation string `json:"deliverylocation"`
Deliverycity string `json:"deliverycity"`
Deliverylocationid int `json:"deliverylocationid"`
Deliverylat FlexibleString `json:"deliverylat"`
Deliverylong FlexibleString `json:"deliverylong"`
Promotionid int `json:"promotionid"`
Promoname string `json:"promoname"`
Promoterms string `json:"promoterms"`
Promovalue int `json:"promovalue"`
Promoamount float32 `json:"promoamount"`
Orderamount float32 `json:"orderamount"`
Taxamount float32 `json:"taxamount"`
Ordercharges float32 `json:"ordercharges"`
Ordervalue float32 `json:"ordervalue"`
Itemcount int `json:"itemcount"`
Paymenttype int `json:"paymenttype"`
Paymentstatus int `json:"paymentstatus"`
Deliverycharge float32 `json:"deliverycharge"`
Ordernotes string `json:"ordernotes"`
Kms FlexibleString `json:"kms"`
Remarks string `json:"remarks"`
Tenantuserid int `json:"tenantuserid"`
Partneruserid int `json:"partneruserid"`
Smsdelivery int `json:"smsdelivery" gorm:"default:0"`
Items []OrderDetail `json:"items" gorm:"-"`
}
type OrderDetails struct {
Orderdetailid int `json:"orderdetailid" gorm:"primaryKey;autoIncrement"`
Orderheaderid int `json:"orderheaderid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Productid int `json:"productid"`
Productname string `json:"productname"`
Productdescription string `json:"productdescription"`
Supplyqty float64 `json:"supplyqty"`
Balanceqty float64 `json:"balanceqty"`
Orderqty float64 `json:"orderqty"`
Price float64 `json:"price"`
Unitid int `json:"unitid"`
Unitname string `json:"unitname"`
Productaddonid int `json:"productaddonid"`
Addontypeid int `json:"addontypeid"`
Productmapid int `json:"productmapid"`
Productvariantid int `json:"productvariantid"`
Productaddondescription string `json:"productaddondescription"`
Discountid int `json:"discountid"`
Discountname string `json:"discountname"`
Discountcode string `json:"discountcode"`
Discountterms string `json:"discountterms"`
Discountpercentage float64 `json:"discountpercentage"`
Discountamount float64 `json:"discountamount"`
Landingamount float64 `json:"landingamount"`
Taxpercentage float64 `json:"taxpercentage"`
Taxamount float64 `json:"taxamount"`
Totaltaxamount float64 `json:"totaltaxamount"`
Productsumprice float64 `json:"productsumprice"`
Itemstatus string `json:"itemstatus"`
Delivered string `json:"delivered"`
Orderamount float64 `json:"Orderamount"`
Productimage string `json:"productimage"`
}
type OrderDetail struct {
Orderdetailid int `json:"orderdetailid" gorm:"primaryKey;autoIncrement"`
Orderheaderid int `json:"orderheaderid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Productid int `json:"productid"`
Productname string `json:"productname"`
Productdescription string `json:"productdescription"`
Supplyqty float64 `json:"supplyqty"`
Balanceqty float64 `json:"balanceqty"`
Orderqty float64 `json:"orderqty"`
Price float64 `json:"price"`
Unitid int `json:"unitid"`
Unitname string `json:"unitname"`
Productaddonid int `json:"productaddonid"`
Addontypeid int `json:"addontypeid"`
Productmapid int `json:"productmapid"`
Productvariantid int `json:"productvariantid"`
Productaddondescription string `json:"productaddondescription"`
Discountid int `json:"discountid"`
Discountname string `json:"discountname"`
Discountcode string `json:"discountcode"`
Discountterms string `json:"discountterms"`
Discountpercentage float64 `json:"discountpercentage"`
Discountamount float64 `json:"discountamount"`
Landingamount float64 `json:"landingamount"`
Taxpercentage float64 `json:"taxpercentage"`
Taxamount float64 `json:"taxamount"`
Productsumprice float64 `json:"productsumprice"`
Itemstatus string `json:"itemstatus"`
Delivered string `json:"delivered"`
Orderamount float64 `json:"-" gorm:"-"`
Productimage string `json:"productimage" gorm:"-"` // only for JSON
}
type CustomerOrder struct {
Orderheaderid int `json:"orderheaderid" gorm:"Primary_Key"`
Applocationid int `json:"applocationid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Partnerid int `json:"partnerid"`
Configid int `json:"configid"`
Categoryid int `json:"categoryid"`
Subcategoryid int `json:"subcategoryid"`
Moduleid int `json:"moduleid"`
Orderid string `json:"orderid"`
Orderstatus string `json:"orderstatus"`
Orderdate string `json:"orderdate,omitempty"`
Ordernotes string `json:"ordernotes"`
Itemcount int `json:"itemcount"`
Deliverytime string `json:"deliverytime"` // alias for delivered
Pending string `json:"pending"`
Processing string `json:"processing"`
Ready string `json:"ready"`
Delivered string `json:"delivered"` // original delivered column
Cancelled string `json:"cancelled"`
Deliverycharge float32 `json:"deliverycharge"`
Kms FlexibleString `json:"kms"`
Smsdelivery int `json:"smsdelivery"`
// Tenant Info
Tenantname string `json:"tenantname"`
Tenanttoken string `json:"tenanttoken"`
Tenantcontactno string `json:"tenantcontactno"`
Tenantpostcode string `json:"tenantpostcode"`
Tenantsuburb string `json:"tenantsuburb"`
Tenantcity string `json:"tenantcity"`
Registrationno string `json:"registrationno"`
// Location Info
Locationname string `json:"locationname"`
Locationcontactno string `json:"locationcontactno"`
Locationpostcode string `json:"locationpostcode"`
Locationsuburb string `json:"locationsuburb"`
Locationcity string `json:"locationcity"`
// App Location
Applocation string `json:"applocation"`
// Delivery Info (from `deliveries` table)
Deliverystatus string `json:"deliverystatus"`
DeliveryUserID int `json:"deliveryid"` // alias
Assigntime string `json:"assigntime"`
Starttime string `json:"starttime"`
Arrivaltime string `json:"arrivaltime"`
Pickuptime string `json:"pickuptime"`
Finaldeliverytime string `json:"finaldeliverytime"` // alias for f.deliverytime
Canceltime string `json:"canceltime"`
Riderkms FlexibleString `json:"riderkms"`
// Actualkms sql.NullFloat64 `json:"actualkms"`
// Actualkms sql.NullFloat64 `json:"actualkms"`
// Riderkms sql.NullFloat64 `json:"riderkms"`
// Deliveryamt sql.NullFloat64 `json:"deliveryamt"`
Droplat FlexibleString `json:"droplat"`
Droplon FlexibleString `json:"droplon"`
// Rider
Rider string `json:"rider"`
Orderamount float64 `json:"orderamount"`
Taxamount float64 `json:"taxamount"`
Totaltaxamount float64 `json:"totaltaxamount"`
Riderkms_v2 FlexibleString `json:"-" gorm:"column:riderkms"` // Extra safety
// Items if applicable
OrderDetails []OrderDetails `json:"orderdetails" gorm:"-"`
}
type Ordersequences struct {
Sequenceid int `json:"sequenceid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Orderprefix string `json:"orderprefix" gorm:"default:ORD"`
Customerprefix string `json:"customerprefix" gorm:"default:CUS"`
Appointmentprefix string `json:"appointmentprefix" gorm:"default:ORD"`
Receiptprefix string `json:"receiptprefix" gorm:"default:REC"`
Paymentprefix string `json:"paymentprefix" gorm:"default:PAY"`
}

106
models/partner.go Normal file
View File

@@ -0,0 +1,106 @@
package models
type RiderInfo struct {
Userid int `json:"userid"`
Authname string `json:"authname"`
Configid int `json:"configid"`
Authmode int `json:"authmode"`
Roleid int `json:"roleid"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Fullname string `json:"fullname"`
Password string `json:"password"`
Email string `json:"email"`
Contactno string `json:"contactno"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Userfcmtoken string `json:"userfcmtoken"`
Pin int `json:"pin"`
Partnerid int `json:"partnerid"`
Identificationno string `json:"identificationno"`
Vehiclename string `json:"vehiclename"`
Vehicleno string `json:"vehicleno"`
Licenseno string `json:"licenseno"`
Insuranceno string `json:"insoranceno"`
Insurancedate string `json:"insurancedate"`
Shiftid int `json:"shiftid"`
Starttime string `json:"starttime"`
Endtime string `json:"endtime"`
Shifthours float32 `json:"shifthours"`
Basefare float32 `json:"basefare"`
Additionalcharges float32 `json:"additionalcharges"`
Orders int `json:"orders"`
Fuelcharge float32 `json:"fuelcharge"`
Logdate string `json:"logdate"`
Applocationid int `json:"applocationid"`
Applocation string `json:"applocation"`
Logseconds int `json:"logseconds"`
Riderid int `json:"riderid"`
Status string `json:"status"`
Tenantid int `json:"tenantid"`
}
type Partnerinfo struct {
Partnerid int `json:"partnerid" gorm:"Primary_Key"`
Partnertypeid int `json:"partnertypeid"`
Applocationid int `json:"applocationid"`
Partnername string `json:"partnername"`
Registrationno string `json:"registrationno"`
Primarycontact string `json:"primartcontact"`
Primaryemail string `json:"primaryemail"`
Contactno string `json:"contactno"`
Bizcategoryid int `json:"bizcategoryid"`
Bizsubcategoryid int `json:"bizsubcategoryid"`
Adderss string `json:"address"`
Suburb string `json:"suburb"`
State string `json:"state"`
City string `json:"city"`
Postcode string `json:"postcode"`
Partnerinfo string `json:"partnerinfo"`
Partnerimage string `json:"partnerimage"`
}
type Ridershifts struct {
Shiftid int `json:"shiftid" gorm:"Primary_Key"`
Shiftdate string `json:"shiftdate"`
Starttime string `json:"starttime"`
Endtime string `json:"endtime"`
Shifthours float32 `json:"shifthours"`
Basefare float32 `json:"basefare"`
Additionalkm float32 `json:"additionalkm"`
Additionalcharges float32 `json:"additionalcharges"`
Orders int `json:"orders"`
Fuelcharge float32 `json:"fuelcharge"`
Shiftname string `json:"shiftname" gorm:"<-:false"`
}
type Locationconfigs struct {
Applocationid int `json:"applocationid"`
Configid int `json:"configid"`
Locationname string `json:"locationname"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Status string `json:"status"`
}
type RiderlogDetails struct {
Logid int `json:"logid"`
Logdate string `json:"logdate"`
Userid int `json:"userid"`
Username string `json:"username"`
Partnerid int `json:"partnerid"`
Shiftid int `json:"shiftid"`
Shifthours float32 `json:"shifthours"`
Login string `json:"login"`
Logout string `json:"logout"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Workhours float32 `json:"workhours"`
Shorthours float32 `json:"shorthours"`
Breakhours float32 `json:"breakhours"`
Logstatus int `json:"logstatus"`
}

284
models/product.go Normal file
View File

@@ -0,0 +1,284 @@
package models
import "time"
type ProductSubCategory struct {
Subcatid int `json:"subcatid"`
Categoryid int `json:"categoryid,omitempty"`
Tenantid int `json:"tenantid,omitempty"`
Subcatname string `json:"subcatname,omitempty"`
Image string `json:"image,omitempty"`
Status string `json:"status,omitempty"`
Sortorder int `json:"sortorder,omitempty"`
Createdby int `json:"createdby,omitempty"`
Created time.Time `json:"created,omitempty"`
Updated time.Time `json:"updated,omitempty"`
}
type Productcount struct {
Total int `json:"total"`
Available int `json:"available"`
Outofstock int `json:"outofstock"`
}
type ProductCategory struct {
Categoryid int `json:"categoryid"`
Moduleid int `json:"moduleid"`
Tenantid int `json:"tenantid,omitempty"`
Categorytypeid int `json:"categorytypeid,omitempty"`
Categoryname string `json:"categoryname,omitempty"`
Image string `json:"image,omitempty"`
Catalougecategoryid int `json:"catalougecategoryid,omitempty"`
Sortorder int `json:"sortorder,omitempty"`
Status string `json:"status"`
Createdby int `json:"createdby,omitempty"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
type Productvariant struct {
Variantid int `json:"variantid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Variantname string `json:"variantname"`
Categoryid int `json:"categoryid" gorm:"default:0"`
Categoryname string `json:"categoryname" gorm:"-"`
Subcategoryid int `json:"subcategoryid"`
Status string `json:"status" gorm:"default:active"`
}
type Products struct {
Productid int `json:"productid" gorm:"primaryKey;autoIncrement"`
AppLocationid int `json:"applocationid" gorm:"column:applocationid"`
Productlocationid int `json:"productlocationid" gorm:"->"`
Tenantid int `json:"tenantid,omitempty"`
Categoryid int `json:"categoryid"`
Categoryname string `json:"categoryname" gorm:"->"`
Subcategoryid int `json:"subcategoryid,omitempty"`
Subcategoryname string `json:"Subcategoryname" gorm:"->"`
Catalogueid int `json:"catalogueid,omitempty"`
Addonid int `json:"addonid,omitempty"`
Discountid int `json:"discountid"`
Discountvalue float64 `json:"discountvalue"`
Pricingid int `json:"pricingid,omitempty"`
Productname string `json:"productname,omitempty"`
Productimage string `json:"productimage,omitempty"`
Productdesc string `json:"productdesc,omitempty"`
Productsku string `json:"productsku,omitempty"`
Brandid int `json:"brandid,omitempty"`
Productbrand string `json:"productbrand,omitempty"`
Productunit string `json:"productunit,omitempty"`
Unitvalue string `json:"unitvalue,omitempty"`
Toppicks string `json:"toppicks,omitempty"`
Productcost float64 `json:"productcost,omitempty"`
Taxamount float64 `json:"taxamount,omitempty"`
Taxpercent float64 `json:"taxpercent,omitempty"`
Producttax int `json:"producttax" gorm:"default:0"`
Productstock int `json:"productstock" gorm:"default:0"`
Productcombo int `json:"productcombo" gorm:"default:0"`
Variants int `json:"variants" gorm:"default:0"`
Quantity int `json:"quantity"`
Retailprice float64 `json:"retailprice,omitempty"`
Diffprice float64 `json:"diffprice,omitempty"`
Diffpercent float64 `json:"diffpercent,omitempty"`
Othercost float64 `json:"othercost,omitempty"`
Approve int `json:"approve"`
Productstatus string `json:"productstatus" `
// Status string `json:"status" gorm:"default:InActive"`
// Status string `json:"status" gorm:"-"`
}
type Locationproducts struct {
Productid int `json:"productid"`
AppLocationid int `json:"applocationid" gorm:"column:applocationid"`
Productlocationid int `json:"productlocationid" gorm:"->"`
Tenantid int `json:"tenantid,omitempty"`
Categoryid int `json:"categoryid"`
Categoryname string `json:"categoryname" gorm:"->"`
Subcategoryid int `json:"subcategoryid,omitempty"`
Subcategoryname string `json:"Subcategoryname" gorm:"->"`
Catalogueid int `json:"catalogueid,omitempty"`
Addonid int `json:"addonid,omitempty"`
Discountid int `json:"discountid,omitempty"`
Pricingid int `json:"pricingid,omitempty"`
Productname string `json:"productname,omitempty"`
Productimage string `json:"productimage,omitempty"`
Productdesc string `json:"productdesc,omitempty"`
Productsku string `json:"productsku,omitempty"`
Brandid int `json:"brandid,omitempty"`
Productbrand string `json:"productbrand,omitempty"`
Productunit string `json:"productunit,omitempty"`
Unitvalue string `json:"unitvalue,omitempty"`
Toppicks string `json:"toppicks,omitempty"`
Productcost float64 `json:"productcost,omitempty"`
Taxamount float64 `json:"taxamount,omitempty"`
Taxpercent float64 `json:"taxpercent,omitempty"`
Producttax int `json:"producttax" gorm:"default:0"`
Productstock int `json:"productstock" gorm:"default:0"`
Productcombo int `json:"productcombo" gorm:"default:0"`
Variants int `json:"variants" gorm:"default:0"`
Quantity int `json:"quantity"`
Retailprice float64 `json:"retailprice,omitempty"`
Diffprice float64 `json:"diffprice,omitempty"`
Diffpercent float64 `json:"diffpercent,omitempty"`
Othercost float64 `json:"othercost,omitempty"`
Approve int `json:"approve" gorm:"default:0"`
// Productstatus string `json:"productstatus" gorm:"default:available"`
Status string `json:"status" gorm:"default:outofstock"`
}
type Productstocks struct {
Productstockid int `json:"productstockid" gorm:"Primary_Key"`
Locationid int `json:"locationid"`
Tenantid int `json:"tenantid"`
Stockdate string `json:"stockdate"`
Productid int `json:"productid"`
Quantity int `json:"quantity"`
Stocktype string `json:"stocktype"`
Status string `json:"status"`
AppLocationid int `json:"applocationid"`
Categoryid int `json:"categoryid"`
Categoryname string `json:"categoryname" gorm:"->"`
Subcategoryid int `json:"subcategoryid,omitempty"`
Subcategoryname string `json:"Subcategoryname" `
Productname string `json:"productname,omitempty"`
Productimage string `json:"productimage,omitempty"`
Productdesc *string `json:"productdesc,omitempty"`
Productsku *string `json:"productsku,omitempty"`
Brandid *int `json:"brandid,omitempty"`
Productbrand *string `json:"productbrand,omitempty"`
Productunit *string `json:"productunit,omitempty"`
Unitvalue *string `json:"unitvalue,omitempty"`
Toppicks *string `json:"toppicks,omitempty"`
Productcost *float64 `json:"productcost,omitempty"`
Taxamount *float64 `json:"taxamount,omitempty"`
Taxpercent *float64 `json:"taxpercent,omitempty"`
Producttax *int `json:"producttax,omitempty"`
Productstock *int `json:"productstock,omitempty"`
Productcombo *int `json:"productcombo,omitempty"`
Variants int `json:"variants"`
Retailprice float64 `json:"retailprice,omitempty"`
Diffprice float64 `json:"diffprice,omitempty"`
Diffpercent float64 `json:"diffpercent,omitempty"`
Othercost float64 `json:"othercost,omitempty"`
Approve *int `json:"approve"`
}
type Productstock struct {
Productstockid int `json:"productstockid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Stockdate time.Time `json:"stockdate"`
Locationid int `json:"locationid"`
Productid int `json:"productid"`
Quantity int `json:"quantity"`
Stocktype string `json:"stocktype"`
Status string `json:"status"`
}
type Productstockstatement struct {
Productid int `json:"productid"`
Productname string `json:"productname"`
Productimage string `json:"productimage"`
Categoryid int `json:"categoryid"`
Subcategoryid int `json:"subcategoryid"`
Productunit string `json:"productunit"`
Unitvalue string `json:"unitvalue"`
Productcost float32 `json:"productcost"`
Taxpercent float32 `json:"taxpercent"`
Taxamount float32 `json:"taxamount"`
Retailprice float32 `json:"retailprice"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Opening int `json:"opening"`
Credit int `json:"credit"`
Debit int `json:"debit"`
Closing int `json:"closing"`
}
type ProductSummary struct {
Subcategoryid int `json:"subcategoryid"`
Subcategroyname string `json:"subcategroyname"`
Image string `json:"image"`
Productcount int `json:"productcount"`
}
type Tenantproducts struct {
Tenant TenantInfo `json:"tenant"`
Products []Products `json:"products"`
// Locationproducts []Locationproducts `json:"locationproducts"`
}
type TenantInfo struct {
Tenantid int `json:"tenantid"`
Tenantname string `json:"tenantname"`
Userfcmtoken string `json:"userfcmtoken"`
Address string `json:"address"`
Licenseno string `json:"licenseno"`
Primaryemail string `json:"primaryemail"`
Primarycontact string `json:"primarycontact"`
Pickuplocationid int `json:"pickuplocationid"`
Applocationid int `json:"applocationid"`
Suburb string `json:"suburb"`
City string `json:"city"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Postcode string `json:"postcode"`
Tenantimage string `json:"tenantimage"`
Locationid int `json:"locationid"`
Locationname string `json:"locationname"`
Subcategoryid int `json:"subcategoryid"`
Categoryid int `json:"categoryid"`
Registrationno string `json:"registrationno"`
Orderscount int `json:"orderscount"`
// Products []Products `json:"products" gorm:"-"`
ProductSubcategory []ProductSubcategory `json:"productsubcategory" gorm:"-"`
}
type SubcategoryProductResponse struct {
SubcategoryID int `json:"subcategoryid"`
SubcategoryName string `json:"subcategoryname"`
Image string `json:"image"`
Products []Products `json:"products"`
}
type ProductFilter struct {
CategoryID int
TenantID int
AppLocationID int
ProductID int
Keyword string
LocationID int
}
type Subcategory struct {
Subcategoryid int `json:"subcategoryid" gorm:"column:subcatid"`
Subcategoryname string `json:"subcategoryname" gorm:"column:subcatname"`
Categoryid int `json:"categoryid" gorm:"column:categoryid"`
Image string `json:"image" gorm:"column:image"`
}
type Productlocations struct {
Productlocationid int `json:"productlocationid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Productid int `json:"productid"`
Catlougeid int `json:"catlougeid"`
Minquantity int `json:"minquantity" gorm:"default:0"`
Maxquantity int `json:"maxquantity" gorm:"default:0"`
Price float32 `json:"price" gorm:"default:0.0"`
Quantity int `json:"quantity" gorm:"<-:false"`
Stocktype string `json:"stocktype" gorm:"<-:false"`
Status string `json:"status"`
}
type ProductSubcategory struct {
Subcatid int `json:"subcatid"`
Categoryid int `json:"categoryid"`
Tenantid int `json:"tenantid"`
Subcatname string `json:"subcatname"`
Status string `json:"status"`
Sortorder int `json:"sortorder"`
Createdby int `json:"createdby"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Image string `json:"image"`
}

218
models/tenant.go Normal file
View File

@@ -0,0 +1,218 @@
package models
import "time"
type Tenantinfo struct {
Tenantid int `json:"tenantid" gorm:"Primary_Key"`
Locationid int `json:"locationid"`
Tenantname string `json:"tenantname"`
Locationname string `json:"locationname"`
Tenanttype string `json:"tenanttype"`
Registrationno string `json:"registrationno"`
Tenanttoken string `json:"tenanttoken"`
Companyname string `json:"companyname"`
Primaryemail string `json:"primaryemail"`
Primarycontact string `json:"primarycontact"`
Locationcatact string `json:"locationcontact"`
Categoryid int `json:"categoryid"`
Subcategoryid int `json:"subcategoryid"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Tenantimage string `json:"tenantimage"`
Tenantinfo string `json:"tenantinfo"`
Paymenttype int `json:"paymenttype"`
Paymode1 int `json:"paymode1"`
Paymode2 int `json:"paymode2"`
Promotion int `json:"promotion"`
Partnerid int `json:"partnerid"`
Minorder int `json:"minorder"`
Applocationid int `json:"applolcationid"`
Applocation string `json:"applocation"`
Approved int `json:"approved"`
Moduleid int `json:"moduleid"`
Subcategoryname string `json:"subcategoryname"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Accountname string `json:"Accountname"`
Status string `json:"status"`
Allocationid int `json:"allocationid"`
Allocationtype string `json:"allocationtype"`
Allocationmode int `json:"allocationmode"`
}
type Tenantlocations struct {
Locationid int `json:"locationid" gorm:"Primary_Key"`
Tenantid int `json:"tenantid"`
Applocationid int `json:"applocationid"`
Moduleid int `json:"moduleid"`
Roleid int `json:"roleid" gorm:"-"`
Locationname string `json:"locationname"`
Email string `json:"email"`
Contactno string `json:"contactno"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Opentime string `json:"opentime"`
Closetime string `json:"closetime"`
Partnerid int `json:"partnerid"`
Deliveryradius int `json:"deliveryradius"`
Deliverymins int `json:"deliverymins"`
Cancelsecs int `json:"cancelsecs"`
Status string `json:"status" gorm:"default:Active"`
}
type Tenantslot struct {
Slot1 string `json:"slot1"`
Slot2 string `json:"slot2"`
Slot3 string `json:"slot3"`
}
type CreateTenantCustomerRequest struct {
ModuleID int `json:"moduleid"`
TenantID int `json:"tenantid"`
LocationID int `json:"locationid"`
CustomerID int `json:"customerid"`
CustomerLocationID int `json:"customerlocationid"`
Status int `json:"status"`
}
type Tenantcustomer struct {
TenantCustomerID int `json:"tenantcustomerid" gorm:"primaryKey;column:tenantcustomerid"`
ModuleID int `json:"moduleid" gorm:"column:moduleid"`
TenantID int `json:"tenantid" gorm:"column:tenantid"`
LocationID int `json:"locationid" gorm:"column:locationid"`
CustomerID int `json:"customerid" gorm:"column:customerid"`
CustomerLocationID int `json:"customerlocationid" gorm:"column:customerlocationid"`
Status int `json:"status" gorm:"column:status"`
Created time.Time `json:"created" gorm:"column:created;autoCreateTime"`
Updated time.Time `json:"updated" gorm:"column:updated;autoUpdateTime"`
}
type CustomerTenantResponse struct {
// Customer Customers `json:"customer"`
Details []TenantInfo `json:"details"`
}
type Tenantpricing struct {
Tenantpricingid int `json:"tenantpricingid" gorm:"Primary_Key"`
Pricingid int `json:"pricingid"`
Tenantid int `json:"tenantid"`
Applocationid int `json:"applocationid"`
Pricingtypeid int `json:"pricingtypeid"`
Slab string `json:"slab"`
Configid int `json:"configid"`
Pricingdate string `json:"pricingdate"`
Baseprice float32 `json:"baseprice"`
Priceperkm float32 `json:"priceperkm"`
Minkm int `json:"minkm"`
Maxkm int `json:"maxkm"`
Orders int `json:"orders"`
Othercharges float32 `json:"othercharges"`
}
type StaffInfo struct {
Userid int `json:"userid"`
Authname string `json:"authname"`
Configid int `json:"configid"`
Authmode int `json:"authmode"`
Roleid int `json:"roleid"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Fullname string `json:"fullname"`
Password string `json:"password"`
Email string `json:"email"`
Contactno string `json:"contactno"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Userfcmtoken string `json:"userfcmtoken"`
Pin int `json:"pin"`
Applocationid int `json:"applocationid"`
Partnerid int `json:"partnerid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Locationname string `json:"locationname"`
}
type Tenantuser struct {
Userid int `json:"userid" gorm:"Primary_Key"`
Authname string `json:"authname"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Password string `json:"password"`
Email string `json:"email"`
Dialcode string `json:"dialcode"`
Contactno string `json:"contactno"`
Configid int `json:"configid"`
Authmode int `json:"authmode"`
Roleid int `json:"roleid"`
Pin int `json:"pin"`
Deviceid string `json:"deviceid"`
Devicetype string `json:"devicetype"`
Userfcmtoken string `json:"userfcmtoken"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Partnerid int `json:"partnerid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Applocationid int `json:"applocationid"`
Status string `json:"status"`
}
type Tenants struct {
Tenantid int `json:"tenantid" gorm:"Primary_Key"`
Tenantname string `json:"tenantname"`
Configid int `json:"configid"`
Partnerid int `json:"partnerid"`
Moduleid int `json:"moduleid"`
Tenanttype string `json:"tenanttype"`
Registrationno string `json:"registrationno"`
Tenanttoken string `json:"tenanttoken"`
Companyname string `json:"companyname"`
Devicetype string `json:"devicetype"`
Deviceid string `json:"deviceid"`
Firstname string `json:"firstname"`
Primaryemail string `json:"primaryemail"`
Primarycontact string `json:"primarycontact"`
Categoryid int `json:"categoryid"`
Subcategoryid int `json:"subcategoryid"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Tenantimage string `json:"tenantimage"`
Tenantinfo string `json:"tenantinfo"`
Paymode1 int `json:"paymode1"`
Paymode2 int `json:"paymode2"`
Promotion int `json:"promotion"`
Minorder int `json:"minorder"`
Applocationid int `json:"applocationid"`
Approved *int `json:"approved" gorm:"default:0"`
Status string `json:"status" gorm:"default:Active"`
Partneruserid int `json:"partneruserid"`
Tenantlocations Tenantlocations `json:"tenantlocations" gorm:"ForeignKey:tenantid"`
// Tenantsubscriptions Tenantsubscriptions `json:"tenantsubscriptions" gorm:"ForeignKey:tenantid"`
}
type TenantSearch struct {
Tenantname string `json:"tenantname"`
Productname string `json:"productname"`
Subcatname string `json:"subcatname"`
}

102
models/users.go Normal file
View File

@@ -0,0 +1,102 @@
package models
type UserInfo struct {
Userid int `json:"userid"`
Authname string `json:"authname"`
Configid int `json:"configid"`
Authmode int `json:"authmode"`
Roleid int `json:"roleid"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Fullname string `json:"fullname"`
Password string `json:"password"`
Email string `json:"email"`
Contactno string `json:"contactno"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Userfcmtoken string `json:"userfcmtoken"`
Shiftid int `json:"shiftid"`
Shiftname string `json:"shiftname"`
Pin int `json:"pin"`
Partnerid int `json:"partnerid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Applocationid int `json:"applocationid"`
Applocation string `json:"applocation"`
Applatitude string `json:"applatitude"`
Applongitude string `json:"applongitude"`
Appradius int `json:"appradius"`
Status string `json:"status"`
}
type User struct {
Userid int `json:"userid" gorm:"Primary_Key"`
Authname string `json:"authname"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Password string `json:"password"`
Email string `json:"email"`
Dialcode string `json:"dialcode"`
Contactno string `json:"contactno"`
Configid int `json:"configid"`
Authmode int `json:"authmode"`
Roleid int `json:"roleid"`
Pin int `json:"pin"`
Deviceid string `json:"deviceid"`
Devicetype string `json:"devicetype"`
Userfcmtoken string `json:"userfcmtoken"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Partnerid int `json:"partnerid"`
Tenantid int `json:"tenantid"`
Locationid int `json:"locationid"`
Applocationid int `json:"applocationid"`
Status string `json:"status"`
Shiftid int `json:"shiftid"`
}
type TenantUserInfo struct {
Userid int `json:"userid"`
Authname string `json:"authname"`
Configid int `json:"configid"`
Authmode int `json:"authmode"`
Roleid int `json:"roleid"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Fullname string `json:"fullname"`
Password string `json:"password"`
Email string `json:"email"`
Contactno string `json:"contactno"`
Address string `json:"address"`
Suburb string `json:"suburb"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Userfcmtoken string `json:"userfcmtoken"`
Pin int `json:"pin"`
Partnerid int `json:"partnerid"`
Locationid int `json:"locationid"`
Applocationid int `json:"applocationid"`
Tenantid int `json:"tenantid"`
Tenantname string `json:"tenantname"`
Tenantaddress string `json:"tenantaddress"`
Tenantcity string `json:"tenantcity"`
Tenantpostcode string `json:"tenantpostcode"`
Tenantlat string `json:"tenantlat"`
Tenantlong string `json:"tenantlong"`
Locationname string `json:"locationname"`
Applocation string `json:"applocation"`
Applatitude string `json:"applatitude"`
Applongitude string `json:"applongitude"`
Appradius int `json:"appradius"`
Moduleid int `json:"moduleid"`
Categoryid int `json:"categoryid"`
Categoryname string `json:"categoryname"`
Subcategoryid int `json:"subcategoryid"`
}

84
models/utils.go Normal file
View File

@@ -0,0 +1,84 @@
package models
// Utils model
type Utils struct {
AppVersion string `json:"app_version"`
}
type Apptypes struct {
Apptypeid int `json:"apptypeid"`
Typename string `json:"typename"`
Mapid int `json:"mapid"`
Tag string `json:"tag"`
Status string `json:"status"`
}
type FcmNotification struct {
Title string `json:"title"`
Body string `json:"body"`
}
type Appsubcategories struct {
Subcategoryid int `json:"subcategoryid"`
Categoryid int `json:"categoryid"`
Subcategoryname string `json:"subcategoryname"`
Categoryname string `json:"catgeoryname"`
Moduleid int `json:"moduleid"`
Status string `json:"status"`
}
type Applocations struct {
Applocationid int `json:"applocationid" gorm:"Primary_Key"`
Locationname string `json:"locationname"`
Image string `json:"image"`
City string `json:"city"`
State string `json:"state"`
Postcode string `json:"postcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Opentime string `json:"opentime"`
Closetime string `json:"closetime"`
Radius int `json:"radius"`
Applocationadmins []Applocationadmins `json:"applocationadmins" gorm:"ForeignKey:applocationid"`
}
type Applocationadmins struct {
Applocationconfigid int `json:"applocationconfigid" gorm:"Primary_Key"`
Applocationid int `json:"applocationid"`
Userid int `json:"userid"`
Userfcmtoken string `json:"userfcmtokem"`
Notify string `json:"notify"`
}
type Appconfig struct {
Configid int `json:"configid"`
Appname string `json:"appname"`
Paymentdevkey string `json:"paymentdevkey"`
Paymentlivekey string `json:"paymentlivekey"`
Fcmkey string `json:"fcmkey"`
Googleapikey string `json:"googleapikey"`
Applocationradius int `json:"applocationradius"`
Smsproviderid int `json:"smsproviderid"`
Providerapi string `json:"providerapi"`
Providerkey string `json:"providerkey"`
Sender string `json:"sender"`
Templateid string `json:"templateid"`
Defaultprovider int `json:"defaultprovider"`
Created string `json:"created"`
Updated string `json:"updated"`
}
type AppCategory struct {
Categoryid int `json:"categoryid" gorm:"Primary_Key"`
Categoryname string `json:"categoryname"`
Categorytype int `json:"categorytype"`
Sortorder int `json:"sortorder"`
Imageurl string `json:"imageurl"`
Iconurl string `json:"iconurl"`
Profileurl string `json:"profileurl"`
Crossaxis int `json:"crossaxis"`
Mainaxis int `json:"mainaxis"`
Status string `json:"status"`
Created string `json:"created"`
Updated string `json:"updated"`
}

View File

@@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "nearle-gear",
"private_key_id": "23ca3b3609076b93b29a730f63e1da76d68e4baa",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDfsSE/Otsp0LTJ\nrTBUoOcdd0MF3rRZtcL4/WCekyEUh8tTh0YtSqaaDoO2lpg2Ym9jS031z1U0UOqg\n83L9IwyQD0UV0rYFkOm9LWNU60ZvL/KjE8YcRf0j8nj/Sv6S9rrrQmQKKDXINs2t\noXyBi7R4WTGxJmRzyAr9jTgS/aghGpvo57z7aln2veYXUVxw1kVDEou9dFEu2eHC\nPY4Bb6ACDFvxtGNAClwHy3pYHv+6QirF5O2z+JPjGuYJXSOqiT6SOhLHnv9P7W4y\nUY5/wFiRpvK6iYjRFEnpw3c950UH3y19njiPyZN+pS6tCqyE6w0tQPIaxX7c39dg\nmq9esOGbAgMBAAECggEAVzfIP9Ah/fbbVrtJWeX21x1WK6a+6S+emtioYIv7XPbp\nh2L6MNSniu/X2Ux0gtf0mGGXPx2dGi3mneTuU9bjohPiGvUydY8gI9vbnBO0PcwT\nLhSarRF49xgmp1vFUOYU0X/sY61z8uGzZlzNn/Ep57bXUjwm9KHt7xit4XG3qVfs\n84+hYWGl6vy15LfgmRb5MzTWexYMfQnaxk0we0mUzSIXmOCvI/OrkQwKenkgkR2F\n7r/0LZQBbVhZ/kB9avWBNnsj89nDNld9MtuKHqjcwFfHFgBzSz+3Qy2LolCVtN5Z\nMEjJ3/t1cocDAnKRBJeA9B3Hj2ud1BCxSQceTnb22QKBgQD3tOa/KWQbgmfoFh/w\nni2EJM0KDKvibxJfIC+p6z4/EiXENmJDQx32yqURCO75mwtBX/VYxGSLb1wLTfIn\nGVRu5KWs5oLV8FqyAQPYh5Urz6DVqg6CQRQadCz0emMMbjRk2XDE2j7f18VOB4DV\nZCxpx1Bv1wiU2ITNxczlteH6zwKBgQDnLmXTw1jfZ1DS69idby5L8PpcnP3GWV4t\nxAHH6QJhqUrMo5/eFKOL6aaSR4cIg47NdtP4yKo71TyaFl68xo4VWyoy2xJffdyd\niGf1kG2prNmHAtcU6W9QdgK4qgHpYVpqZufAn2XW/KMrsyhd4jwVR/UFNogswLI5\nXXy8Tx7vdQKBgGRHHL64n+kvEqd3BXkgX+bGCyeNV6w0MOjHm+Qa8rkPvLBBH+iA\n7ElzYf2Sc0QjCxxtH2LPJrD35PhClsxTScYW1Cc5ri+zvNOg65Cl2rLAvCijTnpW\npC/NZkGWpjBrENTe3fMjMx7lN9/N088PXZd488xC7htrx9+RutAnoJMrAoGAd8Px\nvONXB2Xe2WaVsfoHYhBVo+UxE7D4uXzx7z8nnLC3r4yVJdhLYhCJ2v5zVlXRhWAq\nMJjEmHrACpPMQMAcm7O/CNm1iwMJaBNiyDUqmtyRVQCDrLHCmUyJ3GE23FEzJixp\no8DwYZBAeEM4hmrN9bhxl2HI6mZp7o4gMO5MeIECgYAuqqv/hq9t57qnJhk2S5mi\nSmDMk+Zz/pVFYfpUlRL33k/t+8c/8+qTdSruRZzLzSAtdZY6XE85lidt2zwdCgqO\nEuviAb474iF8UOY0hf4mQkrIHmlojd2nZmUQbPjPTR+kiUvhJGvQuaJywbX54+wR\n+8tH+pbwRbkrENWHqJHxhg==\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-l9oha@nearle-gear.iam.gserviceaccount.com",
"client_id": "118373484295110637143",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-l9oha%40nearle-gear.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

View File

@@ -0,0 +1,359 @@
package repositories
import (
"fmt"
"nearle/models"
"strings"
"gorm.io/gorm"
)
type CustomerRepository interface {
GetCustomer(cid int, cno string) (*models.CustomerInfo, error)
UpdateCustomer(input models.Customers) error
GetCustomerLocations(cid int) ([]models.Customerlocations, error)
CreateCustomerLocation(input models.Customerlocations) (int, error)
CreateCustomerRequest(req *models.CustomerRequest) error
GetCustomerRequests(customerID int, pageNo, pageSize int) ([]models.CustomerRequest, int64, error)
GetTenantCustomers(tid, lid, pageno, pagesize int, keyword string) []models.CustomerInfo
SearchCustomer(keyword string, tid int) []models.CustomerInfo
CheckCustomer(contactno string) int
CheckTenantCustomer(cid, tid int) int
CreateTenantCustomer(input models.Customers) int
CreateCustomer(input models.Customers) int
GetCustomerByContactNo(contactNo string) (*models.Customers, error)
}
type customerRepository struct {
db *gorm.DB
}
func NewCustomerRepository(db *gorm.DB) CustomerRepository {
return &customerRepository{db: db}
}
func (r *customerRepository) GetCustomer(cid int, cno string) (*models.CustomerInfo, error) {
var data models.CustomerInfo
q := `
SELECT a.customerid,a.firstname,a.lastname,a.contactno,a.email,a.profileimage,a.dialcode,
a.deviceid,a.devicetype,a.authmode,a.configid,a.customertoken,a.intro,a.gender,a.dob,
b.locationid as deliverylocationid,b.address,b.suburb,b.city,b.state,b.landmark,b.doorno,b.postcode,
b.latitude,b.longitude,a.applocationid,
c.locationid as tenantlocationid,c.tenantid,
a.status,
d.qrmode,d.latitude as selectedlatitude,d.longitude as selectedlongitude,d.radius,d.applocationid,
e.allocationid
FROM customers a
INNER JOIN customerlocations b ON a.customerid=b.customerid AND b.primaryaddress=1
INNER JOIN tenantcustomers c ON a.customerid=c.customerid
LEFT JOIN app_location d ON a.applocationid=d.applocationid
LEFT JOIN tenants e ON e.tenantid=c.tenantid
WHERE %s LIMIT 1
`
var err error
if cid != 0 {
err = r.db.Raw(fmt.Sprintf(q, "a.customerid = ?"), cid).Scan(&data).Error
} else {
err = r.db.Raw(fmt.Sprintf(q, "a.contactno = ?"), cno).Scan(&data).Error
}
if err != nil {
return nil, err
}
return &data, nil
}
func (r *customerRepository) UpdateCustomer(input models.Customers) error {
var custloc models.Customerlocations
tx := r.db.Begin()
if err := tx.Where("customerid=?", input.Customerid).Updates(&input).Error; err != nil {
tx.Rollback()
return err
}
custloc.Customerid = input.Customerid
custloc.Address = input.Address
custloc.Suburb = input.Suburb
custloc.City = input.City
custloc.State = input.State
custloc.Postcode = input.Postcode
custloc.Latitude = input.Latitude
custloc.Longitude = input.Longitude
custloc.Doorno = input.Doorno
custloc.Landmark = input.Landmark
if err := tx.Table("customerlocations").
Where("customerid=? and primaryaddress=?", input.Customerid, 1).
Updates(&custloc).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
fmt.Println("Commit failed:", err)
return err
}
return nil
}
func (r *customerRepository) GetCustomerLocations(cid int) ([]models.Customerlocations, error) {
var data []models.Customerlocations
if cid == 0 {
return data, nil
}
query := `SELECT a.locationid, a.customerid, b.applocationid, a.address, a.suburb,
a.city, a.state, a.landmark, a.doorno, a.postcode, a.latitude,
a.longitude, a.defaultaddress, a.primaryaddress, a.status
FROM customerlocations a
LEFT JOIN customers b ON a.customerid = b.customerid
WHERE a.customerid = ?`
if err := r.db.Raw(query, cid).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *customerRepository) CreateCustomerLocation(input models.Customerlocations) (int, error) {
// Duplicate address checking
var count int
err := r.db.Raw(`
SELECT COUNT(*) FROM customerlocations
WHERE customerid = ?
AND address = ?
AND suburb = ?
AND city = ?
AND state = ?
AND postcode = ?
AND landmark = ?
AND doorno = ?
`, input.Customerid, input.Address, input.Suburb, input.City, input.State,
input.Postcode, input.Landmark, input.Doorno).
Scan(&count).Error
if err != nil {
return 0, err
}
if count > 0 {
// Duplicate found
return -1, nil
}
// Insert new address
if err := r.db.Create(&input).Error; err != nil {
return 0, err
}
return input.Customerid, nil
}
func (r *customerRepository) CreateCustomerRequest(req *models.CustomerRequest) error {
return r.db.Table("customerrequest").Create(req).Error
}
func (r *customerRepository) GetCustomerRequests(customerID, pageNo, pageSize int) ([]models.CustomerRequest, int64, error) {
var requests []models.CustomerRequest
var total int64
query := r.db.Table("customerrequest")
if customerID != 0 {
query = query.Where("customerid = ?", customerID)
}
query.Count(&total)
offset := (pageNo - 1) * pageSize
if err := query.Order("created desc").Offset(offset).Limit(pageSize).Find(&requests).Error; err != nil {
return nil, 0, err
}
return requests, total, nil
}
func (r *customerRepository) GetTenantCustomers(tid, lid, pageno, pagesize int, keyword string) []models.CustomerInfo {
var data []models.CustomerInfo
offset := (pageno - 1) * pagesize
var q1 string
var args []interface{}
searchLike := "%" + keyword + "%"
if lid != 0 {
q1 = `SELECT a.customerid,a.firstname,a.lastname,a.contactno,a.email,
b.locationid as deliverylocationid,b.address,b.suburb,b.city,b.state,b.landmark,b.doorno,b.postcode,
b.latitude,b.longitude,a.applocationid,c.locationid as tenantlocationid,a.status
FROM customers a
LEFT JOIN customerlocations b ON a.customerid=b.customerid
INNER JOIN tenantcustomers c ON a.customerid=c.customerid
WHERE c.locationid = ? AND c.tenantid = ?`
args = append(args, lid, tid)
if keyword != "" {
q1 += ` AND (a.firstname LIKE ? OR a.contactno LIKE ? OR b.suburb LIKE ?)`
args = append(args, searchLike, searchLike, searchLike)
}
q1 += ` ORDER BY a.customerid DESC LIMIT ? OFFSET ?`
args = append(args, pagesize, offset)
} else {
q1 = `SELECT a.customerid,a.firstname,a.lastname,a.contactno,a.email,
a.address,a.suburb,a.city,a.state,a.landmark,a.doorno,a.postcode,
a.latitude,a.longitude,a.applocationid,c.locationid as tenantlocationid,a.status
FROM customers a
INNER JOIN tenantcustomers c ON a.customerid=c.customerid
WHERE c.tenantid = ?`
args = append(args, tid)
if keyword != "" {
searchLike := "%" + strings.ToLower(keyword) + "%"
q1 += ` AND (LOWER(a.firstname) LIKE ? OR LOWER(a.contactno) LIKE ? OR LOWER(a.suburb) LIKE ?)`
args = append(args, searchLike, searchLike, searchLike)
}
q1 += ` ORDER BY a.customerid DESC LIMIT ? OFFSET ?`
args = append(args, pagesize, offset)
}
print(q1)
r.db.Raw(q1, args...).Find(&data)
return data
}
func (r *customerRepository) SearchCustomer(keyword string, tid int) []models.CustomerInfo {
var data []models.CustomerInfo
searchLike := strings.ToLower(keyword) + "%"
var q1 string
var args []interface{}
if tid != 0 {
q1 = `SELECT a.customerid,a.firstname,a.lastname,a.contactno,a.email,
a.address,a.suburb,a.city,a.state,a.landmark,a.doorno,a.postcode,
a.latitude,a.longitude,a.applocationid,c.locationid as tenantlocationid,a.status
FROM customers a
INNER JOIN tenantcustomers c ON a.customerid=c.customerid
WHERE c.tenantid = ? AND (LOWER(a.firstname) LIKE ? OR LOWER(a.contactno) LIKE ?)`
args = append(args, tid, searchLike, searchLike)
} else {
q1 = `SELECT a.customerid,a.firstname,a.lastname,a.contactno,a.email,
a.address,a.suburb,a.city,a.state,a.landmark,a.doorno,a.postcode,
a.latitude,a.longitude,a.applocationid,c.locationid as tenantlocationid,a.status
FROM customers a
INNER JOIN tenantcustomers c ON a.customerid=c.customerid
WHERE (LOWER(a.firstname) LIKE ? OR LOWER(a.contactno) LIKE ?)`
args = append(args, searchLike, searchLike)
}
r.db.Raw(q1, args...).Find(&data)
return data
}
func (r *customerRepository) CheckCustomer(contactno string) int {
var data models.Customers
q1 := `SELECT a.customerid FROM customers a WHERE a.contactno = ?`
r.db.Raw(q1, contactno).Find(&data)
return data.Customerid
}
func (r *customerRepository) CheckTenantCustomer(cid, tid int) int {
var data models.Customers
q1 := `SELECT a.customerid FROM tenantcustomers a WHERE a.customerid = ? AND a.tenantid = ?`
r.db.Raw(q1, cid, tid).Find(&data)
return data.Customerid
}
func (r *customerRepository) CreateTenantCustomer(input models.Customers) int {
var tcust models.Tenantcustomers
tcust.Customerid = input.Customerid
tcust.Tenantid = input.Tenantid
tx := r.db.Begin()
if err := tx.Table("tenantcustomers").Create(&tcust).Error; err != nil {
fmt.Println(err)
tx.Rollback()
return 0
}
tx.Commit()
return input.Customerid
}
func (r *customerRepository) CreateCustomer(input models.Customers) int {
var custloc models.Customerlocations
var tcust models.Tenantcustomers
tx := r.db.Begin()
if err := tx.Create(&input).Error; err != nil {
fmt.Println(err)
tx.Rollback()
return 0
}
custloc = models.Customerlocations{
Customerid: input.Customerid,
Address: input.Address,
Suburb: input.Suburb,
City: input.City,
State: input.State,
Postcode: input.Postcode,
Latitude: input.Latitude,
Longitude: input.Longitude,
Doorno: input.Doorno,
Landmark: input.Landmark,
Primaryaddress: 1,
}
if err := tx.Table("customerlocations").Create(&custloc).Error; err != nil {
fmt.Println(err)
tx.Rollback()
return 0
}
tcust = models.Tenantcustomers{
Customerid: input.Customerid,
Tenantid: input.Tenantid,
}
if err := tx.Table("tenantcustomers").Create(&tcust).Error; err != nil {
fmt.Println(err)
tx.Rollback()
return 0
}
tx.Commit()
return input.Customerid
}
func (r *customerRepository) GetCustomerByContactNo(contactNo string) (*models.Customers, error) {
var customer models.Customers
query := `
SELECT a.customerid, a.authmode, a.configid, a.deviceid, a.devicetype, a.customertoken,
a.firstname, a.lastname, a.contactno, a.profileimage, a.address, a.suburb,
a.city, a.state, a.landmark, a.doorno, a.postcode, a.latitude, a.longitude,
a.applocationid, a.status, a.profileimage, a.dialcode, a.intro,
b.tenantid, b.locationid,
c.qrmode
FROM customers a
INNER JOIN tenantcustomers b ON a.customerid = b.customerid
LEFT JOIN app_location c ON a.applocationid = c.applocationid
WHERE a.configid = 2 AND a.contactno = ?
`
if err := r.db.Raw(query, contactNo).Scan(&customer).Error; err != nil {
return nil, err
}
return &customer, nil
}

View File

@@ -0,0 +1,922 @@
package repositories
import (
"fmt"
"log"
"nearle/models"
"strconv"
"strings"
"github.com/jinzhu/copier"
"gorm.io/gorm"
)
type DeliveriesRepository interface {
CreateDeliveries(data []models.Deliveries) error
UpdateDelivery(data models.UpdateDeliveryStatus) error
GetDeliverySummary(tid, pid, uid, aid, lid int, fdate, tdate string) (models.DeliverySummary, error)
GetDeliveryInsight(tid int) ([]models.OrderInsightv1, error)
GetLocationDeliverySummary(tenantID int) ([]models.Ordersummarylocation, error)
GetReportSummary(tid, pid, uid, aid int, fdate, tdate string) ([]models.ReportSummary, error)
GetRiderSummary(aid, pid, tid int, fdate, tdate string) ([]models.Ridersummary, error)
GetTenantDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetPartnerDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetCustomerDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetAdminDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetUserDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetAppUserDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetDeliveryQueues(uid int, fdate, tdate string) ([]models.Deliveryinfo, error)
GetTenantLocationDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
}
type deliveriesRepository struct {
db *gorm.DB
}
func NewDeliveriesRepository(db *gorm.DB) DeliveriesRepository {
return &deliveriesRepository{db: db}
}
const (
core = `SELECT COUNT(*) AS total,
SUM(CASE WHEN orderstatus = 'pending' THEN 1 ELSE 0 END) AS pending,
SUM(CASE WHEN orderstatus = 'accepted' THEN 1 ELSE 0 END) AS accepted,
SUM(CASE WHEN orderstatus = 'arrived' THEN 1 ELSE 0 END) AS arrived,
SUM(CASE WHEN orderstatus = 'picked' THEN 1 ELSE 0 END) AS picked,
SUM(CASE WHEN orderstatus = 'active' THEN 1 ELSE 0 END) AS active,
SUM(CASE WHEN orderstatus = 'delivered' THEN 1 ELSE 0 END) AS delivered,
SUM(CASE WHEN orderstatus = 'cancelled' THEN 1 ELSE 0 END) AS cancelled`
reports = `SELECT b.tenantid,b.tenantname,
COUNT(*) AS totalorders,
SUM(CASE WHEN a.orderstatus = 'created' THEN 1 ELSE 0 END) AS orderscreated,
SUM(CASE WHEN a.orderstatus = 'pending' THEN 1 ELSE 0 END) AS orderspending,
SUM(CASE WHEN a.orderstatus = 'cancelled' THEN 1 ELSE 0 END) AS orderscancelled,
SUM(CASE WHEN a.orderstatus = 'delivered' THEN 1 ELSE 0 END) AS orderscompleted,
SUM(CASE WHEN c.orderstatus = 'pending' THEN 1 ELSE 0 END) AS deliveriespending,
SUM(CASE WHEN c.orderstatus = 'delivered' THEN 1 ELSE 0 END) AS deliveriescompleted,
SUM(CASE WHEN c.orderstatus = 'cancelled' THEN 1 ELSE 0 END) AS deliveriescancelled,
SUM(CASE WHEN c.paymenttype = 64 THEN c.deliveryamt ELSE 0 END) AS paylater,
SUM(CASE WHEN c.paymenttype = 43 THEN c.deliveryamt ELSE 0 END) AS payondelivery,
ROUND(SUM(c.kms), 2) AS kms,
ROUND(SUM(c.actualkms), 2) AS actualkms,
SUM(c.deliveryamt) AS charges
FROM
tenants b
right JOIN orders a ON b.tenantid = a.tenantid
right JOIN deliveries c ON a.orderheaderid = c.orderheaderid `
Ridersummary = `SELECT a.userid, a.firstname, a.lastname,
CONCAT(a.firstname, ' ', a.lastname) AS fullname,a.status,
SUM(CASE WHEN b.orderstatus = 'pending' THEN 1 ELSE 0 END) AS deliveries,
SUM(CASE WHEN b.orderstatus = 'assigned' THEN 1 ELSE 0 END) AS assigned,
SUM(CASE WHEN b.orderstatus = 'accepted' THEN 1 ELSE 0 END) AS accepted,
SUM(CASE WHEN b.orderstatus = 'arrived' THEN 1 ELSE 0 END) AS arrived,
SUM(CASE WHEN b.orderstatus = 'picked' THEN 1 ELSE 0 END) AS picked,
SUM(CASE WHEN b.orderstatus = 'delivered' THEN 1 ELSE 0 END) AS delivered,
SUM(CASE WHEN b.orderstatus = 'delivered' THEN b.actualkms ELSE 0 END) AS actualkms,
SUM(CASE WHEN b.orderstatus = 'delivered' THEN b.kms ELSE 0 END) AS kms,
SUM(CASE WHEN b.paymenttype = 64 THEN b.deliveryamt ELSE 0 END) AS paylater,
SUM(CASE WHEN b.paymenttype = 43 THEN b.deliveryamt ELSE 0 END) AS payondelivery,
SUM(CASE WHEN b.orderstatus = 'delivered' THEN b.deliveryamt ELSE 0 END) AS deliveryamt
FROM app_users a
LEFT JOIN deliveries b ON a.userid = b.userid`
)
const (
deliveries = `SELECT distinct a.deliveryid,a.applocationid,f.locationname AS applocation,a.orderheaderid,a.configid,a.tenantid,a.partnerid,a.locationid,a.userid,a.categoryid,a.subcategoryid,a.moduleid,
a.orderid,a.deliverydate,a.orderstatus,a.assigntime,a.starttime,a.arrivaltime,a.pickuptime,a.deliverytime,a.canceltime,
a.customerid,a.pickupcustomer,a.pickupcontactno,a.pickuplocationid,a.pickupaddress,a.pickuplocation,a.pickuplat,a.pickuplon,
a.deliverycustomerid,a.deliverycustomer,a.deliverycontactno,a.deliverylocationid,a.deliveryaddress,a.deliverylocation,
a.droplat,a.droplon,a.deliverylat,a.deliverylong,
a.riderslat,a.riderslon,a.deliveryamt,a.kms,a.actualkms,a.riderkms,a.deliverycharges,a.deliverytype,a.paymenttype,a.smsdelivery,
a.expecteddeliverytime,a.profit,a.transitminutes,a.calculationdistancekm,
a.notes,a.ordernotes,b.tenantname,b.primarycontact as tenantcontactno,b.tenanttoken,b.suburb as tenantsuburb,b.city as tenantcity,
c.firstname AS ridername,c.userfcmtoken,e.locationname,e.suburb AS locationsuburb,e.contactno AS locationcontactno
FROM deliveries a
INNER JOIN tenants b ON a.tenantid=b.tenantid
INNER JOIN app_users c ON a.userid=c.userid
INNER JOIN tenantlocations e ON a.locationid=e.locationid
INNER JOIN app_location f ON a.applocationid = f.applocationid
INNER JOIN app_locationconfig g ON f.applocationid = g.applocationid`
)
func (r *deliveriesRepository) CreateDeliveries(data []models.Deliveries) error {
var que []models.Deliveryqueues
var ord models.Updateorderstatus
tx := r.db.Begin()
for i := range data {
if err := tx.Create(&data[i]).Error; err != nil {
tx.Rollback()
return err
}
if err := copier.Copy(&que, &data[i]); err != nil {
tx.Rollback()
return err
}
if err := tx.Create(&que).Error; err != nil {
tx.Rollback()
return err
}
ord.Orderstatus = data[i].Orderstatus
ord.Pending = data[i].Deliverydate
if err := tx.Table("orders").
Where("orderheaderid=?", data[i].Orderheaderid).
Updates(&ord).Error; err != nil {
tx.Rollback()
return err
}
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *deliveriesRepository) UpdateDelivery(data models.UpdateDeliveryStatus) error {
var ord models.Updateorderstatus
var cloc models.Customerlocations
tx := r.db.Begin()
if err := tx.Table("deliveries").Where("deliveryid = ?", data.Deliveryid).Updates(&data).Error; err != nil {
tx.Rollback()
return err
}
switch data.Orderstatus {
case "pending":
ord.Orderstatus = data.Orderstatus
ord.Pending = data.Assigntime
if err := tx.Table("orders").Where("orderheaderid = ?", data.Orderheaderid).Updates(&ord).Error; err != nil {
tx.Rollback()
return err
}
case "picked":
if data.Pickuplocationid != 0 && data.Deliverytype != "B" {
cloc.Latitude = data.Riderslat
cloc.Longitude = data.Riderslon
cloc.Address = data.Address
cloc.Suburb = data.Suburb
cloc.City = data.City
cloc.State = data.State
cloc.Postcode = data.Postcode
if err := tx.Table("customerlocations").Where("locationid = ?", data.Pickuplocationid).Updates(&cloc).Error; err != nil {
tx.Rollback()
return err
}
}
case "delivered":
ord.Orderstatus = data.Orderstatus
ord.Delivered = data.Deliverytime
if err := tx.Table("orders").Where("orderheaderid = ?", data.Orderheaderid).Updates(&ord).Error; err != nil {
tx.Rollback()
return err
}
if data.Deliverylocationid != 0 && data.Deliverytype != "B" {
cloc.Latitude = data.Deliverylat
cloc.Longitude = data.Deliverylong
cloc.Address = data.Address
cloc.Suburb = data.Suburb
cloc.City = data.City
cloc.State = data.State
cloc.Postcode = data.Postcode
if err := tx.Table("customerlocations").Where("locationid = ?", data.Deliverylocationid).Updates(&cloc).Error; err != nil {
tx.Rollback()
return err
}
}
case "cancelled":
ord.Orderstatus = data.Orderstatus
ord.Cancelled = data.Canceltime
if err := tx.Table("orders").Where("orderheaderid = ?", data.Orderheaderid).Updates(&ord).Error; err != nil {
tx.Rollback()
return err
}
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *deliveriesRepository) GetDeliverySummary(tid, pid, uid, aid, lid int, fdate, tdate string) (models.DeliverySummary, error) {
var data models.DeliverySummary
var q1 string
var params []interface{}
// Base query
q1 = core + " FROM deliveries WHERE configid = 1"
// Filters (allow multiple together)
if tid != 0 {
q1 += " AND tenantid = ?"
params = append(params, tid)
}
if pid != 0 {
q1 += " AND partnerid = ?"
params = append(params, pid)
}
if uid != 0 {
q1 += " AND userid = ?"
params = append(params, uid)
}
if aid != 0 {
q1 += " AND applocationid = ?"
params = append(params, aid)
}
if lid != 0 {
q1 += " AND locationid = ?"
params = append(params, lid)
}
// Date filter
if fdate != "" && tdate != "" {
q1 += " AND deliverydate::date BETWEEN ? AND ?"
params = append(params, fdate, tdate)
}
// Execute query
if err := r.db.Raw(q1, params...).Scan(&data).Error; err != nil {
return data, err
}
print(q1)
return data, nil
}
func (r *deliveriesRepository) GetDeliveryInsight(tenantID int) ([]models.OrderInsightv1, error) {
var locations []models.OrderInsightv1
var params []interface{}
// Base query for fetching active locations
q1 := `
SELECT DISTINCT l.locationid, l.locationname
FROM tenantlocations l
LEFT JOIN deliveries d ON l.locationid = d.locationid
WHERE l.status = 'Active'
`
// Add tenant filter if provided
if tenantID != 0 {
q1 += " AND l.tenantid = ?"
params = append(params, tenantID)
}
if err := r.db.Raw(q1, params...).Scan(&locations).Error; err != nil {
return nil, err
}
// Query for monthly deliveries
q2 := `
SELECT
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 1 THEN 1 ELSE 0 END), 0) AS jan,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 2 THEN 1 ELSE 0 END), 0) AS feb,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 3 THEN 1 ELSE 0 END), 0) AS mar,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 4 THEN 1 ELSE 0 END), 0) AS apr,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 5 THEN 1 ELSE 0 END), 0) AS may,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 6 THEN 1 ELSE 0 END), 0) AS jun,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 7 THEN 1 ELSE 0 END), 0) AS jul,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 8 THEN 1 ELSE 0 END), 0) AS aug,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 9 THEN 1 ELSE 0 END), 0) AS sep,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 10 THEN 1 ELSE 0 END), 0) AS oct,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 11 THEN 1 ELSE 0 END), 0) AS nov,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM d.deliverydate) = 12 THEN 1 ELSE 0 END), 0) AS dece
FROM deliveries d
WHERE d.locationid = ?
AND EXTRACT(YEAR FROM d.deliverydate) = EXTRACT(YEAR FROM CURRENT_DATE)
`
if tenantID != 0 {
q2 += " AND d.tenantid = ?"
}
// Attach month-wise insights for each location
for i := range locations {
var orderMonths models.Ordermonths
var err error
if tenantID != 0 {
err = r.db.Raw(q2, locations[i].Locationid, tenantID).Scan(&orderMonths).Error
} else {
err = r.db.Raw(q2, locations[i].Locationid).Scan(&orderMonths).Error
}
if err != nil {
return nil, err
}
locations[i].Ordermonths = &orderMonths
}
return locations, nil
}
func (r *deliveriesRepository) GetLocationDeliverySummary(tenantID int) ([]models.Ordersummarylocation, error) {
var data []models.Ordersummarylocation
var params []interface{}
q1 := `
SELECT
b.locationid,
b.locationname,
COALESCE(COUNT(a.orderid), 0) AS total,
COALESCE(SUM(CASE WHEN a.orderstatus = 'created' THEN 1 ELSE 0 END), 0) AS created,
COALESCE(SUM(CASE WHEN a.orderstatus = 'pending' THEN 1 ELSE 0 END), 0) AS pending,
COALESCE(SUM(CASE WHEN a.orderstatus = 'processing' THEN 1 ELSE 0 END), 0) AS processing,
COALESCE(SUM(CASE WHEN a.orderstatus = 'delivered' THEN 1 ELSE 0 END), 0) AS delivered,
COALESCE(SUM(CASE WHEN a.orderstatus = 'cancelled' THEN 1 ELSE 0 END), 0) AS cancelled
FROM tenantlocations b
LEFT JOIN deliveries a
ON a.locationid = b.locationid
AND a.configid = 1
`
// ✅ Only filter tenant locations in WHERE
if tenantID != 0 {
q1 += " WHERE b.tenantid = ?"
params = append(params, tenantID)
}
q1 += " GROUP BY b.locationid, b.locationname ORDER BY b.locationid"
if err := r.db.Raw(q1, params...).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *deliveriesRepository) GetReportSummary(tid, pid, uid, aid int, fdate, tdate string) ([]models.ReportSummary, error) {
var data []models.ReportSummary
var q1 string
switch {
case tid != 0:
if fdate != "" && tdate != "" {
q1 = reports + ` WHERE a.tenantid=` + strconv.Itoa(tid) +
` AND a.orderdate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.tenantid, b.tenantname`
} else {
q1 = reports + ` WHERE a.tenantid=` + strconv.Itoa(tid) + ` GROUP BY a.tenantid, b.tenantname`
}
case pid != 0:
if fdate != "" && tdate != "" {
q1 = reports + ` WHERE a.partnerid=` + strconv.Itoa(pid) +
` AND a.orderdate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.tenantid, b.tenantname`
} else {
q1 = reports + ` WHERE a.partnerid=` + strconv.Itoa(pid) + ` GROUP BY a.tenantid, b.tenantname`
}
case uid != 0:
if fdate != "" && tdate != "" {
q1 = reports + ` WHERE c.userid=` + strconv.Itoa(uid) +
` AND a.orderdate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.tenantid, b.tenantname`
} else {
q1 = reports + ` WHERE c.userid=` + strconv.Itoa(uid) + ` GROUP BY a.tenantid, b.tenantname`
}
case aid != 0:
if fdate != "" && tdate != "" {
q1 = reports + ` WHERE c.applocationid=` + strconv.Itoa(aid) +
` AND a.orderdate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.tenantid, b.tenantname`
} else {
q1 = reports + ` WHERE c.applocationid=` + strconv.Itoa(aid) + ` GROUP BY a.tenantid, b.tenantname`
}
default:
if fdate != "" && tdate != "" {
q1 = reports + ` WHERE a.orderdate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.tenantid, b.tenantname`
} else {
q1 = reports + ` GROUP BY a.tenantid, b.tenantname`
}
}
if err := r.db.Raw(q1).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *deliveriesRepository) GetRiderSummary(aid, pid, tid int, fdate, tdate string) ([]models.Ridersummary, error) {
var data []models.Ridersummary
var q1 string
switch {
case aid != 0:
if fdate != "" && tdate != "" {
q1 = Ridersummary + ` WHERE a.configid=6 AND a.applocationid=` + strconv.Itoa(aid) +
` AND b.deliverydate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.userid, a.firstname, a.lastname`
} else {
q1 = Ridersummary + ` WHERE a.configid=6 AND a.applocationid=` + strconv.Itoa(aid) +
` GROUP BY a.userid, a.firstname, a.lastname`
}
case pid != 0:
if fdate != "" && tdate != "" {
q1 = Ridersummary + ` WHERE a.configid=6 AND a.partnerid=` + strconv.Itoa(pid) +
` AND b.deliverydate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.userid, a.firstname, a.lastname`
} else {
q1 = Ridersummary + ` WHERE a.configid=6 AND a.partnerid=` + strconv.Itoa(pid) +
` GROUP BY a.userid, a.firstname, a.lastname`
}
case tid != 0:
if fdate != "" && tdate != "" {
q1 = Ridersummary + ` WHERE a.configid=6 AND b.tenantid=` + strconv.Itoa(tid) +
` AND b.deliverydate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.userid, a.firstname, a.lastname`
} else {
q1 = Ridersummary + ` WHERE a.configid=6 AND b.tenantid=` + strconv.Itoa(tid) +
` GROUP BY a.userid, a.firstname, a.lastname`
}
default:
if fdate != "" && tdate != "" {
q1 = Ridersummary + ` WHERE a.configid=6 AND b.deliverydate::date BETWEEN '` + fdate + `' AND '` + tdate + `' GROUP BY a.userid, a.firstname, a.lastname`
} else {
q1 = Ridersummary + ` WHERE a.configid=6 GROUP BY a.userid, a.firstname, a.lastname`
}
}
if err := r.db.Raw(q1).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *deliveriesRepository) GetTenantDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
fmt.Println("🔍 Fetching Tenant Deliveries")
var data []models.Deliveryinfo
var queryBuilder strings.Builder
var params []interface{}
offset := (input.Pageno - 1) * input.Pagesize
baseQuery := `
SELECT a.*, b.tenantname, c.firstname AS ridername, c.contactno AS ridercontact
FROM deliveries a
JOIN tenants b ON a.tenantid = b.tenantid
JOIN app_users c ON a.userid = c.userid
WHERE a.tenantid = ?
`
queryBuilder.WriteString(baseQuery)
params = append(params, input.Tenantid)
if input.Status != "" {
queryBuilder.WriteString(" AND a.orderstatus = ?")
params = append(params, input.Status)
}
if input.Fromdate != "" && input.ToDate != "" {
queryBuilder.WriteString(" AND a.deliverydate::date BETWEEN ? AND ?")
params = append(params, input.Fromdate, input.ToDate)
}
if input.Keyword != "" {
k := "%" + input.Keyword + "%"
queryBuilder.WriteString(`
AND (
a.pickupcustomer LIKE ? OR
a.deliverycustomer LIKE ? OR
a.pickupcontactno LIKE ? OR
a.deliverycontactno LIKE ? OR
a.orderid LIKE ?
)
`)
for i := 0; i < 5; i++ {
params = append(params, k)
}
}
queryBuilder.WriteString(" ORDER BY a.deliveryid DESC")
if input.Pagesize != 0 {
queryBuilder.WriteString(" LIMIT ? OFFSET ?")
params = append(params, input.Pagesize, offset)
}
query := queryBuilder.String()
fmt.Println("Final query:", query)
fmt.Println("Params:", params)
r.db.Raw(query, params...).Scan(&data)
return data
}
func (r *deliveriesRepository) GetPartnerDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
fmt.Println("🔍 Fetching Partner Deliveries")
var data []models.Deliveryinfo
var queryBuilder strings.Builder
var params []interface{}
offset := (input.Pageno - 1) * input.Pagesize
queryBuilder.WriteString(deliveries + ` WHERE a.partnerid = ?`)
params = append(params, input.Partnerid)
if input.Status != "" {
queryBuilder.WriteString(" AND a.orderstatus = ?")
params = append(params, input.Status)
}
if input.Fromdate != "" && input.ToDate != "" {
queryBuilder.WriteString(" AND a.deliverydate::date BETWEEN ? AND ?")
params = append(params, input.Fromdate, input.ToDate)
}
queryBuilder.WriteString(" ORDER BY a.deliveryid DESC")
if input.Pagesize > 0 {
queryBuilder.WriteString(" LIMIT ? OFFSET ?")
params = append(params, input.Pagesize, offset)
}
finalQuery := queryBuilder.String()
log.Println("Final Partner Query:", finalQuery, "Params:", params)
r.db.Raw(finalQuery, params...).Scan(&data)
return data
}
func (r *deliveriesRepository) GetCustomerDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
fmt.Println("🔍 Fetching Customer Deliveries")
var data []models.Deliveryinfo
var queryBuilder strings.Builder
var params []interface{}
offset := (input.Pageno - 1) * input.Pagesize
queryBuilder.WriteString(deliveries + ` WHERE a.customerid = ?`)
params = append(params, input.Customerid)
if input.Partnerid != 0 {
queryBuilder.WriteString(" AND a.partnerid = ?")
params = append(params, input.Partnerid)
}
if input.Status != "" {
queryBuilder.WriteString(" AND a.orderstatus = ?")
params = append(params, input.Status)
}
if input.Fromdate != "" && input.ToDate != "" {
queryBuilder.WriteString(" AND a.deliverydate::date BETWEEN ? AND ?")
params = append(params, input.Fromdate, input.ToDate)
}
if input.Keyword != "" {
k := "%" + input.Keyword + "%"
queryBuilder.WriteString(` AND (
a.pickupcustomer LIKE ? OR
a.deliverycustomer LIKE ? OR
a.pickupcontactno LIKE ? OR
a.deliverycontactno LIKE ? OR
a.orderid LIKE ?
)`)
for i := 0; i < 5; i++ {
params = append(params, k)
}
}
queryBuilder.WriteString(" ORDER BY a.deliveryid DESC")
if input.Pagesize != 0 {
queryBuilder.WriteString(" LIMIT ? OFFSET ?")
params = append(params, input.Pagesize, offset)
}
query := queryBuilder.String()
fmt.Println("Final query:", query)
fmt.Println("Params:", params)
r.db.Raw(query, params...).Scan(&data)
return data
}
func (r *deliveriesRepository) GetAdminDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
fmt.Println("Admin Deliveries")
var data []models.Deliveryinfo
var queryBuilder strings.Builder
var params []interface{}
offset := (input.Pageno - 1) * input.Pagesize
queryBuilder.WriteString(`
SELECT a.*, b.tenantname, c.firstname as ridername
FROM deliveries a
JOIN tenants b ON a.tenantid = b.tenantid
JOIN app_users c ON c.userid = a.userid
WHERE a.applocationid = ?
`)
params = append(params, input.Applocationid)
if input.Status != "" {
queryBuilder.WriteString(" AND a.orderstatus = ?")
params = append(params, input.Status)
}
if input.Fromdate != "" && input.ToDate != "" {
queryBuilder.WriteString(" AND a.deliverydate::date BETWEEN ? AND ?")
params = append(params, input.Fromdate, input.ToDate)
}
if input.Keyword != "" {
k := "%" + input.Keyword + "%"
queryBuilder.WriteString(`
AND (
a.pickupcustomer LIKE ? OR
b.tenantname LIKE ? OR
a.deliverycustomer LIKE ? OR
a.pickupcontactno LIKE ? OR
a.deliverycontactno LIKE ? OR
a.orderid LIKE ?
)
`)
for i := 0; i < 6; i++ {
params = append(params, k)
}
}
queryBuilder.WriteString(" ORDER BY a.deliveryid DESC")
if input.Pagesize > 0 {
queryBuilder.WriteString(" LIMIT ? OFFSET ?")
params = append(params, input.Pagesize, offset)
}
finalQuery := queryBuilder.String()
log.Println("AdminDeliveries query:", finalQuery)
log.Println("Params:", params)
r.db.Raw(finalQuery, params...).Scan(&data)
return data
}
func (r *deliveriesRepository) GetUserDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
var q1 string
offset := (input.Pageno - 1) * input.Pagesize
var data []models.Deliveryinfo
if input.Status != "" {
if input.Pagesize != 0 {
fmt.Println("Rider Deliveriesv2")
q1 = deliveries + ` where a.userid=` + strconv.Itoa(input.UserID) + ` and a.orderstatus='` + input.Status + `'
and a.deliverydate::date between '` + input.Fromdate + `' and '` + input.ToDate + `' order by deliveryid
desc LIMIT ` + strconv.Itoa(input.Pagesize) + ` OFFSET ` + strconv.Itoa(offset)
} else {
fmt.Println("Rider Deliveriesv1")
q1 = deliveries + ` where a.userid=` + strconv.Itoa(input.UserID) + ` and a.orderstatus='` + input.Status + `'
and a.deliverydate::date between '` + input.Fromdate + `' and '` + input.ToDate + `' order by deliveryid asc`
}
} else {
if input.Pagesize != 0 {
fmt.Println("Rider Deliveriesv2")
q1 = deliveries + ` where a.orderstatus in ('accepted','arrived','picked') and a.userid=` + strconv.Itoa(input.UserID) + ` and
a.deliverydate::date between '` + input.Fromdate + `' and '` + input.ToDate + `' order by deliveryid
desc LIMIT ` + strconv.Itoa(input.Pagesize) + ` OFFSET ` + strconv.Itoa(offset)
} else {
fmt.Println("Rider Deliveriesv1")
q1 = deliveries + ` where a.orderstatus in ('accepted','arrived','picked') and a.userid=` + strconv.Itoa(input.UserID) + ` and
a.deliverydate::date between '` + input.Fromdate + `' and '` + input.ToDate + `' order by deliveryid desc`
}
}
r.db.Raw(q1).Find(&data)
return data
}
func (r *deliveriesRepository) GetAppUserDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
var data []models.Deliveryinfo
fmt.Println("Appsuser Deliveries -new")
var q1 string
offset := (input.Pageno - 1) * input.Pagesize
q1 = deliveries + ` WHERE g.status = 'Active' AND g.userid=` + strconv.Itoa(input.Appuserid)
if input.Status != "" {
q1 += ` AND a.orderstatus='` + input.Status + `'`
}
if input.Fromdate != "" && input.ToDate != "" {
q1 += ` AND a.deliverydate::date BETWEEN '` + input.Fromdate + `' AND '` + input.ToDate + `'`
}
if input.Keyword != "" {
k := "%" + input.Keyword + "%"
q1 += ` AND (
a.pickupcustomer LIKE '` + k + `' OR
b.tenantname LIKE '` + k + `' OR
a.deliverycustomer LIKE '` + k + `' OR
a.pickupcontactno LIKE '` + k + `' OR
a.deliverycontactno LIKE '` + k + `' OR
CAST(a.orderid AS TEXT) LIKE '` + k + `'
)`
}
q1 += ` ORDER BY a.deliveryid DESC`
if input.Pagesize != 0 {
q1 += ` LIMIT ` + strconv.Itoa(input.Pagesize) + ` OFFSET ` + strconv.Itoa(offset)
}
log.Println("Final Query:", q1)
r.db.Raw(q1).Find(&data)
return data
}
func (r *deliveriesRepository) GetDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
var data []models.Deliveryinfo
var queryBuilder strings.Builder
var params []interface{}
offset := (input.Pageno - 1) * input.Pagesize
baseQuery := `
SELECT a.*, b.tenantname, c.firstname as ridername, c.contactno as ridercontact, d.customertoken
FROM deliveries a
JOIN tenants b ON a.tenantid = b.tenantid
Join app_users c ON a.userid = c.userid
JOIN customer d ON a.deliverycustomerid = d.customerid
WHERE 1=1
`
queryBuilder.WriteString(baseQuery)
if input.Fromdate != "" && input.ToDate != "" {
queryBuilder.WriteString(" AND a.deliverydate::date BETWEEN ? AND ?")
params = append(params, input.Fromdate, input.ToDate)
}
if input.Status != "" {
queryBuilder.WriteString(" AND a.orderstatus = ?")
params = append(params, input.Status)
}
if input.Keyword != "" {
k := "%" + input.Keyword + "%"
queryBuilder.WriteString(`
AND (
a.pickupcustomer LIKE ? OR
b.tenantname LIKE ? OR
a.deliverycustomer LIKE ? OR
a.pickupcontactno LIKE ? OR
a.deliverycontactno LIKE ? OR
a.orderid LIKE ?
)
`)
for i := 0; i < 6; i++ {
params = append(params, k)
}
}
queryBuilder.WriteString(" ORDER BY a.deliveryid DESC")
if input.Pagesize != 0 {
queryBuilder.WriteString(" LIMIT ? OFFSET ?")
params = append(params, input.Pagesize, offset)
}
query := queryBuilder.String()
log.Println("Final query:", query)
log.Println("With params:", params)
r.db.Raw(query, params...).Scan(&data)
return data
}
func (r *deliveriesRepository) GetDeliveryQueues(uid int, fdate, tdate string) ([]models.Deliveryinfo, error) {
var data []models.Deliveryinfo
var q1 string
if fdate != "" && tdate != "" {
q1 = deliveries + `
WHERE a.orderstatus='pending'
AND a.userid=?
AND DATE(a.deliverydate) BETWEEN ? AND ?
ORDER BY a.deliveryid ASC`
if err := r.db.Raw(q1, uid, fdate, tdate).Find(&data).Error; err != nil {
return nil, err
}
} else {
q1 = deliveries + `
WHERE a.orderstatus='pending'
AND a.userid=?
AND DATE(a.deliverydate)=CURDATE()
ORDER BY a.deliveryid ASC`
if err := r.db.Raw(q1, uid).Find(&data).Error; err != nil {
return nil, err
}
}
return data, nil
}
func (r *deliveriesRepository) GetTenantLocationDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
var data []models.Deliveryinfo
var params []interface{}
var qb strings.Builder
offset := (input.Pageno - 1) * input.Pagesize
qb.WriteString(`
SELECT a.*, b.tenantname, c.firstname AS ridername,
c.contactno AS ridercontact, d.customertoken
FROM deliveries a
JOIN tenants b ON a.tenantid = b.tenantid
JOIN app_users c ON a.userid = c.userid
JOIN customers d ON a.deliverycustomerid = d.customerid
WHERE a.tenantid = ? AND a.locationid = ?
`)
params = append(params, input.Tenantid, input.Locationid)
if input.Fromdate != "" && input.ToDate != "" {
qb.WriteString(" AND DATE(a.deliverydate) BETWEEN ? AND ?")
params = append(params, input.Fromdate, input.ToDate)
}
if input.Status != "" {
qb.WriteString(" AND a.orderstatus = ?")
params = append(params, input.Status)
}
if input.Keyword != "" {
like := "%" + input.Keyword + "%"
qb.WriteString(`
AND (
a.pickupcustomer LIKE ? OR
b.tenantname LIKE ? OR
a.deliverycustomer LIKE ? OR m
a.pickupcontactno LIKE ? OR
a.deliverycontactno LIKE ? OR
a.orderid LIKE ?
)
`)
for i := 0; i < 6; i++ {
params = append(params, like)
}
}
qb.WriteString(" ORDER BY a.deliveryid DESC")
if input.Pagesize != 0 {
qb.WriteString(" LIMIT ? OFFSET ?")
params = append(params, input.Pagesize, offset)
}
query := qb.String()
log.Println("Tenant+Location Query:", query)
log.Println("Params:", params)
r.db.Raw(query, params...).Scan(&data)
return data
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,199 @@
package repositories
import (
"fmt"
"nearle/models"
"strconv"
"gorm.io/gorm"
)
type PartnerRepository interface {
GetActiveRiders(partnerid, aid, uid, tid int) ([]models.RiderInfo, error)
GetPartners(aid, pid, uid int) ([]models.Partnerinfo, error)
GetRiderShifts(aid int) ([]models.Ridershifts, error)
GetLocationConfig(uid, cid int) ([]models.Locationconfigs, error)
GetRiderLogs(pid, aid int, fdate, tdate string) ([]models.RiderlogDetails, error)
GetRiderInfo(userid int) (models.RiderInfo, error)
}
type partnerRepository struct {
db *gorm.DB
}
func NewPartnerRepository(db *gorm.DB) PartnerRepository {
return &partnerRepository{db: db}
}
func (r *partnerRepository) GetActiveRiders(partnerid, aid, uid, tid int) ([]models.RiderInfo, error) {
var data []models.RiderInfo
var q1 string
const riders = `SELECT DISTINCT b.poolid, a.userid, a.firstname, a.lastname,CONCAT(a.firstname, ' ', a.lastname) AS fullname,a.contactno, a.userfcmtoken, a.partnerid, a.applocationid,
c.identificationno, c.registrationno, c.licenseno, c.vehiclename, c.vehicleno,d.shiftid, d.starttime, d.endtime, d.shifthours, d.basefare, d.fuelcharge,e.logdate,
e.login, e.logout, e.workhours, e.shorthours, e.logstatus, a.status,f.locationname AS applocation
FROM app_users a
INNER JOIN app_userpools b ON a.userid = b.userid
INNER JOIN ridersettings c ON a.userid = c.userid
INNER JOIN ridershifts d ON c.shiftid = d.shiftid
INNER JOIN (
SELECT r1.*
FROM riderlogs r1
INNER JOIN (
SELECT userid, MAX(logdate) AS max_logdate
FROM riderlogs
WHERE logdate::date = CURRENT_DATE
GROUP BY userid
) r2 ON r1.userid = r2.userid AND r1.logdate = r2.max_logdate
) e ON a.userid = e.userid
INNER JOIN app_location f ON a.applocationid = f.applocationid
INNER JOIN app_locationconfig g ON g.applocationid = f.applocationid`
if aid != 0 {
q1 = riders + ` WHERE a.configid = 6 AND a.status = 'Active' AND b.onduty = 1
AND e.logdate::date = CURRENT_DATE AND e.logstatus = 0 AND a.applocationid = ` + strconv.Itoa(aid)
} else if partnerid != 0 {
q1 = riders + ` WHERE a.configid = 6 AND a.status = 'Active' AND b.onduty = 1
AND e.logdate::date = CURRENT_DATE AND e.logstatus = 0 AND a.partnerid = ` + strconv.Itoa(partnerid)
} else if tid != 0 {
q1 = riders + ` WHERE a.configid = 6 AND a.status = 'Active' AND b.onduty = 1
AND e.logdate::date = CURRENT_DATE AND e.logstatus = 0 AND a.tenantid = ` + strconv.Itoa(tid)
} else {
q1 = riders + ` WHERE g.status = 'Active' AND a.configid = 6 AND a.status = 'Active'
AND b.onduty = 1 AND e.logdate::date = CURRENT_DATE AND e.logstatus = 0 AND g.userid = ` + strconv.Itoa(uid)
}
err := r.db.Raw(q1).Find(&data).Error
if err != nil {
return nil, err
}
return data, nil
}
func (r *partnerRepository) GetPartners(aid, pid, uid int) ([]models.Partnerinfo, error) {
var data []models.Partnerinfo
var q1 string
var args []interface{}
if pid != 0 {
q1 = `select partnerid,applocationid,partnertypeid,partnername,primarycontact,primaryemail,
contactno,address,suburb,state,city,partnerimage
from partnerinfo where status='Active' and partnerid=?`
args = append(args, pid)
} else if aid != 0 {
q1 = `select partnerid,applocationid,partnertypeid,partnername,primarycontact,primaryemail,
contactno,address,suburb,state,city,partnerimage
from partnerinfo where status='Active' and applocationid=?`
args = append(args, aid)
} else {
q1 = `select partnerid,applocationid,partnertypeid,partnername,primarycontact,primaryemail,
contactno,address,suburb,state,city,partnerimage
from partnerinfo where status='Active'`
}
err := r.db.Raw(q1, args...).Find(&data).Error
if err != nil {
return nil, err
}
print(q1)
return data, nil
}
func (r *partnerRepository) GetRiderShifts(aid int) ([]models.Ridershifts, error) {
var data []models.Ridershifts
q1 := `Select a.*,concat(a.starttime,'-',a.endtime) as shiftname from ridershifts a where a.applocationid=` + strconv.Itoa(aid)
err := r.db.Raw(q1).Find(&data).Error
if err != nil {
return nil, err
}
print(q1)
return data, nil
}
func (r *partnerRepository) GetLocationConfig(uid, cid int) ([]models.Locationconfigs, error) {
var data []models.Locationconfigs
q1 := fmt.Sprintf(`SELECT a.applocationid,a.locationname FROM app_location a
inner join app_locationconfig b ON a.applocationid=b.applocationid
WHERE b.status='Active' and b.userid=%d`, uid)
err := r.db.Raw(q1).Find(&data).Error
if err != nil {
return nil, err
}
print(q1)
return data, nil
}
func (r *partnerRepository) GetRiderLogs(pid, aid int, fdate, tdate string) ([]models.RiderlogDetails, error) {
var data []models.RiderlogDetails
var args []interface{}
baseQuery := `
SELECT a.*, b.*, CONCAT(b.firstname,' ',b.lastname) AS username,
COALESCE(SUM(c.breakhours),0) AS breakhours
FROM riderlogs a
INNER JOIN app_users b ON a.userid = b.userid
LEFT JOIN riderbreaks c ON a.logid = c.logid AND a.userid = c.userid
WHERE 1=1
`
if pid != 0 {
baseQuery += " AND a.partnerid = ?"
args = append(args, pid)
}
if aid != 0 {
baseQuery += " AND b.applocationid = ?"
args = append(args, aid)
}
if fdate != "" && tdate != "" {
baseQuery += " AND logdate::date BETWEEN ? AND ?"
args = append(args, fdate, tdate)
} else {
baseQuery += " AND a.logdate::date = CURRENT_DATE"
}
baseQuery += " GROUP BY a.userid ORDER BY logid ASC"
if err := r.db.Raw(baseQuery, args...).Find(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *partnerRepository) GetRiderInfo(userid int) (models.RiderInfo, error) {
var data models.RiderInfo
q1 := `SELECT a.userid,a.firstname,a.lastname, CONCAT(a.firstname,' ',a.lastname) as fullname,
a.partnerid,a.configid,a.contactno,
a.address,a.suburb,a.city,a.state,a.postcode,a.latitude,a.longitude,
b.identificationno,b.vehicleno,b.vehiclename,b.licenseno,b.insuranceno,b.insurancedate,
c.shiftid,c.starttime,c.endtime,c.shifthours,c.basefare,c.additionalcharges,c.orders,c.fuelcharge,a.status,
a.applocationid,d.locationname as applocation,d.logseconds
FROM app_users a
INNER JOIN ridersettings b ON a.userid=b.userid
INNER JOIN ridershifts c ON b.shiftid=c.shiftid
INNER JOIN app_location d ON a.applocationid=d.applocationid
WHERE a.userid = ?`
if err := r.db.Raw(q1, userid).Scan(&data).Error; err != nil {
return models.RiderInfo{}, err
}
return data, nil
}

View File

@@ -0,0 +1,747 @@
package repositories
import (
"fmt"
"strconv"
"strings"
"time"
"nearle/models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type ProductRepository interface {
GetProductSubCategory(categoryID, tenantID int) ([]models.ProductSubCategory, error)
GetProductCount(tenantID, categoryID, subcategoryID int, approve string) ([]models.Productcount, error)
GetProductCategory() ([]models.ProductCategory, error)
GetProductVariants(tenantID, subcategoryID int) ([]models.Productvariant, error)
GetCatalougeProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Products, error)
GetProductStocks(tenantID, locationID string) ([]models.Productstocks, error)
CreateProductStock(stocks []models.Productstock) error
UpdateProductStatus(productIDs []int, status string) error
CreateProduct(product models.Products) error
UpdateProduct(product models.Products) error
DeleteProduct(productID int) error
GetStockStatement(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Productstockstatement, error)
GetLocationProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Locationproducts, error)
GetLocationProductSummary(tenantID, locationID int) ([]models.ProductSummary, error)
FetchFilteredProducts(categoryID, subcategoryID, productID, applocationID, tenantID, locationID int, keyword, productStatus, approve string, pageno, pagesize int) ([]models.Tenantproducts, error)
GetProductByVariant(tenantid, variantid int) ([]models.Products, error)
GetSubcategories(categoryID int) ([]models.Subcategory, error)
GetProducts(params models.ProductFilter) ([]models.Products, error)
GetTenantInfo(tenantID, applocationID int) (map[string]interface{}, error)
UpdateProductLocation(input models.Productlocations) error
CreateProductLocation(input []models.Productlocations) error
CreateProductVariant(input models.Productvariant) error
}
type productRepository struct {
db *gorm.DB
}
func NewProductRepository(db *gorm.DB) ProductRepository {
return &productRepository{db: db}
}
func (r *productRepository) GetProductSubCategory(categoryID, tenantID int) ([]models.ProductSubCategory, error) {
var data []models.ProductSubCategory
var query strings.Builder
var args []interface{}
query.WriteString("SELECT * FROM productsubcategories WHERE 1=1")
if tenantID != 0 {
query.WriteString(" AND tenantid = ?")
args = append(args, tenantID)
}
if categoryID != 0 {
query.WriteString(" AND categoryid = ?")
args = append(args, categoryID)
}
if err := r.db.Raw(query.String(), args...).Scan(&data).Error; err != nil {
return nil, err
}
// print()
return data, nil
}
func (r *productRepository) GetProductCount(tenantid, categoryid, subcategory int, approve string) ([]models.Productcount, error) {
var data []models.Productcount
baseQuery := `
SELECT
COUNT(*) AS total,
SUM(CASE WHEN a.productstatus = 'available' THEN 1 ELSE 0 END) AS available,
SUM(CASE WHEN a.productstatus = 'outofstock' THEN 1 ELSE 0 END) AS outofstock
FROM products a
WHERE 1 = 1
`
var conditions []string
var params []interface{}
if tenantid != 0 {
conditions = append(conditions, "a.tenantid = ?")
params = append(params, tenantid)
}
if categoryid != 0 {
conditions = append(conditions, "a.categoryid = ?")
params = append(params, categoryid)
}
if subcategory != 0 {
conditions = append(conditions, "a.subcategoryid = ?")
params = append(params, subcategory)
}
if approve != "" {
conditions = append(conditions, "a.approve = ?")
params = append(params, approve)
}
if len(conditions) > 0 {
baseQuery += " AND " + strings.Join(conditions, " AND ")
}
if err := r.db.Raw(baseQuery, params...).Scan(&data).Error; err != nil {
return nil, err
}
print(baseQuery)
return data, nil
}
func (r *productRepository) GetProductCategory() ([]models.ProductCategory, error) {
var data []models.ProductCategory
q1 := `SELECT * FROM productcategories WHERE moduleid = 2 AND status = 'Active'`
r.db.Raw(q1).Scan(&data)
print(q1)
return data, nil
}
func (r *productRepository) GetProductVariants(tenantID int, subcategoryID int) ([]models.Productvariant, error) {
var data []models.Productvariant
var query string
var params []interface{}
query = `
SELECT a.*, b.categoryname
FROM productvariants a
JOIN app_category b ON a.categoryid = b.categoryid
WHERE a.tenantid = ?
`
params = append(params, tenantID)
if subcategoryID != 0 {
query += " AND a.subcategoryid = ?"
params = append(params, subcategoryID)
}
r.db.Raw(query, params...).Scan(&data)
//print(query)
return data, nil
}
func (r *productRepository) GetCatalougeProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Products, error) {
var data []models.Products
if pageno < 1 {
pageno = 1
}
if pagesize < 1 {
pagesize = 10
}
offset := (pageno - 1) * pagesize
params := []interface{}{locationID, tenantID}
// Base query
query := `
SELECT a.*
FROM products a
LEFT JOIN productlocations b
ON a.productid = b.productid
AND b.locationid = ?
AND b.tenantid = a.tenantid
WHERE a.approve = 1
AND a.tenantid = ?
AND b.productid IS NULL
`
// Optional filters
if subcategoryID != 0 {
query += " AND a.subcategoryid = ?"
params = append(params, subcategoryID)
}
if keyword != "" {
query += " AND LOWER(a.productname) LIKE ?"
params = append(params, "%"+strings.ToLower(keyword)+"%")
}
// Pagination
query += " ORDER BY a.productid DESC LIMIT " + strconv.Itoa(pagesize) + " OFFSET " + strconv.Itoa(offset)
// Debug logs
fmt.Println("Executing query:", query)
fmt.Println("Params:", params)
// Execute query
if err := r.db.Raw(query, params...).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *productRepository) GetProductStocks(tenantID, locationID string) ([]models.Productstocks, error) {
var stocks []models.Productstocks
var params []interface{}
var conditions []string
query := `
SELECT
a.productid, a.tenantid, MAX(a.stockdate) AS stockdate, a.locationid, a.stocktype, a.maxquantity, a.minquantity, a.status,
b.applocationid, b.categoryid, b.subcategoryid, b.catalogueid, b.addonid, b.discountid, b.pricingid,
b.productname, b.productimage, b.productdesc, b.productsku, b.brandid, b.productbrand, b.productunit,
b.unitvalue, b.toppicks, b.productcost, b.taxamount, b.taxpercent, b.producttax, b.productstock,
b.productcombo, b.variants, b.retailprice, b.diffprice, b.diffpercent, b.othercost, b.approve,
b.productstatus, b.created, b.updated, c.subcatname AS subcategoryname,
SUM(CASE WHEN a.stocktype = 'in' THEN a.quantity ELSE 0 END) -
SUM(CASE WHEN a.stocktype = 'out' THEN a.quantity ELSE 0 END) AS quantity
FROM productstocks a
JOIN products b ON a.productid = b.productid
INNER JOIN productsubcategories c ON c.subcatid = b.subcategoryid
`
if tenantID != "" {
conditions = append(conditions, "a.tenantid = ?")
params = append(params, tenantID)
}
if locationID != "" {
conditions = append(conditions, "a.locationid = ?")
params = append(params, locationID)
}
if len(conditions) > 0 {
query += " WHERE " + strings.Join(conditions, " AND ")
}
query += " GROUP BY a.productid"
if err := r.db.Raw(query, params...).Scan(&stocks).Error; err != nil {
return nil, err
}
return stocks, nil
}
func (r *productRepository) CreateProductStock(stocks []models.Productstock) error {
return r.db.Table("productstocks").Create(&stocks).Error
}
func (r *productRepository) UpdateProductStatus(productIDs []int, status string) error {
return r.db.Table("products").
Where("productid IN ?", productIDs).
Update("productstatus", status).Error
}
func (r *productRepository) CreateProduct(product models.Products) error {
tx := r.db.Begin()
if err := tx.Create(&product).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *productRepository) UpdateProduct(product models.Products) error {
tx := r.db.Begin()
if err := tx.Table("productlocations").
Where("productid = ?", product.Productid).
Select("status"). // only update 'approve' field
Updates(product).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
func (r *productRepository) DeleteProduct(productID int) error {
tx := r.db.Begin()
if err := tx.Table("products").Where("productid = ?", productID).Delete(&models.Products{}).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *productRepository) GetStockStatement(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Productstockstatement, error) {
data := make([]models.Productstockstatement, 0)
if pageno < 1 {
pageno = 1
}
if pagesize < 1 {
pagesize = 10
}
offset := (pageno - 1) * pagesize
params := []interface{}{tenantID, locationID}
query := `SELECT a.productid,a.productname,a.productimage,a.categoryid,a.subcategoryid,a.productunit,a.unitvalue,a.productcost,a.taxpercent,a.taxamount,a.retailprice,b.tenantid,b.locationid,
COALESCE( SUM(CASE WHEN UPPER(c.stocktype) = 'IN' AND c.stockdate::date <= CURRENT_DATE THEN c.quantity ELSE 0 END) -
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND c.stockdate::date <= CURRENT_DATE THEN c.quantity ELSE 0 END),0 )
AS opening,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' AND c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END), 0) AS credit,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END), 0) AS debit,
COALESCE(
( SUM(CASE WHEN UPPER(c.stocktype) = 'IN' AND c.stockdate::date < CURRENT_DATE THEN c.quantity ELSE 0 END) -
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND c.stockdate::date < CURRENT_DATE THEN c.quantity ELSE 0 END)
) +
SUM(CASE WHEN UPPER(c.stocktype) = 'IN' AND c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END) -
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END),
0
) AS closing
FROM products a
JOIN productlocations b ON a.productid = b.productid AND a.tenantid = b.tenantid
LEFT JOIN productstocks c ON a.productid = c.productid AND b.locationid = c.locationid AND b.tenantid = c.tenantid
WHERE b.tenantid = ? AND b.locationid = ?`
if subcategoryID != 0 {
query += " AND a.subcategoryid = ?"
params = append(params, subcategoryID)
}
if keyword != "" {
query += " AND (CAST(a.productid AS TEXT) LIKE ? OR LOWER(a.productname) LIKE ?)"
likeParam := "%" + strings.ToLower(keyword) + "%"
params = append(params, likeParam, likeParam)
}
query += `
GROUP BY
a.productid, a.productname, a.productimage,
a.categoryid, a.subcategoryid, a.productunit,
a.productcost, a.taxpercent, a.taxamount,
a.retailprice, b.tenantid, b.locationid
ORDER BY a.productid DESC LIMIT ` + strconv.Itoa(pagesize) + ` OFFSET ` + strconv.Itoa(offset)
if err := r.db.Raw(query, params...).Scan(&data).Error; err != nil {
return nil, err
}
print(query)
return data, nil
}
func (r *productRepository) GetLocationProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Locationproducts, error) {
var data []models.Locationproducts
if pageno < 1 {
pageno = 1
}
if pagesize < 1 {
pagesize = 10
}
offset := (pageno - 1) * pagesize
params := []interface{}{tenantID, locationID}
query := `SELECT a.*, b.productlocationid, b.status,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END), 0) AS total_in,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS total_out,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END) -
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS productstock
FROM products a
INNER JOIN productlocations b ON a.productid = b.productid AND a.tenantid = b.tenantid
LEFT JOIN productstocks c ON a.productid = c.productid AND b.locationid = c.locationid AND a.tenantid = c.tenantid
WHERE a.approve=1 AND a.tenantid = ? AND b.locationid = ?`
if subcategoryID != 0 {
query += " AND a.subcategoryid = ?"
params = append(params, subcategoryID)
}
if keyword != "" {
query += " AND LOWER(a.productname) LIKE ?"
params = append(params, "%"+strings.ToLower(keyword)+"%")
}
query += ` GROUP BY a.productid, a.productname, a.productimage, a.categoryid, a.subcategoryid,
a.productunit, a.productcost, a.taxpercent, a.taxamount, a.retailprice,
b.tenantid, b.locationid, b.productlocationid, b.status
ORDER BY a.productid DESC LIMIT ? OFFSET ?`
params = append(params, pagesize, offset)
if err := r.db.Raw(query, params...).Scan(&data).Error; err != nil {
return nil, err
}
print(query)
return data, nil
}
func (r *productRepository) GetLocationProductSummary(tenantID, locationID int) ([]models.ProductSummary, error) {
data := make([]models.ProductSummary, 0)
query := `
SELECT
a.subcatid AS subcategoryid,
a.subcatname AS subcategroyname,
a.image,
COUNT(DISTINCT c.productid) AS productcount
FROM productsubcategories a
LEFT JOIN products b
ON a.subcatid = b.subcategoryid
AND b.approve = 1
AND b.tenantid = ?
LEFT JOIN productlocations c
ON b.productid = c.productid
AND c.tenantid = ?
AND c.locationid = ?
WHERE a.categoryid = 2
GROUP BY a.subcatid, a.subcatname, a.image
ORDER BY a.subcatid;
`
// Only 3 params: tenantID for products, tenantID for locations, locationID
params := []interface{}{tenantID, tenantID, locationID}
if err := r.db.Raw(query, params...).Scan(&data).Error; err != nil {
return nil, err
}
// Correct "All" count: sum of only products that exist in this location
total := 0
for _, d := range data {
total += d.Productcount
}
all := models.ProductSummary{
Subcategoryid: 0,
Subcategroyname: "All",
Productcount: total,
}
data = append([]models.ProductSummary{all}, data...)
return data, nil
}
func (r *productRepository) FetchFilteredProducts(
categoryID, subcategoryID, productID, applocationID, tenantID,
locationID int, keyword, productStatus, approve string, pageno, pagesize int,
) ([]models.Tenantproducts, error) {
offset := (pageno - 1) * pagesize
results := make([]models.Tenantproducts, 0)
if tenantID == 0 {
return results, nil
}
// Fetch tenant info
var tenant models.TenantInfo
if err := r.db.Table("tenants").Where("tenantid = ?", tenantID).First(&tenant).Error; err != nil {
return nil, err
}
// Build product query
var products []models.Products
query := r.db.
Table("products a").
Select(`
a.*,
b.status,
c.categoryname,
d.subcatname AS subcategoryname,
ps.locationid,
COALESCE(ps.quantity, 0) AS quantity
`).
Joins("LEFT JOIN productlocations b ON a.productid = b.productid").
Joins("LEFT JOIN productcategories c ON a.categoryid = c.categoryid").
Joins("LEFT JOIN productsubcategories d ON a.subcategoryid = d.subcatid").
Joins(`
LEFT JOIN (
SELECT
productid,
locationid,
SUM(CASE WHEN stocktype = 'in' THEN quantity ELSE 0 END) -
SUM(CASE WHEN stocktype = 'out' THEN quantity ELSE 0 END) AS quantity
FROM productstocks
GROUP BY productid, locationid
) ps ON ps.productid = a.productid
`).
Where("a.tenantid = ?", tenantID).
Order("a.productid DESC")
if categoryID != 0 {
query = query.Where("a.categoryid = ?", categoryID)
}
if subcategoryID != 0 {
query = query.Where("a.subcategoryid = ?", subcategoryID)
}
if productID != 0 {
query = query.Where("a.productid = ?", productID)
}
if productStatus != "" {
query = query.Where("a.productstatus = ?", productStatus)
}
if locationID != 0 {
query = query.Where("e.locationid = ?", locationID)
}
if approve != "" {
query = query.Where("a.approve = ?", approve)
}
if keyword != "" {
like := "%" + strings.ToLower(keyword) + "%"
query = query.Where(
r.db.Where("LOWER(a.productname) LIKE ?", like).
Or("LOWER(a.unitvalue) LIKE ?", like).
Or("LOWER(CAST(a.productcost AS TEXT)) LIKE ?", like),
)
}
if pagesize > 0 && offset >= 0 {
query = query.Limit(pagesize).Offset(offset)
}
if err := query.Scan(&products).Error; err != nil {
return nil, err
}
if products == nil {
products = []models.Products{}
}
results = append(results, models.Tenantproducts{
Tenant: tenant,
Products: products,
})
print(query)
return results, nil
}
func (r *productRepository) GetProductByVariant(tenantid, variantid int) ([]models.Products, error) {
var data []models.Products
err := r.db.
Table("products p").
Select(`
p.*,
c.categoryname,
d.subcatname AS subcategoryname,
COALESCE(pd.discountvalue, 0) AS discountvalue,
pd.discountid
`).
Joins("LEFT JOIN productcategories c ON p.categoryid = c.categoryid").
Joins("LEFT JOIN productsubcategories d ON p.subcategoryid = d.subcatid").
Joins("LEFT JOIN productdiscounts pd ON pd.productid = p.productid").
Where("p.tenantid = ? AND p.variants = ?", tenantid, variantid).
Order("p.productid DESC").
Scan(&data).Error
if err != nil {
return nil, err
}
return data, nil
}
func (r *productRepository) GetSubcategories(categoryID int) ([]models.Subcategory, error) {
var subcats []models.Subcategory
err := r.db.Table("productsubcategories").
Where("categoryid = ?", categoryID).
Find(&subcats).Error
return subcats, err
}
func (r *productRepository) GetProducts(params models.ProductFilter) ([]models.Products, error) {
var products []models.Products
q := r.db.Table("products a").
Joins("LEFT JOIN productlocations pl ON pl.productid = a.productid").
Joins("LEFT JOIN productdiscounts pd ON pd.productid = a.productid").
Joins("LEFT JOIN productcategories c ON a.categoryid = c.categoryid").
Where("a.categoryid = ?", params.CategoryID)
if params.TenantID > 0 {
q = q.Where("a.tenantid = ?", params.TenantID)
}
if params.LocationID > 0 {
q = q.Where("pl.locationid = ?", params.LocationID)
}
if params.AppLocationID > 0 {
q = q.Where("a.applocationid = ?", params.AppLocationID)
}
if params.ProductID > 0 {
q = q.Where("a.productid = ?", params.ProductID)
}
if params.Keyword != "" {
like := "%" + strings.ToLower(params.Keyword) + "%"
q = q.Where(
r.db.Where("LOWER(a.productname) LIKE ?", like).
Or("LOWER(a.unitvalue) LIKE ?", like).
Or("LOWER(CAST(a.productcost AS TEXT)) LIKE ?", like),
)
}
err := q.Select(`
a.*,
COALESCE(pd.discountvalue, 0) AS discountvalue
`).Find(&products).Error
return products, err
}
func (r *productRepository) GetTenantInfo(tenantID, applocationID int) (map[string]interface{}, error) {
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 := r.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
`, tenantID, applocationID).Scan(&tenant).Error
if err != nil {
return nil, err
}
return map[string]interface{}{
"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,
}, nil
}
func (r *productRepository) UpdateProductLocation(input models.Productlocations) error {
tx := r.db.Begin()
t1 := tx.Where("productlocationid = ?", input.Productlocationid).Updates(&input)
if t1.Error != nil {
tx.Rollback()
return t1.Error
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *productRepository) CreateProductLocation(input []models.Productlocations) error {
var stk []models.Productstock
tx := r.db.Begin()
// Insert or update product location
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "tenantid"}, {Name: "locationid"}, {Name: "productid"}},
DoUpdates: clause.AssignmentColumns([]string{"price", "minquantity", "maxquantity"}),
}).Create(&input).Error; err != nil {
tx.Rollback()
return err
}
// Prepare product stock entries
for _, loc := range input {
if loc.Quantity > 0 {
stk = append(stk, models.Productstock{
Tenantid: loc.Tenantid,
Stockdate: time.Now(),
Locationid: loc.Locationid,
Productid: loc.Productid,
Quantity: loc.Quantity,
Stocktype: loc.Stocktype,
})
}
}
// Insert stock records if available
if len(stk) > 0 {
if err := tx.Create(&stk).Error; err != nil {
tx.Rollback()
return err
}
}
// Commit transaction
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *productRepository) CreateProductVariant(input models.Productvariant) error {
tx := r.db.Begin()
if err := tx.Create(&input).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,737 @@
package repositories
import (
"errors"
"fmt"
"nearle/models"
"strconv"
"strings"
"github.com/jinzhu/copier"
"gorm.io/gorm"
)
type TenantRepository interface {
SearchTenant(status, searchstr string) ([]models.Tenantinfo, error)
GetAllTenants(pageno, pagesize, aid int, status, tenanttype, keyword string) ([]models.Tenantinfo, error)
GetTenantLocations(tid int) ([]models.Tenantlocations, error)
GetTenantSlot() (models.Tenantslot, error)
CreateTenantCustomer(customer models.Tenantcustomer) (*models.Tenantcustomer, error)
GetCustomerTenants(customerID int, categoryID int, tenantFlag int) ([]models.TenantInfo, error)
GetTenantPricing(tid, aid int) (*models.Tenantpricing, error)
UpdateLocation(input models.Tenantlocations) error
CreateLocation(data models.Tenantlocations) error
GetStaffs(tid int) ([]models.StaffInfo, error)
CreateStaff(user models.User) error
UpdateStaff(user models.User) error
CreateTenantLocation(data models.Tenantlocations) error
UpdateTenantLocation(data models.Tenantlocations) error
CheckTenantByNo(cno string) int
CreateTenantUser(data models.Tenants) (bool, error)
GetUserByNo(cno string) models.UserInfo
GetTenantByID(tid int, locationid int) (models.Tenantinfo, error)
GetTenantByKeyword(keyword string) ([]models.TenantSearch, error)
}
type tenantRepository struct {
db *gorm.DB
}
func NewTenantRepository(db *gorm.DB) TenantRepository {
return &tenantRepository{db: db}
}
func (r *tenantRepository) SearchTenant(status, keyword string) ([]models.Tenantinfo, error) {
var data []models.Tenantinfo
var query string
searchStr := strings.ToLower(keyword)
if strings.ToLower(status) != "pending" {
query = `
SELECT a.*, b.subcategoryname, c.firstname, c.lastname,
CONCAT(c.firstname, ' ', c.lastname) AS accountname
FROM tenants a
INNER JOIN app_subcategory b ON a.subcategoryid = b.subcategoryid
LEFT JOIN app_users c ON c.userid = a.partneruserid
WHERE a.approved = 1
AND LOWER(a.status) = ?
AND LOWER(a.tenantname) LIKE ?
`
r.db.Raw(query, strings.ToLower(status), searchStr+"%").Scan(&data)
} else {
query = `
SELECT a.*, b.subcategoryname, c.firstname, c.lastname,
CONCAT(c.firstname, ' ', c.lastname) AS accountname
FROM tenants a
INNER JOIN app_subcategory b ON a.subcategoryid = b.subcategoryid
LEFT JOIN app_users c ON c.userid = a.partneruserid
WHERE a.approved = 0
AND LOWER(a.tenantname) LIKE ?
`
r.db.Raw(query, searchStr+"%").Scan(&data)
}
return data, nil
}
func (r *tenantRepository) GetAllTenants(pageno, pagesize, aid int, status, tenanttype, keyword string) ([]models.Tenantinfo, error) {
offset := (pageno - 1) * pagesize
var data []models.Tenantinfo
base := `SELECT * FROM tenants a WHERE 1 = 1`
var (
conds []string
params []interface{}
)
switch strings.ToLower(status) {
case "active":
conds = append(conds, "a.approved = 1 AND a.status = 'Active'")
case "inactive":
conds = append(conds, "a.approved = 1 AND a.status = 'InActive'")
case "pending":
conds = append(conds, "a.approved = 0")
}
if aid != 0 {
conds = append(conds, "a.applocationid = ?")
params = append(params, aid)
}
if tenanttype != "" {
conds = append(conds, "a.tenanttype = ?")
params = append(params, tenanttype)
}
if keyword != "" {
kw := "%" + strings.ToLower(keyword) + "%"
conds = append(conds,
"(LOWER(a.tenantname) LIKE ? OR LOWER(a.primarycontact) LIKE ?)")
params = append(params, kw, kw)
}
if len(conds) > 0 {
base += " AND " + strings.Join(conds, " AND ")
}
base += " ORDER BY a.tenantid DESC LIMIT ? OFFSET ?"
params = append(params, pagesize, offset)
err := r.db.Raw(base, params...).Scan(&data).Error
if err != nil {
return nil, err
}
return data, nil
}
func (r *tenantRepository) GetTenantLocations(tid int) ([]models.Tenantlocations, error) {
var data []models.Tenantlocations
q1 := `SELECT a.*, b.roleid FROM tenantlocations a
LEFT JOIN app_users b ON a.locationid = b.locationid
AND a.tenantid = b.tenantid
WHERE a.tenantid = ?`
if err := r.db.Raw(q1, tid).Find(&data).Error; err != nil {
return nil, err
}
print(q1)
return data, nil
}
func (r *tenantRepository) GetTenantSlot() (models.Tenantslot, error) {
var data models.Tenantslot
err := r.db.Raw(`SELECT * FROM tenantslot`).Find(&data).Error
if err != nil {
return models.Tenantslot{}, err
}
return data, nil
}
func (r *tenantRepository) CreateTenantCustomer(customer models.Tenantcustomer) (*models.Tenantcustomer, error) {
var existing models.Tenantcustomer
// 🔍 Step 1: Check if a record already exists with same customerid and locationid
err := r.db.
Where("customerid = ? AND locationid = ?", customer.CustomerID, customer.LocationID).
First(&existing).Error
// If record found, prevent insertion
if err == nil {
return nil, fmt.Errorf("customer already exists for this location")
}
// If error other than record not found, return it
if !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
// ✅ Step 2: Insert new record if no duplicate found
if err := r.db.Create(&customer).Error; err != nil {
return nil, err
}
return &customer, nil
}
func (r *tenantRepository) GetCustomerTenants(customerID int, categoryID int, tenantFlag int) ([]models.TenantInfo, error) {
var tenants []models.TenantInfo
query := `
SELECT a.customerid, a.locationid, b.tenantid,b.tenantname,b.address,b.licenseno,
b.primaryemail,b.primarycontact,b.applocationid,b.suburb,b.city,
b.latitude,b.longitude,b.postcode,b.tenantimage,b.subcategoryid,
b.categoryid,b.registrationno,d.userfcmtoken,c.locationname,
COALESCE(o.orderscount, 0) AS orderscount
FROM tenantcustomers a
LEFT JOIN tenants b ON a.tenantid = b.tenantid
INNER JOIN tenantlocations c ON a.locationid = c.locationid
LEFT JOIN (
SELECT tenantid, customerid, COUNT(*) AS orderscount
FROM orders
GROUP BY tenantid, customerid
) o ON b.tenantid = o.tenantid AND o.customerid = a.customerid
LEFT JOIN (
SELECT locationid,
MAX(userfcmtoken) AS userfcmtoken
FROM app_users
GROUP BY locationid
) d ON d.locationid = a.locationid
WHERE a.customerid = ?
AND b.tenantid IS NOT NULL
`
args := []interface{}{customerID}
if categoryID != 0 {
query += " AND b.categoryid = ?"
args = append(args, categoryID)
}
if tenantFlag == 1 {
query += " AND COALESCE(o.orderscount,0) > 0"
}
if err := r.db.Raw(query, args...).Scan(&tenants).Error; err != nil {
return nil, err
}
if tenants == nil {
return []models.TenantInfo{}, nil
}
// Attach top 5 subcategories
if len(tenants) > 0 {
var subcategories []models.ProductSubcategory
if err := r.db.Table("productsubcategories").
Order("subcatid ASC").
Limit(5).
Find(&subcategories).Error; err != nil {
return nil, err
}
for i := range tenants {
tenants[i].ProductSubcategory = subcategories
}
}
print(tenants)
return tenants, nil
}
func (r *tenantRepository) GetTenantPricing(tid, aid int) (*models.Tenantpricing, error) {
var data models.Tenantpricing
var q1 string
if tid != 0 {
q1 = `SELECT *
FROM tenantpricing
WHERE pricingdate = (
SELECT MAX(pricingdate)
FROM tenantpricing
WHERE tenantid=` + strconv.Itoa(tid) + `
)
AND tenantid=?
ORDER BY tenantpricingid DESC`
}
if err := r.db.Raw(q1, tid).Find(&data).Error; err != nil {
return nil, err
}
return &data, nil
}
func (r *tenantRepository) UpdateLocation(input models.Tenantlocations) error {
tx := r.db.Begin()
if err := tx.Where("locationid=?", input.Locationid).Updates(&input).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *tenantRepository) CreateLocation(data models.Tenantlocations) error {
var cust models.Customers
var tcust models.Tenantcustomers
var custloc models.Customerlocations
tx := r.db.Begin()
if err := tx.Create(&data).Error; err != nil {
tx.Rollback()
return err
}
cust.Firstname = data.Locationname
cust.Email = data.Email
cust.Contactno = data.Contactno
cust.Address = data.Address
cust.Suburb = data.Suburb
cust.City = data.City
cust.State = data.State
cust.Postcode = data.Postcode
cust.Applocationid = data.Applocationid
cust.Latitude = data.Latitude
cust.Longitude = data.Longitude
cust.Primaryaddress = 0
if err := tx.Table("customers").Create(&cust).Error; err != nil {
tx.Rollback()
return err
}
if err := copier.Copy(&custloc, &cust); err != nil {
tx.Rollback()
return err
}
if err := tx.Table("customerlocations").Create(&custloc).Error; err != nil {
tx.Rollback()
return err
}
tcust.Customerid = cust.Customerid
tcust.Tenantid = data.Tenantid
tcust.Locationid = data.Locationid
tcust.Moduleid = data.Moduleid
if err := tx.Table("tenantcustomers").Create(&tcust).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *tenantRepository) GetStaffs(tid int) ([]models.StaffInfo, error) {
var data []models.StaffInfo
q1 := `SELECT a.userid,a.firstname,a.lastname,
CONCAT(a.firstname,' ',a.lastname) AS fullname,
a.email,a.contactno,a.address,a.suburb,a.city,
a.state,a.postcode,a.userfcmtoken,a.pin,a.applocationid,
a.roleid,a.partnerid,a.tenantid,a.locationid,
b.locationname
FROM app_users a
INNER JOIN tenantlocations b ON a.locationid = b.locationid
WHERE a.tenantid = ?`
if err := r.db.Raw(q1, tid).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}
func (r *tenantRepository) CreateStaff(user models.User) error {
if err := r.db.Table("app_users").Create(&user).Error; err != nil {
return err
}
return nil
}
func (r *tenantRepository) UpdateStaff(user models.User) error {
if err := r.db.Table("app_users").Where("userid = ?", user.Userid).Updates(&user).Error; err != nil {
return err
}
return nil
}
func (r *tenantRepository) CreateTenantLocation(data models.Tenantlocations) error {
var user models.Tenantuser
tx := r.db.Begin()
// Set status BEFORE insert
data.Status = "InActive"
// Step 1: Insert into tenantlocations
if err := tx.Create(&data).Error; err != nil {
tx.Rollback()
return err
}
// Step 2: Insert into app_users
user.Authname = data.Email
user.Firstname = data.Locationname
user.Email = data.Email
user.Contactno = data.Contactno
user.Address = data.Address
user.Suburb = data.Suburb
user.City = data.City
user.State = data.State
user.Postcode = data.Postcode
user.Partnerid = data.Partnerid
user.Tenantid = data.Tenantid
user.Locationid = data.Locationid
user.Applocationid = data.Applocationid
user.Configid = 1
user.Status = "InActive"
user.Roleid = 0
user.Authmode = 0
user.Password = ""
user.Dialcode = "+91"
if err := tx.Table("app_users").Create(&user).Error; err != nil {
tx.Rollback()
return err
}
// Commit
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
func (r *tenantRepository) UpdateTenantLocation(input models.Tenantlocations) error {
tx := r.db.Begin()
// ✅ Step 1: Prepare map for tenantlocations update
locationUpdate := make(map[string]interface{})
if input.Locationname != "" {
locationUpdate["locationname"] = input.Locationname
}
if input.Email != "" {
locationUpdate["email"] = input.Email
}
if input.Contactno != "" {
locationUpdate["contactno"] = input.Contactno
}
if input.Address != "" {
locationUpdate["address"] = input.Address
}
if input.Suburb != "" {
locationUpdate["suburb"] = input.Suburb
}
if input.City != "" {
locationUpdate["city"] = input.City
}
if input.State != "" {
locationUpdate["state"] = input.State
}
if input.Postcode != "" {
locationUpdate["postcode"] = input.Postcode
}
if input.Partnerid != 0 {
locationUpdate["partnerid"] = input.Partnerid
}
if input.Tenantid != 0 {
locationUpdate["tenantid"] = input.Tenantid
}
if input.Applocationid != 0 {
locationUpdate["applocationid"] = input.Applocationid
}
if input.Status != "" {
locationUpdate["status"] = input.Status
}
// ✅ Step 2: Update tenantlocations (only provided fields)
if len(locationUpdate) > 0 {
if err := tx.Table("tenantlocations").
Where("locationid = ?", input.Locationid).
Updates(locationUpdate).Error; err != nil {
tx.Rollback()
return err
}
}
// ✅ Step 3: Prepare map for app_users update (only matching fields)
userUpdate := make(map[string]interface{})
if input.Locationname != "" {
userUpdate["firstname"] = input.Locationname
}
if input.Email != "" {
userUpdate["email"] = input.Email
}
if input.Contactno != "" {
userUpdate["contactno"] = input.Contactno
}
if input.Address != "" {
userUpdate["address"] = input.Address
}
if input.Suburb != "" {
userUpdate["suburb"] = input.Suburb
}
if input.City != "" {
userUpdate["city"] = input.City
}
if input.State != "" {
userUpdate["state"] = input.State
}
if input.Postcode != "" {
userUpdate["postcode"] = input.Postcode
}
if input.Tenantid != 0 {
userUpdate["tenantid"] = input.Tenantid
}
if input.Partnerid != 0 {
userUpdate["partnerid"] = input.Partnerid
}
if input.Applocationid != 0 {
userUpdate["applocationid"] = input.Applocationid
}
if input.Status != "" {
userUpdate["status"] = input.Status
}
// ✅ Step 4: Update app_users (only provided fields)
if len(userUpdate) > 0 {
if err := tx.Table("app_users").
Where("locationid = ?", input.Locationid).
Updates(userUpdate).Error; err != nil {
tx.Rollback()
return err
}
}
// ✅ Commit transaction
if err := tx.Commit().Error; err != nil {
return err
}
return nil
}
// ✅ Check if tenant exists
func (r *tenantRepository) CheckTenantByNo(cno string) int {
var id int
q1 := "SELECT tenantid FROM tenants WHERE primarycontact = '" + cno + `'`
r.db.Raw(q1).Find(&id)
return id
}
// ✅ Create tenant + user + customer records
func (r *tenantRepository) CreateTenantUser(data models.Tenants) (bool, error) {
var seq models.Ordersequences
var user models.User
var cust models.Customers
var custloc models.Customerlocations
var tcust models.Tenantcustomers
tx := r.db.Begin()
// Step 1: Insert into tenants
if err := tx.Create(&data).Error; err != nil {
tx.Rollback()
return false, errors.New("error in tenant creation")
}
// Step 2: Create order sequence
seq.Tenantid = data.Tenantid
if err := tx.Table("ordersequences").Create(&seq).Error; err != nil {
tx.Rollback()
return false, errors.New("error in sequence")
}
// Step 3: Create app_user
if err := copier.Copy(&user, &data); err != nil {
tx.Rollback()
return false, err
}
user.Userfcmtoken = data.Tenanttoken
user.Contactno = data.Primarycontact
user.Email = data.Primaryemail
user.Authname = data.Primaryemail
user.Deviceid = data.Deviceid
user.Tenantid = data.Tenantid
user.Locationid = data.Tenantlocations.Locationid
user.Roleid = 1
if err := tx.Table("app_users").Create(&user).Error; err != nil {
tx.Rollback()
return false, errors.New("error in user creation")
}
// Step 4: Create / Update customers
cust.Configid = data.Configid
cust.Firstname = data.Tenantname
cust.Email = data.Primaryemail
cust.Contactno = data.Primarycontact
cust.Deviceid = data.Deviceid
cust.Devicetype = data.Devicetype
cust.Customertoken = data.Tenanttoken
cust.Profileimage = data.Tenantimage
cust.Address = data.Address
cust.Suburb = data.Suburb
cust.City = data.City
cust.State = data.State
cust.Postcode = data.Postcode
cust.Applocationid = data.Applocationid
cust.Latitude = data.Latitude
cust.Longitude = data.Longitude
cust.Primaryaddress = 1
cid := r.CheckCustomer(data.Primarycontact)
if cid == 0 {
if err := tx.Table("customers").Create(&cust).Error; err != nil {
tx.Rollback()
return false, errors.New("error in customer creation")
}
if err := copier.Copy(&custloc, &cust); err != nil {
tx.Rollback()
return false, err
}
if err := tx.Table("customerlocations").Create(&custloc).Error; err != nil {
tx.Rollback()
return false, errors.New("error in customer location")
}
} else {
if err := tx.Table("customers").Where("customerid=?", cid).Updates(&cust).Error; err != nil {
tx.Rollback()
return false, errors.New("error updating customer")
}
if err := copier.Copy(&custloc, &cust); err != nil {
tx.Rollback()
return false, err
}
if err := tx.Table("customerlocations").Where("customerid=?", cid).Updates(&custloc).Error; err != nil {
tx.Rollback()
return false, errors.New("error updating customer location")
}
}
// Step 5: Create tenant-customer link
tcust.Customerid = cust.Customerid
tcust.Tenantid = data.Tenantid
tcust.Locationid = data.Tenantlocations.Locationid
if err := tx.Table("tenantcustomers").Create(&tcust).Error; err != nil {
tx.Rollback()
return false, errors.New("error in tenant customer")
}
// ✅ Commit transaction
if err := tx.Commit().Error; err != nil {
return false, errors.New("error in tenant creation")
}
return true, nil
}
// ✅ Check if customer exists
func (r *tenantRepository) CheckCustomer(cno string) int {
var id int
q := "SELECT customerid FROM customers WHERE contactno = '" + cno + `'`
r.db.Raw(q).Find(&id)
return id
}
// ✅ Get user by contact number
func (r *tenantRepository) GetUserByNo(cno string) models.UserInfo {
var user models.UserInfo
q1 := `SELECT a.userid,a.authname,a.email,a.configid,a.roleid,a.authmode,a.contactno,
a.firstname,a.lastname,CONCAT(a.firstname,' ',a.lastname) AS fullname,
a.userfcmtoken,a.pin,a.deviceid,a.devicetype,a.tenantid,a.locationid,
b.partnerid,b.moduleid,b.categoryid,b.subcategoryid,
b.applocationid,b.tenantname,b.address AS tenantaddress,b.state AS tenantstate,b.city AS tenantcity,
b.postcode AS tenantpostcode,b.latitude AS tenantlat,b.longitude AS tenantlong
FROM app_users a
LEFT JOIN tenants b ON a.tenantid = b.tenantid
WHERE a.contactno = '` + cno + `'`
r.db.Raw(q1).Find(&user)
return user
}
func (r *tenantRepository) GetTenantByID(tid int, locationid int) (models.Tenantinfo, error) {
var data models.Tenantinfo
q1 := `
SELECT a.*,b.categoryname,c.locationname AS applocation, d.allocationid AS allocationmode,e.typename AS allocationtype,e.mapid AS allocationid,f.locationid,
f.locationname, f.contactno as locationcontact
FROM tenants a
INNER JOIN app_category b ON a.categoryid = b.categoryid
INNER JOIN app_location c ON a.applocationid = c.applocationid
LEFT JOIN partnerinfo d ON a.partnerid = d.partnerid
LEFT JOIN app_types e ON d.allocationid = e.apptypeid
LEFT JOIN tenantlocations f ON a.tenantid = f.tenantid
WHERE a.tenantid = ?
`
var args []interface{}
args = append(args, tid)
if locationid != 0 {
q1 += " AND f.locationid = ?"
args = append(args, locationid)
}
if err := r.db.Raw(q1, args...).Find(&data).Error; err != nil {
return data, err
}
return data, nil
}
func (r *tenantRepository) GetTenantByKeyword(keyword string) ([]models.TenantSearch, error) {
var data []models.TenantSearch
kw := "%" + strings.ToLower(keyword) + "%"
query := `
SELECT a.tenantname, b.productname, c.subcatname
FROM tenants a
LEFT JOIN products b ON a.tenantid = b.tenantid
LEFT JOIN productsubcategories c ON b.subcategoryid = c.subcatid
WHERE c.categoryid = 2
AND (LOWER(a.tenantname) LIKE ? OR LOWER(b.productname) LIKE ? OR LOWER(c.subcatname) LIKE ?)
`
if err := r.db.Raw(query, kw, kw, kw).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}

View File

@@ -0,0 +1,279 @@
package repositories
import (
"fmt"
"strings"
"nearle/models"
"gorm.io/gorm"
)
type UserRepository interface {
GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error)
GetUserByID(uid int) (models.UserInfo, error)
Login(user models.User) (models.UserInfo, error)
FindUserID(authname, contactno string, configid int) (int, error)
GetTenantUserByID(userid int) (models.TenantUserInfo, error)
UpdateStaff(user models.User) error
GetUserByAuthname(authname string, configid int) (int, string, string)
GetUserByContactNo(contactno string, configid int) (int, string, string)
UpdateFCMToken(userid int, token string) error
GetTenantUserById(userid int) models.TenantUserInfo
CreateUser(user models.User) (int, error)
GetUserById(uid int) (models.UserInfo, error)
GetUserLogin(field, value string, configid int) (int, string, string, int)
UpdateUserFcmToken(uid int, token string) error
}
type userRepository struct {
db *gorm.DB
}
func NewUserRepository(db *gorm.DB) UserRepository {
return &userRepository{db: db}
}
func (r *userRepository) GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error) {
var users []models.UserInfo
var params []interface{}
var queryBuilder strings.Builder
offset := (pageno - 1) * pagesize
queryBuilder.WriteString(`SELECT
a.userid, a.authname, a.email, a.configid, a.roleid, a.authmode, a.contactno,
a.firstname, a.lastname, CONCAT(a.firstname, ' ', a.lastname) AS fullname,
a.address, a.suburb, a.city, a.state, a.postcode,
a.userfcmtoken, a.pin, a.deviceid, a.devicetype, a.tenantid, a.status, a.shiftid,
a.applocationid, b.locationname AS applocation, b.latitude AS applatitude, concat(c.starttime, ' - ', c.endtime) as shiftname,
b.longitude AS applongitude, b.radius AS appradius
FROM app_users a
LEFT JOIN app_location b ON a.applocationid = b.applocationid
LEFT JOIN ridershifts c ON a.shiftid = c.shiftid
WHERE 1=1`)
if roleID != 0 {
queryBuilder.WriteString(" AND a.roleid = ?")
params = append(params, roleID)
}
if tenantID != 0 {
queryBuilder.WriteString(" AND a.tenantid = ?")
params = append(params, tenantID)
}
if keyword != "" {
queryBuilder.WriteString(` AND (
LOWER(a.firstname) LIKE ? OR
LOWER(a.contactno) LIKE ? OR
LOWER(a.suburb) LIKE ?
)`)
search := "%" + strings.ToLower(keyword) + "%"
params = append(params, search, search, search)
}
queryBuilder.WriteString(" ORDER BY a.userid DESC LIMIT ? OFFSET ?")
params = append(params, pagesize, offset)
print(queryBuilder.String())
if err := r.db.Raw(queryBuilder.String(), params...).Scan(&users).Error; err != nil {
return nil, err
}
return users, nil
}
func (r *userRepository) GetUserByID(uid int) (models.UserInfo, error) {
var user models.UserInfo
q := `SELECT a.userid,a.authname,a.email,a.configid,a.roleid,a.authmode,a.contactno,
a.firstname,a.lastname,concat(a.firstname,' ',a.lastname) as fullname,a.password,a.address,a.suburb,a.city,a.state,a.postcode,
a.userfcmtoken,a.pin,a.deviceid,a.devicetype,a.tenantid,a.shiftid,a.locationid,
a.applocationid,b.locationname as applocation,b.latitude as applatitude,b.longitude as applongitude, b.radius as appradius,
concat(c.starttime, ' - ', c.endtime) as shiftname
FROM app_users a
INNER JOIN app_location b ON a.applocationid = b.applocationid
LEFT JOIN ridershifts c ON a.shiftid = c.shiftid
WHERE a.userid = ?`
if err := r.db.Raw(q, uid).Scan(&user).Error; err != nil {
return models.UserInfo{}, err
}
return user, nil
}
func (r *userRepository) Login(user models.User) (models.UserInfo, error) {
var uid int
var userInfo models.UserInfo
var q string
if user.Authname != "" {
q = `SELECT a.userid FROM app_users a
WHERE a.authname = ? AND a.configid = ?`
if err := r.db.Raw(q, user.Authname, user.Configid).Scan(&uid).Error; err != nil {
return models.UserInfo{}, err
}
} else {
q = `SELECT a.userid FROM app_users a
WHERE a.contactno = ? AND a.configid = ?`
if err := r.db.Raw(q, user.Contactno, user.Configid).Scan(&uid).Error; err != nil {
return models.UserInfo{}, err
}
}
if uid == 0 {
return models.UserInfo{}, gorm.ErrRecordNotFound
}
// ✅ Update FCM token in app_users table if provided
if user.Userfcmtoken != "" {
if err := r.db.Table("app_users").
Where("userid = ?", uid).
Update("userfcmtoken", user.Userfcmtoken).Error; err != nil {
return models.UserInfo{}, err
}
}
userInfo, err := r.GetUserByID(uid)
if err != nil {
return models.UserInfo{}, err
}
return userInfo, nil
}
func (r *userRepository) FindUserID(authname, contactno string, configid int) (int, error) {
var uid int
var query string
if authname != "" {
query = `SELECT a.userid FROM app_users a WHERE a.authname = ? AND a.configid = ?`
if err := r.db.Raw(query, authname, configid).Scan(&uid).Error; err != nil {
return 0, err
}
} else {
query = `SELECT a.userid FROM app_users a WHERE a.contactno = ? AND a.configid = ?`
if err := r.db.Raw(query, contactno, configid).Scan(&uid).Error; err != nil {
return 0, err
}
}
return uid, nil
}
func (r *userRepository) GetTenantUserByID(userid int) (models.TenantUserInfo, error) {
var info models.TenantUserInfo
query := `SELECT a.userid, a.authname, a.contactno, a.tenantid, t.tenantname
FROM app_users a
LEFT JOIN tenants t ON a.tenantid = t.tenantid
WHERE a.userid = ?`
if err := r.db.Raw(query, userid).Scan(&info).Error; err != nil {
return info, err
}
return info, nil
}
func (r *userRepository) UpdateStaff(user models.User) error {
return r.db.Table("app_users").Where("userid = ?", user.Userid).Updates(&user).Error
}
func (r *userRepository) GetUserByAuthname(authname string, configid int) (int, string, string) {
var uid int
var password, status string
query := `SELECT userid, password, status FROM app_users WHERE authname = ? AND configid = ?`
r.db.Raw(query, authname, configid).Row().Scan(&uid, &password, &status)
return uid, password, status
}
func (r *userRepository) GetUserByContactNo(contactno string, configid int) (int, string, string) {
var uid int
var password, status string
query := `SELECT userid, password, status FROM app_users WHERE contactno = ? AND configid = ?`
r.db.Raw(query, contactno, configid).Row().Scan(&uid, &password, &status)
return uid, password, status
}
func (r *userRepository) UpdateFCMToken(userid int, token string) error {
query := `UPDATE app_users SET userfcmtoken = ? WHERE userid = ?`
return r.db.Exec(query, token, userid).Error
}
func (r *userRepository) GetTenantUserById(userid int) models.TenantUserInfo {
var info models.TenantUserInfo
query := `
SELECT a.userid,a.authname,a.email,a.configid,a.roleid,a.authmode,a.contactno,
a.firstname,a.lastname,concat(a.firstname,' ',a.lastname) as fullname,
a.userfcmtoken,a.pin,a.deviceid,a.devicetype,a.tenantid,a.locationid,a.applocationid,
b.partnerid,b.moduleid,b.categoryid as categoryid,b.subcategoryid as subcategoryid,
b.applocationid,b.tenantname,b.address as tenantaddress,b.state as tenantstate,b.city as tenantcity,
b.postcode as tenantpostcode,b.latitude as tenantlat,b.longitude as tenantlong,c.locationname AS applocation,
c.latitude as applatitude,c.longitude as applongitude,c.radius as appradius, d.categoryname, e.locationname
from app_users a
LEFT JOIN tenants b ON a.tenantid=b.tenantid
INNER JOIN app_location c on c.applocationid=b.applocationid
LEFT JOIN app_category d ON b.categoryid=d.categoryid
LEFT JOIN tenantlocations e ON a.locationid=e.locationid
WHERE a.userid = ?
`
r.db.Raw(query, userid).Scan(&info)
print(query)
return info
}
func (r *userRepository) CreateUser(user models.User) (int, error) {
tx := r.db.Begin()
if err := tx.Table("app_users").Create(&user).Error; err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit().Error; err != nil {
return 0, err
}
return user.Userid, nil
}
func (r *userRepository) GetUserById(uid int) (models.UserInfo, error) {
var user models.UserInfo
q1 := `SELECT a.userid,a.authname,a.email,a.configid,a.roleid,a.authmode,a.contactno,
a.firstname,a.lastname,concat(a.firstname,' ',a.lastname) as fullname,a.password,a.address,a.suburb,a.city,a.state,a.postcode,
a.userfcmtoken,a.pin,a.deviceid,a.devicetype,a.tenantid,a.shiftid,
a.applocationid,b.locationname as applocation,b.latitude as applatitude,b.longitude as applongitude, b.radius as appradius , concat(c.starttime, ' - ', c.endtime) as shiftname
FROM app_users a
INNER JOIN app_location b on a.applocationid=b.applocationid
LEFT JOIN ridershifts c ON a.shiftid = c.shiftid
WHERE a.userid= ?`
if err := r.db.Raw(q1, uid).Scan(&user).Error; err != nil {
return models.UserInfo{}, err
}
return user, nil
}
func (r *userRepository) GetUserLogin(field, value string, configid int) (int, string, string, int) {
var uid, roleid int
var password, status string
query := fmt.Sprintf(`
SELECT userid, password, status, roleid
FROM app_users
WHERE %s = ? AND configid = ?`, field)
r.db.Raw(query, value, configid).Row().Scan(&uid, &password, &status, &roleid)
return uid, password, status, roleid
}
func (r *userRepository) UpdateUserFcmToken(userid int, fcmToken string) error {
query := `UPDATE app_users SET userfcmtoken = ? WHERE userid = ?`
return r.db.Exec(query, fcmToken, userid).Error
}

View File

@@ -0,0 +1,203 @@
package repositories
import (
"context"
"fmt"
"nearle/models"
"strconv"
firebase "firebase.google.com/go"
"firebase.google.com/go/messaging"
"google.golang.org/api/option"
"gorm.io/gorm"
)
type UtilsRepository interface {
GetApptypes(tag string) ([]models.Apptypes, error)
SendNotification(token string, notification models.FcmNotification, data map[string]string) error
GetSubcategories(moduleid int, categoryid int) ([]models.Appsubcategories, error)
GetApplocations(aid int) ([]models.Applocations, error)
GetApplocationConfig(aid int) ([]models.Applocations, error)
GetAppConfig(configID int) (models.Appconfig, error)
GetAppCategory() ([]models.AppCategory, error)
}
type utilsRepository struct {
db *gorm.DB
}
func NewUtilsRepository(db *gorm.DB) UtilsRepository {
return &utilsRepository{db: db}
}
func (r *utilsRepository) GetApptypes(tag string) ([]models.Apptypes, error) {
var data []models.Apptypes
q1 := `Select * from app_types where status ='Active' and tag='` + tag + `'`
print(q1)
err := r.db.Raw(q1).Find(&data).Error
if err != nil {
return nil, err
}
return data, nil
}
func (r *utilsRepository) SendNotification(token string, notification models.FcmNotification, data map[string]string) error {
opt := option.WithCredentialsFile("nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json")
app, err := firebase.NewApp(context.Background(), nil, opt)
if err != nil {
return fmt.Errorf("error initializing Firebase app: %v", err)
}
client, err := app.Messaging(context.Background())
if err != nil {
return fmt.Errorf("error getting Messaging client: %v", err)
}
message := &messaging.Message{
Token: token,
Notification: &messaging.Notification{
Title: notification.Title,
Body: notification.Body,
},
Android: &messaging.AndroidConfig{
Priority: "high",
Notification: &messaging.AndroidNotification{
Sound: "ring",
},
},
Data: data,
}
_, err = client.Send(context.Background(), message)
if err != nil {
return fmt.Errorf("error sending FCM message: %v", err)
}
return nil
}
func (r *utilsRepository) GetSubcategories(moduleid int, categoryid int) ([]models.Appsubcategories, error) {
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)
}
if err := r.db.Raw(query, params...).Scan(&data).Error; err != nil {
return nil, err
}
print(query)
return data, nil
}
func (r *utilsRepository) GetApplocations(aid int) ([]models.Applocations, error) {
var data []models.Applocations
q1 := `Select * from app_location where status='Active'`
if aid != 0 {
q1 += ` and applocationid = ?`
params := []interface{}{aid}
err := r.db.Raw(q1, params...).Scan(&data).Error
if err != nil {
return nil, err
}
} else {
err := r.db.Raw(q1).Scan(&data).Error
if err != nil {
return nil, err
}
}
print(q1)
return data, nil
}
func (r *utilsRepository) GetApplocationConfig(aid int) ([]models.Applocations, error) {
var data []models.Applocations
var q1, q2 string
if aid != 0 {
q1 = `SELECT * FROM app_location WHERE status='Active' AND applocationid=` + strconv.Itoa(aid)
} else {
q1 = `SELECT * FROM app_location WHERE status='Active'`
}
if err := r.db.Raw(q1).Scan(&data).Error; err != nil {
return nil, err
}
for i := range data {
q2 = `
SELECT a.userid, a.userfcmtoken, b.notify, b.applocationid
FROM app_users a
INNER JOIN app_locationconfig b ON a.userid = b.userid
WHERE b.notify='true' AND b.applocationid=` + strconv.Itoa(data[i].Applocationid)
var users []models.Applocationadmins
if err := r.db.Raw(q2).Scan(&users).Error; err != nil {
return nil, err
}
data[i].Applocationadmins = users
}
print(q1)
return data, nil
}
func (r *utilsRepository) GetAppConfig(configID int) (models.Appconfig, error) {
var data models.Appconfig
var q1 string
if configID != 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=` + strconv.Itoa(configID)
} 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`
}
fmt.Println(q1)
if err := r.db.Raw(q1).Find(&data).Error; err != nil {
return data, err
}
return data, nil
}
func (r *utilsRepository) GetAppCategory() ([]models.AppCategory, error) {
var data []models.AppCategory
query := `SELECT * FROM app_category WHERE status = 'Active' ORDER BY sortorder ASC`
if err := r.db.Raw(query).Scan(&data).Error; err != nil {
return nil, err
}
return data, nil
}

27
routes/customerroutes.go Normal file
View File

@@ -0,0 +1,27 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterCustomerRoutes(api fiber.Router, f *facade.Facade) {
customer := api.Group("/v1/mob/customers")
customer.Get("/getbyid", f.CustomerController.GetCustomer)
customer.Put("/update", f.CustomerController.UpdateCustomer)
customer.Get("/getcustomerlocation", f.CustomerController.GetCustomerLocations)
customer.Post("/createlocations", f.CustomerController.CreateCustomerLocation)
customer.Post("/createcustomerrequest", f.CustomerController.CreateCustomerRequest)
customer.Get("/getcustomerrequests", f.CustomerController.GetCustomerRequests)
customer.Get("/gettenantcustomers", f.CustomerController.GetTenantCustomers)
customer.Get("/search", f.CustomerController.SearchCustomer)
customer.Post("/login", f.CustomerController.CustomerLogin)
customer.Post("/create", f.CustomerController.CreateCustomer)
customer = api.Group("/v1/web/customers")
customer.Get("/gettenantcustomers", f.CustomerController.GetTenantCustomers)
}

View File

@@ -0,0 +1,30 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterDeliveriesRoutes(api fiber.Router, f *facade.Facade) {
deliveries := api.Group("/v1/web/deliveries")
deliveries.Post("/createdeliveries", f.DeliveriesController.CreateDeliveries)
deliveries.Put("/updatedelivery", f.DeliveriesController.UpdateDelivery)
deliveries.Get("/deliverysummary", f.DeliveriesController.GetDeliverySummary)
deliveries.Get("/getdeliveryinsight", f.DeliveriesController.GetDeliveryInsight)
deliveries.Get("/getlocationsummary", f.DeliveriesController.GetLocationDeliverySummary)
deliveries.Get("/getreportsummary", f.DeliveriesController.GetReportSummary)
deliveries.Get("/getridersummary", f.DeliveriesController.GetRiderSummary)
deliveries.Get("/getdeliveries", f.DeliveriesController.GetDeliveries)
deliveries = api.Group("/v1/mob/deliveries")
deliveries.Get("/deliverysummary", f.DeliveriesController.GetDeliverySummary)
deliveries.Get("/getdeliveries", f.DeliveriesController.GetDeliveries)
deliveries.Get("/getdeliveryqueues", f.DeliveriesController.GetDeliveryQueues)
deliveries.Put("/updatedelivery", f.DeliveriesController.UpdateDelivery)
deliveries.Post("/createdeliveries", f.DeliveriesController.CreateDeliveries)
}

34
routes/orderroutes.go Normal file
View File

@@ -0,0 +1,34 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterOrderRoutes(api fiber.Router, f *facade.Facade) {
orders := api.Group("/v1/web/orders")
orders.Get("tenant/getorders", f.OrderController.GetOrders)
orders.Get("partner/getorders", f.OrderController.GetOrders)
orders.Get("customer/getorders", f.OrderController.GetOrders)
orders.Get("user/getorders", f.OrderController.GetOrders)
orders.Get("admin/getorders", f.OrderController.GetOrders)
orders.Get("/getorders", f.OrderController.GetOrders)
orders.Get("/getordersummary", f.OrderController.GetOrderSummary)
orders.Get("/getlocationsummary", f.OrderController.GetlocationOrderSummary)
orders.Get("/getorderinsight", f.OrderController.GetOrderInsights)
orders.Get("/getorderdetails", f.OrderController.GetOrderDetails)
orders.Put("/updateorder", f.OrderController.UpdateOrder)
orders.Post("/createorder", f.OrderController.CreateOrderv3)
orders = api.Group("/v1/mob/orders")
orders.Post("/createorder", f.OrderController.CreateOrderv3)
orders.Get("/getcustomerorders", f.OrderController.GetCustomerOrders)
orders.Get("tenant/getorders", f.OrderController.GetOrders)
orders.Put("/updateorder", f.OrderController.UpdateOrder)
orders.Get("/getorderdetails", f.OrderController.GetOrderDetails)
}

26
routes/partnerroutes.go Normal file
View File

@@ -0,0 +1,26 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterPartnerRoutes(api fiber.Router, f *facade.Facade) {
partner := api.Group("/v1/web/partners")
partner.Get("/getriders", f.PartnerController.GetActiveRiders)
partner.Get("/getpartners", f.PartnerController.GetPartners)
partner.Get("/getridershifts", f.PartnerController.GetRiderShifts)
partner.Get("/getlocations", f.PartnerController.GetLocationConfig)
partner.Get("/getriderlogs", f.PartnerController.GetRiderLogs)
partner = api.Group("/v1/mob/partners")
partner.Get("/getpartners", f.PartnerController.GetPartners)
partner.Get("/getriderlogs", f.PartnerController.GetRiderLogs)
partner.Get("/getriderinfo", f.PartnerController.GetRiderInfo)
partner.Get("/getriders", f.PartnerController.GetActiveRiders)
}

41
routes/productroutes.go Normal file
View File

@@ -0,0 +1,41 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterProductRoutes(api fiber.Router, f *facade.Facade) {
products := api.Group("/v1/web/products")
products.Get("/getproductsubcategories", f.ProductController.GetProductSubCategory)
products.Get("/getproductscount", f.ProductController.GetProductCount)
products.Get("/getproductcategories", f.ProductController.GetProductCategory)
products.Get("/getproductvariants", f.ProductController.GetProductVariants)
products.Get("/getcatalougeproducts", f.ProductController.GetCatalougeProducts)
products.Get("/getproductstocks", f.ProductController.GetProductStocks)
products.Post("/createproductstock", f.ProductController.CreateProductStock)
products.Post("/create", f.ProductController.CreateProduct)
products.Put("/update", f.ProductController.UpdateProduct)
products.Delete("/delete", f.ProductController.DeleteProduct)
products.Get("/getstockstatement", f.ProductController.GetStockStatement)
products.Get("/getlocationproducts", f.ProductController.GetLocationProducts)
products.Get("/getlocationproductsummary", f.ProductController.GetLocationProductSummary)
products.Get("/getallproducts", f.ProductController.GetAllProducts)
products.Put("/updateproductlocation", f.ProductController.UpdateProductLocation)
products.Post("/createproductlocation", f.ProductController.CreateProductLocation)
products.Post("/createproductvariant", f.ProductController.CreateProductVariant)
products = api.Group("/v1/mob/products")
products.Get("/getproductbyvariant", f.ProductController.GetProductByVariant)
products.Get("/getproductsubcategories", f.ProductController.GetProductSubCategory)
products.Get("/getallproducts", f.ProductController.GetAllProducts)
products.Get("/getproductsbysubcategory", f.ProductController.GetProductsBySubcategory)
products.Put("/update", f.ProductController.UpdateProduct)
products.Get("/getlocationproducts", f.ProductController.GetLocationProducts)
products.Put("/updateproductlocation", f.ProductController.UpdateProductLocation)
}

21
routes/routes.go Normal file
View File

@@ -0,0 +1,21 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterRoutes(app *fiber.App, f *facade.Facade) {
api := app.Group("/live/api")
RegisterUserRoutes(api, f)
RegisterProductRoutes(api, f)
RegisterOrderRoutes(api, f)
RegisterDeliveriesRoutes(api, f)
RegisterUtilsRoutes(api, f)
RegisterTenantRoutes(api, f)
RegisterPartnerRoutes(api, f)
RegisterCustomerRoutes(api, f)
}

38
routes/tenantroutes.go Normal file
View File

@@ -0,0 +1,38 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterTenantRoutes(api fiber.Router, f *facade.Facade) {
tenant := api.Group("/v1/web/tenants")
tenant.Get("/search", f.TenantController.SearchTenant)
tenant.Get("/searchbykeyword", f.TenantController.GetTenantByKeyword)
tenant.Get("/getalltenants", f.TenantController.GetAllTenants)
tenant.Get("/gettenantlocations", f.TenantController.GetTenantLocations)
tenant.Post("/createtenantcustomer", f.TenantController.CreateTenantCustomer)
tenant.Put("/updatelocation", f.TenantController.UpdateLocation)
tenant.Post("/createlocation", f.TenantController.CreateLocation)
tenant.Post("/createtenantlocation", f.TenantController.CreateTenantLocation)
tenant.Put("/updatetenantlocation", f.TenantController.UpdateTenantLocation)
tenant = api.Group("/v1/mob/tenants")
tenant.Get("/gettenantslot", f.TenantController.GetTenantSlot)
tenant.Get("/searchbykeyword", f.TenantController.GetTenantByKeyword)
tenant.Post("/createtenantcustomer", f.TenantController.CreateTenantCustomer)
tenant.Get("/getcustomertenants", f.TenantController.GetCustomerTenants)
tenant.Get("/gettenantlocations", f.TenantController.GetTenantLocations)
tenant.Get("/gettenantpricing", f.TenantController.GetTenantPricing)
tenant.Put("/updatelocation", f.TenantController.UpdateLocation)
tenant.Post("/createlocation", f.TenantController.CreateLocation)
tenant.Get("/getstaffs", f.TenantController.GetStaffs)
tenant.Post("/createstaff", f.TenantController.CreateStaff)
tenant.Post("/createtenantuser", f.TenantController.CreateTenantUser)
tenant.Get("/gettenantinfo", f.TenantController.GetTenantInfo)
}

24
routes/userroutes.go Normal file
View File

@@ -0,0 +1,24 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterUserRoutes(api fiber.Router, f *facade.Facade) {
users := api.Group("/v1/web/users")
users.Get("/getallusers", f.UserController.GetAllUsers)
users.Get("/getusers", f.UserController.GetUserInfo)
users.Post("/applogin", f.UserController.AppLogin)
users.Post("/create", f.UserController.CreateUser)
users.Post("/tenant/weblogin", f.UserController.TenantWebLogin)
users.Put("/update", f.UserController.UpdateStaff)
users = api.Group("/v1/mob/users")
users.Post("/tenant/login", f.UserController.Login)
users.Get("/getusers", f.UserController.GetUserInfo)
users.Post("/create", f.UserController.CreateUser)
users.Put("/update", f.UserController.UpdateStaff)
}

29
routes/utilsroutes.go Normal file
View File

@@ -0,0 +1,29 @@
package routes
import (
"nearle/facade"
"github.com/gofiber/fiber/v2"
)
func RegisterUtilsRoutes(api fiber.Router, f *facade.Facade) {
utils := api.Group("/v1/web/utils")
utils.Get("/getapptypes", f.UtilsController.GetAppTypes)
// utils.Post("/notifyuser", f.UtilsController.NotifyUser)
utils.Get("/getsubcategories", f.UtilsController.GetSubcategories)
utils.Get("/getapplocations", f.UtilsController.GetApplocations)
utils.Get("/getappcategories", f.UtilsController.GetAppCategory)
utils = api.Group("/v1/mob/utils")
utils.Get("/getapplocationconfig", f.UtilsController.GetApplocationConfig)
// utils.Post("/notifyadmin", f.UtilsController.NotifyAdmin)
utils.Get("/getapplocations", f.UtilsController.GetApplocations)
utils.Get("/getapptypes", f.UtilsController.GetAppTypes)
utils.Get("/getappconfig", f.UtilsController.GetAppConfig)
utils.Get("/getsubcategories", f.UtilsController.GetSubcategories)
utils.Get("/getappcategories", f.UtilsController.GetAppCategory)
}

148
services/customerService.go Normal file
View File

@@ -0,0 +1,148 @@
package services
import (
"errors"
"nearle/models"
"nearle/repositories"
"net/http"
"strconv"
)
type CustomerService interface {
GetCustomer(cid int, cno string) (*models.CustomerInfo, error)
UpdateCustomer(input models.Customers) models.Result
GetCustomerLocations(cid int) models.CustomerLocationResult
CreateCustomerLocation(input models.Customerlocations) (int, error)
CreateCustomerRequest(req models.CustomerRequest) (models.CustomerRequest, error)
GetCustomerRequests(customerIDStr string, pageNo, pageSize int) ([]models.CustomerRequest, int64, error)
GetTenantCustomers(tid, lid, pageno, pagesize int, keyword string) []models.CustomerInfo
SearchCustomer(keyword string, tid int) []models.CustomerInfo
CreateCustomer(input models.Customers) (models.CustomerInfo, error)
LoginCustomer(contactNo string) (*models.Customers, error)
}
type customerService struct {
repo repositories.CustomerRepository
}
func NewCustomerService(repo repositories.CustomerRepository) CustomerService {
return &customerService{repo: repo}
}
func (s *customerService) GetCustomer(cid int, cno string) (*models.CustomerInfo, error) {
return s.repo.GetCustomer(cid, cno)
}
func (s *customerService) UpdateCustomer(input models.Customers) models.Result {
err := s.repo.UpdateCustomer(input)
if err != nil {
return models.Result{
Code: http.StatusConflict,
Status: false,
Message: "Update Customer Failed",
}
}
return models.Result{
Code: http.StatusAccepted,
Status: true,
Message: "Customer update successful",
}
}
func (s *customerService) CreateCustomerLocation(input models.Customerlocations) (int, error) {
return s.repo.CreateCustomerLocation(input)
}
func (s *customerService) GetCustomerLocations(cid int) models.CustomerLocationResult {
data, err := s.repo.GetCustomerLocations(cid)
if err != nil {
return models.CustomerLocationResult{
Code: http.StatusInternalServerError,
Status: false,
Message: "Failed to fetch customer locations",
Details: []models.Customerlocations{},
}
}
return models.CustomerLocationResult{
Code: http.StatusOK,
Status: true,
Message: "Successful",
Details: data,
}
}
func (s *customerService) CreateCustomerRequest(req models.CustomerRequest) (models.CustomerRequest, error) {
err := s.repo.CreateCustomerRequest(&req)
if err != nil {
return models.CustomerRequest{}, err
}
return req, nil
}
func (s *customerService) GetCustomerRequests(customerIDStr string, pageNo, pageSize int) ([]models.CustomerRequest, int64, error) {
if pageNo < 1 {
pageNo = 1
}
if pageSize < 1 {
pageSize = 10
}
var customerID int
var err error
if customerIDStr != "" {
customerID, err = strconv.Atoi(customerIDStr)
if err != nil {
return nil, 0, errors.New("invalid customerid")
}
}
return s.repo.GetCustomerRequests(customerID, pageNo, pageSize)
}
func (s *customerService) GetTenantCustomers(tid, lid, pageno, pagesize int, keyword string) []models.CustomerInfo {
return s.repo.GetTenantCustomers(tid, lid, pageno, pagesize, keyword)
}
func (s *customerService) SearchCustomer(keyword string, tid int) []models.CustomerInfo {
return s.repo.SearchCustomer(keyword, tid)
}
func (s *customerService) CreateCustomer(input models.Customers) (models.CustomerInfo, error) {
cid := s.repo.CheckCustomer(input.Contactno)
if cid != 0 {
input.Customerid = cid
tcid := s.repo.CheckTenantCustomer(input.Customerid, input.Tenantid)
if tcid != 0 {
return models.CustomerInfo{}, errors.New("Customer Already available")
}
s.repo.CreateTenantCustomer(input)
} else {
cid = s.repo.CreateCustomer(input)
}
result, err := s.repo.GetCustomer(cid, "")
if err != nil {
return models.CustomerInfo{}, err
}
return *result, nil
}
func (s *customerService) LoginCustomer(contactNo string) (*models.Customers, error) {
customer, err := s.repo.GetCustomerByContactNo(contactNo)
if err != nil {
return nil, err
}
if customer.Customerid == 0 {
return nil, nil // handle "not found" in controller
}
return customer, nil
}

View File

@@ -0,0 +1,87 @@
package services
import (
"nearle/models"
"nearle/repositories"
)
type DeliveriesService interface {
CreateDeliveriesService(data []models.Deliveries) error
UpdateDeliveryService(data models.UpdateDeliveryStatus) error
GetDeliverySummary(tid, pid, uid, aid, lid int, fdate, tdate string) (models.DeliverySummary, error)
GetDeliveryInsightService(tid int) ([]models.OrderInsightv1, error)
GetLocationDeliverySummary(tenantID int) ([]models.Ordersummarylocation, error)
GetReportSummary(tid, pid, uid, aid int, fdate, tdate string) ([]models.ReportSummary, error)
GetRiderSummary(aid, pid, tid int, fdate, tdate string) ([]models.Ridersummary, error)
GetDeliveries(input models.DeliveryQuery) []models.Deliveryinfo
GetDeliveryQueues(uid int, fdate, tdate string) ([]models.Deliveryinfo, error)
}
type deliveriesService struct {
repo repositories.DeliveriesRepository
}
func NewDeliveriesService(repo repositories.DeliveriesRepository) DeliveriesService {
return &deliveriesService{repo: repo}
}
func (s *deliveriesService) CreateDeliveriesService(data []models.Deliveries) error {
return s.repo.CreateDeliveries(data)
}
func (s *deliveriesService) UpdateDeliveryService(data models.UpdateDeliveryStatus) error {
return s.repo.UpdateDelivery(data)
}
func (s *deliveriesService) GetDeliverySummary(tid, pid, uid, aid, lid int, fdate, tdate string) (models.DeliverySummary, error) {
return s.repo.GetDeliverySummary(tid, pid, uid, aid, lid, fdate, tdate)
}
func (s *deliveriesService) GetDeliveryInsightService(tid int) ([]models.OrderInsightv1, error) {
return s.repo.GetDeliveryInsight(tid)
}
func (s *deliveriesService) GetLocationDeliverySummary(tenantID int) ([]models.Ordersummarylocation, error) {
return s.repo.GetLocationDeliverySummary(tenantID)
}
func (s *deliveriesService) GetReportSummary(tid, pid, uid, aid int, fdate, tdate string) ([]models.ReportSummary, error) {
return s.repo.GetReportSummary(tid, pid, uid, aid, fdate, tdate)
}
func (s *deliveriesService) GetRiderSummary(aid, pid, tid int, fdate, tdate string) ([]models.Ridersummary, error) {
return s.repo.GetRiderSummary(aid, pid, tid, fdate, tdate)
}
func (s *deliveriesService) GetDeliveries(input models.DeliveryQuery) []models.Deliveryinfo {
switch {
case input.Tenantid != 0 && input.Locationid != 0:
return s.repo.GetTenantLocationDeliveries(input) // 👈 NEW
case input.Tenantid != 0:
return s.repo.GetTenantDeliveries(input)
case input.Partnerid != 0:
return s.repo.GetPartnerDeliveries(input)
case input.Customerid != 0:
return s.repo.GetCustomerDeliveries(input)
case input.Applocationid != 0:
return s.repo.GetAdminDeliveries(input)
case input.UserID != 0:
return s.repo.GetUserDeliveries(input)
case input.Appuserid != 0:
return s.repo.GetAppUserDeliveries(input)
default:
return s.repo.GetDeliveries(input)
}
}
func (s *deliveriesService) GetDeliveryQueues(uid int, fdate, tdate string) ([]models.Deliveryinfo, error) {
return s.repo.GetDeliveryQueues(uid, fdate, tdate)
}

88
services/orderService.go Normal file
View File

@@ -0,0 +1,88 @@
package services
import (
"nearle/models"
"nearle/repositories"
)
type OrderService interface {
GetTenantOrders(input models.DeliveryQuery) ([]models.OrderInfo, error)
GetPartnerOrders(stat, fdate, tdate string, pid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error)
GetCustomerOrders(stat, fdate, tdate string, cid, mid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error)
GetAdminOrders(stat, fdate, tdate string, aid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error)
GetUserOrders(stat, fdate, tdate string, uid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error)
GetAllOrders(stat, fdate, tdate string, pageno, pagesize int, keyword string) ([]models.OrderInfo, error)
GetOrderSummary(tid, pid, cid, lid int, fdate, tdate string) ([]models.Ordersummarydaily, error)
GetLocationOrderSummary(tenantID int) ([]models.Ordersummarylocation, error)
GetOrderInsights(tenantID int) ([]models.OrderInsightv1, error)
GetOrderDetails(orderHeaderID int) ([]models.OrderDetails, error)
UpdateOrder(order *models.Orders) error
CreateOrder(order models.Orders) (models.Orders, error)
GetCustomerOrdersv3(customerID, tenantID, moduleID, fromDate, toDate, orderStatus, keyword string, pageSize, offset int) ([]models.CustomerOrder, error)
GetTenantLocationOrders(input models.DeliveryQuery) ([]models.OrderInfo, error)
}
type orderService struct {
repo repositories.OrderRepository
}
func NewOrderService(repo repositories.OrderRepository) OrderService {
return &orderService{repo: repo}
}
func (s *orderService) GetTenantOrders(input models.DeliveryQuery) ([]models.OrderInfo, error) {
return s.repo.GetTenantOrders(input)
}
func (s *orderService) GetPartnerOrders(stat, fdate, tdate string, pid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error) {
return s.repo.GetPartnerOrders(stat, fdate, tdate, pid, pageno, pagesize, keyword)
}
func (s *orderService) GetCustomerOrders(stat, fdate, tdate string, cid, mid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error) {
return s.repo.GetCustomerOrders(stat, fdate, tdate, cid, mid, pageno, pagesize, keyword)
}
func (s *orderService) GetAdminOrders(stat, fdate, tdate string, aid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error) {
return s.repo.GetAdminOrders(stat, fdate, tdate, aid, pageno, pagesize, keyword)
}
func (s *orderService) GetUserOrders(stat, fdate, tdate string, uid, pageno, pagesize int, keyword string) ([]models.OrderInfo, error) {
return s.repo.GetUserOrders(stat, fdate, tdate, uid, pageno, pagesize, keyword)
}
func (s *orderService) GetAllOrders(stat, fdate, tdate string, pageno, pagesize int, keyword string) ([]models.OrderInfo, error) {
return s.repo.GetAllOrders(stat, fdate, tdate, pageno, pagesize, keyword)
}
func (s *orderService) GetOrderSummary(tid, pid, cid, lid int, fdate, tdate string) ([]models.Ordersummarydaily, error) {
return s.repo.GetOrderSummary(tid, pid, cid, lid, fdate, tdate)
}
func (s *orderService) GetLocationOrderSummary(tenantID int) ([]models.Ordersummarylocation, error) {
return s.repo.GetLocationOrderSummary(tenantID)
}
func (s *orderService) GetOrderInsights(tenantID int) ([]models.OrderInsightv1, error) {
return s.repo.GetOrderInsights(tenantID)
}
func (s *orderService) GetOrderDetails(orderHeaderID int) ([]models.OrderDetails, error) {
return s.repo.GetOrderDetails(orderHeaderID)
}
func (s *orderService) UpdateOrder(order *models.Orders) error {
return s.repo.UpdateOrder(order)
}
func (s *orderService) CreateOrder(order models.Orders) (models.Orders, error) {
return s.repo.CreateOrder(order)
}
func (s *orderService) GetCustomerOrdersv3(customerID, tenantID, moduleID, fromDate, toDate, orderStatus, keyword string, pageSize, offset int) ([]models.CustomerOrder, error) {
return s.repo.GetCustomerOrdersv3(customerID, tenantID, moduleID, fromDate, toDate, orderStatus, keyword, pageSize, offset)
}
func (s *orderService) GetTenantLocationOrders(input models.DeliveryQuery) ([]models.OrderInfo, error) {
return s.repo.GetTenantLocationOrders(input)
}

View File

@@ -0,0 +1,55 @@
package services
import (
"nearle/models"
"nearle/repositories"
)
type PartnerService interface {
GetActiveRiders(partnerid, aid, uid, tid int) ([]models.RiderInfo, error)
GetPartners(aid, pid, uid int) ([]models.Partnerinfo, error)
GetRiderShifts(aid int) ([]models.Ridershifts, error)
GetLocationConfig(uid, cid int) ([]models.Locationconfigs, error)
GetRiderLogs(pid, aid int, fdate, tdate string) ([]models.RiderlogDetails, error)
GetRiderInfo(userid int) (models.RiderInfo, error)
}
type partnerService struct {
repo repositories.PartnerRepository
}
func NewPartnerService(repo repositories.PartnerRepository) PartnerService {
return &partnerService{repo: repo}
}
func (s *partnerService) GetActiveRiders(partnerid, aid, uid, tid int) ([]models.RiderInfo, error) {
return s.repo.GetActiveRiders(partnerid, aid, uid, tid)
}
func (s *partnerService) GetPartners(aid, pid, uid int) ([]models.Partnerinfo, error) {
result, err := s.repo.GetPartners(aid, pid, uid)
if err != nil {
return nil, err
}
return result, nil
}
func (s *partnerService) GetRiderShifts(aid int) ([]models.Ridershifts, error) {
return s.repo.GetRiderShifts(aid)
}
func (s *partnerService) GetLocationConfig(uid, cid int) ([]models.Locationconfigs, error) {
return s.repo.GetLocationConfig(uid, cid)
}
func (s *partnerService) GetRiderLogs(pid, aid int, fdate, tdate string) ([]models.RiderlogDetails, error) {
return s.repo.GetRiderLogs(pid, aid, fdate, tdate)
}
func (s *partnerService) GetRiderInfo(userid int) (models.RiderInfo, error) {
return s.repo.GetRiderInfo(userid)
}

208
services/productService.go Normal file
View File

@@ -0,0 +1,208 @@
package services
import (
"nearle/models"
"nearle/repositories"
"time"
)
type ProductService interface {
GetProductSubCategory(categoryID, tenantID int) ([]models.ProductSubCategory, error)
GetProductCount(tenantID, categoryID, subcategoryID int, approve string) ([]models.Productcount, error)
GetProductCategory() ([]models.ProductCategory, error)
GetProductVariants(tenantID, subcategoryID int) ([]models.Productvariant, error)
GetCatalougeProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Products, error)
GetProductStocks(tenantID, locationID string) ([]models.Productstocks, error)
UpdateProductStatus(productIDs []int, status string) error
CreateProductStock(stocks []models.Productstock) error
CreateProduct(product models.Products) error
UpdateProduct(product models.Products) error
DeleteProduct(productID int) error
GetStockStatement(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Productstockstatement, error)
GetLocationProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Locationproducts, error)
GetLocationProductSummary(tenantID, locationID int) ([]models.ProductSummary, error)
FetchFilteredProducts(categoryID, subcategoryID, productID, applocationID, tenantID, locationID int, keyword, productStatus, approve string, pageno, pagesize int) ([]models.Tenantproducts, error)
GetProductByVariant(tenantid, variantid int) ([]models.Products, error)
GetProductsBySubcategory(params models.ProductFilter) (map[string]interface{}, error)
UpdateProductLocation(input models.Productlocations) error
CreateProductLocation(input []models.Productlocations) error
CreateProductVariant(input models.Productvariant) error
}
type productService struct {
repo repositories.ProductRepository
}
func NewProductService(repo repositories.ProductRepository) ProductService {
return &productService{repo: repo}
}
func (s *productService) GetProductSubCategory(categoryID, tenantID int) ([]models.ProductSubCategory, error) {
return s.repo.GetProductSubCategory(categoryID, tenantID)
}
func (s *productService) GetProductCount(tenantID, categoryID, subcategoryID int, approve string) ([]models.Productcount, error) {
return s.repo.GetProductCount(tenantID, categoryID, subcategoryID, approve)
}
func (s *productService) GetProductCategory() ([]models.ProductCategory, error) {
return s.repo.GetProductCategory()
}
func (s *productService) GetProductVariants(tenantID, subcategoryID int) ([]models.Productvariant, error) {
return s.repo.GetProductVariants(tenantID, subcategoryID)
}
func (s *productService) GetCatalougeProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Products, error) {
return s.repo.GetCatalougeProducts(tenantID, locationID, subcategoryID, pageno, pagesize, keyword)
}
func (s *productService) GetProductStocks(tenantID, locationID string) ([]models.Productstocks, error) {
return s.repo.GetProductStocks(tenantID, locationID)
}
func (s *productService) CreateProductStock(stocks []models.Productstock) error {
for i := range stocks {
stocks[i].Stockdate = time.Now()
}
if err := s.repo.CreateProductStock(stocks); err != nil {
return err
}
idMap := make(map[int]struct{})
var productIDs []int
for _, s := range stocks {
if s.Productid > 0 {
if _, exists := idMap[s.Productid]; !exists {
idMap[s.Productid] = struct{}{}
productIDs = append(productIDs, s.Productid)
}
}
}
if len(productIDs) > 0 {
if err := s.repo.UpdateProductStatus(productIDs, "available"); err != nil {
return err
}
}
return nil
}
func (s *productService) UpdateProductStatus(productIDs []int, status string) error {
return s.repo.UpdateProductStatus(productIDs, status)
}
func (s *productService) CreateProduct(product models.Products) error {
return s.repo.CreateProduct(product)
}
func (s *productService) UpdateProduct(product models.Products) error {
return s.repo.UpdateProduct(product)
}
func (s *productService) DeleteProduct(productID int) error {
return s.repo.DeleteProduct(productID)
}
func (s *productService) GetStockStatement(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Productstockstatement, error) {
return s.repo.GetStockStatement(tenantID, locationID, subcategoryID, pageno, pagesize, keyword)
}
func (s *productService) GetLocationProducts(tenantID, locationID, subcategoryID, pageno, pagesize int, keyword string) ([]models.Locationproducts, error) {
return s.repo.GetLocationProducts(tenantID, locationID, subcategoryID, pageno, pagesize, keyword)
}
func (s *productService) GetLocationProductSummary(tenantID, locationID int) ([]models.ProductSummary, error) {
return s.repo.GetLocationProductSummary(tenantID, locationID)
}
func (s *productService) FetchFilteredProducts(categoryID, subcategoryID, productID, applocationID, tenantID, locationID int, keyword, productStatus,
approve string, pageno, pagesize int) ([]models.Tenantproducts, error) {
return s.repo.FetchFilteredProducts(categoryID, subcategoryID, productID, applocationID, tenantID, locationID, keyword, productStatus, approve, pageno, pagesize)
}
func (s *productService) GetProductByVariant(tenantid, variantid int) ([]models.Products, error) {
var data []models.Products
result, err := s.repo.GetProductByVariant(tenantid, variantid)
if err != nil {
return nil, err
}
data = result
return data, nil
}
func (s *productService) GetProductsBySubcategory(params models.ProductFilter) (map[string]interface{}, error) {
subcategories, err := s.repo.GetSubcategories(params.CategoryID)
if err != nil {
return nil, err
}
products, err := s.repo.GetProducts(params)
if err != nil {
return nil, err
}
var details []models.SubcategoryProductResponse
var uncategorized []models.Products
for _, sub := range subcategories {
var subProducts []models.Products
for _, p := range products {
if p.Subcategoryid == sub.Subcategoryid {
subProducts = append(subProducts, p)
}
}
if len(subProducts) > 0 {
details = append(details, models.SubcategoryProductResponse{
SubcategoryID: sub.Subcategoryid,
SubcategoryName: sub.Subcategoryname,
Image: sub.Image,
Products: subProducts,
})
}
}
for _, p := range products {
if p.Subcategoryid == 0 {
uncategorized = append(uncategorized, p)
}
}
if len(uncategorized) > 0 {
details = append(details, models.SubcategoryProductResponse{
SubcategoryID: 0,
SubcategoryName: "Uncategorized",
Products: uncategorized,
})
}
if params.TenantID > 0 {
tenantInfo, err := s.repo.GetTenantInfo(params.TenantID, params.AppLocationID)
if err == nil && tenantInfo != nil {
tenantInfo["details"] = details
return tenantInfo, nil
}
}
return map[string]interface{}{"details": details}, nil
}
func (s *productService) UpdateProductLocation(input models.Productlocations) error {
return s.repo.UpdateProductLocation(input)
}
func (s *productService) CreateProductLocation(input []models.Productlocations) error {
return s.repo.CreateProductLocation(input)
}
func (s *productService) CreateProductVariant(input models.Productvariant) error {
return s.repo.CreateProductVariant(input)
}

162
services/tenantService.go Normal file
View File

@@ -0,0 +1,162 @@
package services
import (
"errors"
"nearle/models"
"nearle/repositories"
"net/http"
)
type TenantService interface {
SearchTenant(status, keyword string) ([]models.Tenantinfo, error)
GetAllTenants(pageno, pagesize, aid int, status, tenanttype, keyword string) ([]models.Tenantinfo, error)
GetTenantLocations(tid int) ([]models.Tenantlocations, error)
GetTenantSlot() (models.Tenantslot, error)
CreateTenantCustomer(req models.CreateTenantCustomerRequest) (*models.Tenantcustomer, error)
GetCustomerTenants(customerID int, categoryID int, tenantFlag int) (*models.CustomerTenantResponse, error)
GetTenantPricing(tid, aid int) (models.Tenantpricing, error)
UpdateLocation(input models.Tenantlocations) error
CreateLocation(data models.Tenantlocations) error
GetStaffs(tid int) ([]models.StaffInfo, error)
CreateStaff(user models.User) error
UpdateStaff(user models.User) error
CreateTenantLocation(data models.Tenantlocations) map[string]interface{}
UpdateTenantLocation(data models.Tenantlocations) map[string]interface{}
CreateTenantUser(data models.Tenants) (models.UserInfo, error)
GetTenantByID(tid int, locationid int) (models.Tenantinfo, error)
GetTenantByKeyword(keyword string) ([]models.TenantSearch, error)
}
type tenantService struct {
repo repositories.TenantRepository
}
func NewTenantService(repo repositories.TenantRepository) TenantService {
return &tenantService{repo: repo}
}
func (s *tenantService) SearchTenant(status, keyword string) ([]models.Tenantinfo, error) {
return s.repo.SearchTenant(status, keyword)
}
func (s *tenantService) GetAllTenants(pageno, pagesize, aid int, status, tenanttype, keyword string) ([]models.Tenantinfo, error) {
return s.repo.GetAllTenants(pageno, pagesize, aid, status, tenanttype, keyword)
}
func (s *tenantService) GetTenantLocations(tid int) ([]models.Tenantlocations, error) {
return s.repo.GetTenantLocations(tid)
}
func (s *tenantService) GetTenantSlot() (models.Tenantslot, error) {
return s.repo.GetTenantSlot()
}
func (s *tenantService) CreateTenantCustomer(req models.CreateTenantCustomerRequest) (*models.Tenantcustomer, error) {
tenantCustomer := models.Tenantcustomer{
TenantID: req.TenantID,
LocationID: req.LocationID,
CustomerID: req.CustomerID,
CustomerLocationID: req.CustomerLocationID,
Status: req.Status,
}
return s.repo.CreateTenantCustomer(tenantCustomer)
}
func (s *tenantService) GetCustomerTenants(customerID int, categoryID int, tenantFlag int) (*models.CustomerTenantResponse, error) {
details, err := s.repo.GetCustomerTenants(customerID, categoryID, tenantFlag)
if err != nil {
return nil, err
}
return &models.CustomerTenantResponse{
Details: details,
}, nil
}
func (s *tenantService) GetTenantPricing(tid, aid int) (models.Tenantpricing, error) {
result, err := s.repo.GetTenantPricing(tid, aid)
if err != nil {
return models.Tenantpricing{}, err
}
return *result, nil
}
func (s *tenantService) UpdateLocation(input models.Tenantlocations) error {
return s.repo.UpdateLocation(input)
}
func (s *tenantService) CreateLocation(data models.Tenantlocations) error {
return s.repo.CreateLocation(data)
}
func (s *tenantService) GetStaffs(tid int) ([]models.StaffInfo, error) {
return s.repo.GetStaffs(tid)
}
func (s *tenantService) CreateStaff(user models.User) error {
return s.repo.CreateStaff(user)
}
func (s *tenantService) UpdateStaff(user models.User) error {
return s.repo.UpdateStaff(user)
}
func (s *tenantService) CreateTenantLocation(data models.Tenantlocations) map[string]interface{} {
err := s.repo.CreateTenantLocation(data)
if err != nil {
return map[string]interface{}{
"code": http.StatusConflict,
"message": err.Error(),
"status": false,
}
}
return map[string]interface{}{
"code": http.StatusCreated,
"message": "Tenant Location Successfully Created",
"status": true,
}
}
func (s *tenantService) UpdateTenantLocation(data models.Tenantlocations) map[string]interface{} {
err := s.repo.UpdateTenantLocation(data)
if err != nil {
return map[string]interface{}{
"status": false,
"code": http.StatusConflict,
"message": err.Error(),
}
}
return map[string]interface{}{
"status": true,
"code": http.StatusAccepted,
"message": "Tenant Location update successful",
}
}
func (s *tenantService) CreateTenantUser(data models.Tenants) (models.UserInfo, error) {
// ✅ Check if tenant already exists
exists := s.repo.CheckTenantByNo(data.Primarycontact)
if exists != 0 {
return models.UserInfo{}, errors.New("Tenant Already Exists")
}
// ✅ Create Tenant User
status, err := s.repo.CreateTenantUser(data)
if err != nil || !status {
return models.UserInfo{}, err
}
// ✅ Get user details by contact number
result := s.repo.GetUserByNo(data.Primarycontact)
return result, nil
}
func (s *tenantService) GetTenantByID(tid int, locationid int) (models.Tenantinfo, error) {
return s.repo.GetTenantByID(tid, locationid)
}
func (s *tenantService) GetTenantByKeyword(keyword string) ([]models.TenantSearch, error) {
return s.repo.GetTenantByKeyword(keyword)
}

267
services/userService.go Normal file
View File

@@ -0,0 +1,267 @@
package services
import (
"errors"
"nearle/models"
"nearle/repositories"
"strings"
"github.com/gofiber/fiber"
)
type UserService interface {
GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error)
GetUserByID(uid int) (models.UserInfo, error)
Login(user models.User) (models.UserInfo, error)
TenantLogin(user models.User) (models.TenantUserInfo, error)
UpdateStaff(user models.User) error
AppLogin(user models.User) (models.TenantUserInfo, fiber.Map, error)
CreateUser(user models.User) (models.UserInfo, error)
TenantWebLogin(user models.User) (models.TenantUserInfo, map[string]interface{})
}
type userService struct {
repo repositories.UserRepository
}
func NewUserService(repo repositories.UserRepository) UserService {
return &userService{repo: repo}
}
func (s *userService) GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error) {
return s.repo.GetAllUsers(roleID, tenantID, pageno, pagesize, keyword)
}
func (s *userService) GetUserByID(uid int) (models.UserInfo, error) {
return s.repo.GetUserByID(uid)
}
func (s *userService) Login(user models.User) (models.UserInfo, error) {
return s.repo.Login(user)
}
func (s *userService) TenantLogin(user models.User) (models.TenantUserInfo, error) {
uid, err := s.repo.FindUserID(user.Authname, user.Contactno, user.Configid)
if err != nil {
return models.TenantUserInfo{}, err
}
if uid == 0 {
return models.TenantUserInfo{}, errors.New("user not found")
}
return s.repo.GetTenantUserByID(uid)
}
func (s *userService) UpdateStaff(user models.User) error {
return s.repo.UpdateStaff(user)
}
func (s *userService) AppLogin(user models.User) (models.TenantUserInfo, fiber.Map, error) {
var uid int
var status, dbPassword string
// Get user by authname or contactno
if user.Authname != "" {
uid, dbPassword, status = s.repo.GetUserByAuthname(user.Authname, user.Configid)
} else if user.Contactno != "" {
uid, dbPassword, status = s.repo.GetUserByContactNo(user.Contactno, user.Configid)
} else {
resp := fiber.Map{
"code": 400,
"status": false,
"message": "authname or contactno required",
}
return models.TenantUserInfo{}, resp, errors.New("missing authname or contactno")
}
// Invalid user
if uid == 0 {
resp := fiber.Map{
"status": false,
"code": 409,
"message": "Invalid Email",
"tenantform": true,
}
return models.TenantUserInfo{}, resp, errors.New("invalid user")
}
// Inactive account
if status == "InActive" {
resp := fiber.Map{
"status": false,
"code": 403,
"message": "Inactive Account. Contact admin.",
}
return models.TenantUserInfo{}, resp, errors.New("inactive account")
}
// No password set
if strings.TrimSpace(dbPassword) == "" {
resp := fiber.Map{
"status": true,
"code": 409,
"message": "Please setup a password.",
"tenantform": true,
"details": fiber.Map{
"userid": uid,
"setup": true,
},
}
return models.TenantUserInfo{}, resp, nil
}
// Empty request password
if strings.TrimSpace(user.Password) == "" {
resp := fiber.Map{
"status": true,
"code": 401,
"message": "Password is required",
"tenantform": true,
}
return models.TenantUserInfo{}, resp, nil
}
// Incorrect password
if user.Password != dbPassword {
resp := fiber.Map{
"status": false,
"code": 401,
"message": "Incorrect password",
"tenantform": true,
}
return models.TenantUserInfo{}, resp, errors.New("incorrect password")
}
// Update FCM token
if user.Userfcmtoken != "" {
_ = s.repo.UpdateFCMToken(uid, user.Userfcmtoken)
}
// ✅ Fetch tenant user info
info := s.repo.GetTenantUserById(uid)
// ✅ Return success response
resp := fiber.Map{
"status": true,
"code": 200,
"message": "Login successful",
"details": info,
}
return info, resp, nil
}
func (s *userService) CreateUser(user models.User) (models.UserInfo, error) {
// Call repository to create user
userid, err := s.repo.CreateUser(user)
if err != nil {
return models.UserInfo{}, err
}
// Get user info by id
info, err := s.repo.GetUserById(userid)
if err != nil {
return models.UserInfo{}, err
}
return info, nil
}
func (s *userService) TenantWebLogin(user models.User) (models.TenantUserInfo, map[string]interface{}) {
tenantFormExists := true
uid, dbPassword, status, roleid := 0, "", "", 0
// Step 1: Login by authname or contactno
if user.Authname != "" {
uid, dbPassword, status, roleid = s.repo.GetUserLogin("authname", user.Authname, user.Configid)
} else if user.Contactno != "" {
uid, dbPassword, status, roleid = s.repo.GetUserLogin("contactno", user.Contactno, user.Configid)
} else {
return models.TenantUserInfo{}, map[string]interface{}{
"status": true,
"code": 400,
"message": "authname or contactno required",
}
}
// Step 2: Validate user
if uid == 0 {
return models.TenantUserInfo{}, map[string]interface{}{
"status": false,
"code": 409,
"message": "Invalid Email",
"tenantform": tenantFormExists,
}
}
if status == "InActive" {
return models.TenantUserInfo{}, map[string]interface{}{
"status": false,
"code": 403,
"message": "Inactive Account. Contact admin.",
}
}
if user.Roleid != roleid {
return models.TenantUserInfo{}, map[string]interface{}{
"status": false,
"code": 403,
"message": "Unauthorized email.",
}
}
// Step 3: Password checks
if strings.TrimSpace(dbPassword) == "" {
return models.TenantUserInfo{}, map[string]interface{}{
"status": true,
"code": 409,
"message": "Please setup a password.",
"tenantform": tenantFormExists,
"details": map[string]interface{}{
"userid": uid,
"setup": true,
},
}
}
if strings.TrimSpace(user.Password) == "" {
return models.TenantUserInfo{}, map[string]interface{}{
"status": true,
"code": 401,
"message": "Password is required",
"tenantform": tenantFormExists,
}
}
if user.Password != dbPassword {
return models.TenantUserInfo{}, map[string]interface{}{
"status": false,
"code": 401,
"message": "Incorrect password",
"tenantform": tenantFormExists,
}
}
user.Userid = uid
// Step 4: Update FCM if provided
if user.Userfcmtoken != "" {
_ = s.repo.UpdateUserFcmToken(uid, user.Userfcmtoken)
}
// Step 5: Get full tenant info
info := s.repo.GetTenantUserById(uid)
return info, map[string]interface{}{
"status": true,
"code": 200,
"message": "Login successful",
}
}

52
services/utilsService.go Normal file
View File

@@ -0,0 +1,52 @@
package services
import (
"nearle/models"
"nearle/repositories"
)
type UtilsService interface {
GetApptypes(tag string) ([]models.Apptypes, error)
SendNotification(token string, notification models.FcmNotification, data map[string]string) error
GetSubcategories(moduleid int, categoryid int) ([]models.Appsubcategories, error)
GetApplocations(aid int) ([]models.Applocations, error)
GetApplocationConfig(aid int) ([]models.Applocations, error)
GetAppConfig(configID int) (models.Appconfig, error)
GetAppCategory() ([]models.AppCategory, error)
}
type utilsService struct {
repo repositories.UtilsRepository
}
func NewUtilsService(repo repositories.UtilsRepository) UtilsService {
return &utilsService{repo: repo}
}
func (s *utilsService) GetApptypes(tag string) ([]models.Apptypes, error) {
return s.repo.GetApptypes(tag)
}
func (s *utilsService) SendNotification(token string, notification models.FcmNotification, data map[string]string) error {
return s.repo.SendNotification(token, notification, data)
}
func (s *utilsService) GetSubcategories(moduleid int, categoryid int) ([]models.Appsubcategories, error) {
return s.repo.GetSubcategories(moduleid, categoryid)
}
func (s *utilsService) GetApplocations(aid int) ([]models.Applocations, error) {
return s.repo.GetApplocations(aid)
}
func (s *utilsService) GetApplocationConfig(aid int) ([]models.Applocations, error) {
return s.repo.GetApplocationConfig(aid)
}
func (s *utilsService) GetAppConfig(configID int) (models.Appconfig, error) {
return s.repo.GetAppConfig(configID)
}
func (s *utilsService) GetAppCategory() ([]models.AppCategory, error) {
return s.repo.GetAppCategory()
}

51
utils/config.go Normal file
View File

@@ -0,0 +1,51 @@
package utils
import (
"fmt"
"os"
"github.com/spf13/viper"
)
func DevConfig() (Port, DBname, Password, Username, Host, key, secret string) {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
fmt.Println("fatal error config file: default \n", err)
os.Exit(1)
}
dbname := viper.GetString("DEV.DATABASE_NAME")
dbpassword := viper.GetString("DEV.DATABASE_PASSWORD")
dbusername := viper.GetString("DEV.DATABASE_USERNAME")
dbport := viper.GetString("DEV.DATABASE_PORT")
dbhost := viper.GetString("DEV.DATABASE_SERVER_HOST")
contextkey := viper.GetString("DEV.USER_CONTEXT_KEY")
jwtkey := viper.GetString("DEV.JWT_SECRET_KEY")
return dbport, dbname, dbpassword, dbusername, dbhost, contextkey, jwtkey
}
func LiveConfig() (Port, DBname, Password, Username, Host, key, secret string) {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
fmt.Println("fatal error config file: default \n", err)
os.Exit(1)
}
dbname := viper.GetString("APP.DATABASE_NAME")
dbpassword := viper.GetString("APP.DATABASE_PASSWORD")
dbusername := viper.GetString("APP.DATABASE_USERNAME")
dbport := viper.GetString("APP.DATABASE_PORT")
dbhost := viper.GetString("APP.DATABASE_SERVER_HOST")
contextkey := viper.GetString("APP.USER_CONTEXT_KEY")
jwtkey := viper.GetString("APP.JWT_SECRET_KEY")
return dbport, dbname, dbpassword, dbusername, dbhost, contextkey, jwtkey
}