GWM : filter data and structured response

This commit is contained in:
Gowtham M 2025-01-08 12:43:30 +05:30
parent 065e62b750
commit 9afc6fcca1
8 changed files with 3624 additions and 147 deletions

3432
filter_files/divorces.json Normal file

File diff suppressed because it is too large Load Diff

339
main.go
View File

@ -69,7 +69,7 @@ func removeNamespace(xmlBytes []byte) string {
} }
// Function to fetch XML from an API and convert it to JSON // Function to fetch XML from an API and convert it to JSON
func fetchAndConvertXMLToJSON(apiURL string, kpiName string, chartId string) ([]map[string]interface{}, error) { func fetchAndConvertXMLToJSON(apiURL string, outputDir string, fileName string, tableName string, id string) ([]map[string]interface{}, error) {
// Call the API and get the XML response // Call the API and get the XML response
resp, err := http.Get(apiURL) resp, err := http.Get(apiURL)
if err != nil { if err != nil {
@ -110,21 +110,19 @@ func fetchAndConvertXMLToJSON(apiURL string, kpiName string, chartId string) ([]
} }
// Save the JSON data to a file if required // Save the JSON data to a file if required
// Ensure the folder exists // Ensure the folder exists
outputDir := "kpi_files"
if err := os.MkdirAll(outputDir, os.ModePerm); err != nil { if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
return nil, err return nil, err
} }
// Save the file with a timestamped filename // Save the file
fileName := fmt.Sprintf("%s/%s.json", outputDir, kpiName) file := fmt.Sprintf("%s/%s.json", outputDir, fileName)
if err := ioutil.WriteFile(fileName, jsonData, 0644); err != nil { if err := ioutil.WriteFile(file, jsonData, 0644); err != nil {
return nil, err return nil, err
} }
// Find the charts record // Find the charts record
record, err := app.Dao().FindRecordById("charts", chartId) record, err := app.Dao().FindRecordById(tableName, id)
if err != nil { if err != nil {
// return c.JSON(500, map[string]interface{}{"code": 500,"message": "Error finding user.",}) // return c.JSON(500, map[string]interface{}{"code": 500,"message": "Error finding user.",})
} }
@ -137,9 +135,10 @@ func fetchAndConvertXMLToJSON(apiURL string, kpiName string, chartId string) ([]
} }
// Function to read JSON data from a file // Function to read JSON data from a file
func readJSONFromFile(kpiName string) ([]map[string]interface{}, error) { // Function to read JSON data from a file
// Construct the file path func readJSONFromFile(folderName, kpiName string) ([]map[string]interface{}, error) {
filePath := fmt.Sprintf("kpi_files/%s.json", kpiName) // Construct the file path dynamically using the folder name
filePath := fmt.Sprintf("%s/%s.json", folderName, kpiName)
// Read and return the JSON content from the file // Read and return the JSON content from the file
fileContent, err := ioutil.ReadFile(filePath) fileContent, err := ioutil.ReadFile(filePath)
@ -211,6 +210,60 @@ func generateFilters(responseRaw []map[string]interface{}, filterKeys []string)
return filters, nil return filters, nil
} }
// Function to fetch filter data of dataset
func fetchfilterJSON(dataset string) ([]FilterGroup, error) {
// Define struct for the result
var dataSetFilter struct {
Id string `db:"id" json:"id"`
FullDataUrl string `db:"full_data_url" json:"full_data_url"`
FilterKeys string `db:"filter_keys" json:"filter_keys"`
FileStatus bool `db:"file_status" json:"file_status"`
DataSet string `db:"dataset" json:"dataset"`
}
// Query to get one row from the data_set_filter table
err := app.DB().
Select("id", "full_data_url", "filter_keys", "file_status", "dataset").
From("data_set_filter").
Where(dbx.HashExp{"dataset": dataset}).
One(&dataSetFilter)
if err != nil {
log.Printf("Failed to fetch data_set_filter data: %v", err)
return nil, err
}
// Fetch and convert XML to JSON if file is not saved
if !dataSetFilter.FileStatus { // Check if FileStatus is false
_, err := fetchAndConvertXMLToJSON(dataSetFilter.FullDataUrl, "filter_files", dataSetFilter.DataSet, "data_set_filter", dataSetFilter.Id)
if err != nil {
log.Printf("Failed to process URL '%s': %v", dataSetFilter.FullDataUrl, err)
return nil, err
}
}
// Read the JSON data from the file
response, err := readJSONFromFile("filter_files", dataSetFilter.DataSet)
if err != nil {
log.Printf("Failed to read JSON for dataset '%s': %v", dataSetFilter.DataSet, err)
return nil, err
}
// Parse the filter keys
filterKeys := strings.Split(dataSetFilter.FilterKeys, ",")
// Generate filters
filters, err := generateFilters(response, filterKeys)
if err != nil {
log.Printf("Failed to generate filters: %v", err)
return nil, err
}
// Return the filters directly
return filters, nil
}
var app *pocketbase.PocketBase var app *pocketbase.PocketBase
func main() { func main() {
@ -388,49 +441,49 @@ func main() {
return c.HTML(http.StatusOK, ` return c.HTML(http.StatusOK, `
<html> <html>
<head> <head>
<style> <style>
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
background-color: #f0f8ff; background-color: #f0f8ff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 100vh; height: 100vh;
margin: 0; margin: 0;
} }
.message-container { .message-container {
text-align: center; text-align: center;
background-color: #e0f7fa; background-color: #e0f7fa;
padding: 20px; padding: 20px;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
} }
.message-container h1 { .message-container h1 {
font-size: 24px; font-size: 24px;
color: #00796b; color: #00796b;
margin-bottom: 10px; margin-bottom: 10px;
} }
.message-container p { .message-container p {
font-size: 16px; font-size: 16px;
color: #004d40; color: #004d40;
} }
.icon { .icon {
font-size: 50px; font-size: 50px;
color: #00796b; color: #00796b;
margin-bottom: 20px; margin-bottom: 20px;
} }
</style> </style>
</head> </head>
<body> <body>
<div class="message-container"> <div class="message-container">
<i>&#x2714;</i> <i>&#x2714;</i>
<h1>User Approved Successfully</h1> <h1>User Approved Successfully</h1>
<p>The user has been approved, and the approval email has been sent.</p> <p>The user has been approved, and the approval email has been sent.</p>
</div> </div>
</body> </body>
</html> </html>
`) `)
}) })
return nil return nil
@ -460,50 +513,50 @@ func main() {
// Check if the email is already verified // Check if the email is already verified
if record.GetBool("reviewed") { if record.GetBool("reviewed") {
return c.HTML(http.StatusOK, ` return c.HTML(http.StatusOK, `
<html> <html>
<head> <head>
<style> <style>
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
background-color: #f0f8ff; background-color: #f0f8ff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 100vh; height: 100vh;
margin: 0; margin: 0;
} }
.message-container { .message-container {
text-align: center; text-align: center;
background-color: #ffe0e0; background-color: #ffe0e0;
padding: 20px; padding: 20px;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
} }
.message-container h1 { .message-container h1 {
font-size: 24px; font-size: 24px;
color: #b71c1c; color: #b71c1c;
margin-bottom: 10px; margin-bottom: 10px;
} }
.message-container p { .message-container p {
font-size: 16px; font-size: 16px;
color: #880e4f; color: #880e4f;
} }
.icon { .icon {
font-size: 50px; font-size: 50px;
color: #b71c1c; color: #b71c1c;
margin-bottom: 20px; margin-bottom: 20px;
} }
</style> </style>
</head> </head>
<body> <body>
<div class="message-container"> <div class="message-container">
<div class="icon">&#x2716;</div> <div class="icon">&#x2716;</div>
<h1>Your Already Reviewed</h1> <h1>Your Already Reviewed</h1>
<p>You have already been reviewed. No further action is required.</p> <p>You have already been reviewed. No further action is required.</p>
</div> </div>
</body> </body>
</html> </html>
`) `)
} }
// Check if the status is already "Denied" to avoid duplicate email // Check if the status is already "Denied" to avoid duplicate email
@ -630,32 +683,32 @@ func main() {
// Email body in HTML format // Email body in HTML format
body := fmt.Sprintf(` body := fmt.Sprintf(`
<html> <html>
<body> <body>
<p>Dear %s,</p> <p>Dear %s,</p>
<p> You have received new feedback from a user through the mobile application.</p> <p> You have received new feedback from a user through the mobile application.</p>
<p><b>User Details:</b></p> <p><b>User Details:</b></p>
<ul> <ul>
<li><b>Name</b> %s</li> <li><b>Name</b> %s</li>
<li><b>Date of Submission:</b> %s</li> <li><b>Date of Submission:</b> %s</li>
<li><b>Time of Submission:</b> %s</li> <li><b>Time of Submission:</b> %s</li>
</ul> </ul>
<p><b>Feedback:</b></p> <p><b>Feedback:</b></p>
<pre> <pre>
1. How was your experience with us today? Rating: %s 1. How was your experience with us today? Rating: %s
2. How did we perform in key areas? 2. How did we perform in key areas?
1. Ease of Use: %s 1. Ease of Use: %s
2. Quality: %s 2. Quality: %s
3. Design: %s 3. Design: %s
4. Redundancy: %s 4. Redundancy: %s
3. Additional Feedback: 3. Additional Feedback:
1. %s 1. %s
</pre> </pre>
<p>Thank you,</p> <p>Thank you,</p>
<p>The FCSC App Team</p> <p>The FCSC App Team</p>
</body> </body>
</html> </html>
`, adminName, userName, formattedDate, formattedDateTime, emojiRating, easeOfUse, quality, design, redundancy, additionalFeedback) `, adminName, userName, formattedDate, formattedDateTime, emojiRating, easeOfUse, quality, design, redundancy, additionalFeedback)
// Define the target type (e.g., "smtp") // Define the target type (e.g., "smtp")
targetType := "feedback_receive_mail" targetType := "feedback_receive_mail"
@ -829,6 +882,9 @@ func main() {
} }
var aggregatedResponse []map[string]interface{} var aggregatedResponse []map[string]interface{}
filterData, err := fetchfilterJSON(dataset)
for _, record := range records { for _, record := range records {
// Extract the URL for each record // Extract the URL for each record
apiURL := record.GetString("url") apiURL := record.GetString("url")
@ -842,7 +898,7 @@ func main() {
saveToFile := record.GetBool("file_status") saveToFile := record.GetBool("file_status")
chartId := record.GetString("id") chartId := record.GetString("id")
if !saveToFile { // Check if saveToFile is false if !saveToFile { // Check if saveToFile is false
_, err := fetchAndConvertXMLToJSON(apiURL, kpi, chartId) _, err := fetchAndConvertXMLToJSON(apiURL, "kpi_files", kpi, "charts", chartId)
if err != nil { if err != nil {
log.Printf("Failed to process URL '%s': %v", apiURL, err) log.Printf("Failed to process URL '%s': %v", apiURL, err)
continue // Skip this record and proceed with others continue // Skip this record and proceed with others
@ -850,30 +906,12 @@ func main() {
} }
// Read the JSON data from the file // Read the JSON data from the file
response, err := readJSONFromFile(kpi) response, err := readJSONFromFile("kpi_files", kpi)
if err != nil { if err != nil {
log.Printf("Failed to read JSON for KPI '%s': %v", kpi, err) log.Printf("Failed to read JSON for KPI '%s': %v", kpi, err)
continue // Skip this record and proceed with others continue // Skip this record and proceed with others
} }
var filters []FilterGroup
filterKeysRaw := record.GetString("filter")
if record.GetBool("is_chart") {
// Split the filter keys if they come as a comma-separated string
filterKeys := strings.Split(filterKeysRaw, ",")
// Generate filters
var err error
filters, err = generateFilters(response, filterKeys)
if err != nil {
panic(err)
}
} else {
// Assign an empty filter slice
filters = []FilterGroup{}
}
// Prepare the structure with URL and its response // Prepare the structure with URL and its response
recordResult := map[string]interface{}{ recordResult := map[string]interface{}{
"url": apiURL, "url": apiURL,
@ -884,7 +922,6 @@ func main() {
"is_chart": record.GetString("is_chart"), "is_chart": record.GetString("is_chart"),
"chart_type": record.GetString("chart_type"), "chart_type": record.GetString("chart_type"),
"response": response, "response": response,
"filters": filters,
"group_by": record.GetString("group_by"), "group_by": record.GetString("group_by"),
"chart_heading": record.GetString("chart_heading"), "chart_heading": record.GetString("chart_heading"),
} }
@ -894,11 +931,17 @@ func main() {
} }
// Create the response structure
response := map[string]interface{}{
"filter_data": filterData,
"data": aggregatedResponse,
}
if len(aggregatedResponse) == 0 { if len(aggregatedResponse) == 0 {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "No data could be fetched from the provided URLs"}) return c.JSON(http.StatusInternalServerError, map[string]string{"error": "No data could be fetched from the provided URLs"})
} }
return c.JSON(http.StatusOK, aggregatedResponse) return c.JSON(http.StatusOK, response)
}) })
e.Router.GET("/api/getHomePageData", func(c echo.Context) error { e.Router.GET("/api/getHomePageData", func(c echo.Context) error {
@ -907,13 +950,14 @@ func main() {
mainTopics := []struct { mainTopics := []struct {
MainTopic string `db:"main_topic" json:"main_topic"` MainTopic string `db:"main_topic" json:"main_topic"`
MainTopicListOrder string `db:"main_topic_list_order" json:"main_topic_list_order"` MainTopicListOrder string `db:"main_topic_list_order" json:"main_topic_list_order"`
ColorPattern string `db:"color_pattern" json:"color_pattern"`
}{} }{}
// Execute the query // Execute the query
err := app.DB(). err := app.DB().
Select("main_topic", "main_topic_list_order"). Select("main_topic", "main_topic_list_order", "color_pattern").
From("home_screen"). From("home_screen").
GroupBy("main_topic"). GroupBy("main_topic", "color_pattern").
OrderBy("main_topic_list_order ASC"). OrderBy("main_topic_list_order ASC").
All(&mainTopics) All(&mainTopics)
@ -987,6 +1031,7 @@ func main() {
result = append(result, map[string]interface{}{ result = append(result, map[string]interface{}{
"main_topic": mainTopic.MainTopic, "main_topic": mainTopic.MainTopic,
"main_topic_list_order": mainTopic.MainTopicListOrder, "main_topic_list_order": mainTopic.MainTopicListOrder,
"color_pattern": mainTopic.ColorPattern,
"sub_topics": result2, "sub_topics": result2,
}) })
} }

Binary file not shown.

BIN
pb_data/data.db-shm Normal file

Binary file not shown.

BIN
pb_data/data.db-wal Normal file

Binary file not shown.

Binary file not shown.

BIN
pb_data/logs.db-shm Normal file

Binary file not shown.

BIN
pb_data/logs.db-wal Normal file

Binary file not shown.