package controllers import ( "nearle/db" "nearle/domain" "nearle/models" "nearle/utils" "net/http" "strconv" "strings" "github.com/gofiber/fiber/v2" ) const ( core = `SELECT COUNT(DISTINCT a.deliveryid) AS total, COUNT(DISTINCT CASE WHEN a.orderstatus = 'pending' THEN a.deliveryid END) AS pending, COUNT(DISTINCT CASE WHEN a.orderstatus = 'accepted' THEN a.deliveryid END) AS accepted, COUNT(DISTINCT CASE WHEN a.orderstatus = 'arrived' THEN a.deliveryid END) AS arrived, COUNT(DISTINCT CASE WHEN a.orderstatus = 'picked' THEN a.deliveryid END) AS picked, COUNT(DISTINCT CASE WHEN a.orderstatus = 'active' THEN a.deliveryid END) AS active, COUNT(DISTINCT CASE WHEN a.orderstatus = 'delivered' THEN a.deliveryid END) AS delivered, COUNT(DISTINCT CASE WHEN a.orderstatus = 'cancelled' THEN a.deliveryid END) AS cancelled, COUNT(DISTINCT CASE WHEN a.orderstatus = 'skipped' THEN a.deliveryid END) AS skipped` reports = `SELECT c.userid,e.firstname,e.lastname,e.contactno AS ridercontact,b.tenantid,b.tenantname,a.locationid, d.locationname, 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(CAST(COALESCE(NULLIF(c.kms, ''), '0') AS NUMERIC)), 2) AS kms, ROUND(SUM(CAST(COALESCE(NULLIF(c.actualkms, ''), '0') AS NUMERIC)), 2) AS actualkms, SUM(c.deliveryamt) AS charges, SUM(CASE WHEN c.orderstatus = 'delivered' THEN c.cumulativekms ELSE 0 END) AS cumulativekms, SUM(CASE WHEN c.orderstatus = 'delivered' THEN c.deliveryamt ELSE 0 END) AS deliveryamt, SUM(c.previouskms) AS previouskms, SUM(c.previouskms) AS previouskms, SUM(CAST(COALESCE(NULLIF(c.riderkms, ''), '0') AS NUMERIC)) AS riderkms, SUM(c.quantity) AS quantity, SUM(c.collectionamt) AS collectionamt, SUM(c.collectedamt) AS collectedamt, c.collectionstatus FROM tenants b right JOIN orders a ON b.tenantid = a.tenantid right JOIN deliveries c ON a.orderheaderid = c.orderheaderid LEFT JOIN tenantlocations d ON a.locationid = d.locationid LEFT JOIN app_users e ON e.userid = c.userid` Ridersummary = `SELECT a.userid, a.firstname, a.lastname, a.contactno AS ridercontact, MAX(b.tenantid) AS tenantid, MAX(c.tenantname) AS tenantname, MAX(b.locationid) AS locationid, MAX(d.locationname) AS locationname, CONCAT(a.firstname, ' ', a.lastname) AS fullname, a.status, SUM(COALESCE(b.quantity,0)) AS quantity, SUM(COALESCE(b.collectionamt,0)) AS collectionamt, SUM(COALESCE(b.collectedamt,0)) AS collectedamt, COALESCE(MAX(b.collectionstatus),0) AS collectionstatus, COUNT(b.orderid) AS totalorders, SUM(CASE WHEN b.orderstatus = 'pending' THEN 1 ELSE 0 END) AS pending, 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 = 'active' THEN 1 ELSE 0 END) AS active, SUM(CASE WHEN b.orderstatus = 'skipped' THEN 1 ELSE 0 END) AS skipped, SUM(CASE WHEN b.orderstatus = 'delivered' THEN 1 ELSE 0 END) AS delivered, SUM(CASE WHEN b.orderstatus = 'cancelled' THEN 1 ELSE 0 END) AS cancelled, SUM(CASE WHEN b.orderstatus = 'delivered' THEN CAST(COALESCE(NULLIF(b.actualkms, ''), '0') AS NUMERIC) ELSE 0 END) AS actualkms, SUM(CASE WHEN b.orderstatus = 'delivered' THEN CAST(COALESCE(NULLIF(b.kms, ''), '0') AS NUMERIC) 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.cumulativekms ELSE 0 END) AS cumulativekms, SUM(CASE WHEN b.orderstatus = 'delivered' THEN b.deliveryamt ELSE 0 END) AS deliveryamt, SUM(b.previouskms) AS previouskms FROM app_users a LEFT JOIN deliveries b ON a.userid = b.userid LEFT JOIN tenants c ON b.tenantid = c.tenantid LEFT JOIN tenantlocations d ON b.locationid = d.locationid` ) func PublishLog(c *fiber.Ctx) error { var data []models.Deliverylogs if err := c.BodyParser(&data); err != nil { return err } err := domain.PublishLog(data) if err != nil { return c.JSON(fiber.Map{ "status": false, "code": http.StatusConflict, "message": err, }) } return c.JSON(fiber.Map{ "status": true, "code": http.StatusOK, "message": "successful", }) } func GetDeliverylogs(c *fiber.Ctx) error { did, _ := strconv.Atoi(c.Query("deliveryid")) result := domain.GetDeliverylogs(did) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveriesV1(c *fiber.Ctx) error { var result []models.Deliveryinfo 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")) fdate := c.Query("fromdate") tdate := c.Query("todate") stat := c.Query("status") var info models.DeliveryQuery info.Partnerid = pid info.Tenantid = tid info.UserID = uid info.Appuserid = aud info.Applocationid = aid info.Fromdate = fdate info.ToDate = tdate info.Status = stat if tid != 0 { result = domain.GetTenantDeliveries(info) } else if pid != 0 { result = domain.GetPartnerDeliveries(info) } else if cid != 0 { result = domain.GetCustomerDeliveries(info) } else if aid != 0 { result = domain.GetAdminDeliveries(info) } else if uid != 0 { result = domain.GetUserDeliveries(info) } else if aud != 0 { result = domain.GetAppUserDeliveries(info) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveriesV2(c *fiber.Ctx) error { var result []models.Deliveryinfo pid, _ := strconv.Atoi(c.Query("partnerid")) tid, _ := strconv.Atoi(c.Query("tenantid")) lid, _ := strconv.Atoi(c.Query("locationid")) uid, _ := strconv.Atoi(c.Query("userid")) cid, _ := strconv.Atoi(c.Query("customerid")) aid, _ := strconv.Atoi(c.Query("applocationid")) aud, _ := strconv.Atoi(c.Query("appuserid")) fdate := c.Query("fromdate") tdate := c.Query("todate") stat := c.Query("status") keyword := c.Query("keyword") pagenoStr := c.Query("pageno") pagesizeStr := c.Query("pagesize") var pageno, pagesize int var err error if pagenoStr != "" { pageno, err = strconv.Atoi(pagenoStr) if err != nil || pageno <= 0 { pageno = 1 } } if pagesizeStr != "" { pagesize, err = strconv.Atoi(pagesizeStr) if err != nil || pagesize <= 0 { pagesize = 10 } } info := models.DeliveryQuery{ Partnerid: pid, Tenantid: tid, Locationid: lid, UserID: uid, Appuserid: aud, Applocationid: aid, Fromdate: fdate, ToDate: tdate, Status: stat, Pageno: pageno, Pagesize: pagesize, Keyword: keyword, } utils.Logger.Infow("Searching Delivery", "keyword", keyword) switch { case tid != 0 && lid != 0: result = domain.GetTenantLocationDeliveries(info) case tid != 0: result = domain.GetTenantDeliveries(info) case lid != 0: result = domain.GetLocationDeliveries(info) case pid != 0: result = domain.GetPartnerDeliveries(info) case cid != 0: result = domain.GetCustomerDeliveries(info) case aid != 0: result = domain.GetAdminDeliveries(info) case uid != 0: result = domain.GetUserDeliveries(info) case aud != 0: result = domain.GetAppUserDeliveries(info) default: result = domain.GetDeliveries(info) } if result == nil { result = []models.Deliveryinfo{} } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveriesV3(c *fiber.Ctx) error { var result []models.Deliveryinfo 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")) 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") var info models.DeliveryQuery info.Partnerid = pid info.Tenantid = tid info.UserID = uid info.Appuserid = aud info.Applocationid = aid info.Fromdate = fdate info.ToDate = tdate info.Status = stat info.Pageno = pageno info.Pagesize = pagesize info.Keyword = keyword utils.Logger.Infow("Searching Delivery", "keyword", keyword) // Choose which delivery function to call switch { case tid != 0: result = domain.GetTenantDeliveries(info) case pid != 0: result = domain.GetPartnerDeliveries(info) case cid != 0: result = domain.GetCustomerDeliveries(info) case aid != 0: result = domain.GetAdminDeliveries(info) case uid != 0: result = domain.GetUserDeliveriesv1(info) case aud != 0: result = domain.GetAppUserDeliveries(info) default: result = domain.GetDeliveries(info) } // Ensure result is not nil (avoid "null" in JSON) if result == nil { result = []models.Deliveryinfo{} } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveries(c *fiber.Ctx) error { pid, _ := strconv.Atoi(c.Query("partnerid")) tid, _ := strconv.Atoi(c.Query("tenantid")) uid, _ := strconv.Atoi(c.Query("userid")) aid, _ := strconv.Atoi(c.Query("applocationid")) aud, _ := strconv.Atoi(c.Query("appuserid")) fdate := c.Query("fromdate") tdate := c.Query("todate") stat := c.Query("status") var info models.DeliveryQuery info.Partnerid = pid info.Tenantid = tid info.UserID = uid info.Appuserid = aud info.Applocationid = aid info.Fromdate = fdate info.ToDate = tdate info.Status = stat data := domain.GetDeliveries(info) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func 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") var data []models.ReportSummary var q1 string var params []interface{} q1 = reports if tid != 0 { q1 += " WHERE a.tenantid=? " params = append(params, tid) } else if pid != 0 { q1 += " WHERE a.partnerid=? " params = append(params, pid) } else if uid != 0 { q1 += " WHERE c.userid=? " params = append(params, uid) } else if aid != 0 { q1 += " WHERE c.applocationid=? " params = append(params, aid) } else { q1 += " WHERE 1=1 " } if fdate != "" && tdate != "" { q1 += " AND a.orderdate::date between ?::date and ?::date " params = append(params, fdate, tdate) } q1 += " GROUP BY a.tenantid, b.tenantname, c.userid, e.firstname, e.lastname, e.contactno, a.locationid, d.locationname, c.collectionstatus" utils.Logger.Debugw("ReportSummary SQL generated", "query", q1) db.DB.Raw(q1, params...).Find(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func GetReportLocationSummary(c *fiber.Ctx) error { tid, _ := strconv.Atoi(c.Query("tenantid")) lid, _ := strconv.Atoi(c.Query("locationid")) 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") keyword := c.Query("keyword") var data []models.ReportSummary var q1 string var params []interface{} q1 = reports + " WHERE 1=1 " if tid != 0 { q1 += " AND a.tenantid=? " params = append(params, tid) } if lid != 0 { q1 += " AND a.locationid=? " params = append(params, lid) } if pid != 0 { q1 += " AND a.partnerid=? " params = append(params, pid) } if uid != 0 { q1 += " AND c.userid=? " params = append(params, uid) } if aid != 0 { q1 += " AND c.applocationid=? " params = append(params, aid) } if keyword != "" { q1 += " AND LOWER(d.locationname) LIKE LOWER(?) " params = append(params, "%"+keyword+"%") } if fdate != "" && tdate != "" { q1 += " AND a.orderdate::date BETWEEN ?::date AND ?::date " params = append(params, fdate, tdate) } q1 += " GROUP BY a.locationid, b.tenantid, b.tenantname, c.userid, e.firstname, e.lastname, e.contactno, d.locationname, c.collectionstatus" utils.Logger.Debugw("ReportLocationSummary SQL generated", "query", q1) db.DB.Raw(q1, params...).Scan(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func GetRiderLocationReportSummary(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") var data []models.ReportSummary var q1 string base := ` SELECT b.tenantid,b.tenantname,a.locationid,d.locationname,e.userid,e.firstname,e.lastname, 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(CAST(COALESCE(NULLIF(c.kms, ''), '0') AS NUMERIC)), 2) AS kms, ROUND(SUM(CAST(COALESCE(NULLIF(c.actualkms, ''), '0') AS NUMERIC)), 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 LEFT JOIN tenantlocations d ON a.locationid = d.locationid LEFT JOIN app_users e ON e.userid = c.userid ` // WHERE conditions var where []string var params []interface{} // Tenant filter if tid != 0 { where = append(where, "a.tenantid=?") params = append(params, tid) } // Partner filter if pid != 0 { where = append(where, "a.partnerid=?") params = append(params, pid) } // Rider (userid) filter if uid != 0 { where = append(where, "c.userid=?") params = append(params, uid) } // Location filter if aid != 0 { where = append(where, "a.locationid=?") params = append(params, aid) } // Date filter if fdate != "" && tdate != "" { where = append(where, "a.orderdate::date BETWEEN ?::date AND ?::date") where = append(where, "c.deliverydate::date BETWEEN ?::date AND ?::date") params = append(params, fdate, tdate, fdate, tdate) } // Build WHERE clause if len(where) > 0 { q1 = base + " WHERE " + strings.Join(where, " AND ") } else { q1 = base } // GROUP BY q1 += " GROUP BY a.locationid, b.tenantid, b.tenantname, d.locationname, e.userid, e.firstname, e.lastname" utils.Logger.Debugw("RiderLocationReportSummary SQL generated", "query", q1) db.DB.Raw(q1, params...).Find(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func GetRiderSummary(c *fiber.Ctx) error { aid, _ := strconv.Atoi(c.Query("applocationid")) pid, _ := strconv.Atoi(c.Query("partnerid")) tid, _ := strconv.Atoi(c.Query("tenantid")) lid, _ := strconv.Atoi(c.Query("locationid")) uid, _ := strconv.Atoi(c.Query("userid")) fdate := c.Query("fromdate") tdate := c.Query("todate") keyword := c.Query("keyword") var data []models.Ridersummary var params []interface{} q1 := Ridersummary + " WHERE a.configid = 6" if uid != 0 { q1 += " AND a.userid=?" params = append(params, uid) } if tid != 0 { q1 += " AND b.tenantid=?" params = append(params, tid) } if lid != 0 { q1 += " AND b.locationid=?" params = append(params, lid) } if aid != 0 { q1 += " AND a.applocationid=?" params = append(params, aid) } if pid != 0 { q1 += " AND a.partnerid=?" params = append(params, pid) } if fdate != "" && tdate != "" { q1 += " AND b.deliverydate::date BETWEEN ?::date AND ?::date" params = append(params, fdate, tdate) } if keyword != "" { k := "%" + strings.ToLower(keyword) + "%" q1 += " AND (LOWER(a.firstname) LIKE ? OR LOWER(a.lastname) LIKE ? OR LOWER(CONCAT(a.firstname, ' ', a.lastname)) LIKE ?)" params = append(params, k, k, k) } q1 += " GROUP BY a.userid, a.firstname, a.lastname, a.contactno, a.status" utils.Logger.Debugw("RiderSummary SQL generated", "query", q1) db.DB.Raw(q1, params...).Scan(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func GetRiderLocationSummary(c *fiber.Ctx) error { aid, _ := strconv.Atoi(c.Query("applocationid")) pid, _ := strconv.Atoi(c.Query("partnerid")) tid, _ := strconv.Atoi(c.Query("tenantid")) lid, _ := strconv.Atoi(c.Query("locationid")) fdate := c.Query("fromdate") tdate := c.Query("todate") var data []models.Ridersummary var q1 string var params []interface{} q1 = Ridersummary + " WHERE a.configid=6 " if tid != 0 { q1 += " AND b.tenantid=? " params = append(params, tid) } if lid != 0 { q1 += " AND b.locationid=? " params = append(params, lid) } if aid != 0 { q1 += " AND a.applocationid=? " params = append(params, aid) } if pid != 0 { q1 += " AND a.partnerid=? " params = append(params, pid) } if fdate != "" && tdate != "" { q1 += " AND b.deliverydate::date BETWEEN ?::date AND ?::date " params = append(params, fdate, tdate) } q1 += " GROUP BY a.userid, b.locationid, a.firstname, a.lastname, a.contactno, b.tenantid, c.tenantname, d.locationname, a.status" db.DB.Raw(q1, params...).Scan(&data) utils.Logger.Debugw("RiderLocationSummary SQL generated", "query", q1) return c.JSON(fiber.Map{ "code": 200, "message": "Success", "status": true, "details": data, }) } func GetDeliverySummary(c *fiber.Ctx) error { // 🔹 Query params appuid, _ := strconv.Atoi(c.Query("appuserid")) tid, _ := strconv.Atoi(c.Query("tenantid")) lid, _ := strconv.Atoi(c.Query("locationid")) aid, _ := strconv.Atoi(c.Query("applocationid")) uid, _ := strconv.Atoi(c.Query("userid")) status := c.Query("status") fdate := c.Query("fromdate") tdate := c.Query("todate") var data models.DeliverySummary var qb strings.Builder var params []interface{} qb.WriteString(core + ` 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 WHERE b.moduleid = 6 AND g.status = 'Active' `) if appuid != 0 { qb.WriteString(" AND g.userid = ?") params = append(params, appuid) } if tid != 0 { qb.WriteString(" AND a.tenantid = ?") params = append(params, tid) } if lid != 0 { qb.WriteString(" AND a.locationid = ?") params = append(params, lid) } if aid != 0 { qb.WriteString(" AND a.applocationid = ?") params = append(params, aid) } if uid != 0 { qb.WriteString(" AND a.userid = ?") params = append(params, uid) } if status != "" && strings.ToLower(status) != "all" { qb.WriteString(" AND a.orderstatus = ?") params = append(params, status) } // 🔹 DATE FILTER (INDEX-FRIENDLY) if fdate != "" && tdate != "" { qb.WriteString(` AND a.deliverydate >= (CONCAT(?::text, ' 00:00:00'))::timestamp AND a.deliverydate <= (CONCAT(?::text, ' 23:59:59'))::timestamp `) params = append(params, fdate, tdate) } finalQuery := qb.String() utils.Logger.Infow("DeliverySummary SQL generated", "query", finalQuery, "params", params) db.DB.Raw(finalQuery, params...).Scan(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "status": true, "message": "Success", "details": data, }) } func GetlocationdeliverySummary(c *fiber.Ctx) error { tenantIDStr := c.Query("tenantid") tenantID, _ := strconv.Atoi(tenantIDStr) var data []models.Ordersummary var q1 string var params []interface{} q1 = `SELECT b.locationname, a.applocationid, COUNT(*) AS total, SUM(CASE WHEN orderstatus = 'created' THEN 1 ELSE 0 END) AS created, SUM(CASE WHEN orderstatus = 'pending' THEN 1 ELSE 0 END) AS pending, SUM(CASE WHEN orderstatus = 'processing' THEN 1 ELSE 0 END) AS processing, SUM(CASE WHEN orderstatus = 'delivered' THEN 1 ELSE 0 END) AS delivered, SUM(CASE WHEN orderstatus = 'cancelled' THEN 1 ELSE 0 END) AS cancelled FROM orders a INNER JOIN app_location b ON a.applocationid = b.applocationid` // Apply tenant filter only if tenantID != 0 if tenantID != 0 { q1 += " WHERE a.tenantid = ?" params = append(params, tenantID) } q1 += " GROUP BY a.applocationid, b.locationname" if err := db.DB.Raw(q1, params...).Scan(&data).Error; 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 GetDeliveryInsight(c *fiber.Ctx) error { tenantIDStr := c.Query("tenantid") tenantID, _ := strconv.Atoi(tenantIDStr) var locations []models.OrderInsight var params []interface{} // Query 1: Get distinct locations q1 := `SELECT DISTINCT a.applocationid, b.locationname FROM deliveries a INNER JOIN app_location b ON a.applocationid = b.applocationid WHERE b.status = 'Active'` if tenantID != 0 { q1 += " AND a.tenantid = ?" params = append(params, tenantID) } if err := db.DB.Raw(q1, params...).Scan(&locations).Error; err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } // Query 2: Fetch delivery insights for each location q2 := `SELECT COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 1 THEN 1 ELSE 0 END), 0) AS jan, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 2 THEN 1 ELSE 0 END), 0) AS feb, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 3 THEN 1 ELSE 0 END), 0) AS mar, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 4 THEN 1 ELSE 0 END), 0) AS apr, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 5 THEN 1 ELSE 0 END), 0) AS may, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 6 THEN 1 ELSE 0 END), 0) AS jun, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 7 THEN 1 ELSE 0 END), 0) AS jul, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 8 THEN 1 ELSE 0 END), 0) AS aug, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 9 THEN 1 ELSE 0 END), 0) AS sep, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 10 THEN 1 ELSE 0 END), 0) AS oct, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 11 THEN 1 ELSE 0 END), 0) AS nov, COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM a.deliverydate) = 12 THEN 1 ELSE 0 END), 0) AS dece FROM deliveries a WHERE a.applocationid = ? AND EXTRACT(YEAR FROM a.deliverydate) = EXTRACT(YEAR FROM CURRENT_DATE)` if tenantID != 0 { q2 += " AND a.tenantid = ?" } // Fetch monthly delivery counts for each location for i := range locations { var orderMonths models.Ordermonths if tenantID != 0 { if err := db.DB.Raw(q2, locations[i].Applocationid, tenantID).Scan(&orderMonths).Error; err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } } else { if err := db.DB.Raw(q2, locations[i].Applocationid).Scan(&orderMonths).Error; err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } } locations[i].Ordermonths = &orderMonths } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": locations, }) } func DeliverySummary(c *fiber.Ctx) error { pid, _ := strconv.Atoi(c.Query("partnerid")) var data models.DeliverySummary q1 := `SELECT COUNT(*) AS deliveries, SUM(CASE WHEN orderstatus = 'cancelled' THEN 1 ELSE 0 END) AS cancelled, SUM(round(kms, 2)) AS kms, SUM(deliveryamt) AS amount FROM deliveries WHERE partnerid =?` db.DB.Raw(q1, pid).Find(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func CreateDelivery(c *fiber.Ctx) error { var data models.Deliveries if err := c.BodyParser(&data); err != nil { return err } err := domain.CreateDelivery(data) if err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err, "status": false, }) } else { return c.JSON(fiber.Map{ "code": http.StatusCreated, "message": "Success", "status": true, }) } } func CreateDeliveries(c *fiber.Ctx) error { var data []models.Deliveries if err := c.BodyParser(&data); err != nil { return err } err := domain.CreateDeliveries(data) if err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusCreated, "message": "Success", "status": true, }) } func CreateDeliveriesV2(c *fiber.Ctx) error { var data []models.Deliveries if err := c.BodyParser(&data); err != nil { return c.Status(400).JSON(fiber.Map{ "status": false, "code": 400, "message": "Invalid JSON body", }) } utils.Logger.Infow("CreateDeliveriesV2 Call", "records", len(data)) ids, err := domain.CreateDeliveriesV2(data) if err != nil { return c.Status(409).JSON(fiber.Map{ "status": false, "code": 409, "message": err.Error(), }) } return c.JSON(fiber.Map{ "status": true, "code": 201, "message": "Deliveries created successfully", "deliveryids": ids, }) } func UpdateDelivery(c *fiber.Ctx) error { var data models.UpdateDeliveryStatus if err := c.BodyParser(&data); err != nil { return err } err := domain.UpdateDelivery(data) if err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusCreated, "message": "Success", "status": true, }) } func GetDeliveryQueues(c *fiber.Ctx) error { fdate := c.Query("fromdate") tdate := c.Query("todate") uid, _ := strconv.Atoi(c.Query("userid")) result := domain.GetDeliveryQueues(uid, fdate, tdate) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveryQueuesV1(c *fiber.Ctx) error { fdate := c.Query("fromdate") tdate := c.Query("todate") uid, _ := strconv.Atoi(c.Query("userid")) result := domain.GetDeliveryQueuesV1(uid, fdate, tdate) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveryQueuesPicked(c *fiber.Ctx) error { fdate := c.Query("fromdate") tdate := c.Query("todate") uid, _ := strconv.Atoi(c.Query("userid")) result := domain.GetDeliveryQueuesPicked(uid, fdate, tdate) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetlocationdeliverySummaryDaily(c *fiber.Ctx) error { tenantIDStr := c.Query("tenantid") tenantID, _ := strconv.Atoi(tenantIDStr) var data []models.Ordersummarylocation var q1 string 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 orders a ON a.locationid = b.locationid ` // ✅ Apply tenant filter on tenantlocations (not orders only) if tenantID != 0 { q1 += " WHERE b.tenantid = ?" params = append(params, tenantID) } q1 += " GROUP BY b.locationid, b.locationname" if err := db.DB.Raw(q1, params...).Scan(&data).Error; 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 GetDeliveryInsightDaily(c *fiber.Ctx) error { tenantIDStr := c.Query("tenantid") tenantID, _ := strconv.Atoi(tenantIDStr) var locations []models.OrderInsightv1 var params []interface{} q1 := `SELECT DISTINCT l.locationid, l.locationname FROM tenantlocations l LEFT JOIN deliveries d ON l.locationid = d.locationid WHERE l.status = 'Active'` if tenantID != 0 { q1 += " AND l.tenantid = ?" params = append(params, tenantID) } if err := db.DB.Raw(q1, params...).Scan(&locations).Error; err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } 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 = ?" } for i := range locations { var orderMonths models.Ordermonths if tenantID != 0 { if err := db.DB.Raw(q2, locations[i].Locationid, tenantID).Scan(&orderMonths).Error; err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } } else { if err := db.DB.Raw(q2, locations[i].Locationid).Scan(&orderMonths).Error; err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, }) } } locations[i].Ordermonths = &orderMonths } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": locations, }) } func PublishLogv1(c *fiber.Ctx) error { var data []models.Deliverylogs if err := c.BodyParser(&data); err != nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "status": false, "code": http.StatusBadRequest, "message": "Invalid JSON body", }) } err := domain.PublishLogv1(data) if 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.StatusOK, "message": "Successfully saved logs to Redis", }) } func GetDeliverylogsv1(c *fiber.Ctx) error { did, _ := strconv.Atoi(c.Query("deliveryid")) result, err := domain.GetDeliverylogsv1(did) if err != nil { return c.JSON(fiber.Map{ "code": http.StatusConflict, "message": err.Error(), "status": false, "details": []models.Deliverylogs{}, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func GetDeliveryLogsv1(c *fiber.Ctx) error { deliveryID := c.Query("deliveryid") if deliveryID == "" { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "deliveryid is required", "status": false, }) } logs, err := domain.GetDeliveryLogsv1(deliveryID) 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": 200, "details": logs, "status": true, }) } func GetRiderByDelivery(c *fiber.Ctx) error { fromdate := strings.TrimSpace(c.Query("fromdate")) todate := strings.TrimSpace(c.Query("todate")) keyword := strings.TrimSpace(c.Query("keyword")) if fromdate == "" || todate == "" { return c.Status(400).JSON(fiber.Map{ "code": 400, "status": false, "message": "fromdate and todate are required", }) } applocationidStr := strings.TrimSpace(c.Query("applocationid")) tenantidStr := strings.TrimSpace(c.Query("tenantid")) locationidStr := strings.TrimSpace(c.Query("locationid")) applocationid, _ := strconv.Atoi(applocationidStr) tenantid, _ := strconv.Atoi(tenantidStr) locationid, _ := strconv.Atoi(locationidStr) var users []models.User var params []interface{} query := ` SELECT b.userid,b.authname,b.firstname,b.lastname,b.password,b.email,b.dialcode,b.contactno,b.configid,b.authmode,b.roleid,b.pin,b.deviceid,b.devicetype,b.userfcmtoken, b.address,b.suburb,b.city,b.state,b.postcode,b.partnerid,a.tenantid,a.locationid,a.applocationid,b.status,b.shiftid,b.hashsalt FROM deliveries a LEFT JOIN app_users b ON a.userid = b.userid WHERE a.deliverydate::date BETWEEN ?::date AND ?::date ` params = append(params, fromdate, todate) if tenantid != 0 { query += " AND a.tenantid = ?" params = append(params, tenantid) } if locationid != 0 { query += " AND a.locationid = ?" params = append(params, locationid) } if applocationid != 0 { query += " AND a.applocationid = ?" params = append(params, applocationid) } if keyword != "" { k := "%" + strings.ToLower(keyword) + "%" query += ` AND ( LOWER(b.firstname) LIKE ? OR LOWER(b.lastname) LIKE ? OR LOWER(b.contactno) LIKE ? ) ` params = append(params, k, k, k) } query += " GROUP BY b.userid ORDER BY b.userid DESC" if err := db.DB.Raw(query, params...).Scan(&users).Error; err != nil { return c.Status(500).JSON(fiber.Map{ "code": 500, "status": false, "message": "Database error: " + err.Error(), }) } return c.JSON(fiber.Map{ "code": 200, "status": true, "details": users, }) } func GetLastDeliveryByContact(c *fiber.Ctx) error { deliverycontactno := c.Query("deliverycontactno") fromdate := c.Query("fromdate") todate := c.Query("todate") var data []models.Deliveries var query string var args []interface{} dateCondition := "" if fromdate != "" && todate != "" { dateCondition = " AND deliverydate::date BETWEEN ?::date AND ?::date " args = append(args, fromdate, todate) } else if fromdate != "" { dateCondition = " AND deliverydate::date >= ?::date " args = append(args, fromdate) } else if todate != "" { dateCondition = " AND deliverydate::date <= ?::date " args = append(args, todate) } if deliverycontactno == "" { query = ` SELECT d.* FROM deliveries d INNER JOIN ( SELECT deliverycontactno, MAX(deliveryid) AS maxid FROM deliveries WHERE 1=1 ` + dateCondition + ` GROUP BY deliverycontactno ) t ON d.deliveryid = t.maxid ORDER BY d.deliveryid DESC; ` } else { query = ` SELECT * FROM deliveries WHERE deliverycontactno = ? ` + dateCondition + ` ORDER BY deliveryid DESC LIMIT 1; ` args = append([]interface{}{deliverycontactno}, args...) } if err := db.DB.Raw(query, args...).Scan(&data).Error; err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "code": 500, "message": err.Error(), "status": false, }) } return c.Status(200).JSON(fiber.Map{ "code": 200, "message": "Success", "details": data, "status": true, }) } func GetUserReportSummary(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") var data []models.UserReportSummary var q1 string var params []interface{} q1 = reports if tid != 0 { q1 += " WHERE a.tenantid = ?" params = append(params, tid) } else if uid != 0 { q1 += " WHERE c.userid = ?" params = append(params, uid) } else { q1 += " WHERE 1=1" } if fdate != "" && tdate != "" { q1 += " AND a.orderdate::date BETWEEN ?::date AND ?::date" params = append(params, fdate, tdate) } q1 += ` GROUP BY c.userid, e.firstname, e.lastname, e.contactno, b.tenantid, b.tenantname` utils.Logger.Debugw("RiderLocationReportSummary SQL generated", "query", q1) db.DB.Raw(q1, params...).Scan(&data) return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": data, }) } func GetUserDeliveryLogs(c *fiber.Ctx) error { userid, err := strconv.Atoi(c.Query("userid")) if err != nil || userid == 0 { return c.Status(400).JSON(fiber.Map{ "code": 400, "message": "Invalid userid", "status": false, "details": []models.Deliverylogs{}, }) } fromdate := strings.TrimSpace(c.Query("fromdate")) todate := strings.TrimSpace(c.Query("todate")) result, err := domain.GetUserDeliveryLogs(userid, fromdate, todate) if err != nil { return c.JSON(fiber.Map{ "code": 409, "message": err.Error(), "status": false, "details": []models.Deliverylogs{}, }) } return c.JSON(fiber.Map{ "code": 200, "message": "Success", "status": true, "details": result, }) }