package system import ( "time" "wails-app/internal/global" parkingService "wails-app/internal/service/parking" ) type DeviceStatus struct { ChannelName string `json:"channel_name"` Direction string `json:"direction"` DeviceCode string `json:"device_code"` DeviceName string `json:"device_name"` DeviceStatus string `json:"device_status"` } type MonitorData struct { TotalSpaces int64 `json:"total_spaces"` UsedSpaces int64 `json:"used_spaces"` InPark int64 `json:"in_park"` TodayIncome float64 `json:"today_income"` TodayEntry int64 `json:"today_entry"` TodayExit int64 `json:"today_exit"` Devices []DeviceStatus `json:"devices"` } type DashboardService struct{} func (s *DashboardService) GetMonitorData() (MonitorData, error) { var d MonitorData today := time.Now().Format("2006-01-02") var spaces struct { TotalSpaces int64 UsedSpaces int64 } if err := global.GVA_DB.Raw(`SELECT COALESCE(SUM(capacity), 0) AS total_spaces, COALESCE(SUM(occupied), 0) AS used_spaces FROM parking_lot WHERE deleted_at IS NULL`).Scan(&spaces).Error; err != nil { return d, err } d.TotalSpaces = spaces.TotalSpaces d.UsedSpaces = spaces.UsedSpaces d.InPark = d.UsedSpaces if err := global.GVA_DB.Raw(`SELECT COALESCE(SUM(amount), 0) FROM payment_record WHERE deleted_at IS NULL AND paid_at >= ? AND paid_at < ?`, today, today+" 23:59:59").Scan(&d.TodayIncome).Error; err != nil { return d, err } if err := global.GVA_DB.Raw(`SELECT COUNT(*) FROM vehicle_record WHERE deleted_at IS NULL AND entry_time >= ? AND entry_time < ?`, today, today+" 23:59:59").Scan(&d.TodayEntry).Error; err != nil { return d, err } if err := global.GVA_DB.Raw(`SELECT COUNT(*) FROM vehicle_record WHERE deleted_at IS NULL AND exit_time >= ? AND exit_time < ?`, today, today+" 23:59:59").Scan(&d.TodayExit).Error; err != nil { return d, err } if err := global.GVA_DB.Raw(`SELECT ch.channel_name, ch.direction, COALESCE(uhf.device_code, '') as device_code, COALESCE(uhf.device_name, '-') as device_name, 'unbound' as device_status FROM channel ch LEFT JOIN uhf_reader uhf ON uhf.channel_id = ch.id AND uhf.deleted_at IS NULL WHERE ch.deleted_at IS NULL ORDER BY ch.id`).Scan(&d.Devices).Error; err != nil { return d, err } for i := range d.Devices { device := &d.Devices[i] if device.DeviceCode == "" { device.DeviceStatus = "unbound" continue } status := parkingService.GetGateRuntimeStatus(device.DeviceCode) switch { case status.Simulated && status.Connected: device.DeviceStatus = "simulated" case status.Connected: device.DeviceStatus = "online" default: device.DeviceStatus = "offline" } } return d, nil }