fix: GET /hub/dashboard now honors from/to date range

Previously always scoped parcels_received_today, batches_sent_today,
exceptions, and parcels_sorted to "since midnight today", ignoring any
from/to query params — so any non-default range silently returned
zeros. Now parses optional from/to (YYYY-MM-DD, same semantics as
GET /hub/report) and defaults to today when omitted.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 12:36:49 +05:30
parent 5a2da49c35
commit 624891b7bd

View File

@@ -100,6 +100,36 @@ func todayMidnight() time.Time {
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
}
// parseHubDashboardRange parses optional from/to (YYYY-MM-DD) query params
// for GetHubDashboardStats, defaulting to "today so far" when both are
// omitted. Mirrors GetHubReport's range semantics: to is inclusive of the
// whole day.
func parseHubDashboardRange(c *fiber.Ctx) (time.Time, time.Time, error) {
fromStr := c.Query("from")
toStr := c.Query("to")
if fromStr == "" && toStr == "" {
return todayMidnight(), time.Now(), nil
}
if fromStr == "" || toStr == "" {
return time.Time{}, time.Time{}, fmt.Errorf("both from and to query params are required (YYYY-MM-DD)")
}
from, err := time.ParseInLocation("2006-01-02", fromStr, time.Local)
if err != nil {
return time.Time{}, time.Time{}, fmt.Errorf("invalid from date, expected YYYY-MM-DD")
}
toDate, err := time.ParseInLocation("2006-01-02", toStr, time.Local)
if err != nil {
return time.Time{}, time.Time{}, fmt.Errorf("invalid to date, expected YYYY-MM-DD")
}
to := toDate.Add(24*time.Hour - time.Nanosecond)
if to.Before(from) {
return time.Time{}, time.Time{}, fmt.Errorf("to date must not be before from date")
}
return from, to, nil
}
// hubPincodePrefix returns the first 3 digits of a hub's pincode, following
// the same zone-prefix convention used in pricing_helpers.go and city_gate.go.
func hubPincodePrefix(hubID int) string {
@@ -183,12 +213,16 @@ func isDoormileStaff(staff *models.HubStaffAccount) bool {
func GetHubDashboardStats(c *fiber.Ctx) error {
hubID := c.Locals("hubid").(int)
midnight := todayMidnight()
prefix := hubPincodePrefix(hubID)
from, to, err := parseHubDashboardRange(c)
if err != nil {
return utils.BadRequest(c, err.Error())
}
var parcelsReceivedToday int64
db.DB.Model(&models.Consignment{}).
Where("currenthubid = ? AND status = ? AND updatedat >= ?", hubID, constants.ConsignmentInwardedAtHub, midnight).
Where("currenthubid = ? AND status = ? AND updatedat BETWEEN ? AND ?", hubID, constants.ConsignmentInwardedAtHub, from, to).
Count(&parcelsReceivedToday)
var milersAvailable int64
@@ -210,12 +244,12 @@ func GetHubDashboardStats(c *fiber.Ctx) error {
var batchesSentToday int64
db.DB.Model(&models.Tripsheet{}).
Where("sourcehubid = ? AND dispatchtime >= ?", hubID, midnight).
Where("sourcehubid = ? AND dispatchtime BETWEEN ? AND ?", hubID, from, to).
Count(&batchesSentToday)
var exceptions int64
db.DB.Model(&models.ConsignmentException{}).
Where("hubid = ? AND createdat >= ?", hubID, midnight).
Where("hubid = ? AND createdat BETWEEN ? AND ?", hubID, from, to).
Count(&exceptions)
// Sorting happens at inbound scan (CreateInboundScan assigns a shelf), so