@flowselections/floriday-voorraad 1.0.22 → 1.0.26

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 (65) hide show
  1. package/dist-lib/assets/floriday-logo.png.asset.json +4 -4
  2. package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
  3. package/dist-lib/components/voorraad/ArtikelWizard.js +655 -93
  4. package/dist-lib/components/voorraad/FloridayInfoCard.d.ts +12 -0
  5. package/dist-lib/components/voorraad/FloridayInfoCard.d.ts.map +1 -0
  6. package/dist-lib/components/voorraad/FloridayInfoCard.js +85 -0
  7. package/dist-lib/components/voorraad/StepSamenstelling.d.ts +10 -0
  8. package/dist-lib/components/voorraad/StepSamenstelling.d.ts.map +1 -0
  9. package/dist-lib/components/voorraad/StepSamenstelling.js +333 -0
  10. package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
  11. package/dist-lib/components/voorraad/VoorraadPage.js +14 -3
  12. package/dist-lib/components/voorraad/VoorraadTable.d.ts.map +1 -1
  13. package/dist-lib/components/voorraad/VoorraadTable.js +8 -1
  14. package/dist-lib/hooks/useFloridayPriceGroups.d.ts +20 -0
  15. package/dist-lib/hooks/useFloridayPriceGroups.d.ts.map +1 -0
  16. package/dist-lib/hooks/useFloridayPriceGroups.js +55 -0
  17. package/dist-lib/hooks/useFloridayVbnRequired.d.ts +5 -0
  18. package/dist-lib/hooks/useFloridayVbnRequired.d.ts.map +1 -0
  19. package/dist-lib/hooks/useFloridayVbnRequired.js +16 -0
  20. package/dist-lib/hooks/useLocalTradeItems.d.ts.map +1 -1
  21. package/dist-lib/hooks/useLocalTradeItems.js +14 -0
  22. package/dist-lib/hooks/useTradeItemSpec.d.ts.map +1 -1
  23. package/dist-lib/hooks/useTradeItemSpec.js +48 -1
  24. package/dist-lib/hooks/useVoorraadData.d.ts.map +1 -1
  25. package/dist-lib/hooks/useVoorraadData.js +36 -5
  26. package/dist-lib/integrations/supabase/auth-middleware.d.ts +2388 -345
  27. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  28. package/dist-lib/integrations/supabase/client.d.ts +2388 -345
  29. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  30. package/dist-lib/integrations/supabase/client.server.d.ts +2388 -345
  31. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  32. package/dist-lib/integrations/supabase/types.d.ts +2437 -343
  33. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  34. package/dist-lib/integrations/supabase/types.js +11 -9
  35. package/dist-lib/lib/centralSecrets.server.d.ts +21 -0
  36. package/dist-lib/lib/centralSecrets.server.d.ts.map +1 -0
  37. package/dist-lib/lib/centralSecrets.server.js +111 -0
  38. package/dist-lib/lib/floricode-required-features.functions.d.ts +2388 -345
  39. package/dist-lib/lib/floricode-required-features.functions.d.ts.map +1 -1
  40. package/dist-lib/lib/floriday-client.d.ts +4 -0
  41. package/dist-lib/lib/floriday-client.d.ts.map +1 -1
  42. package/dist-lib/lib/floriday-customer-offer.functions.d.ts +2388 -345
  43. package/dist-lib/lib/floriday-customer-offer.functions.d.ts.map +1 -1
  44. package/dist-lib/lib/floriday-gateway.functions.d.ts +10860 -645
  45. package/dist-lib/lib/floriday-gateway.functions.d.ts.map +1 -1
  46. package/dist-lib/lib/floriday-gateway.server.d.ts.map +1 -1
  47. package/dist-lib/lib/floriday-gateway.server.js +34 -9
  48. package/dist-lib/lib/floriday-info.d.ts +54 -0
  49. package/dist-lib/lib/floriday-info.d.ts.map +1 -0
  50. package/dist-lib/lib/floriday-info.js +114 -0
  51. package/dist-lib/lib/floriday-payload.d.ts +21 -3
  52. package/dist-lib/lib/floriday-payload.d.ts.map +1 -1
  53. package/dist-lib/lib/floriday-payload.js +167 -34
  54. package/dist-lib/lib/floriday-vbn-required.functions.d.ts +27769 -0
  55. package/dist-lib/lib/floriday-vbn-required.functions.d.ts.map +1 -0
  56. package/dist-lib/lib/floriday-vbn-required.functions.js +85 -0
  57. package/dist-lib/lib/floriday-warehouse.functions.d.ts +6602 -473
  58. package/dist-lib/lib/floriday-warehouse.functions.d.ts.map +1 -1
  59. package/dist-lib/lib/floriday-writes.functions.d.ts +4681 -594
  60. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  61. package/dist-lib/lib/floriday-writes.functions.js +36 -1
  62. package/dist-lib/lib/trade-item-prices.d.ts +43 -0
  63. package/dist-lib/lib/trade-item-prices.d.ts.map +1 -0
  64. package/dist-lib/lib/trade-item-prices.js +229 -0
  65. package/package.json +3 -3
@@ -107,11 +107,11 @@ export const stepSchemas = {
107
107
  }),
108
108
  beschikbaarheid: z
109
109
  .object({
110
- yearRound: z.boolean(),
110
+ availabilityMode: z.enum(["YEAR_ROUND", "SPECIFIC", "UNSPECIFIED"]),
111
111
  weeks: z.array(z.number().int().min(1).max(53)),
112
112
  })
113
- .refine((v) => v.yearRound || v.weeks.length > 0, {
114
- message: "Kies jaarrond of selecteer minstens één week",
113
+ .refine((v) => v.availabilityMode !== "SPECIFIC" || v.weeks.length > 0, {
114
+ message: "Selecteer minstens één week of kies jaarrond/niet gespecificeerd",
115
115
  path: ["weeks"],
116
116
  }),
117
117
  aanbieden: z
@@ -265,11 +265,18 @@ export function buildPackingConfigPayload(p, primary = false) {
265
265
  if (!vbnPackageCode && !customPackageId) {
266
266
  throw new Error(`Fusttype ontbreekt voor beladingsconfiguratie "${p.id}" — kies een VBN-fust of een custom package.`);
267
267
  }
268
+ // Floriday's `package`-union accepteert exact één tak. Bij SUPPLIER met een
269
+ // geldige custom package heeft die voorrang; anders vallen we terug op VBN.
268
270
  const pkg = {};
269
- if (vbnPackageCode)
271
+ if (customPackageId && p.source === "SUPPLIER") {
272
+ pkg.customPackageId = customPackageId;
273
+ }
274
+ else if (vbnPackageCode) {
270
275
  pkg.vbnPackageCode = vbnPackageCode;
271
- if (customPackageId)
276
+ }
277
+ else if (customPackageId) {
272
278
  pkg.customPackageId = customPackageId;
279
+ }
273
280
  const payload = {
274
281
  primary: Boolean(primary),
275
282
  piecesPerPackage: Math.max(1, Math.min(9999, Number(p.unitsPerPackage) || 1)),
@@ -277,7 +284,7 @@ export function buildPackingConfigPayload(p, primary = false) {
277
284
  packagesPerLayer: Math.max(1, Math.min(9999, Number(p.packagesPerLayer) || 1)),
278
285
  layersPerLoadCarrier: Math.max(1, Math.min(9999, Number(p.layersPerLoadCarrier) || 1)),
279
286
  loadCarrier: normaliseLoadCarrier(p.loadCarrier),
280
- isHiddenForDirectSales: false,
287
+ isHiddenForDirectSales: Boolean(p.isHiddenForDirectSales),
281
288
  };
282
289
  // Alleen geldige VRS-packaging UUIDs meesturen; supplierId-string uit de
283
290
  // hardcoded lijst is GEEN uuid en hoort niet in de Floriday-payload.
@@ -285,7 +292,9 @@ export function buildPackingConfigPayload(p, primary = false) {
285
292
  payload.floricodeVrsPackagingId = p.packagingSupplierId;
286
293
  }
287
294
  if (p.isCustomerSpecific && p.customerOrganizationIds.length > 0) {
288
- payload.allowedCustomerOrganizationIds = p.customerOrganizationIds;
295
+ const uuids = p.customerOrganizationIds.filter(isUuid);
296
+ if (uuids.length > 0)
297
+ payload.allowedCustomerOrganizationIds = uuids;
289
298
  }
290
299
  if (p.photoUrl)
291
300
  payload.photoUrl = p.photoUrl;
@@ -416,18 +425,24 @@ export function buildAddTradeItemPayload(d) {
416
425
  tradeItemName: { nl: tradeItemNameNl },
417
426
  characteristics,
418
427
  customerOrganizationIds: isCustomerSpecific ? d.customerOrganizationIds : [],
419
- seasonalPeriods: d.yearRound
428
+ seasonalPeriods: d.availabilityMode === "YEAR_ROUND"
420
429
  ? [{ startWeek: 1, endWeek: 53 }]
421
- : weeksToSeasonalPeriods(d.weeks),
430
+ : d.availabilityMode === "UNSPECIFIED"
431
+ ? []
432
+ : (() => {
433
+ const p = weeksToSeasonalPeriods(d.weeks);
434
+ if (p.length === 0) {
435
+ throw new Error("Kies minstens één week voor 'Specifieke periode', of kies jaarrond/niet gespecificeerd.");
436
+ }
437
+ return p;
438
+ })(),
422
439
  photos,
423
440
  warehouseId,
424
441
  packingConfigurations,
425
- botanicalNames: botanicalNames.length ? botanicalNames : undefined,
426
- countryOfOriginIsoCodes: countryOfOriginIsoCodes.length ? countryOfOriginIsoCodes : undefined,
427
- additionalPackagingMaterialIds: additionalPackagingMaterialIds.length
428
- ? additionalPackagingMaterialIds
429
- : undefined,
430
- isHiddenInCatalog: isCustomerSpecific ? true : !d.visibleInExplorer,
442
+ botanicalNames,
443
+ countryOfOriginIsoCodes,
444
+ additionalPackagingMaterialIds,
445
+ isHiddenInCatalog: !d.visibleInExplorer,
431
446
  };
432
447
  }
433
448
  /**
@@ -461,29 +476,74 @@ export const emptyWizardData = {
461
476
  warehouseId: "",
462
477
  packingConfigurations: [],
463
478
  additionalPackaging: [],
464
- yearRound: true,
479
+ availabilityMode: "YEAR_ROUND",
465
480
  weeks: [],
466
481
  offerForSale: true,
467
482
  salePricePerPiece: 0,
468
483
  saleStockPieces: 0,
469
484
  offerStartDate: new Date().toISOString().slice(0, 10),
485
+ priceGroupPrices: {},
486
+ vatRate: null,
487
+ vatCode: null,
470
488
  };
471
489
  // -------- Reverse mapper: Floriday cache row -> WizardData ----------------
472
490
  // Used by the detail/edit page to hydrate the wizard from an existing
473
491
  // published trade item.
474
- function productGroupFromVbn(vbnProductCode) {
475
- const n = Number(vbnProductCode);
476
- if (!Number.isFinite(n) || n <= 0)
492
+ function productGroupFromFloricodePrefix(raw) {
493
+ const text = String(raw ?? "").trim();
494
+ if (!/^\d+$/.test(text))
477
495
  return null;
478
- const s = String(Math.floor(n));
479
- if (s.startsWith("10"))
496
+ if (text.startsWith("10") || text.startsWith("11"))
480
497
  return "CUT_FLOWER";
481
- if (s.startsWith("20"))
498
+ if (text.startsWith("20") || text.startsWith("21") || text.startsWith("29"))
482
499
  return "POT_PLANT";
483
- if (s.startsWith("30"))
500
+ if (text.startsWith("30") || text.startsWith("31"))
484
501
  return "GARDEN_PLANT";
485
502
  return null;
486
503
  }
504
+ function productGroupFromVbn(vbnProductCode) {
505
+ return productGroupFromFloricodePrefix(vbnProductCode);
506
+ }
507
+ export function normalizeFloridayProductGroup(raw) {
508
+ if (!raw)
509
+ return null;
510
+ if (typeof raw === "object") {
511
+ const o = raw;
512
+ const candidates = [
513
+ o.productGroup,
514
+ o.productGroupId,
515
+ o.product_group_id,
516
+ o.vbnProductGroup,
517
+ o.vbnProductGroupId,
518
+ o.vbn_product_group_id,
519
+ o.code,
520
+ o.id,
521
+ o.name,
522
+ o.description,
523
+ o.value,
524
+ ];
525
+ for (const candidate of candidates) {
526
+ const group = normalizeFloridayProductGroup(candidate);
527
+ if (group)
528
+ return group;
529
+ }
530
+ return null;
531
+ }
532
+ const prefixed = productGroupFromFloricodePrefix(raw);
533
+ if (prefixed)
534
+ return prefixed;
535
+ const s = String(raw).trim().toUpperCase().replace(/[\s-]+/g, "_");
536
+ if (s === "CUT_FLOWER" || s === "POT_PLANT" || s === "GARDEN_PLANT") {
537
+ return s;
538
+ }
539
+ if (s.includes("TUIN") || s.includes("GARDEN"))
540
+ return "GARDEN_PLANT";
541
+ if (s.includes("SNIJ") || s.includes("CUT") || s.includes("FLOWER"))
542
+ return "CUT_FLOWER";
543
+ if (s.includes("KAMER") || s.includes("POT"))
544
+ return "POT_PLANT";
545
+ return null;
546
+ }
487
547
  function pickName(value) {
488
548
  if (!value)
489
549
  return "";
@@ -512,15 +572,44 @@ function expandSeasonalPeriods(periods) {
512
572
  const e = Number(p?.endWeek ?? p?.startWeek);
513
573
  if (!Number.isFinite(s) || !Number.isFinite(e))
514
574
  continue;
515
- for (let w = Math.max(1, s); w <= Math.min(53, e); w++)
516
- out.add(w);
575
+ const sc = Math.max(1, Math.min(53, s));
576
+ const ec = Math.max(1, Math.min(53, e));
577
+ if (ec >= sc) {
578
+ for (let w = sc; w <= ec; w++)
579
+ out.add(w);
580
+ }
581
+ else {
582
+ // Wrap-around (bv. week 50..3) — Floriday interpreteert dit als
583
+ // [start..53] + [1..end].
584
+ for (let w = sc; w <= 53; w++)
585
+ out.add(w);
586
+ for (let w = 1; w <= ec; w++)
587
+ out.add(w);
588
+ }
517
589
  }
518
590
  return [...out].sort((a, b) => a - b);
519
591
  }
520
592
  export function floridayCacheToWizardData(raw) {
521
593
  if (!raw || typeof raw !== "object")
522
594
  return { ...emptyWizardData };
523
- const vbn = raw.vbnProductCode ?? raw.vbnCode ?? "";
595
+ const vbn = raw.vbnProductCode ??
596
+ raw.vbnCode ??
597
+ raw.vbnProduct?.code ??
598
+ raw.vbnProduct?.vbnCode ??
599
+ raw.vbnProductCodeId ??
600
+ "";
601
+ const vbnNameHint = (typeof raw.vbnProduct?.name === "object"
602
+ ? (raw.vbnProduct.name?.nl ?? raw.vbnProduct.name?.en)
603
+ : raw.vbnProduct?.name) ?? "";
604
+ const productGroup = normalizeFloridayProductGroup(raw.productGroup) ??
605
+ normalizeFloridayProductGroup(raw.productGroupId) ??
606
+ normalizeFloridayProductGroup(raw.product_group_id) ??
607
+ normalizeFloridayProductGroup(raw.vbnProductGroup) ??
608
+ normalizeFloridayProductGroup(raw.vbnProductGroupId) ??
609
+ normalizeFloridayProductGroup(raw.vbn_product_group_id) ??
610
+ normalizeFloridayProductGroup(raw.vbnProduct) ??
611
+ normalizeFloridayProductGroup(raw.product) ??
612
+ productGroupFromVbn(vbn);
524
613
  const characteristics = Array.isArray(raw.characteristics) ? raw.characteristics : [];
525
614
  const features = {};
526
615
  for (const c of characteristics) {
@@ -540,6 +629,7 @@ export function floridayCacheToWizardData(raw) {
540
629
  url: p.url,
541
630
  primary: i === primaryPhotoIdxNorm,
542
631
  sortOrder: p.sortIndex ?? i,
632
+ type: p?.type ?? "WEBSHOPFRIENDLY",
543
633
  }));
544
634
  const packings = Array.isArray(raw.packingConfigurations)
545
635
  ? raw.packingConfigurations
@@ -550,24 +640,31 @@ export function floridayCacheToWizardData(raw) {
550
640
  })();
551
641
  const packingConfigurations = packings.map((p, i) => {
552
642
  const vrsId = p?.floricodeVrsPackagingId ?? p?.packagingSupplierId ?? undefined;
643
+ const customPkgId = p?.package?.customPackageId ?? p?.packagingSupplierMaterialId ?? undefined;
553
644
  const allowed = Array.isArray(p?.allowedCustomerOrganizationIds)
554
645
  ? p.allowedCustomerOrganizationIds
555
646
  : Array.isArray(p?.customerOrganizationIds)
556
647
  ? p.customerOrganizationIds
557
648
  : [];
649
+ const hasSupplier = Boolean(vrsId) || Boolean(customPkgId);
558
650
  return {
559
651
  id: `existing-${i}`,
560
- source: vrsId ? "SUPPLIER" : "VBN",
652
+ floridayId: p?.packingConfigurationId ?? p?.id ?? undefined,
653
+ source: hasSupplier ? "SUPPLIER" : "VBN",
561
654
  packagingType: String(p?.package?.vbnPackageCode ?? ""),
562
- loadCarrier: String(p?.loadCarrier ?? "NONE"),
655
+ loadCarrier: String(p?.loadCarrier ?? ""),
563
656
  packagingSupplierId: vrsId ?? undefined,
564
- packagingMaterialId: p?.package?.customPackageId ?? p?.packagingSupplierMaterialId ?? undefined,
657
+ packagingSupplierName: p?.packagingSupplierName ?? undefined,
658
+ packagingMaterialId: customPkgId ?? undefined,
659
+ packagingMaterialName: p?.packagingMaterialName ?? undefined,
565
660
  unitsPerPackage: Number(p?.piecesPerPackage ?? 1),
566
661
  packagesPerLayer: Number(p?.packagesPerLayer ?? 1),
567
662
  layersPerLoadCarrier: Number(p?.layersPerLoadCarrier ?? 1),
663
+ photoUrl: typeof p?.photoUrl === "string" ? p.photoUrl : undefined,
568
664
  isCustomerSpecific: allowed.length > 0,
569
665
  customerOrganizationIds: allowed,
570
666
  isPrimary: i === primaryPackingIdxNorm,
667
+ isHiddenForDirectSales: Boolean(p?.isHiddenForDirectSales),
571
668
  };
572
669
  });
573
670
  const customerOrgIds = Array.isArray(raw.customerOrganizationIds)
@@ -583,10 +680,25 @@ export function floridayCacheToWizardData(raw) {
583
680
  ? raw.seasonalPeriods
584
681
  : [];
585
682
  const weeks = expandSeasonalPeriods(seasonalPeriods);
683
+ // Sync S62 (Land van herkomst characteristic) met stap-3 land-van-oorsprong.
684
+ // Floriday kan één van beide leeg laten; wij houden ze deterministisch gelijk
685
+ // zodat de PUT-payload nooit afhangt van welke stap laatst is geopend.
686
+ const firstCountry = countries
687
+ .map((c) => String(c ?? "").trim().toUpperCase())
688
+ .find((c) => /^[A-Z]{2}$/.test(c));
689
+ const existingS62 = String(features["S62"] ?? "").trim().toUpperCase();
690
+ if (!existingS62 && firstCountry) {
691
+ features["S62"] = firstCountry;
692
+ }
693
+ const hydratedCountryOfOrigin = countries.length
694
+ ? countries.join(",")
695
+ : existingS62
696
+ ? existingS62
697
+ : firstCountry ?? "";
586
698
  return {
587
- productGroup: productGroupFromVbn(vbn),
699
+ productGroup,
588
700
  vbnCode: vbn ? String(vbn) : "",
589
- vbnName: "",
701
+ vbnName: vbnNameHint ? String(vbnNameHint) : "",
590
702
  articleCode: String(raw.supplierArticleCode ?? raw.articleCode ?? ""),
591
703
  name: pickName(raw.tradeItemName ?? raw.name),
592
704
  nameEn: pickNameEn(raw.tradeItemName ?? raw.name),
@@ -595,7 +707,7 @@ export function floridayCacheToWizardData(raw) {
595
707
  articleType: customerOrgIds.length > 0 ? "CUSTOMER_SPECIFIC" : "REGULAR",
596
708
  visibleInExplorer: !raw.isHiddenInCatalog,
597
709
  botanicalName: botanicalNames.join("; "),
598
- countryOfOrigin: countries.join(","),
710
+ countryOfOrigin: hydratedCountryOfOrigin,
599
711
  producerCode: "",
600
712
  lotNumber: "",
601
713
  features,
@@ -604,13 +716,34 @@ export function floridayCacheToWizardData(raw) {
604
716
  warehouseId: String(raw.warehouseId ?? raw.warehouse?.warehouseId ?? ""),
605
717
  packingConfigurations,
606
718
  additionalPackaging: [],
607
- yearRound: weeks.length === 0 || weeks.length >= 52,
608
- weeks: weeks.length >= 52 ? [] : weeks,
719
+ availabilityMode: (() => {
720
+ if (seasonalPeriods.length === 0)
721
+ return "UNSPECIFIED";
722
+ if (seasonalPeriods.length === 1 &&
723
+ Number(seasonalPeriods[0]?.startWeek) === 1 &&
724
+ (Number(seasonalPeriods[0]?.endWeek) === 53 ||
725
+ Number(seasonalPeriods[0]?.endWeek) === 52)) {
726
+ return "YEAR_ROUND";
727
+ }
728
+ return "SPECIFIC";
729
+ })(),
730
+ weeks: (() => {
731
+ if (seasonalPeriods.length === 0)
732
+ return [];
733
+ if (seasonalPeriods.length === 1 &&
734
+ Number(seasonalPeriods[0]?.startWeek) === 1 &&
735
+ (Number(seasonalPeriods[0]?.endWeek) === 53 ||
736
+ Number(seasonalPeriods[0]?.endWeek) === 52)) {
737
+ return [];
738
+ }
739
+ return weeks;
740
+ })(),
609
741
  // Reeds gepubliceerd via de wizard — commerciële velden staan uit voor edit,
610
742
  // want een bestaand CustomerOffer wordt hier niet opnieuw aangemaakt.
611
743
  offerForSale: false,
612
744
  salePricePerPiece: 0,
613
745
  saleStockPieces: 0,
614
746
  offerStartDate: new Date().toISOString().slice(0, 10),
747
+ priceGroupPrices: {},
615
748
  };
616
749
  }