diff --git a/internal/report/create.go b/internal/report/create.go index 15b0b51..f502580 100644 --- a/internal/report/create.go +++ b/internal/report/create.go @@ -3,17 +3,19 @@ package report import ( "bytes" "context" + "database/sql" "fmt" "log/slog" "reflect" "strconv" + "time" "vctp/db" "github.com/xuri/excelize/v2" ) func CreateReport(logger *slog.Logger, Database db.Database, ctx context.Context) ([]byte, error) { - var xlsx *excelize.File + //var xlsx *excelize.File sheetName := "Inventory Report" var buffer bytes.Buffer @@ -29,6 +31,23 @@ func CreateReport(logger *slog.Logger, Database db.Database, ctx context.Context return nil, fmt.Errorf("Empty inventory results") } + // Create excek workbook + xlsx := excelize.NewFile() + err = xlsx.SetSheetName("Sheet1", sheetName) + if err != nil { + logger.Error("Error setting sheet name", "error", err, "sheet_name", sheetName) + return nil, err + } + + // Set the document properties + err = xlsx.SetDocProps(&excelize.DocProperties{ + Creator: "json2excel", + Created: time.Now().Format(time.RFC3339), + }) + if err != nil { + logger.Error("Error setting document properties", "error", err, "sheet_name", sheetName) + } + // Use reflection to determine column headings from the first item firstItem := results[0] v := reflect.ValueOf(firstItem) @@ -45,7 +64,8 @@ func CreateReport(logger *slog.Logger, Database db.Database, ctx context.Context v = reflect.ValueOf(item) for j := 0; j < v.NumField(); j++ { column := string(rune('A'+j)) + strconv.Itoa(i+2) // Start from row 2 - xlsx.SetCellValue(sheetName, column, v.Field(j).Interface()) + value := getFieldValue(v.Field(j)) + xlsx.SetCellValue(sheetName, column, value) } } @@ -56,3 +76,38 @@ func CreateReport(logger *slog.Logger, Database db.Database, ctx context.Context return buffer.Bytes(), nil } + +// Helper function to get the actual value of sql.Null types +func getFieldValue(field reflect.Value) interface{} { + switch field.Kind() { + case reflect.Struct: + // Handle sql.Null types based on their concrete type + switch field.Interface().(type) { + case sql.NullString: + ns := field.Interface().(sql.NullString) + if ns.Valid { + return ns.String + } + return "" + case sql.NullInt64: + ni := field.Interface().(sql.NullInt64) + if ni.Valid { + return ni.Int64 + } + return 0 + case sql.NullFloat64: + nf := field.Interface().(sql.NullFloat64) + if nf.Valid { + return nf.Float64 + } + return nil + case sql.NullBool: + nb := field.Interface().(sql.NullBool) + if nb.Valid { + return nb.Bool + } + return false + } + } + return field.Interface() // Return the value as-is for non-sql.Null types +} diff --git a/server/handler/vmModifyEvent.go b/server/handler/vmModifyEvent.go index fc8a135..7a44271 100644 --- a/server/handler/vmModifyEvent.go +++ b/server/handler/vmModifyEvent.go @@ -203,6 +203,7 @@ func (h *Handler) processConfigChanges(configChanges string) []map[string]string // Result will hold a list of changes with type and new value var result []map[string]string + matchFound := false for _, change := range changes { // Trim any extra spaces and skip empty lines @@ -215,6 +216,7 @@ func (h *Handler) processConfigChanges(configChanges string) []map[string]string // Find the matches using the regex match := re.FindStringSubmatch(change) if len(match) > 0 { + matchFound = true // Create a map with 'type' and 'newValue' changeMap := map[string]string{ "type": match[1], // config type @@ -227,6 +229,10 @@ func (h *Handler) processConfigChanges(configChanges string) []map[string]string } } + if !matchFound { + h.Logger.Info("No matches found for config change string", "input", configChanges) + } + return result }