GWM : CARD calculation sum,avg,min,max,diff
This commit is contained in:
parent
a3fe3e4d33
commit
59de2e648e
100
main.go
100
main.go
@ -593,11 +593,9 @@ func main() {
|
||||
chartData = filterDynamicChartData(chartData, keyToFilter, valueToExclude)
|
||||
}
|
||||
|
||||
cRes := utils.ProcessChartData(chartData, languageSourceConverted, langKey)
|
||||
|
||||
//logo url generating
|
||||
var logoURL string
|
||||
cardLogo := record.GetString("card_logo")
|
||||
|
||||
if cardLogo == "" {
|
||||
logoURL = ""
|
||||
} else {
|
||||
@ -608,24 +606,75 @@ func main() {
|
||||
)
|
||||
}
|
||||
|
||||
cResRaw := utils.ProcessChartData(chartData, languageSourceConverted, langKey)
|
||||
|
||||
// Convert cResRaw ([]map[string]interface{}) to []utils.Observation
|
||||
var cRes []utils.Observation
|
||||
cResJSON, err := json.Marshal(cResRaw)
|
||||
if err != nil {
|
||||
fmt.Println("Error encoding chart data:", err)
|
||||
}
|
||||
err = json.Unmarshal(cResJSON, &cRes)
|
||||
if err != nil {
|
||||
fmt.Println("Error decoding chart data:", err)
|
||||
}
|
||||
|
||||
// card data calculation
|
||||
var cardResults []map[string]string
|
||||
if record.GetString("is_chart") == "false" {
|
||||
|
||||
// Extract `card_type` JSON from `record.Get("card_type")`
|
||||
requestData := record.Get("card_type")
|
||||
requestJSON, err := json.Marshal(requestData) // Convert interface{} to JSON string
|
||||
if err != nil {
|
||||
fmt.Println("Error encoding request data:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Decode JSON into an array of `utils.Request`
|
||||
var requests []utils.Request
|
||||
err = json.Unmarshal(requestJSON, &requests)
|
||||
if err != nil {
|
||||
fmt.Println("Error decoding request data:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Process each request and store results
|
||||
for _, req := range requests {
|
||||
result, err := utils.Calculate(cRes, req)
|
||||
if err != nil {
|
||||
fmt.Println("Error processing data:", err)
|
||||
continue // Skip this request and move to the next
|
||||
}
|
||||
cardResults = append(cardResults, result)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
chartHeadingKey := "chart_heading_" + language
|
||||
tabHeadingKey := "tab_heading_" + language
|
||||
// Prepare the structure with URL and its response
|
||||
// Correct conditional assignment for "response"
|
||||
recordResult := map[string]interface{}{
|
||||
"url": apiURL,
|
||||
"dataset": record.GetString("dataset"),
|
||||
"main_id": record.GetString("main_id"),
|
||||
"sub_id": record.GetString("sub_id"),
|
||||
"kpi": record.GetString("kpi"),
|
||||
"is_chart": record.GetString("is_chart"),
|
||||
"chart_type": record.GetString("chart_type"),
|
||||
"response": cRes,
|
||||
"url": apiURL,
|
||||
"dataset": record.GetString("dataset"),
|
||||
"main_id": record.GetString("main_id"),
|
||||
"sub_id": record.GetString("sub_id"),
|
||||
"kpi": record.GetString("kpi"),
|
||||
"is_chart": record.GetString("is_chart"),
|
||||
"chart_type": record.GetString("chart_type"),
|
||||
// "response": record.GetString("is_chart") = true cRes : cardResults,
|
||||
"group_by": record.GetString("group_by"),
|
||||
"chart_heading": record.GetString(chartHeadingKey),
|
||||
"tab_heading": record.GetString(tabHeadingKey),
|
||||
"unset_value": record.Get("unset_value"),
|
||||
"card_logo": logoURL,
|
||||
"order_id": record.Get("order_id"),
|
||||
"card_type": record.Get("card_type"),
|
||||
}
|
||||
if record.GetString("is_chart") == "true" {
|
||||
recordResult["response"] = cRes
|
||||
} else {
|
||||
recordResult["response"] = cardResults
|
||||
}
|
||||
|
||||
// Add the result to the aggregated response
|
||||
@ -660,10 +709,32 @@ func main() {
|
||||
}
|
||||
//--------------------
|
||||
|
||||
//mainTopic kpi heading and screen color
|
||||
headingAndColor := struct {
|
||||
DataSet string `db:"data_set" json:"data_set"`
|
||||
MainTopic string `db:"main_topic" json:"main_topic"`
|
||||
SubTopic string `db:"sub_topic" json:"sub_topic"`
|
||||
DataSetTileHeading string `db:"data_set_tile_heading" json:"data_set_tile_heading"`
|
||||
HeaderColor string `db:"header_color" json:"header_color"`
|
||||
BodyColor string `db:"body_color" json:"body_color"`
|
||||
BorderColor string `db:"border_color" json:"border_color"`
|
||||
}{}
|
||||
|
||||
data_set_tile_heading := "data_set_tile_heading_" + language
|
||||
main_topic := "main_topic_" + language
|
||||
sub_topic := "sub_topic_" + language
|
||||
query := ` SELECT id,data_set,` + data_set_tile_heading + ` AS data_set_tile_heading,` + main_topic + ` AS main_topic,` + sub_topic + ` AS sub_topic,header_color,body_color,border_color FROM uae_numbers_screen WHERE data_set = {:data_set} `
|
||||
err = app.DB().NewQuery(query).Bind(dbx.Params{"data_set": dataset}).One(&headingAndColor)
|
||||
if err != nil {
|
||||
log.Printf("Failed to fetch data-set for sub topic %s: %v", dataset, err)
|
||||
}
|
||||
//---------------------
|
||||
|
||||
// Create the response structure
|
||||
response := map[string]interface{}{
|
||||
"new_filter_data": aggregatedFilterResponse,
|
||||
"data": aggregatedResponse,
|
||||
"new_filter_data": aggregatedFilterResponse,
|
||||
"data": aggregatedResponse,
|
||||
"screen_heading_and_color": headingAndColor,
|
||||
}
|
||||
|
||||
if len(aggregatedResponse) == 0 {
|
||||
@ -932,6 +1003,7 @@ func main() {
|
||||
"bookmark": bookmark.Dataset,
|
||||
}).
|
||||
One(&dataSets)
|
||||
|
||||
log.Printf("query %s: %v", bookmark.Dataset, query)
|
||||
if err != nil {
|
||||
log.Printf("Failed to fetch data-set for sub topic %s: %v", bookmark.Dataset, err)
|
||||
|
||||
200
utils/card_calculation.go
Normal file
200
utils/card_calculation.go
Normal file
@ -0,0 +1,200 @@
|
||||
// utils/calculations.go
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Observation struct with json.Number for flexible value handling
|
||||
type Observation struct {
|
||||
ObsKey map[string]string `json:"ObsKey"`
|
||||
ObsValue struct {
|
||||
Value json.Number `json:"Value"`
|
||||
} `json:"ObsValue"`
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
Formula string `json:"formula"`
|
||||
RecordCount string `json:"record_count"`
|
||||
RecodeIndex string `json:"record_index"`
|
||||
RecordKey string `json:"record_key"`
|
||||
NumberFormat string `json:"number_format"`
|
||||
Conversion string `json:"conversion"`
|
||||
}
|
||||
|
||||
func Calculate(data []Observation, req Request) (map[string]string, error) {
|
||||
// Sort the data in descending order based on TimePeriod
|
||||
sort.Slice(data, func(i, j int) bool {
|
||||
return data[i].ObsKey["TIME_PERIOD"] > data[j].ObsKey["TIME_PERIOD"]
|
||||
})
|
||||
|
||||
var selectedData []Observation
|
||||
if req.RecodeIndex != "" {
|
||||
// Convert RecodeIndex to an integer
|
||||
index, err := strconv.Atoi(req.RecodeIndex)
|
||||
if err != nil || index < 0 || index >= len(data) {
|
||||
return nil, errors.New("invalid record index")
|
||||
}
|
||||
// Select only the requested index record
|
||||
selectedData = []Observation{data[index]}
|
||||
|
||||
} else {
|
||||
// Determine the number of records to use
|
||||
n := len(data) // array leangth
|
||||
if req.RecordCount != "all" {
|
||||
var err error
|
||||
n, err = strconv.Atoi(req.RecordCount)
|
||||
if err != nil || n > len(data) {
|
||||
return nil, errors.New("invalid record count")
|
||||
}
|
||||
}
|
||||
selectedData = data[:n]
|
||||
}
|
||||
|
||||
var result float64
|
||||
switch req.Formula {
|
||||
case "none":
|
||||
result = none(selectedData)
|
||||
case "total":
|
||||
result = sum(selectedData)
|
||||
case "average":
|
||||
result = average(selectedData)
|
||||
case "highest":
|
||||
result = highest(selectedData)
|
||||
case "lowest":
|
||||
result = lowest(selectedData)
|
||||
case "different":
|
||||
result = difference(selectedData)
|
||||
default:
|
||||
return nil, errors.New("invalid formula")
|
||||
}
|
||||
|
||||
convertedValue := applyConversion(result, req.Conversion, req.NumberFormat)
|
||||
displayValue := extractRecordKeyValue(selectedData, req.RecordKey, req.Formula, result)
|
||||
|
||||
return map[string]string{
|
||||
"value": convertedValue,
|
||||
"display_value": displayValue,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Helper function to convert json.Number to float64 safely
|
||||
func getFloatValue(num json.Number) float64 {
|
||||
val, err := num.Float64()
|
||||
if err != nil {
|
||||
fmt.Println("Error converting value:", err)
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func none(data []Observation) float64 {
|
||||
total := 0.0
|
||||
for _, obs := range data {
|
||||
total += getFloatValue(obs.ObsValue.Value)
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func sum(data []Observation) float64 {
|
||||
total := 0.0
|
||||
for _, obs := range data {
|
||||
total += getFloatValue(obs.ObsValue.Value)
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func average(data []Observation) float64 {
|
||||
if len(data) == 0 {
|
||||
return 0
|
||||
}
|
||||
return sum(data) / float64(len(data))
|
||||
}
|
||||
|
||||
func highest(data []Observation) float64 {
|
||||
max := getFloatValue(data[0].ObsValue.Value)
|
||||
for _, obs := range data {
|
||||
val := getFloatValue(obs.ObsValue.Value)
|
||||
if val > max {
|
||||
max = val
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
func lowest(data []Observation) float64 {
|
||||
min := getFloatValue(data[0].ObsValue.Value)
|
||||
for _, obs := range data {
|
||||
val := getFloatValue(obs.ObsValue.Value)
|
||||
if val < min {
|
||||
min = val
|
||||
}
|
||||
}
|
||||
return min
|
||||
}
|
||||
|
||||
func difference(data []Observation) float64 {
|
||||
if len(data) < 2 {
|
||||
return 0
|
||||
}
|
||||
latest := getFloatValue(data[0].ObsValue.Value)
|
||||
previous := getFloatValue(data[1].ObsValue.Value)
|
||||
if previous == 0 {
|
||||
return 0
|
||||
}
|
||||
return ((latest - previous) / previous) * 100
|
||||
}
|
||||
|
||||
func applyConversion(value float64, conversion string, numberFormat string) string {
|
||||
|
||||
if numberFormat == "M" {
|
||||
value *= 1000000
|
||||
} else if numberFormat == "T" {
|
||||
value *= 1000000000000
|
||||
} else if numberFormat == "K" {
|
||||
value *= 1000
|
||||
}
|
||||
|
||||
switch conversion {
|
||||
case "M":
|
||||
return fmt.Sprintf("%.2fM", value/1000000)
|
||||
case "T":
|
||||
return fmt.Sprintf("%.2fT", value/1000000000000)
|
||||
case "K":
|
||||
return fmt.Sprintf("%.2fK", value/1000)
|
||||
case "%":
|
||||
return fmt.Sprintf("%.2f%%", value)
|
||||
default:
|
||||
return fmt.Sprintf("%.2f", value)
|
||||
}
|
||||
}
|
||||
|
||||
func extractRecordKeyValue(data []Observation, key string, formula string, targetValue float64) string {
|
||||
if len(data) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch formula {
|
||||
case "highest", "lowest", "none":
|
||||
for _, obs := range data {
|
||||
value, err := obs.ObsValue.Value.Float64()
|
||||
if err == nil && value == targetValue {
|
||||
if val, exists := obs.ObsKey[key]; exists {
|
||||
return val
|
||||
}
|
||||
}
|
||||
}
|
||||
case "total", "average", "different":
|
||||
if val1, exists1 := data[0].ObsKey[key]; exists1 {
|
||||
if val2, exists2 := data[len(data)-1].ObsKey[key]; exists2 {
|
||||
return val1 + " - " + val2
|
||||
}
|
||||
return val1
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user