@fayz-ai/plugin-inventory 0.18.9 → 0.18.11

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.
package/dist/index.js CHANGED
@@ -193,6 +193,11 @@ function ProductStockTab({ item, onChanged }) {
193
193
  " ",
194
194
  /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground tabular-nums", children: onHand })
195
195
  ] }),
196
+ hasMinimum(item.minQuantity) && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
197
+ t("inventory.productDetail.minimum"),
198
+ ": ",
199
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground tabular-nums", children: item.minQuantity })
200
+ ] }),
196
201
  /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => setEntryVerb("entry"), children: [
197
202
  /* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-3.5 w-3.5" }),
198
203
  t("inventory.productDetail.newMovement")
@@ -682,8 +687,6 @@ function packagingFields(t) {
682
687
  function ingredientFields(t) {
683
688
  const when = yes("isIngredient");
684
689
  return [
685
- { key: "ingMinimumQuantity", label: t("inventory.productForm.ingMinQuantity"), type: "number", group: "ingredient", min: 0, visibleWhen: when, showInTable: false },
686
- { key: "ingMaximumQuantity", label: t("inventory.productForm.ingMaxQuantity"), type: "number", group: "ingredient", min: 0, placeholder: t("inventory.productForm.optional"), visibleWhen: when, showInTable: false },
687
690
  {
688
691
  key: "ingReorderPoint",
689
692
  label: t("inventory.productForm.ingReorderPoint"),
@@ -848,15 +851,9 @@ function fichaGroups(t) {
848
851
  var FICHA_KEYS = {
849
852
  ingredientInfo: {
850
853
  prefix: "ing",
851
- keys: [
852
- "minimumQuantity",
853
- "maximumQuantity",
854
- "reorderPoint",
855
- "leadTimeDays",
856
- "shelfLifeDays",
857
- "storageTemperature",
858
- "notes"
859
- ]
854
+ // No minimum/maximum here: the stock minimum is the general one
855
+ // (product_settings), the only one alerts and restock read.
856
+ keys: ["reorderPoint", "leadTimeDays", "shelfLifeDays", "storageTemperature", "notes"]
860
857
  },
861
858
  saleInfo: {
862
859
  prefix: "sale",
@@ -1001,8 +998,6 @@ function toFichas(values) {
1001
998
  taxInfo: values.isForSale === true
1002
999
  };
1003
1000
  const numeric = /* @__PURE__ */ new Set([
1004
- "minimumQuantity",
1005
- "maximumQuantity",
1006
1001
  "reorderPoint",
1007
1002
  "leadTimeDays",
1008
1003
  "shelfLifeDays",
@@ -7658,6 +7653,7 @@ var en = {
7658
7653
  "inventory.productDetail.stockTab": "Stock",
7659
7654
  "inventory.productDetail.positionsTitle": "Stock by location",
7660
7655
  "inventory.productDetail.onHand": "On hand",
7656
+ "inventory.productDetail.minimum": "Minimum",
7661
7657
  "inventory.productDetail.noPositions": "No stock in any location",
7662
7658
  "inventory.productDetail.historyTitle": "Movement history",
7663
7659
  "inventory.productDetail.undoLast": "Undo last movement",
@@ -7753,8 +7749,6 @@ var en = {
7753
7749
  "inventory.productForm.notes": "Notes",
7754
7750
  "inventory.productForm.ingredientSection": "Ingredient",
7755
7751
  "inventory.productForm.ingredientSectionDesc": "What purchasing needs to restock in time.",
7756
- "inventory.productForm.ingMinQuantity": "Minimum quantity",
7757
- "inventory.productForm.ingMaxQuantity": "Maximum quantity",
7758
7752
  "inventory.productForm.ingReorderPoint": "Reorder point",
7759
7753
  "inventory.productForm.ingReorderPointHint": "Sits ABOVE the minimum: the warning that still arrives in time to buy.",
7760
7754
  "inventory.productForm.ingLeadTime": "Lead time (days)",
@@ -8527,6 +8521,7 @@ var ptBR = {
8527
8521
  "inventory.productDetail.stockTab": "Estoque",
8528
8522
  "inventory.productDetail.positionsTitle": "Estoque por local",
8529
8523
  "inventory.productDetail.onHand": "Em estoque",
8524
+ "inventory.productDetail.minimum": "M\xEDnimo",
8530
8525
  "inventory.productDetail.noPositions": "Sem estoque em nenhum local",
8531
8526
  "inventory.productDetail.historyTitle": "Movimenta\xE7\xE3o",
8532
8527
  "inventory.productDetail.undoLast": "Desfazer \xFAltimo movimento",
@@ -8622,8 +8617,6 @@ var ptBR = {
8622
8617
  "inventory.productForm.notes": "Observa\xE7\xF5es",
8623
8618
  "inventory.productForm.ingredientSection": "Insumo",
8624
8619
  "inventory.productForm.ingredientSectionDesc": "O que a compra precisa saber para repor na hora certa.",
8625
- "inventory.productForm.ingMinQuantity": "Quantidade m\xEDnima",
8626
- "inventory.productForm.ingMaxQuantity": "Quantidade m\xE1xima",
8627
8620
  "inventory.productForm.ingReorderPoint": "Ponto de reposi\xE7\xE3o",
8628
8621
  "inventory.productForm.ingReorderPointHint": "Fica ACIMA do m\xEDnimo: \xE9 o aviso que ainda chega a tempo de comprar.",
8629
8622
  "inventory.productForm.ingLeadTime": "Prazo de entrega (dias)",
@@ -18488,6 +18481,52 @@ BEGIN
18488
18481
  EXECUTE v_new;
18489
18482
  END $patch$;
18490
18483
  `;
18484
+ var MIGRATION_030_THE_MINIMUM_CAN_BE_SAVED = `-- ============================================================================
18485
+ -- 030 \u2014 the minimum can be saved
18486
+ --
18487
+ -- The product form saves its minimum with an upsert on
18488
+ -- (tenant_id, product_id, unit_id). The only unique index on those columns
18489
+ -- was the expression index (tenant_id, product_id, COALESCE(unit_id, zero)),
18490
+ -- which ON CONFLICT cannot infer from a column list, so every save came back
18491
+ -- 42P10 and the client never looked at the error: "Quantidade M\xEDnima" was
18492
+ -- dropped in silence.
18493
+ --
18494
+ -- A plain column index with NULLS NOT DISTINCT is an arbiter for that
18495
+ -- conflict target and treats the tenant-wide row (unit_id NULL) as one row,
18496
+ -- which is what the expression index already enforced. Both are kept: they
18497
+ -- agree on every row, and dropping the old one is not this fix's business.
18498
+ --
18499
+ -- Hand-applied on cluster-squash-test on 2026-10-22 under this same name, so
18500
+ -- this file must be a no-op there.
18501
+ --
18502
+ -- Second part: the Insumo tab had its own minimum/maximum, stored on
18503
+ -- plg_inventory_product_ingredient_info, which no alert or restock list
18504
+ -- reads. The tab no longer offers them. Whatever was typed there is copied
18505
+ -- into the tenant-wide settings row when the product has none yet, so the
18506
+ -- number the person entered becomes the one that is acted on. The columns
18507
+ -- stay; nothing is dropped.
18508
+ -- ============================================================================
18509
+
18510
+ CREATE UNIQUE INDEX IF NOT EXISTS plg_inventory_product_settings_upsert_key
18511
+ ON public.plg_inventory_product_settings (tenant_id, product_id, unit_id) NULLS NOT DISTINCT;
18512
+
18513
+ INSERT INTO public.plg_inventory_product_settings (tenant_id, product_id, unit_id, min_quantity, max_quantity)
18514
+ SELECT i.tenant_id,
18515
+ i.product_id,
18516
+ NULL,
18517
+ GREATEST(COALESCE(i.minimum_quantity, 0), 0),
18518
+ CASE WHEN i.maximum_quantity >= 0 THEN i.maximum_quantity END
18519
+ FROM public.plg_inventory_product_ingredient_info i
18520
+ JOIN public.products p ON p.id = i.product_id AND p.tenant_id = i.tenant_id
18521
+ WHERE (COALESCE(i.minimum_quantity, 0) > 0 OR i.maximum_quantity IS NOT NULL)
18522
+ AND NOT EXISTS (
18523
+ SELECT 1
18524
+ FROM public.plg_inventory_product_settings s
18525
+ WHERE s.tenant_id = i.tenant_id
18526
+ AND s.product_id = i.product_id
18527
+ AND s.unit_id IS NULL)
18528
+ ON CONFLICT (tenant_id, product_id, unit_id) DO NOTHING;
18529
+ `;
18491
18530
  var MIGRATIONS = [
18492
18531
  { id: "000_baseline", sql: MIGRATION_000_BASELINE },
18493
18532
  { id: "001_the_usage_that_left_stock_can_be_audited", sql: MIGRATION_001_THE_USAGE_THAT_LEFT_STOCK_CAN_BE_AUDITED },
@@ -18518,7 +18557,8 @@ var MIGRATIONS = [
18518
18557
  { id: "026_stock_cost_knows_its_currency", sql: MIGRATION_026_STOCK_COST_KNOWS_ITS_CURRENCY },
18519
18558
  { id: "027_a_receipt_names_the_line_it_came_from", sql: MIGRATION_027_A_RECEIPT_NAMES_THE_LINE_IT_CAME_FROM },
18520
18559
  { id: "028_a_receipt_keeps_the_variant", sql: MIGRATION_028_A_RECEIPT_KEEPS_THE_VARIANT },
18521
- { id: "029_a_reversal_undoes_the_same_variant", sql: MIGRATION_029_A_REVERSAL_UNDOES_THE_SAME_VARIANT }
18560
+ { id: "029_a_reversal_undoes_the_same_variant", sql: MIGRATION_029_A_REVERSAL_UNDOES_THE_SAME_VARIANT },
18561
+ { id: "030_the_minimum_can_be_saved", sql: MIGRATION_030_THE_MINIMUM_CAN_BE_SAVED }
18522
18562
  ];
18523
18563
  var DEFAULT_LABELS = {
18524
18564
  pageTitle: "Inventory",