@flowselections/floriday-authenticatie-module 1.0.14 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist-lib/integrations/supabase/auth-middleware.d.ts +231 -0
  2. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  3. package/dist-lib/integrations/supabase/client.d.ts +231 -0
  4. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  5. package/dist-lib/integrations/supabase/client.server.d.ts +231 -0
  6. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  7. package/dist-lib/integrations/supabase/types.d.ts +239 -0
  8. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  9. package/dist-lib/lib/floricode-product-features.d.ts.map +1 -1
  10. package/dist-lib/lib/floricode-product-features.js +59 -5
  11. package/dist-lib/lib/floricode-regulatory-features.d.ts +15 -0
  12. package/dist-lib/lib/floricode-regulatory-features.d.ts.map +1 -1
  13. package/dist-lib/lib/floricode-regulatory-features.js +77 -21
  14. package/dist-lib/lib/floriday-auction-letters.functions.d.ts +231 -0
  15. package/dist-lib/lib/floriday-auction-letters.functions.d.ts.map +1 -1
  16. package/dist-lib/lib/floriday-labels.functions.d.ts +231 -0
  17. package/dist-lib/lib/floriday-labels.functions.d.ts.map +1 -1
  18. package/dist-lib/lib/floriday-public.functions.d.ts +1386 -0
  19. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  20. package/dist-lib/lib/floriday-stickers.functions.d.ts +231 -0
  21. package/dist-lib/lib/floriday-stickers.functions.d.ts.map +1 -1
  22. package/dist-lib/lib/floriday-sync.functions.d.ts +7161 -0
  23. package/dist-lib/lib/floriday-sync.functions.d.ts.map +1 -1
  24. package/dist-lib/lib/floriday-writes.functions.d.ts +1386 -0
  25. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  26. package/dist-lib/lib/floriday.functions.d.ts +4158 -0
  27. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  28. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"floricode-product-features.d.ts","sourceRoot":"","sources":["../../src/lib/floricode-product-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAShE,QAAA,MAAM,yBAAyB,+BAA+B,CAAC;AAY/D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AA0OD,wBAAsB,mCAAmC,CACvD,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,mBAAmB,EAChC,gBAAgB,EAAE,MAAM,GAAG,MAAM,EACjC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,OAAO,CAAC;IACT,EAAE,EAAE,IAAI,CAAC;IACT,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACnC,YAAY,EAAE,OAAO,yBAAyB,CAAC;IAC/C,eAAe,EAAE,qBAAqB,EAAE,CAAC;CAC1C,CAAC,CAuDD;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;GAiF1D"}
1
+ {"version":3,"file":"floricode-product-features.d.ts","sourceRoot":"","sources":["../../src/lib/floricode-product-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAShE,QAAA,MAAM,yBAAyB,+BAA+B,CAAC;AAc/D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAuRD,wBAAsB,mCAAmC,CACvD,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,mBAAmB,EAChC,gBAAgB,EAAE,MAAM,GAAG,MAAM,EACjC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,OAAO,CAAC;IACT,EAAE,EAAE,IAAI,CAAC;IACT,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACnC,YAAY,EAAE,OAAO,yBAAyB,CAAC;IAC/C,eAAe,EAAE,qBAAqB,EAAE,CAAC;CAC1C,CAAC,CAiFD;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;GAiF1D"}
@@ -4,6 +4,8 @@ const FLORICODE_PRODUCT_FEATURE_URL = "https://api.floricode.com/v2/VBN/ProductF
4
4
  const PRODUCT_FEATURE_SCOPE = "vbn_productfeature:read";
5
5
  const PRODUCT_FEATURE_LIST_NAME = "vbn-product-characteristic";
6
6
  const PRODUCT_FEATURE_RESOURCE = "ProductFeature";
7
+ const REG_FEATURE_TYPE_RESOURCE = "RegulatoryFeatureType";
8
+ const SENTINEL_NONE_MARKER = "__none__";
7
9
  function normalizeProductCode(input) {
8
10
  const value = String(input).trim();
9
11
  if (!/^\d+$/.test(value)) {
@@ -191,11 +193,41 @@ async function readCachedProductCharacteristics(supabase, environment, productCo
191
193
  });
192
194
  return rows;
193
195
  }
196
+ function cacheIsComplete(cached) {
197
+ // Volledige cache-hit = er staat minimaal één regulatory-feature (S-code) in.
198
+ // Puur B*/T*-rijen zonder regulation_type_id betekent dat de RegulatoryFeatureType-
199
+ // sync dit product nog niet heeft geraakt (bulk-sync nog niet klaar of nieuwe koppeling).
200
+ return cached.some((row) => row.regulationTypeId != null ||
201
+ String(row.payload?.source ?? "") === "Floricode RegulatoryFeatureType");
202
+ }
203
+ async function hasSentinelForProduct(supabase, productCode) {
204
+ const { data } = await supabase
205
+ .from("floricode_records")
206
+ .select("record_id")
207
+ .eq("resource", REG_FEATURE_TYPE_RESOURCE)
208
+ .eq("record_id", `${productCode}:${SENTINEL_NONE_MARKER}`)
209
+ .maybeSingle();
210
+ return !!data;
211
+ }
212
+ async function writeSentinelForProduct(supabase, productCode) {
213
+ const nowIso = new Date().toISOString();
214
+ await supabase.from("floricode_records").upsert({
215
+ resource: REG_FEATURE_TYPE_RESOURCE,
216
+ record_id: `${productCode}:${SENTINEL_NONE_MARKER}`,
217
+ data: {
218
+ product_id: productCode,
219
+ __sentinel: "no-regulatory-features",
220
+ checked_at: nowIso,
221
+ },
222
+ change_date_time: null,
223
+ last_synced_at: nowIso,
224
+ }, { onConflict: "resource,record_id" });
225
+ }
194
226
  export async function getProductCharacteristicsForVbnCode(supabase, environment, productCodeInput, options = {}) {
195
227
  const productCode = normalizeProductCode(productCodeInput);
196
228
  if (!options.forceRefresh) {
197
229
  const cached = await readCachedProductCharacteristics(supabase, environment, productCode);
198
- if (cached.length > 0) {
230
+ if (cached.length > 0 && cacheIsComplete(cached)) {
199
231
  return {
200
232
  ok: true,
201
233
  productCode,
@@ -206,10 +238,25 @@ export async function getProductCharacteristicsForVbnCode(supabase, environment,
206
238
  characteristics: cached,
207
239
  };
208
240
  }
241
+ // Sentinel: eerder bevestigd dat dit product geen regulatory features heeft.
242
+ // Terugvallen op wat er in de cache staat (B*/T* of leeg) zonder Floricode-call.
243
+ if (await hasSentinelForProduct(supabase, productCode)) {
244
+ const meta = await loadProductMeta(supabase, environment, productCode);
245
+ return {
246
+ ok: true,
247
+ productCode,
248
+ productGroupId: cached[0]?.productGroupId ?? meta.productGroupId,
249
+ productName: cached[0]?.productName ?? meta.productName,
250
+ source: "cache",
251
+ codeListName: PRODUCT_FEATURE_LIST_NAME,
252
+ characteristics: cached,
253
+ };
254
+ }
209
255
  }
210
- // Live-fetch: RegulatoryFeatureType (verplichte/optionele kenmerken) +
211
- // ProductFeature (default-waardes) parallel, upsert in floricode_records
212
- // en daarna RPC draaien zodat de derived code-list weer up-to-date is.
256
+ // Live-fetch: RegulatoryFeatureType (verplichte kenmerken, S-codes) + ProductFeature
257
+ // (default-waarden) parallel, upsert in floricode_records en projectie draaien.
258
+ // ProductFeature is meestal al gedekt door de bulk-sync, maar we halen 'm veiligheidshalve
259
+ // ook op zodat een nieuw product direct default-waarden krijgt.
213
260
  const [regItems, pfItems] = await Promise.all([
214
261
  fetchFloricodeRegulatoryFeaturesForProduct(productCode).catch((e) => {
215
262
  console.warn("[product-characteristics] RegulatoryFeatureType fetch failed:", String(e?.message ?? e));
@@ -225,11 +272,18 @@ export async function getProductCharacteristicsForVbnCode(supabase, environment,
225
272
  if (pfItems.length > 0)
226
273
  await upsertFloricodeProductFeatureRecords(supabase, pfItems);
227
274
  if (regItems.length > 0 || pfItems.length > 0) {
228
- const { error: projError } = await supabase.rpc("refresh_floricode_derived_code_lists");
275
+ // Lichtgewicht per-product projectie i.p.v. de volledige RPC — die is te zwaar
276
+ // om synchroon vanuit een wizard-request te draaien.
277
+ const { error: projError } = await supabase.rpc("refresh_floricode_derived_for_product", { p_product_code: productCode });
229
278
  if (projError) {
230
279
  console.warn("[product-characteristics] projection failed:", projError.message);
231
280
  }
232
281
  }
282
+ // Geen S-codes uit Floricode → sentinel schrijven zodat we dit product niet elke
283
+ // wizard-open opnieuw hoeven te bevragen.
284
+ if (regItems.length === 0) {
285
+ await writeSentinelForProduct(supabase, productCode).catch((e) => console.warn("[product-characteristics] sentinel write failed:", String(e?.message ?? e)));
286
+ }
233
287
  const fresh = await readCachedProductCharacteristics(supabase, environment, productCode);
234
288
  const meta = await loadProductMeta(supabase, environment, productCode);
235
289
  return {
@@ -28,14 +28,29 @@ export declare function syncFloricodeRegulationTypes(supabase: SupabaseClient):
28
28
  export declare function syncFloricodeRegulatoryFeatures(supabase: SupabaseClient, options?: {
29
29
  batchSize?: number;
30
30
  maxBatches?: number;
31
+ resume?: boolean;
31
32
  }): Promise<{
32
33
  ok: true;
33
34
  resource: string;
35
+ completed: boolean;
36
+ startSkip: number;
37
+ endSkip: number;
34
38
  fetched: number;
35
39
  upserted: number;
36
40
  batches: number;
37
41
  projected: any;
38
42
  durationMs: number;
43
+ } | {
44
+ ok: true;
45
+ resource: string;
46
+ completed: boolean;
47
+ startSkip: number;
48
+ endSkip: number;
49
+ fetched: number;
50
+ upserted: number;
51
+ batches: number;
52
+ durationMs: number;
53
+ projected?: undefined;
39
54
  }>;
40
55
  export {};
41
56
  //# sourceMappingURL=floricode-regulatory-features.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floricode-regulatory-features.d.ts","sourceRoot":"","sources":["../../src/lib/floricode-regulatory-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAY5D,UAAU,cAAc;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,cAAc;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAoCD,wBAAsB,0CAA0C,CAC9D,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC,CAgB3B;AAkCD,wBAAsB,8BAA8B,CAClD,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,cAAc,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,cAAc,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAiBD,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,cAAc;;;;;;GA2B1E;AAED,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;GAyE1D"}
1
+ {"version":3,"file":"floricode-regulatory-features.d.ts","sourceRoot":"","sources":["../../src/lib/floricode-regulatory-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAY5D,UAAU,cAAc;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,cAAc;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAoCD,wBAAsB,0CAA0C,CAC9D,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC,CAgB3B;AAkCD,wBAAsB,8BAA8B,CAClD,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,cAAc,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,cAAc,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAiBD,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,cAAc;;;;;;GA2B1E;AAED,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;GAwI5E"}
@@ -157,22 +157,40 @@ export async function syncFloricodeRegulatoryFeatures(supabase, options = {}) {
157
157
  const startedAt = Date.now();
158
158
  const batchSize = Math.min(Math.max(options.batchSize ?? 5000, 1), 5000);
159
159
  const maxBatches = options.maxBatches && options.maxBatches > 0 ? options.maxBatches : Infinity;
160
+ const resume = options.resume !== false;
161
+ // Read cursor from state so we can resume where the previous invocation stopped.
162
+ let skip = 0;
163
+ let maxChangeDateTime = null;
164
+ if (resume) {
165
+ const { data: state } = await supabase
166
+ .from("floricode_sync_state")
167
+ .select("cursor_skip,last_change_date_time,status")
168
+ .eq("resource", REG_FEATURE_TYPE_RESOURCE)
169
+ .maybeSingle();
170
+ if (state && state.status === "running") {
171
+ skip = Number(state.cursor_skip ?? 0) || 0;
172
+ maxChangeDateTime = state.last_change_date_time ?? null;
173
+ }
174
+ }
175
+ const startSkip = skip;
160
176
  let fetched = 0;
161
177
  let upserted = 0;
162
- let skip = 0;
163
178
  let batches = 0;
164
- let maxChangeDateTime = null;
179
+ let completed = false;
165
180
  await setSyncState(supabase, REG_FEATURE_TYPE_RESOURCE, {
166
181
  status: "running",
167
182
  error_message: null,
183
+ cursor_skip: skip,
168
184
  last_sync_at: new Date().toISOString(),
169
185
  });
170
186
  try {
171
187
  const token = await getFloricodeToken(REG_FEATURE_TYPE_SCOPE);
172
188
  while (batches < maxBatches) {
173
189
  const items = await fetchRegFeatureTypePage(token, skip, batchSize);
174
- if (items.length === 0)
190
+ if (items.length === 0) {
191
+ completed = true;
175
192
  break;
193
+ }
176
194
  fetched += items.length;
177
195
  upserted += await upsertRegulatoryFeatureRecords(supabase, items);
178
196
  for (const item of items) {
@@ -182,33 +200,71 @@ export async function syncFloricodeRegulatoryFeatures(supabase, options = {}) {
182
200
  }
183
201
  batches += 1;
184
202
  skip += items.length;
185
- if (items.length < batchSize)
203
+ // Persist cursor after each batch so a crash mid-run resumes correctly.
204
+ await setSyncState(supabase, REG_FEATURE_TYPE_RESOURCE, {
205
+ status: "running",
206
+ error_message: null,
207
+ cursor_skip: skip,
208
+ last_change_date_time: maxChangeDateTime,
209
+ last_sync_at: new Date().toISOString(),
210
+ });
211
+ if (items.length < batchSize) {
212
+ completed = true;
186
213
  break;
214
+ }
187
215
  }
188
- // RegulationType is een kleine lijst — altijd meeladen voor labels.
189
- try {
190
- await syncFloricodeRegulationTypes(supabase);
216
+ // Ook bij partial runs projectie draaien zodat vbn-product-characteristic
217
+ // meegroeit met de raw cache. Fouten hier mogen de cursor niet blokkeren.
218
+ if (!completed && upserted > 0) {
219
+ try {
220
+ await supabase.rpc("refresh_floricode_derived_code_lists");
221
+ }
222
+ catch (e) {
223
+ console.warn("[regulatory] partial projection skipped:", String(e?.message ?? e));
224
+ }
191
225
  }
192
- catch (e) {
193
- console.warn("[regulatory] RegulationType sync skipped:", String(e?.message ?? e));
226
+ if (completed) {
227
+ // RegulationType is een kleine lijst — altijd meeladen voor labels.
228
+ try {
229
+ await syncFloricodeRegulationTypes(supabase);
230
+ }
231
+ catch (e) {
232
+ console.warn("[regulatory] RegulationType sync skipped:", String(e?.message ?? e));
233
+ }
234
+ const { data: projection, error: projectionError } = await supabase.rpc("refresh_floricode_derived_code_lists");
235
+ if (projectionError)
236
+ throw new Error(`Projectie naar code-lists mislukt: ${projectionError.message}`);
237
+ await setSyncState(supabase, REG_FEATURE_TYPE_RESOURCE, {
238
+ status: "success",
239
+ error_message: null,
240
+ cursor_skip: 0,
241
+ last_sequence_number: skip,
242
+ last_change_date_time: maxChangeDateTime,
243
+ last_sync_at: new Date().toISOString(),
244
+ });
245
+ return {
246
+ ok: true,
247
+ resource: REG_FEATURE_TYPE_RESOURCE,
248
+ completed: true,
249
+ startSkip,
250
+ endSkip: skip,
251
+ fetched,
252
+ upserted,
253
+ batches,
254
+ projected: projection ?? [],
255
+ durationMs: Date.now() - startedAt,
256
+ };
194
257
  }
195
- const { data: projection, error: projectionError } = await supabase.rpc("refresh_floricode_derived_code_lists");
196
- if (projectionError)
197
- throw new Error(`Projectie naar code-lists mislukt: ${projectionError.message}`);
198
- await setSyncState(supabase, REG_FEATURE_TYPE_RESOURCE, {
199
- status: "success",
200
- error_message: null,
201
- last_sequence_number: fetched,
202
- last_change_date_time: maxChangeDateTime,
203
- last_sync_at: new Date().toISOString(),
204
- });
258
+ // Partial run — leave status='running' so the next cron tick resumes.
205
259
  return {
206
260
  ok: true,
207
261
  resource: REG_FEATURE_TYPE_RESOURCE,
262
+ completed: false,
263
+ startSkip,
264
+ endSkip: skip,
208
265
  fetched,
209
266
  upserted,
210
267
  batches,
211
- projected: projection ?? [],
212
268
  durationMs: Date.now() - startedAt,
213
269
  };
214
270
  }
@@ -217,7 +273,7 @@ export async function syncFloricodeRegulatoryFeatures(supabase, options = {}) {
217
273
  await setSyncState(supabase, REG_FEATURE_TYPE_RESOURCE, {
218
274
  status: "error",
219
275
  error_message: msg,
220
- last_sequence_number: fetched,
276
+ cursor_skip: skip,
221
277
  last_change_date_time: maxChangeDateTime,
222
278
  last_sync_at: new Date().toISOString(),
223
279
  });
@@ -2747,6 +2747,7 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
2747
2747
  };
2748
2748
  floricode_sync_state: {
2749
2749
  Row: {
2750
+ cursor_skip: number;
2750
2751
  error_message: string | null;
2751
2752
  last_change_date_time: string | null;
2752
2753
  last_sequence_number: number;
@@ -2756,6 +2757,7 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
2756
2757
  updated_at: string;
2757
2758
  };
2758
2759
  Insert: {
2760
+ cursor_skip?: number;
2759
2761
  error_message?: string | null;
2760
2762
  last_change_date_time?: string | null;
2761
2763
  last_sequence_number?: number;
@@ -2765,6 +2767,7 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
2765
2767
  updated_at?: string;
2766
2768
  };
2767
2769
  Update: {
2770
+ cursor_skip?: number;
2768
2771
  error_message?: string | null;
2769
2772
  last_change_date_time?: string | null;
2770
2773
  last_sequence_number?: number;
@@ -5112,6 +5115,93 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
5112
5115
  };
5113
5116
  Relationships: [];
5114
5117
  };
5118
+ manufacture_product_components: {
5119
+ Row: {
5120
+ component_type: string;
5121
+ created_at: string;
5122
+ id: string;
5123
+ manufacture_product_id: string;
5124
+ product_group_id: string | null;
5125
+ quantity: number;
5126
+ trade_item_id: string | null;
5127
+ unit: string;
5128
+ };
5129
+ Insert: {
5130
+ component_type: string;
5131
+ created_at?: string;
5132
+ id?: string;
5133
+ manufacture_product_id: string;
5134
+ product_group_id?: string | null;
5135
+ quantity?: number;
5136
+ trade_item_id?: string | null;
5137
+ unit?: string;
5138
+ };
5139
+ Update: {
5140
+ component_type?: string;
5141
+ created_at?: string;
5142
+ id?: string;
5143
+ manufacture_product_id?: string;
5144
+ product_group_id?: string | null;
5145
+ quantity?: number;
5146
+ trade_item_id?: string | null;
5147
+ unit?: string;
5148
+ };
5149
+ Relationships: [{
5150
+ foreignKeyName: "manufacture_product_components_manufacture_product_id_fkey";
5151
+ columns: ["manufacture_product_id"];
5152
+ isOneToOne: false;
5153
+ referencedRelation: "manufacture_product_possible_stock_view";
5154
+ referencedColumns: ["manufacture_product_id"];
5155
+ }, {
5156
+ foreignKeyName: "manufacture_product_components_manufacture_product_id_fkey";
5157
+ columns: ["manufacture_product_id"];
5158
+ isOneToOne: false;
5159
+ referencedRelation: "manufacture_products";
5160
+ referencedColumns: ["id"];
5161
+ }, {
5162
+ foreignKeyName: "manufacture_product_components_product_group_id_fkey";
5163
+ columns: ["product_group_id"];
5164
+ isOneToOne: false;
5165
+ referencedRelation: "product_groups";
5166
+ referencedColumns: ["id"];
5167
+ }];
5168
+ };
5169
+ manufacture_products: {
5170
+ Row: {
5171
+ created_at: string;
5172
+ description: string | null;
5173
+ id: string;
5174
+ is_active: boolean;
5175
+ name: string;
5176
+ produced_stock: number;
5177
+ product_code: string;
5178
+ tenant_id: string;
5179
+ updated_at: string;
5180
+ };
5181
+ Insert: {
5182
+ created_at?: string;
5183
+ description?: string | null;
5184
+ id?: string;
5185
+ is_active?: boolean;
5186
+ name: string;
5187
+ produced_stock?: number;
5188
+ product_code: string;
5189
+ tenant_id: string;
5190
+ updated_at?: string;
5191
+ };
5192
+ Update: {
5193
+ created_at?: string;
5194
+ description?: string | null;
5195
+ id?: string;
5196
+ is_active?: boolean;
5197
+ name?: string;
5198
+ produced_stock?: number;
5199
+ product_code?: string;
5200
+ tenant_id?: string;
5201
+ updated_at?: string;
5202
+ };
5203
+ Relationships: [];
5204
+ };
5115
5205
  monteurs: {
5116
5206
  Row: {
5117
5207
  avatar_url: string | null;
@@ -6072,6 +6162,66 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
6072
6162
  };
6073
6163
  Relationships: [];
6074
6164
  };
6165
+ product_group_items: {
6166
+ Row: {
6167
+ created_at: string;
6168
+ id: string;
6169
+ product_group_id: string;
6170
+ quantity: number;
6171
+ trade_item_id: string;
6172
+ };
6173
+ Insert: {
6174
+ created_at?: string;
6175
+ id?: string;
6176
+ product_group_id: string;
6177
+ quantity?: number;
6178
+ trade_item_id: string;
6179
+ };
6180
+ Update: {
6181
+ created_at?: string;
6182
+ id?: string;
6183
+ product_group_id?: string;
6184
+ quantity?: number;
6185
+ trade_item_id?: string;
6186
+ };
6187
+ Relationships: [{
6188
+ foreignKeyName: "product_group_items_product_group_id_fkey";
6189
+ columns: ["product_group_id"];
6190
+ isOneToOne: false;
6191
+ referencedRelation: "product_groups";
6192
+ referencedColumns: ["id"];
6193
+ }];
6194
+ };
6195
+ product_groups: {
6196
+ Row: {
6197
+ created_at: string;
6198
+ description: string | null;
6199
+ id: string;
6200
+ is_active: boolean;
6201
+ name: string;
6202
+ tenant_id: string;
6203
+ updated_at: string;
6204
+ };
6205
+ Insert: {
6206
+ created_at?: string;
6207
+ description?: string | null;
6208
+ id?: string;
6209
+ is_active?: boolean;
6210
+ name: string;
6211
+ tenant_id: string;
6212
+ updated_at?: string;
6213
+ };
6214
+ Update: {
6215
+ created_at?: string;
6216
+ description?: string | null;
6217
+ id?: string;
6218
+ is_active?: boolean;
6219
+ name?: string;
6220
+ tenant_id?: string;
6221
+ updated_at?: string;
6222
+ };
6223
+ Relationships: [];
6224
+ };
6075
6225
  products: {
6076
6226
  Row: {
6077
6227
  barcode: string | null;
@@ -7233,6 +7383,48 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
7233
7383
  };
7234
7384
  Relationships: [];
7235
7385
  };
7386
+ trade_item_stock: {
7387
+ Row: {
7388
+ connection_id: string;
7389
+ created_at: string;
7390
+ id: string;
7391
+ incoming_stock: number;
7392
+ minimum_stock: number;
7393
+ notes: string | null;
7394
+ physical_stock: number;
7395
+ reserved_stock: number;
7396
+ trade_item_key: string;
7397
+ updated_at: string;
7398
+ user_id: string;
7399
+ };
7400
+ Insert: {
7401
+ connection_id: string;
7402
+ created_at?: string;
7403
+ id?: string;
7404
+ incoming_stock?: number;
7405
+ minimum_stock?: number;
7406
+ notes?: string | null;
7407
+ physical_stock?: number;
7408
+ reserved_stock?: number;
7409
+ trade_item_key: string;
7410
+ updated_at?: string;
7411
+ user_id: string;
7412
+ };
7413
+ Update: {
7414
+ connection_id?: string;
7415
+ created_at?: string;
7416
+ id?: string;
7417
+ incoming_stock?: number;
7418
+ minimum_stock?: number;
7419
+ notes?: string | null;
7420
+ physical_stock?: number;
7421
+ reserved_stock?: number;
7422
+ trade_item_key?: string;
7423
+ updated_at?: string;
7424
+ user_id?: string;
7425
+ };
7426
+ Relationships: [];
7427
+ };
7236
7428
  twinfield_connections: {
7237
7429
  Row: {
7238
7430
  access_token: string | null;
@@ -8417,6 +8609,35 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
8417
8609
  };
8418
8610
  Relationships: [];
8419
8611
  };
8612
+ manufacture_product_possible_stock_view: {
8613
+ Row: {
8614
+ component_count: number | null;
8615
+ manufacture_product_id: string | null;
8616
+ possible_stock: number | null;
8617
+ };
8618
+ Relationships: [];
8619
+ };
8620
+ product_group_stock_view: {
8621
+ Row: {
8622
+ item_count: number | null;
8623
+ product_group_id: string | null;
8624
+ total_stock: number | null;
8625
+ };
8626
+ Relationships: [{
8627
+ foreignKeyName: "product_group_items_product_group_id_fkey";
8628
+ columns: ["product_group_id"];
8629
+ isOneToOne: false;
8630
+ referencedRelation: "product_groups";
8631
+ referencedColumns: ["id"];
8632
+ }];
8633
+ };
8634
+ trade_item_stock_view: {
8635
+ Row: {
8636
+ stock: number | null;
8637
+ trade_item_id: string | null;
8638
+ };
8639
+ Relationships: [];
8640
+ };
8420
8641
  v_external_customers_exact: {
8421
8642
  Row: {
8422
8643
  account_number: string | null;
@@ -8691,6 +8912,10 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
8691
8912
  Args: never;
8692
8913
  Returns: number;
8693
8914
  };
8915
+ count_distinct_regulatory_products: {
8916
+ Args: never;
8917
+ Returns: number;
8918
+ };
8694
8919
  current_monteur_id: {
8695
8920
  Args: never;
8696
8921
  Returns: string;
@@ -8987,6 +9212,12 @@ export declare const getFlorydayAuctionLetter: import("@tanstack/start-client-co
8987
9212
  row_count: number;
8988
9213
  }[];
8989
9214
  };
9215
+ refresh_floricode_derived_for_product: {
9216
+ Args: {
9217
+ p_product_code: string;
9218
+ };
9219
+ Returns: number;
9220
+ };
8990
9221
  reset_floriday_sync_cursor: {
8991
9222
  Args: {
8992
9223
  p_connection_id: string;