diff --git a/src/modules/parcel-sync/components/parcel-sync-module.tsx b/src/modules/parcel-sync/components/parcel-sync-module.tsx
index f94c2be..152ef82 100644
--- a/src/modules/parcel-sync/components/parcel-sync-module.tsx
+++ b/src/modules/parcel-sync/components/parcel-sync-module.tsx
@@ -3068,6 +3068,30 @@ export function ParcelSyncModule() {
+ {/* Include no-geom toggle (works independently of scan) */}
+ {session.connected && (
+
+ )}
+
{/* Row 2: Background sync buttons */}
{session.connected && (
diff --git a/src/modules/parcel-sync/services/eterra-client.ts b/src/modules/parcel-sync/services/eterra-client.ts
index 70d7d01..96387f4 100644
--- a/src/modules/parcel-sync/services/eterra-client.ts
+++ b/src/modules/parcel-sync/services/eterra-client.ts
@@ -339,6 +339,11 @@ export class EterraClient {
let offset = 0;
const all: EsriFeature[] = [];
+ // ArcGIS servers have a maxRecordCount (typically 1000).
+ // If we request 2000 but get exactly 1000, we hit the server cap.
+ // Track this so we continue paginating instead of stopping.
+ let serverMaxRecordCount: number | null = null;
+
while (true) {
const params = new URLSearchParams();
params.set("f", "json");
@@ -375,11 +380,28 @@ export class EterraClient {
break;
}
+ // Detect server maxRecordCount cap:
+ // If we asked for more than we got AND the result is a round number
+ // (1000, 2000), the server likely capped us. Adjust pageSize to match.
+ if (
+ serverMaxRecordCount === null &&
+ features.length < pageSize &&
+ features.length > 0 &&
+ features.length % 500 === 0 // round cap: 500, 1000, 1500, 2000...
+ ) {
+ serverMaxRecordCount = features.length;
+ pageSize = serverMaxRecordCount;
+ // Don't break — this is a full page at server's cap, continue
+ }
+
all.push(...features);
offset += features.length;
if (onProgress) onProgress(all.length, total);
if (total && all.length >= total) break;
- if (features.length < pageSize) {
+
+ // End of data: fewer features than the effective page size
+ const effectivePageSize = serverMaxRecordCount ?? pageSize;
+ if (features.length < effectivePageSize) {
const nextSize = PAGE_SIZE_FALLBACKS.find((s) => s < pageSize);
if (total && all.length < total && nextSize) {
pageSize = nextSize;
diff --git a/src/modules/parcel-sync/services/no-geom-sync.ts b/src/modules/parcel-sync/services/no-geom-sync.ts
index d895e66..37020af 100644
--- a/src/modules/parcel-sync/services/no-geom-sync.ts
+++ b/src/modules/parcel-sync/services/no-geom-sync.ts
@@ -223,36 +223,53 @@ export async function scanNoGeometryParcels(
// 2. Fetch remote GIS cadastral refs (lightweight — no geometry)
// This is the source of truth for "has geometry" regardless of local DB state.
- // ~4 pages for 8k features with outFields only = very fast.
+ // Count first so pagination knows the total and doesn't stop early.
const terenuriLayer = {
id: "TERENURI_ACTIVE",
name: "TERENURI_ACTIVE",
endpoint: "aut" as const,
whereTemplate: "{{adminField}}={{siruta}} AND IS_ACTIVE=1",
};
+ const [terenuriCount, cladiriCount] = await Promise.all([
+ client.countLayer(terenuriLayer, siruta).catch(() => 0),
+ client
+ .countLayer(
+ {
+ id: "CLADIRI_ACTIVE",
+ name: "CLADIRI_ACTIVE",
+ endpoint: "aut" as const,
+ whereTemplate: "{{adminField}}={{siruta}} AND IS_ACTIVE=1",
+ },
+ siruta,
+ )
+ .catch(() => 0),
+ ]);
const remoteFeatures = await client.fetchAllLayer(terenuriLayer, siruta, {
returnGeometry: false,
outFields: "OBJECTID,NATIONAL_CADASTRAL_REFERENCE,IMMOVABLE_ID",
- pageSize: 2000,
+ pageSize: 1000,
+ total: terenuriCount > 0 ? terenuriCount : undefined,
});
- // 2b. Also fetch CLADIRI_ACTIVE count (lightweight, just OBJECTID)
+ // 2b. Also fetch CLADIRI_ACTIVE features (lightweight, just OBJECTID)
const cladiriLayer = {
id: "CLADIRI_ACTIVE",
name: "CLADIRI_ACTIVE",
endpoint: "aut" as const,
whereTemplate: "{{adminField}}={{siruta}} AND IS_ACTIVE=1",
};
- let remoteCladiriCount = 0;
- try {
- const cladiriFeatures = await client.fetchAllLayer(cladiriLayer, siruta, {
- returnGeometry: false,
- outFields: "OBJECTID",
- pageSize: 2000,
- });
- remoteCladiriCount = cladiriFeatures.length;
- } catch {
- // Non-fatal — just won't show clădiri count
+ let remoteCladiriCount = cladiriCount;
+ if (remoteCladiriCount === 0) {
+ try {
+ const cladiriFeatures = await client.fetchAllLayer(cladiriLayer, siruta, {
+ returnGeometry: false,
+ outFields: "OBJECTID",
+ pageSize: 1000,
+ });
+ remoteCladiriCount = cladiriFeatures.length;
+ } catch {
+ // Non-fatal — just won't show clădiri count
+ }
}
const remoteCadRefs = new Set();