// outlooks_mapper.go maps outlook rows into weather model payloads. // Layer: adapters/outbound/postgres outlook feature. package postgres import ( "database/sql" "encoding/json" "fmt" "gitea.maximumdirect.net/ejr/weatherfeeder/model" ) func mapOutlookRunParentRow(row outlookRunParentRow) model.WeatherOutlookRun { return model.WeatherOutlookRun{ LocationID: stringValue(row.LocationID), LocationName: stringValue(row.LocationName), Latitude: float64Ptr(row.Latitude), Longitude: float64Ptr(row.Longitude), AsOf: row.AsOf.UTC(), IssuedAt: timePtr(row.IssuedAt), } } func mapOutlookRow(row outlookRow) (model.WeatherOutlook, error) { geometry := []byte(row.GeometryJSON) if !json.Valid(geometry) { return model.WeatherOutlook{}, fmt.Errorf("decode outlook geometry: invalid JSON") } return model.WeatherOutlook{ ID: row.OutlookID, Provider: row.Provider, Product: row.Product, Day: row.Day, OutlookType: row.OutlookType, Label: row.Label, LabelText: stringValue(row.LabelText), SeverityRank: intPtr(row.SeverityRank), ValidFrom: row.ValidFrom.UTC(), ValidTo: row.ValidTo.UTC(), IssuedAt: row.IssuedAt.UTC(), ExpiresAt: row.ExpiresAt.UTC(), Forecaster: stringValue(row.Forecaster), SourceURL: stringValue(row.SourceURL), ImageURL: stringValue(row.ImageURL), ContainsLocation: row.ContainsLocation, Geometry: json.RawMessage(append([]byte(nil), geometry...)), }, nil } func mapOutlookDiscussionRow(row outlookDiscussionRow) model.WeatherOutlookDiscussion { return model.WeatherOutlookDiscussion{ Day: row.Day, Headline: stringValue(row.Headline), Summary: stringValue(row.Summary), Discussion: stringValue(row.Discussion), UpdatedAt: timePtr(row.UpdatedAt), } } func intPtr(v sql.NullInt64) *int { if !v.Valid { return nil } out := int(v.Int64) return &out }