package usecasehelper import ( "errors" "fmt" "net/url" "strings" "time" pl "simrs-vx/pkg/logger" "gorm.io/gorm" ) func SafeToResponse[T any](data *T) any { if data == nil { return nil } // Use type assertion to call ToResponse if the type has it if converter, ok := any(data).(interface{ ToResponse() any }); ok { return converter.ToResponse() } if converter, ok := any(*data).(interface{ ToResponse() any }); ok { return converter.ToResponse() } return nil } func HandleReadError(err error, event *pl.Event, itemType string, id interface{}, data any) error { if err == nil { pl.SetLogInfo(event, data, "complete") return nil } if errors.Is(err, gorm.ErrRecordNotFound) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-notFound", Detail: fmt.Sprintf("%s with ID %v not found", itemType, id), Raw: err, } } else { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-read-detail-fail", Detail: fmt.Sprintf("%s read failed", itemType), Raw: err, } } return pl.SetLogError(event, nil) } func HandleSearchError(err error, event *pl.Event, itemType string, query interface{}, data any) error { if err == nil { pl.SetLogInfo(event, data, "complete") return nil } if errors.Is(err, gorm.ErrRecordNotFound) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-notFound", Detail: fmt.Sprintf("%s with query '%v' not found", itemType, query), Raw: err, } } else { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-search-fail", Detail: fmt.Sprintf("%s search failed", itemType), Raw: err, } } return pl.SetLogError(event, nil) } func GetMiddlewareErrorCode(mwType MWType) string { if strings.Contains(string(mwType), "Pre") { return "MW_PRE_FAILED" } return "MW_POST_FAILED" } // GetLogData returns whichever of data or input is non-nil (prefers data) func GetLogData(input interface{}, data interface{}) interface{} { if data != nil { return data } return input } func HandleMiddlewareError(event *pl.Event, mwType, mwName string, logData interface{}, err error) error { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: GetMiddlewareErrorCode(MWType(mwType)), Detail: fmt.Sprintf("%s middleware %s failed: %s", mwType, mwName, err.Error()), Raw: err, } return pl.SetLogError(event, logData) } func IsDataNotFoundError(err error) bool { if err == nil { return false } return strings.Contains(err.Error(), "code: data-notFound") } func AddPrefix(prefix string, str string) string { return prefix + str } func GetPreloads(input string) []string { result := []string{} parts := strings.Split(input, ",") for _, p := range parts { subParts := strings.Split(p, "-") for i := range subParts { subParts[i] = kebabToPascal(subParts[i]) } result = append(result, strings.Join(subParts, ".")) } return result } func kebabToPascal(input string) string { parts := strings.Split(input, "-") for i, p := range parts { if len(p) > 0 { r := []rune(p) r[0] = []rune(strings.ToUpper(string(r[0])))[0] parts[i] = string(r) } } return strings.Join(parts, "") } func GetTimeNow() *time.Time { tmp := time.Now() return &tmp } func IsDateBeforeNow(t *time.Time) bool { if t == nil { return false } return t.Before(time.Now()) } // Contains reports whether v is present in s. func Contains[S ~[]E, E comparable](s S, v E) bool { return index(s, v) >= 0 } // Index returns the index of the first occurrence of v in s, // or -1 if not present. func index[S ~[]E, E comparable](s S, v E) int { for i := range s { if v == s[i] { return i } } return -1 } func FormatIndonesianDate(t time.Time) string { monthNames := [...]string{ "", // dummy index 0 "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember", } return fmt.Sprintf("%d %s %d", t.Day(), monthNames[int(t.Month())], t.Year()) } func GetLastTwoPathSegments(s string) string { u, err := url.Parse(s) var path string if err == nil && u.Path != "" { path = u.Path } else { path = s } parts := strings.Split(strings.Trim(path, "/"), "/") n := len(parts) if n >= 2 { return parts[n-2] + "/" + parts[n-1] } // fallback: return entire string if less than 2 segments return strings.Trim(path, "/") } func FormatPlaceAndDate(place string, t time.Time) string { // Ensure place is uppercase place = strings.ToUpper(strings.TrimSpace(place)) // Format date: DD-MM-YYYY dateStr := t.Format("02-01-2006") return place + ", " + dateStr }