fix: Fix vector with KATO geometry
This commit is contained in:
parent
4fdd12e9a3
commit
f364ce4c6e
@ -166,11 +166,22 @@ func (r *DatasetRepository) SetProperties(ctx context.Context, id uuid.UUID, pro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkReady sets the dataset status to ready and clears any error.
|
// MarkReady sets the dataset status to ready, stores the dissolved feature
|
||||||
func (r *DatasetRepository) MarkReady(ctx context.Context, id uuid.UUID) error {
|
// geometry (GeoJSON in EPSG:4326; nil keeps the existing geometry, reduced to
|
||||||
|
// the union of all features via ST_UnaryUnion), and clears any error.
|
||||||
|
func (r *DatasetRepository) MarkReady(ctx context.Context, id uuid.UUID, geometry []byte) error {
|
||||||
|
var geom any // nil -> SQL NULL -> CASE keeps existing geometry
|
||||||
|
if len(geometry) > 0 {
|
||||||
|
geom = string(geometry)
|
||||||
|
}
|
||||||
tag, err := r.pool.Exec(ctx,
|
tag, err := r.pool.Exec(ctx,
|
||||||
`UPDATE datasets SET status = $2, parse_error = NULL, updated_at = now() WHERE id = $1`,
|
`UPDATE datasets
|
||||||
id, domain.DatasetStatusReady,
|
SET status = $2,
|
||||||
|
geometry = CASE WHEN $3::text IS NULL THEN geometry
|
||||||
|
ELSE ST_UnaryUnion(ST_SetSRID(ST_GeomFromGeoJSON($3), 4326)) END,
|
||||||
|
parse_error = NULL, updated_at = now()
|
||||||
|
WHERE id = $1`,
|
||||||
|
id, domain.DatasetStatusReady, geom,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapError(err)
|
return mapError(err)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ type DatasetRepository interface {
|
|||||||
Delete(ctx context.Context, id uuid.UUID) error
|
Delete(ctx context.Context, id uuid.UUID) error
|
||||||
MarkParsed(ctx context.Context, id uuid.UUID, cols []domain.AttributeColumn) error
|
MarkParsed(ctx context.Context, id uuid.UUID, cols []domain.AttributeColumn) error
|
||||||
MarkParseFailed(ctx context.Context, id uuid.UUID, reason string) error
|
MarkParseFailed(ctx context.Context, id uuid.UUID, reason string) error
|
||||||
MarkReady(ctx context.Context, id uuid.UUID) error
|
MarkReady(ctx context.Context, id uuid.UUID, geometry []byte) error
|
||||||
MarkConverted(ctx context.Context, id uuid.UUID, cogKey string, footprint []byte) error
|
MarkConverted(ctx context.Context, id uuid.UUID, cogKey string, footprint []byte) error
|
||||||
SetProperties(ctx context.Context, id uuid.UUID, properties, geometry []byte) error
|
SetProperties(ctx context.Context, id uuid.UUID, properties, geometry []byte) error
|
||||||
SaveMapping(ctx context.Context, id uuid.UUID, katoColumn string, years []domain.YearColumn) (domain.Dataset, error)
|
SaveMapping(ctx context.Context, id uuid.UUID, katoColumn string, years []domain.YearColumn) (domain.Dataset, error)
|
||||||
@ -515,9 +515,11 @@ func (s *DatasetService) SaveMapping(ctx context.Context, id uuid.UUID, in Mappi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract reads a mapped dataset's file, unpivots its attribute table into
|
// Extract reads a mapped dataset's file, unpivots its attribute table into
|
||||||
// observations keyed by KATO code and date, and marks the dataset ready. It is
|
// observations keyed by KATO code and date, records the dissolved feature
|
||||||
// invoked by the worker. Permanent failures (unparsable file) are recorded;
|
// geometry, and marks the dataset ready. It is invoked by the worker. Permanent
|
||||||
// transient failures (storage/DB) are returned for retry.
|
// failures (unparsable file) are recorded; transient failures (storage/DB) are
|
||||||
|
// returned for retry. Geometry extraction is best-effort: a failure leaves
|
||||||
|
// geometry unset rather than failing the job.
|
||||||
func (s *DatasetService) Extract(ctx context.Context, id uuid.UUID) error {
|
func (s *DatasetService) Extract(ctx context.Context, id uuid.UUID) error {
|
||||||
dataset, err := s.repo.GetByID(ctx, id)
|
dataset, err := s.repo.GetByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -541,7 +543,9 @@ func (s *DatasetService) Extract(ctx context.Context, id uuid.UUID) error {
|
|||||||
if err := s.repo.ReplaceObservations(ctx, id, obs); err != nil {
|
if err := s.repo.ReplaceObservations(ctx, id, obs); err != nil {
|
||||||
return err // transient
|
return err // transient
|
||||||
}
|
}
|
||||||
return s.repo.MarkReady(ctx, id)
|
|
||||||
|
geometry := s.vectorGeometry(ctx, dataset.Filename, data)
|
||||||
|
return s.repo.MarkReady(ctx, id, geometry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildObservations unpivots rows into observations. Rows without a KATO code
|
// buildObservations unpivots rows into observations. Rows without a KATO code
|
||||||
|
|||||||
@ -101,11 +101,14 @@ func (r *stubDatasetRepo) SaveMapping(_ context.Context, id uuid.UUID, kato stri
|
|||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *stubDatasetRepo) MarkReady(_ context.Context, id uuid.UUID) error {
|
func (r *stubDatasetRepo) MarkReady(_ context.Context, id uuid.UUID, geometry []byte) error {
|
||||||
d, ok := r.store[id]
|
d, ok := r.store[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return domain.ErrNotFound
|
return domain.ErrNotFound
|
||||||
}
|
}
|
||||||
|
if len(geometry) > 0 {
|
||||||
|
d.Geometry = geometry
|
||||||
|
}
|
||||||
d.Status = domain.DatasetStatusReady
|
d.Status = domain.DatasetStatusReady
|
||||||
r.store[id] = d
|
r.store[id] = d
|
||||||
return nil
|
return nil
|
||||||
@ -765,7 +768,9 @@ func TestDatasetService_Extract(t *testing.T) {
|
|||||||
}
|
}
|
||||||
rows := []map[string]string{{"като": "751010000", "F_2023": "100"}}
|
rows := []map[string]string{{"като": "751010000", "F_2023": "100"}}
|
||||||
rp := RowParser(func(string, []byte) ([]map[string]string, error) { return rows, nil })
|
rp := RowParser(func(string, []byte) ([]map[string]string, error) { return rows, nil })
|
||||||
svc := NewDatasetService(repo, &stubStore{}, stubCategoryReader{exists: true}, &stubEnqueuer{}, noopParser, rp, &stubConverter{})
|
geom := []byte(`{"type":"GeometryCollection","geometries":[]}`)
|
||||||
|
conv := &stubConverter{vectorGeom: geom}
|
||||||
|
svc := NewDatasetService(repo, &stubStore{}, stubCategoryReader{exists: true}, &stubEnqueuer{}, noopParser, rp, conv)
|
||||||
|
|
||||||
if err := svc.Extract(context.Background(), id); err != nil {
|
if err := svc.Extract(context.Background(), id); err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@ -773,6 +778,9 @@ func TestDatasetService_Extract(t *testing.T) {
|
|||||||
if repo.store[id].Status != domain.DatasetStatusReady {
|
if repo.store[id].Status != domain.DatasetStatusReady {
|
||||||
t.Fatalf("want ready, got %q", repo.store[id].Status)
|
t.Fatalf("want ready, got %q", repo.store[id].Status)
|
||||||
}
|
}
|
||||||
|
if string(repo.store[id].Geometry) != string(geom) {
|
||||||
|
t.Fatalf("want geometry %s, got %s", geom, repo.store[id].Geometry)
|
||||||
|
}
|
||||||
got := repo.observations[id]
|
got := repo.observations[id]
|
||||||
if len(got) != 1 || got[0].KatoCode != "751010000" || got[0].Value == nil || *got[0].Value != 100 {
|
if len(got) != 1 || got[0].KatoCode != "751010000" || got[0].Value == nil || *got[0].Value != 100 {
|
||||||
t.Fatalf("unexpected observations: %+v", got)
|
t.Fatalf("unexpected observations: %+v", got)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user