package store import ( "context" "fmt" "gitea.stevedudenhoeffer.com/steve/pansy/internal/domain" ) // scanPlanting reads a plantings row in table-declared column order (id, // object_id, plant_id, x_cm, y_cm, radius_cm, count, label, planted_at, // removed_at, version, created_at, updated_at) — the order SELECT pl.* yields. func scanPlanting(s scanner) (*domain.Planting, error) { var p domain.Planting if err := s.Scan( &p.ID, &p.ObjectID, &p.PlantID, &p.XCM, &p.YCM, &p.RadiusCM, &p.Count, &p.Label, &p.PlantedAt, &p.RemovedAt, &p.Version, &p.CreatedAt, &p.UpdatedAt, ); err != nil { return nil, err } return &p, nil } // ListActivePlantingsForGarden returns every currently-planted plop (removed_at // IS NULL) across all objects in a garden — the editor's one-shot load. Always a // non-nil slice (empty until plantings CRUD lands in #14). Plop CRUD itself is // #14; this is only the /full read side. func (d *DB) ListActivePlantingsForGarden(ctx context.Context, gardenID int64) ([]domain.Planting, error) { // pl.* returns the plantings columns in table-declared order, which matches // plantingColumns / scanPlanting. rows, err := d.sql.QueryContext(ctx, `SELECT pl.* FROM plantings pl JOIN garden_objects o ON o.id = pl.object_id WHERE o.garden_id = ? AND pl.removed_at IS NULL ORDER BY pl.id`, gardenID, ) if err != nil { return nil, fmt.Errorf("store: list plantings: %w", err) } defer rows.Close() plantings := []domain.Planting{} for rows.Next() { p, err := scanPlanting(rows) if err != nil { return nil, fmt.Errorf("store: scan planting: %w", err) } plantings = append(plantings, *p) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("store: iterate plantings: %w", err) } return plantings, nil }