@open-mercato/core 0.10.1-develop.7920.1.159653827a → 0.10.1-develop.7921.1.e5774a7073

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.
@@ -9,7 +9,7 @@ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuarde
9
9
  import { flashMutationError } from "../../lib/flashMutationError.js";
10
10
  import { ComboboxInput } from "@open-mercato/ui/backend/inputs/ComboboxInput";
11
11
  import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
12
- import { raiseCrudError } from "@open-mercato/ui/backend/utils/serverErrors";
12
+ import { raiseCrudError, readJsonSafe } from "@open-mercato/ui/backend/utils/serverErrors";
13
13
  import { Button } from "@open-mercato/ui/primitives/button";
14
14
  import {
15
15
  Dialog,
@@ -393,6 +393,15 @@ function AdjustInventoryDialog({
393
393
  }
394
394
  );
395
395
  if (!call.ok) {
396
+ const errorBody = await readJsonSafe(call.response.clone(), null);
397
+ if (errorBody?.error === "insufficient_stock") {
398
+ throw new Error(
399
+ t(
400
+ "wms.backend.inventory.adjust.errors.insufficientStock",
401
+ "The adjustment is larger than the available quantity in this location."
402
+ )
403
+ );
404
+ }
396
405
  await raiseCrudError(
397
406
  call.response,
398
407
  t("wms.backend.inventory.adjust.errors.submit", "Failed to adjust inventory.")
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/wms/components/backend/AdjustInventoryDialog.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { Minus, Package, Plus } from 'lucide-react'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flashMutationError } from '../../lib/flashMutationError'\nimport { ComboboxInput } from '@open-mercato/ui/backend/inputs/ComboboxInput'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { FormField } from '@open-mercato/ui/primitives/form-field'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { KbdShortcut } from '@open-mercato/ui/primitives/kbd'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { formatLocaleNumberInput, parseLocaleNumber } from '@open-mercato/shared/lib/number'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { buildInventoryMutationReferenceId } from '../../lib/inventoryMutationUi'\nimport {\n BalanceLookupError,\n ensureLotIdForInventoryMutation,\n fetchBalanceOnHand,\n fetchVariantReorderPoint,\n findLotIdByNumber,\n InventoryLotMutationError,\n loadCatalogVariantOptions,\n loadLocationOptions,\n loadLotNumberOptions,\n loadWarehouseOptions,\n resolveCatalogVariantLabel,\n resolveLocationLabel,\n resolveLotNumberFromId,\n resolveWarehouseLabel,\n} from './inventoryMutationLoaders'\nimport type { useWmsInventoryMutationAccess } from './useWmsInventoryMutationAccess'\n\nconst logger = createLogger('wms')\n\nconst ADJUST_REASON_CODES = ['damaged', 'shrinkage', 'found', 'correction', 'other'] as const\n\ntype AdjustReasonCode = (typeof ADJUST_REASON_CODES)[number]\n\ntype AdjustFormValues = {\n catalogVariantId: string\n warehouseId: string\n locationId: string\n lotNumber: string\n delta: number\n reasonCode: AdjustReasonCode | ''\n notes: string\n serialNumber: string\n}\n\ntype AdjustInventoryDialogProps = {\n open: boolean\n onOpenChange: (open: boolean) => void\n access: ReturnType<typeof useWmsInventoryMutationAccess>\n initialCatalogVariantId?: string\n initialWarehouseId?: string\n initialLocationId?: string\n initialLotId?: string\n}\n\nconst EMPTY_FORM: AdjustFormValues = {\n catalogVariantId: '',\n warehouseId: '',\n locationId: '',\n lotNumber: '',\n delta: 1,\n reasonCode: '',\n notes: '',\n serialNumber: '',\n}\n\nexport function parseDeltaInput(value: string, locale?: string): number | null {\n const trimmed = value.trim()\n if (!trimmed || trimmed === '-' || trimmed === '+') return null\n return parseLocaleNumber(trimmed, locale)\n}\n\nexport function AdjustInventoryDialog({\n open,\n onOpenChange,\n access,\n initialCatalogVariantId,\n initialWarehouseId,\n initialLocationId,\n initialLotId,\n}: AdjustInventoryDialogProps) {\n const t = useT()\n const locale = useLocale()\n const queryClient = useQueryClient()\n const formRef = React.useRef<HTMLFormElement>(null)\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: 'wms-inventory-adjust',\n })\n const mutationContext = React.useMemo(\n () => ({ retryLastMutation }),\n [retryLastMutation],\n )\n const adjustFormSchema = React.useMemo(\n () =>\n z.object({\n catalogVariantId: z.string().uuid(),\n warehouseId: z.string().uuid(),\n locationId: z.string().uuid(),\n lotNumber: z.string().trim().max(120).optional(),\n delta: z.coerce.number().refine((value) => value !== 0, {\n message: t(\n 'wms.backend.inventory.adjust.errors.deltaZero',\n 'Inventory delta must be non-zero.',\n ),\n }),\n reasonCode: z.enum(ADJUST_REASON_CODES),\n notes: z.string().trim().max(500).optional(),\n serialNumber: z.string().trim().max(120).optional(),\n }),\n [t],\n )\n const [submitting, setSubmitting] = React.useState(false)\n const [form, setForm] = React.useState<AdjustFormValues>(EMPTY_FORM)\n // Raw text the user is typing into the delta field, decoupled from `form.delta` (issue\n // #5828): re-deriving the input's display from the committed number on every keystroke\n // drops an in-progress decimal separator the instant it's typed (`2,5` collapses to `2`\n // then the next digit appends, producing `25`). Synced from `form.delta` only while the\n // field is not focused, mirroring `CrudForm.NumberInput`'s buffer.\n const [deltaInputText, setDeltaInputText] = React.useState<string>(() => formatLocaleNumberInput(EMPTY_FORM.delta, locale))\n const deltaInputFocusedRef = React.useRef(false)\n const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({})\n const [onHand, setOnHand] = React.useState<number | null>(null)\n const [previewError, setPreviewError] = React.useState<string | null>(null)\n const [reorderPoint, setReorderPoint] = React.useState(0)\n const [loadingPreview, setLoadingPreview] = React.useState(false)\n const [optionLabelByValue, setOptionLabelByValue] = React.useState<Record<string, string>>({})\n\n const registerOptionLabels = React.useCallback(\n (options: Array<{ value: string; label: string }>) => {\n setOptionLabelByValue((current) => {\n let changed = false\n const next = { ...current }\n for (const option of options) {\n const value = option.value.trim()\n const label = option.label.trim()\n if (!value || !label || next[value] === label) continue\n next[value] = label\n changed = true\n }\n return changed ? next : current\n })\n },\n [],\n )\n\n const resolveOptionLabel = React.useCallback(\n (value: string) => optionLabelByValue[value] ?? value,\n [optionLabelByValue],\n )\n const optionLabelByValueRef = React.useRef(optionLabelByValue)\n optionLabelByValueRef.current = optionLabelByValue\n\n const reasonLabel = React.useCallback(\n (code: AdjustReasonCode) => {\n const fallbacks: Record<AdjustReasonCode, string> = {\n damaged: 'Damaged',\n shrinkage: 'Shrinkage',\n found: 'Found stock',\n correction: 'Correction',\n other: 'Other',\n }\n return t(`wms.backend.inventory.adjust.reasons.${code}`, fallbacks[code])\n },\n [t],\n )\n\n const resetDialog = React.useCallback(() => {\n setForm(EMPTY_FORM)\n setDeltaInputText(formatLocaleNumberInput(EMPTY_FORM.delta, locale))\n setFieldErrors({})\n setOnHand(null)\n setPreviewError(null)\n setReorderPoint(0)\n setLoadingPreview(false)\n setSubmitting(false)\n setOptionLabelByValue({})\n }, [locale])\n\n const closeDialog = React.useCallback(() => {\n onOpenChange(false)\n resetDialog()\n }, [onOpenChange, resetDialog])\n\n const patchForm = React.useCallback((patch: Partial<AdjustFormValues>) => {\n setForm((current) => ({ ...current, ...patch }))\n setFieldErrors({})\n }, [])\n\n React.useEffect(() => {\n if (!deltaInputFocusedRef.current) setDeltaInputText(formatLocaleNumberInput(form.delta, locale))\n }, [form.delta, locale])\n\n React.useEffect(() => {\n if (!open) return\n const catalogVariantId = initialCatalogVariantId?.trim()\n const warehouseId = initialWarehouseId?.trim()\n const locationId = initialLocationId?.trim()\n const lotId = initialLotId?.trim()\n if (!catalogVariantId && !warehouseId && !locationId && !lotId) return\n setForm((current) => ({\n ...current,\n ...(catalogVariantId ? { catalogVariantId } : {}),\n ...(warehouseId ? { warehouseId, locationId: locationId ?? '' } : {}),\n ...(locationId ? { locationId } : {}),\n }))\n if (!lotId) return\n let cancelled = false\n void resolveLotNumberFromId(lotId).then((lotNumber) => {\n if (cancelled || !lotNumber) return\n setForm((current) => ({ ...current, lotNumber }))\n registerOptionLabels([{ value: lotNumber, label: lotNumber }])\n })\n return () => {\n cancelled = true\n }\n }, [\n initialCatalogVariantId,\n initialLocationId,\n initialLotId,\n initialWarehouseId,\n open,\n registerOptionLabels,\n ])\n\n React.useEffect(() => {\n if (!open) return\n let cancelled = false\n\n const ensureLabel = async (value: string, resolve: (id: string) => Promise<string | null>) => {\n const id = value.trim()\n if (!id || optionLabelByValueRef.current[id]) return\n const label = await resolve(id)\n if (cancelled || !label) return\n registerOptionLabels([{ value: id, label }])\n }\n\n void Promise.all([\n ensureLabel(form.catalogVariantId, resolveCatalogVariantLabel),\n ensureLabel(form.warehouseId, resolveWarehouseLabel),\n ensureLabel(form.locationId, resolveLocationLabel),\n ])\n\n return () => {\n cancelled = true\n }\n }, [\n form.catalogVariantId,\n form.locationId,\n form.warehouseId,\n open,\n registerOptionLabels,\n ])\n\n React.useEffect(() => {\n if (!open) return\n const variantId = form.catalogVariantId.trim()\n if (!variantId) {\n setReorderPoint(0)\n return\n }\n let cancelled = false\n void fetchVariantReorderPoint(variantId).then((value) => {\n if (!cancelled) setReorderPoint(value)\n })\n return () => {\n cancelled = true\n }\n }, [form.catalogVariantId, open])\n\n const previewContextReady = Boolean(\n form.catalogVariantId.trim() &&\n form.warehouseId.trim() &&\n form.locationId.trim(),\n )\n\n React.useEffect(() => {\n if (!open) return\n const warehouseId = form.warehouseId.trim()\n const locationId = form.locationId.trim()\n const catalogVariantId = form.catalogVariantId.trim()\n const lotNumber = form.lotNumber.trim()\n if (!warehouseId || !locationId || !catalogVariantId) {\n setOnHand(null)\n setPreviewError(null)\n setLoadingPreview(false)\n return\n }\n let cancelled = false\n setLoadingPreview(true)\n setPreviewError(null)\n void (async () => {\n try {\n const lotId = lotNumber\n ? await findLotIdByNumber(catalogVariantId, lotNumber)\n : null\n if (cancelled) return\n const value = await fetchBalanceOnHand({\n warehouseId,\n locationId,\n catalogVariantId,\n lotId,\n })\n if (!cancelled) {\n setOnHand(value)\n setPreviewError(null)\n }\n } catch (error: unknown) {\n if (cancelled) return\n setOnHand(null)\n if (error instanceof BalanceLookupError) {\n setPreviewError(\n t(\n 'wms.backend.inventory.adjust.errors.previewBalance',\n 'Failed to load balance preview.',\n ),\n )\n return\n }\n logger.error('fetchBalanceOnHand failed', { component: 'AdjustInventoryDialog', err: error })\n setPreviewError(\n t(\n 'wms.backend.inventory.adjust.errors.previewBalance',\n 'Failed to load balance preview.',\n ),\n )\n } finally {\n if (!cancelled) setLoadingPreview(false)\n }\n })()\n return () => {\n cancelled = true\n }\n }, [\n form.catalogVariantId,\n form.locationId,\n form.lotNumber,\n form.warehouseId,\n open,\n t,\n ])\n\n const projectedOnHand =\n onHand != null && form.delta !== 0 ? onHand + form.delta : null\n const showBelowReorder =\n projectedOnHand != null && reorderPoint > 0 && projectedOnHand <= reorderPoint\n\n const handleSubmit = React.useCallback(\n async (event?: React.FormEvent) => {\n event?.preventDefault()\n const parsed = adjustFormSchema.safeParse({\n ...form,\n lotNumber: form.lotNumber.trim() || undefined,\n notes: form.notes.trim() || undefined,\n serialNumber: form.serialNumber.trim() || undefined,\n })\n if (!parsed.success) {\n const nextErrors: Record<string, string> = {}\n for (const issue of parsed.error.issues) {\n const key = String(issue.path[0] ?? 'form')\n if (!nextErrors[key]) nextErrors[key] = issue.message\n }\n setFieldErrors(nextErrors)\n return\n }\n\n if (!access.scopeReady || !access.organizationId || !access.tenantId || !access.userId) {\n flash(\n t(\n 'wms.backend.inventory.mutations.errors.scope',\n 'Select an organization and sign in before posting inventory changes.',\n ),\n 'error',\n )\n return\n }\n\n setSubmitting(true)\n try {\n // Persist the stable reason code (not a locale-rendered label) so activity\n // feeds can re-translate for the viewer's language later.\n const reason = parsed.data.reasonCode\n const notes = parsed.data.notes?.trim()\n const lotNumber = parsed.data.lotNumber?.trim()\n let lotId: string | undefined\n if (lotNumber) {\n try {\n lotId = await ensureLotIdForInventoryMutation({\n catalogVariantId: parsed.data.catalogVariantId,\n lotNumber,\n organizationId: access.organizationId,\n tenantId: access.tenantId,\n })\n } catch (error: unknown) {\n const message =\n error instanceof InventoryLotMutationError\n ? error.message\n : t(\n 'wms.backend.inventory.adjust.errors.lot',\n 'Failed to resolve inventory lot.',\n )\n setFieldErrors({ lotNumber: message })\n return\n }\n }\n const payload: Record<string, unknown> = {\n organizationId: access.organizationId,\n tenantId: access.tenantId,\n warehouseId: parsed.data.warehouseId,\n locationId: parsed.data.locationId,\n catalogVariantId: parsed.data.catalogVariantId,\n delta: parsed.data.delta,\n reason,\n reasonCode: parsed.data.reasonCode,\n referenceType: 'manual',\n referenceId: buildInventoryMutationReferenceId(),\n performedBy: access.userId,\n }\n if (lotId) payload.lotId = lotId\n const serial = parsed.data.serialNumber?.trim()\n if (serial) payload.serialNumber = serial\n if (notes) payload.metadata = { notes }\n\n await runMutation({\n operation: async () => {\n const call = await apiCall<{ ok?: boolean; movementId?: string }>(\n '/api/wms/inventory/adjust',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n )\n if (!call.ok) {\n await raiseCrudError(\n call.response,\n t('wms.backend.inventory.adjust.errors.submit', 'Failed to adjust inventory.'),\n )\n }\n return call.result ?? {}\n },\n context: mutationContext,\n mutationPayload: payload,\n })\n\n flash(t('wms.backend.inventory.adjust.flash.success', 'Inventory adjusted'), 'success')\n await queryClient.invalidateQueries({ queryKey: ['wms-inventory-console'] })\n await queryClient.invalidateQueries({ queryKey: ['wms-sku-detail'] })\n closeDialog()\n } catch (error) {\n flashMutationError(error, t('wms.backend.inventory.adjust.errors.submit', 'Failed to adjust inventory.'), t)\n } finally {\n setSubmitting(false)\n }\n },\n [\n access,\n adjustFormSchema,\n closeDialog,\n form,\n mutationContext,\n queryClient,\n runMutation,\n t,\n ],\n )\n\n const handleDialogKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n closeDialog()\n return\n }\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n if (!submitting) void handleSubmit()\n }\n },\n [closeDialog, handleSubmit, submitting],\n )\n\n const adjustDelta = React.useCallback((step: -1 | 1) => {\n setForm((current) => {\n const next = current.delta + step\n return { ...current, delta: next === 0 ? step : next }\n })\n setFieldErrors({})\n }, [])\n\n return (\n <Dialog open={open} onOpenChange={(next) => (next ? onOpenChange(true) : closeDialog())}>\n <DialogContent\n className=\"max-w-lg gap-0 overflow-hidden p-0\"\n onKeyDown={handleDialogKeyDown}\n >\n <div className=\"border-b px-6 py-4 pr-12\">\n <DialogHeader className=\"space-y-1 text-left\">\n <DialogTitle>\n {t('wms.backend.inventory.adjust.dialog.title', 'Adjust inventory')}\n </DialogTitle>\n <DialogDescription>\n {t(\n 'wms.backend.inventory.adjust.dialog.description',\n 'Append a signed delta to the ledger',\n )}\n </DialogDescription>\n </DialogHeader>\n </div>\n\n <form ref={formRef} onSubmit={handleSubmit} className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"flex flex-col gap-5 overflow-y-auto px-6 py-6\">\n <FormField\n label={t('wms.backend.inventory.adjust.form.variant', 'Variant')}\n required\n error={fieldErrors.catalogVariantId}\n >\n <div className=\"relative [&_input]:pl-9\">\n <Package\n className=\"pointer-events-none absolute left-3 top-1/2 z-10 size-4 -translate-y-1/2 text-muted-foreground\"\n aria-hidden=\"true\"\n />\n <ComboboxInput\n value={form.catalogVariantId}\n onChange={(next) => {\n patchForm({\n catalogVariantId: next.trim(),\n lotNumber: '',\n })\n }}\n loadSuggestions={async (query) => {\n const options = await loadCatalogVariantOptions(query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n description: option.description,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.variantPlaceholder',\n 'Search variant or SKU',\n )}\n allowCustomValues={false}\n disabled={submitting}\n />\n </div>\n </FormField>\n\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <FormField\n label={t('wms.backend.inventory.adjust.form.warehouse', 'Warehouse')}\n required\n error={fieldErrors.warehouseId}\n >\n <ComboboxInput\n value={form.warehouseId}\n onChange={(next) => {\n patchForm({\n warehouseId: next.trim(),\n locationId: '',\n })\n }}\n loadSuggestions={async (query) => {\n const options = await loadWarehouseOptions(query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.warehousePlaceholder',\n 'Select warehouse',\n )}\n allowCustomValues={false}\n disabled={submitting}\n />\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.location', 'Location')}\n required\n error={fieldErrors.locationId}\n >\n <ComboboxInput\n value={form.locationId}\n onChange={(next) => patchForm({ locationId: next.trim() })}\n loadSuggestions={async (query) => {\n const options = await loadLocationOptions(form.warehouseId, query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.locationPlaceholder',\n 'Select location',\n )}\n allowCustomValues={false}\n disabled={submitting || !form.warehouseId}\n />\n </FormField>\n </div>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.lot', 'Lot')}\n error={fieldErrors.lotNumber}\n >\n <ComboboxInput\n value={form.lotNumber}\n onChange={(next) => patchForm({ lotNumber: next.trim() })}\n loadSuggestions={async (query) => {\n const options = await loadLotNumberOptions(form.catalogVariantId, query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.lotPlaceholder',\n 'Select lot (optional)',\n )}\n allowCustomValues\n disabled={submitting || !form.catalogVariantId}\n />\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.serial', 'Serial number')}\n error={fieldErrors.serialNumber}\n >\n <Input\n value={form.serialNumber}\n onChange={(event) => patchForm({ serialNumber: event.target.value })}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.serialPlaceholder',\n 'Optional \u2014 for serial-tracked variants',\n )}\n disabled={submitting}\n />\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t(\n 'wms.backend.inventory.adjust.form.serialHelp',\n 'Use when the variant profile tracks serials.',\n )}\n </p>\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.delta', 'Adjustment')}\n required\n error={fieldErrors.delta}\n >\n <div className=\"flex w-32 items-center gap-2 rounded-md border bg-background p-2 shadow-xs\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('wms.backend.inventory.adjust.form.decrease', 'Decrease quantity')}\n onClick={() => adjustDelta(-1)}\n disabled={submitting}\n >\n <Minus className=\"size-4\" />\n </IconButton>\n <Input\n type=\"text\"\n inputMode=\"decimal\"\n value={deltaInputText}\n onChange={(event) => {\n setDeltaInputText(event.target.value)\n const parsed = parseDeltaInput(event.target.value, locale)\n if (parsed == null) return\n patchForm({ delta: parsed })\n }}\n onFocus={() => {\n deltaInputFocusedRef.current = true\n }}\n onBlur={() => {\n deltaInputFocusedRef.current = false\n setDeltaInputText(formatLocaleNumberInput(form.delta, locale))\n }}\n className=\"h-8 w-auto min-w-0 flex-1 border-0 bg-transparent p-0 shadow-none focus-visible:ring-0\"\n inputClassName=\"text-center [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n disabled={submitting}\n />\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('wms.backend.inventory.adjust.form.increase', 'Increase quantity')}\n onClick={() => adjustDelta(1)}\n disabled={submitting}\n >\n <Plus className=\"size-4\" />\n </IconButton>\n </div>\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.reason', 'Reason')}\n required\n error={fieldErrors.reasonCode}\n >\n <Select\n value={form.reasonCode || undefined}\n onValueChange={(next) =>\n patchForm({ reasonCode: next as AdjustReasonCode })\n }\n disabled={submitting}\n >\n <SelectTrigger>\n <SelectValue\n placeholder={t(\n 'wms.backend.inventory.adjust.form.reasonPlaceholder',\n 'Select reason',\n )}\n />\n </SelectTrigger>\n <SelectContent>\n {ADJUST_REASON_CODES.map((code) => (\n <SelectItem key={code} value={code}>\n {reasonLabel(code)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </FormField>\n\n <FormField label={t('wms.backend.inventory.adjust.form.notes', 'Notes')}>\n <Textarea\n value={form.notes}\n onChange={(event) => patchForm({ notes: event.target.value })}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.notesPlaceholder',\n 'Optional \u2014 context for auditors',\n )}\n rows={3}\n disabled={submitting}\n />\n </FormField>\n\n {previewContextReady ? (\n <div className=\"rounded-lg border bg-muted/40 px-4 py-3.5\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {t('wms.backend.inventory.adjust.preview.title', 'Balance preview')}\n </p>\n <div className=\"mt-2 flex items-center justify-between gap-3\">\n {previewError ? (\n <p className=\"text-sm text-status-warning-fg\">{previewError}</p>\n ) : loadingPreview && onHand == null ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('wms.backend.inventory.adjust.preview.loading', 'Refreshing balance\u2026')}\n </p>\n ) : onHand != null && projectedOnHand != null ? (\n <p className=\"text-sm font-semibold tabular-nums text-foreground\">\n {t('wms.backend.inventory.adjust.preview.onHandLabel', 'On hand')}{' '}\n {onHand}\n {' \u2192 '}\n {projectedOnHand}\n </p>\n ) : onHand != null ? (\n <p className=\"text-sm font-semibold tabular-nums text-foreground\">\n {t('wms.backend.inventory.adjust.preview.onHandLabel', 'On hand')}{' '}\n {onHand}\n </p>\n ) : null}\n {showBelowReorder ? (\n <StatusBadge variant=\"warning\">\n {t(\n 'wms.backend.inventory.adjust.preview.belowReorder',\n 'Below reorder',\n )}\n </StatusBadge>\n ) : null}\n </div>\n {loadingPreview && onHand != null ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t('wms.backend.inventory.adjust.preview.loading', 'Refreshing balance\u2026')}\n </p>\n ) : null}\n </div>\n ) : null}\n </div>\n\n <DialogFooter bordered={false} className=\"border-t px-6 py-4 sm:justify-between\">\n <p className=\"hidden text-xs text-muted-foreground sm:inline-flex sm:items-center sm:gap-1.5\">\n <KbdShortcut keys={['\u2318', 'Enter']} />\n <span>/</span>\n <KbdShortcut keys={['Ctrl', 'Enter']} />\n <span>{t('wms.backend.inventory.adjust.dialog.shortcutSave', 'to save')}</span>\n </p>\n <div className=\"flex w-full flex-col-reverse gap-2 sm:w-auto sm:flex-row\">\n <Button type=\"button\" variant=\"outline\" onClick={closeDialog} disabled={submitting}>\n {t('common.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={submitting}>\n {t('wms.backend.inventory.adjust.dialog.submit', 'Save adjustment')}\n </Button>\n </div>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { Minus, Package, Plus } from 'lucide-react'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flashMutationError } from '../../lib/flashMutationError'\nimport { ComboboxInput } from '@open-mercato/ui/backend/inputs/ComboboxInput'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { raiseCrudError, readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { FormField } from '@open-mercato/ui/primitives/form-field'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { KbdShortcut } from '@open-mercato/ui/primitives/kbd'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { formatLocaleNumberInput, parseLocaleNumber } from '@open-mercato/shared/lib/number'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { buildInventoryMutationReferenceId } from '../../lib/inventoryMutationUi'\nimport {\n BalanceLookupError,\n ensureLotIdForInventoryMutation,\n fetchBalanceOnHand,\n fetchVariantReorderPoint,\n findLotIdByNumber,\n InventoryLotMutationError,\n loadCatalogVariantOptions,\n loadLocationOptions,\n loadLotNumberOptions,\n loadWarehouseOptions,\n resolveCatalogVariantLabel,\n resolveLocationLabel,\n resolveLotNumberFromId,\n resolveWarehouseLabel,\n} from './inventoryMutationLoaders'\nimport type { useWmsInventoryMutationAccess } from './useWmsInventoryMutationAccess'\n\nconst logger = createLogger('wms')\n\nconst ADJUST_REASON_CODES = ['damaged', 'shrinkage', 'found', 'correction', 'other'] as const\n\ntype AdjustReasonCode = (typeof ADJUST_REASON_CODES)[number]\n\ntype AdjustFormValues = {\n catalogVariantId: string\n warehouseId: string\n locationId: string\n lotNumber: string\n delta: number\n reasonCode: AdjustReasonCode | ''\n notes: string\n serialNumber: string\n}\n\ntype AdjustInventoryDialogProps = {\n open: boolean\n onOpenChange: (open: boolean) => void\n access: ReturnType<typeof useWmsInventoryMutationAccess>\n initialCatalogVariantId?: string\n initialWarehouseId?: string\n initialLocationId?: string\n initialLotId?: string\n}\n\nconst EMPTY_FORM: AdjustFormValues = {\n catalogVariantId: '',\n warehouseId: '',\n locationId: '',\n lotNumber: '',\n delta: 1,\n reasonCode: '',\n notes: '',\n serialNumber: '',\n}\n\nexport function parseDeltaInput(value: string, locale?: string): number | null {\n const trimmed = value.trim()\n if (!trimmed || trimmed === '-' || trimmed === '+') return null\n return parseLocaleNumber(trimmed, locale)\n}\n\nexport function AdjustInventoryDialog({\n open,\n onOpenChange,\n access,\n initialCatalogVariantId,\n initialWarehouseId,\n initialLocationId,\n initialLotId,\n}: AdjustInventoryDialogProps) {\n const t = useT()\n const locale = useLocale()\n const queryClient = useQueryClient()\n const formRef = React.useRef<HTMLFormElement>(null)\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: 'wms-inventory-adjust',\n })\n const mutationContext = React.useMemo(\n () => ({ retryLastMutation }),\n [retryLastMutation],\n )\n const adjustFormSchema = React.useMemo(\n () =>\n z.object({\n catalogVariantId: z.string().uuid(),\n warehouseId: z.string().uuid(),\n locationId: z.string().uuid(),\n lotNumber: z.string().trim().max(120).optional(),\n delta: z.coerce.number().refine((value) => value !== 0, {\n message: t(\n 'wms.backend.inventory.adjust.errors.deltaZero',\n 'Inventory delta must be non-zero.',\n ),\n }),\n reasonCode: z.enum(ADJUST_REASON_CODES),\n notes: z.string().trim().max(500).optional(),\n serialNumber: z.string().trim().max(120).optional(),\n }),\n [t],\n )\n const [submitting, setSubmitting] = React.useState(false)\n const [form, setForm] = React.useState<AdjustFormValues>(EMPTY_FORM)\n // Raw text the user is typing into the delta field, decoupled from `form.delta` (issue\n // #5828): re-deriving the input's display from the committed number on every keystroke\n // drops an in-progress decimal separator the instant it's typed (`2,5` collapses to `2`\n // then the next digit appends, producing `25`). Synced from `form.delta` only while the\n // field is not focused, mirroring `CrudForm.NumberInput`'s buffer.\n const [deltaInputText, setDeltaInputText] = React.useState<string>(() => formatLocaleNumberInput(EMPTY_FORM.delta, locale))\n const deltaInputFocusedRef = React.useRef(false)\n const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({})\n const [onHand, setOnHand] = React.useState<number | null>(null)\n const [previewError, setPreviewError] = React.useState<string | null>(null)\n const [reorderPoint, setReorderPoint] = React.useState(0)\n const [loadingPreview, setLoadingPreview] = React.useState(false)\n const [optionLabelByValue, setOptionLabelByValue] = React.useState<Record<string, string>>({})\n\n const registerOptionLabels = React.useCallback(\n (options: Array<{ value: string; label: string }>) => {\n setOptionLabelByValue((current) => {\n let changed = false\n const next = { ...current }\n for (const option of options) {\n const value = option.value.trim()\n const label = option.label.trim()\n if (!value || !label || next[value] === label) continue\n next[value] = label\n changed = true\n }\n return changed ? next : current\n })\n },\n [],\n )\n\n const resolveOptionLabel = React.useCallback(\n (value: string) => optionLabelByValue[value] ?? value,\n [optionLabelByValue],\n )\n const optionLabelByValueRef = React.useRef(optionLabelByValue)\n optionLabelByValueRef.current = optionLabelByValue\n\n const reasonLabel = React.useCallback(\n (code: AdjustReasonCode) => {\n const fallbacks: Record<AdjustReasonCode, string> = {\n damaged: 'Damaged',\n shrinkage: 'Shrinkage',\n found: 'Found stock',\n correction: 'Correction',\n other: 'Other',\n }\n return t(`wms.backend.inventory.adjust.reasons.${code}`, fallbacks[code])\n },\n [t],\n )\n\n const resetDialog = React.useCallback(() => {\n setForm(EMPTY_FORM)\n setDeltaInputText(formatLocaleNumberInput(EMPTY_FORM.delta, locale))\n setFieldErrors({})\n setOnHand(null)\n setPreviewError(null)\n setReorderPoint(0)\n setLoadingPreview(false)\n setSubmitting(false)\n setOptionLabelByValue({})\n }, [locale])\n\n const closeDialog = React.useCallback(() => {\n onOpenChange(false)\n resetDialog()\n }, [onOpenChange, resetDialog])\n\n const patchForm = React.useCallback((patch: Partial<AdjustFormValues>) => {\n setForm((current) => ({ ...current, ...patch }))\n setFieldErrors({})\n }, [])\n\n React.useEffect(() => {\n if (!deltaInputFocusedRef.current) setDeltaInputText(formatLocaleNumberInput(form.delta, locale))\n }, [form.delta, locale])\n\n React.useEffect(() => {\n if (!open) return\n const catalogVariantId = initialCatalogVariantId?.trim()\n const warehouseId = initialWarehouseId?.trim()\n const locationId = initialLocationId?.trim()\n const lotId = initialLotId?.trim()\n if (!catalogVariantId && !warehouseId && !locationId && !lotId) return\n setForm((current) => ({\n ...current,\n ...(catalogVariantId ? { catalogVariantId } : {}),\n ...(warehouseId ? { warehouseId, locationId: locationId ?? '' } : {}),\n ...(locationId ? { locationId } : {}),\n }))\n if (!lotId) return\n let cancelled = false\n void resolveLotNumberFromId(lotId).then((lotNumber) => {\n if (cancelled || !lotNumber) return\n setForm((current) => ({ ...current, lotNumber }))\n registerOptionLabels([{ value: lotNumber, label: lotNumber }])\n })\n return () => {\n cancelled = true\n }\n }, [\n initialCatalogVariantId,\n initialLocationId,\n initialLotId,\n initialWarehouseId,\n open,\n registerOptionLabels,\n ])\n\n React.useEffect(() => {\n if (!open) return\n let cancelled = false\n\n const ensureLabel = async (value: string, resolve: (id: string) => Promise<string | null>) => {\n const id = value.trim()\n if (!id || optionLabelByValueRef.current[id]) return\n const label = await resolve(id)\n if (cancelled || !label) return\n registerOptionLabels([{ value: id, label }])\n }\n\n void Promise.all([\n ensureLabel(form.catalogVariantId, resolveCatalogVariantLabel),\n ensureLabel(form.warehouseId, resolveWarehouseLabel),\n ensureLabel(form.locationId, resolveLocationLabel),\n ])\n\n return () => {\n cancelled = true\n }\n }, [\n form.catalogVariantId,\n form.locationId,\n form.warehouseId,\n open,\n registerOptionLabels,\n ])\n\n React.useEffect(() => {\n if (!open) return\n const variantId = form.catalogVariantId.trim()\n if (!variantId) {\n setReorderPoint(0)\n return\n }\n let cancelled = false\n void fetchVariantReorderPoint(variantId).then((value) => {\n if (!cancelled) setReorderPoint(value)\n })\n return () => {\n cancelled = true\n }\n }, [form.catalogVariantId, open])\n\n const previewContextReady = Boolean(\n form.catalogVariantId.trim() &&\n form.warehouseId.trim() &&\n form.locationId.trim(),\n )\n\n React.useEffect(() => {\n if (!open) return\n const warehouseId = form.warehouseId.trim()\n const locationId = form.locationId.trim()\n const catalogVariantId = form.catalogVariantId.trim()\n const lotNumber = form.lotNumber.trim()\n if (!warehouseId || !locationId || !catalogVariantId) {\n setOnHand(null)\n setPreviewError(null)\n setLoadingPreview(false)\n return\n }\n let cancelled = false\n setLoadingPreview(true)\n setPreviewError(null)\n void (async () => {\n try {\n const lotId = lotNumber\n ? await findLotIdByNumber(catalogVariantId, lotNumber)\n : null\n if (cancelled) return\n const value = await fetchBalanceOnHand({\n warehouseId,\n locationId,\n catalogVariantId,\n lotId,\n })\n if (!cancelled) {\n setOnHand(value)\n setPreviewError(null)\n }\n } catch (error: unknown) {\n if (cancelled) return\n setOnHand(null)\n if (error instanceof BalanceLookupError) {\n setPreviewError(\n t(\n 'wms.backend.inventory.adjust.errors.previewBalance',\n 'Failed to load balance preview.',\n ),\n )\n return\n }\n logger.error('fetchBalanceOnHand failed', { component: 'AdjustInventoryDialog', err: error })\n setPreviewError(\n t(\n 'wms.backend.inventory.adjust.errors.previewBalance',\n 'Failed to load balance preview.',\n ),\n )\n } finally {\n if (!cancelled) setLoadingPreview(false)\n }\n })()\n return () => {\n cancelled = true\n }\n }, [\n form.catalogVariantId,\n form.locationId,\n form.lotNumber,\n form.warehouseId,\n open,\n t,\n ])\n\n const projectedOnHand =\n onHand != null && form.delta !== 0 ? onHand + form.delta : null\n const showBelowReorder =\n projectedOnHand != null && reorderPoint > 0 && projectedOnHand <= reorderPoint\n\n const handleSubmit = React.useCallback(\n async (event?: React.FormEvent) => {\n event?.preventDefault()\n const parsed = adjustFormSchema.safeParse({\n ...form,\n lotNumber: form.lotNumber.trim() || undefined,\n notes: form.notes.trim() || undefined,\n serialNumber: form.serialNumber.trim() || undefined,\n })\n if (!parsed.success) {\n const nextErrors: Record<string, string> = {}\n for (const issue of parsed.error.issues) {\n const key = String(issue.path[0] ?? 'form')\n if (!nextErrors[key]) nextErrors[key] = issue.message\n }\n setFieldErrors(nextErrors)\n return\n }\n\n if (!access.scopeReady || !access.organizationId || !access.tenantId || !access.userId) {\n flash(\n t(\n 'wms.backend.inventory.mutations.errors.scope',\n 'Select an organization and sign in before posting inventory changes.',\n ),\n 'error',\n )\n return\n }\n\n setSubmitting(true)\n try {\n // Persist the stable reason code (not a locale-rendered label) so activity\n // feeds can re-translate for the viewer's language later.\n const reason = parsed.data.reasonCode\n const notes = parsed.data.notes?.trim()\n const lotNumber = parsed.data.lotNumber?.trim()\n let lotId: string | undefined\n if (lotNumber) {\n try {\n lotId = await ensureLotIdForInventoryMutation({\n catalogVariantId: parsed.data.catalogVariantId,\n lotNumber,\n organizationId: access.organizationId,\n tenantId: access.tenantId,\n })\n } catch (error: unknown) {\n const message =\n error instanceof InventoryLotMutationError\n ? error.message\n : t(\n 'wms.backend.inventory.adjust.errors.lot',\n 'Failed to resolve inventory lot.',\n )\n setFieldErrors({ lotNumber: message })\n return\n }\n }\n const payload: Record<string, unknown> = {\n organizationId: access.organizationId,\n tenantId: access.tenantId,\n warehouseId: parsed.data.warehouseId,\n locationId: parsed.data.locationId,\n catalogVariantId: parsed.data.catalogVariantId,\n delta: parsed.data.delta,\n reason,\n reasonCode: parsed.data.reasonCode,\n referenceType: 'manual',\n referenceId: buildInventoryMutationReferenceId(),\n performedBy: access.userId,\n }\n if (lotId) payload.lotId = lotId\n const serial = parsed.data.serialNumber?.trim()\n if (serial) payload.serialNumber = serial\n if (notes) payload.metadata = { notes }\n\n await runMutation({\n operation: async () => {\n const call = await apiCall<{ ok?: boolean; movementId?: string }>(\n '/api/wms/inventory/adjust',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n )\n if (!call.ok) {\n const errorBody = await readJsonSafe<{ error?: string }>(call.response.clone(), null)\n if (errorBody?.error === 'insufficient_stock') {\n throw new Error(\n t(\n 'wms.backend.inventory.adjust.errors.insufficientStock',\n 'The adjustment is larger than the available quantity in this location.',\n ),\n )\n }\n await raiseCrudError(\n call.response,\n t('wms.backend.inventory.adjust.errors.submit', 'Failed to adjust inventory.'),\n )\n }\n return call.result ?? {}\n },\n context: mutationContext,\n mutationPayload: payload,\n })\n\n flash(t('wms.backend.inventory.adjust.flash.success', 'Inventory adjusted'), 'success')\n await queryClient.invalidateQueries({ queryKey: ['wms-inventory-console'] })\n await queryClient.invalidateQueries({ queryKey: ['wms-sku-detail'] })\n closeDialog()\n } catch (error) {\n flashMutationError(error, t('wms.backend.inventory.adjust.errors.submit', 'Failed to adjust inventory.'), t)\n } finally {\n setSubmitting(false)\n }\n },\n [\n access,\n adjustFormSchema,\n closeDialog,\n form,\n mutationContext,\n queryClient,\n runMutation,\n t,\n ],\n )\n\n const handleDialogKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n closeDialog()\n return\n }\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n if (!submitting) void handleSubmit()\n }\n },\n [closeDialog, handleSubmit, submitting],\n )\n\n const adjustDelta = React.useCallback((step: -1 | 1) => {\n setForm((current) => {\n const next = current.delta + step\n return { ...current, delta: next === 0 ? step : next }\n })\n setFieldErrors({})\n }, [])\n\n return (\n <Dialog open={open} onOpenChange={(next) => (next ? onOpenChange(true) : closeDialog())}>\n <DialogContent\n className=\"max-w-lg gap-0 overflow-hidden p-0\"\n onKeyDown={handleDialogKeyDown}\n >\n <div className=\"border-b px-6 py-4 pr-12\">\n <DialogHeader className=\"space-y-1 text-left\">\n <DialogTitle>\n {t('wms.backend.inventory.adjust.dialog.title', 'Adjust inventory')}\n </DialogTitle>\n <DialogDescription>\n {t(\n 'wms.backend.inventory.adjust.dialog.description',\n 'Append a signed delta to the ledger',\n )}\n </DialogDescription>\n </DialogHeader>\n </div>\n\n <form ref={formRef} onSubmit={handleSubmit} className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"flex flex-col gap-5 overflow-y-auto px-6 py-6\">\n <FormField\n label={t('wms.backend.inventory.adjust.form.variant', 'Variant')}\n required\n error={fieldErrors.catalogVariantId}\n >\n <div className=\"relative [&_input]:pl-9\">\n <Package\n className=\"pointer-events-none absolute left-3 top-1/2 z-10 size-4 -translate-y-1/2 text-muted-foreground\"\n aria-hidden=\"true\"\n />\n <ComboboxInput\n value={form.catalogVariantId}\n onChange={(next) => {\n patchForm({\n catalogVariantId: next.trim(),\n lotNumber: '',\n })\n }}\n loadSuggestions={async (query) => {\n const options = await loadCatalogVariantOptions(query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n description: option.description,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.variantPlaceholder',\n 'Search variant or SKU',\n )}\n allowCustomValues={false}\n disabled={submitting}\n />\n </div>\n </FormField>\n\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <FormField\n label={t('wms.backend.inventory.adjust.form.warehouse', 'Warehouse')}\n required\n error={fieldErrors.warehouseId}\n >\n <ComboboxInput\n value={form.warehouseId}\n onChange={(next) => {\n patchForm({\n warehouseId: next.trim(),\n locationId: '',\n })\n }}\n loadSuggestions={async (query) => {\n const options = await loadWarehouseOptions(query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.warehousePlaceholder',\n 'Select warehouse',\n )}\n allowCustomValues={false}\n disabled={submitting}\n />\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.location', 'Location')}\n required\n error={fieldErrors.locationId}\n >\n <ComboboxInput\n value={form.locationId}\n onChange={(next) => patchForm({ locationId: next.trim() })}\n loadSuggestions={async (query) => {\n const options = await loadLocationOptions(form.warehouseId, query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.locationPlaceholder',\n 'Select location',\n )}\n allowCustomValues={false}\n disabled={submitting || !form.warehouseId}\n />\n </FormField>\n </div>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.lot', 'Lot')}\n error={fieldErrors.lotNumber}\n >\n <ComboboxInput\n value={form.lotNumber}\n onChange={(next) => patchForm({ lotNumber: next.trim() })}\n loadSuggestions={async (query) => {\n const options = await loadLotNumberOptions(form.catalogVariantId, query)\n registerOptionLabels(options)\n return options.map((option) => ({\n value: option.value,\n label: option.label,\n }))\n }}\n resolveLabel={resolveOptionLabel}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.lotPlaceholder',\n 'Select lot (optional)',\n )}\n allowCustomValues\n disabled={submitting || !form.catalogVariantId}\n />\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.serial', 'Serial number')}\n error={fieldErrors.serialNumber}\n >\n <Input\n value={form.serialNumber}\n onChange={(event) => patchForm({ serialNumber: event.target.value })}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.serialPlaceholder',\n 'Optional \u2014 for serial-tracked variants',\n )}\n disabled={submitting}\n />\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t(\n 'wms.backend.inventory.adjust.form.serialHelp',\n 'Use when the variant profile tracks serials.',\n )}\n </p>\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.delta', 'Adjustment')}\n required\n error={fieldErrors.delta}\n >\n <div className=\"flex w-32 items-center gap-2 rounded-md border bg-background p-2 shadow-xs\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('wms.backend.inventory.adjust.form.decrease', 'Decrease quantity')}\n onClick={() => adjustDelta(-1)}\n disabled={submitting}\n >\n <Minus className=\"size-4\" />\n </IconButton>\n <Input\n type=\"text\"\n inputMode=\"decimal\"\n value={deltaInputText}\n onChange={(event) => {\n setDeltaInputText(event.target.value)\n const parsed = parseDeltaInput(event.target.value, locale)\n if (parsed == null) return\n patchForm({ delta: parsed })\n }}\n onFocus={() => {\n deltaInputFocusedRef.current = true\n }}\n onBlur={() => {\n deltaInputFocusedRef.current = false\n setDeltaInputText(formatLocaleNumberInput(form.delta, locale))\n }}\n className=\"h-8 w-auto min-w-0 flex-1 border-0 bg-transparent p-0 shadow-none focus-visible:ring-0\"\n inputClassName=\"text-center [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n disabled={submitting}\n />\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('wms.backend.inventory.adjust.form.increase', 'Increase quantity')}\n onClick={() => adjustDelta(1)}\n disabled={submitting}\n >\n <Plus className=\"size-4\" />\n </IconButton>\n </div>\n </FormField>\n\n <FormField\n label={t('wms.backend.inventory.adjust.form.reason', 'Reason')}\n required\n error={fieldErrors.reasonCode}\n >\n <Select\n value={form.reasonCode || undefined}\n onValueChange={(next) =>\n patchForm({ reasonCode: next as AdjustReasonCode })\n }\n disabled={submitting}\n >\n <SelectTrigger>\n <SelectValue\n placeholder={t(\n 'wms.backend.inventory.adjust.form.reasonPlaceholder',\n 'Select reason',\n )}\n />\n </SelectTrigger>\n <SelectContent>\n {ADJUST_REASON_CODES.map((code) => (\n <SelectItem key={code} value={code}>\n {reasonLabel(code)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </FormField>\n\n <FormField label={t('wms.backend.inventory.adjust.form.notes', 'Notes')}>\n <Textarea\n value={form.notes}\n onChange={(event) => patchForm({ notes: event.target.value })}\n placeholder={t(\n 'wms.backend.inventory.adjust.form.notesPlaceholder',\n 'Optional \u2014 context for auditors',\n )}\n rows={3}\n disabled={submitting}\n />\n </FormField>\n\n {previewContextReady ? (\n <div className=\"rounded-lg border bg-muted/40 px-4 py-3.5\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {t('wms.backend.inventory.adjust.preview.title', 'Balance preview')}\n </p>\n <div className=\"mt-2 flex items-center justify-between gap-3\">\n {previewError ? (\n <p className=\"text-sm text-status-warning-fg\">{previewError}</p>\n ) : loadingPreview && onHand == null ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('wms.backend.inventory.adjust.preview.loading', 'Refreshing balance\u2026')}\n </p>\n ) : onHand != null && projectedOnHand != null ? (\n <p className=\"text-sm font-semibold tabular-nums text-foreground\">\n {t('wms.backend.inventory.adjust.preview.onHandLabel', 'On hand')}{' '}\n {onHand}\n {' \u2192 '}\n {projectedOnHand}\n </p>\n ) : onHand != null ? (\n <p className=\"text-sm font-semibold tabular-nums text-foreground\">\n {t('wms.backend.inventory.adjust.preview.onHandLabel', 'On hand')}{' '}\n {onHand}\n </p>\n ) : null}\n {showBelowReorder ? (\n <StatusBadge variant=\"warning\">\n {t(\n 'wms.backend.inventory.adjust.preview.belowReorder',\n 'Below reorder',\n )}\n </StatusBadge>\n ) : null}\n </div>\n {loadingPreview && onHand != null ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t('wms.backend.inventory.adjust.preview.loading', 'Refreshing balance\u2026')}\n </p>\n ) : null}\n </div>\n ) : null}\n </div>\n\n <DialogFooter bordered={false} className=\"border-t px-6 py-4 sm:justify-between\">\n <p className=\"hidden text-xs text-muted-foreground sm:inline-flex sm:items-center sm:gap-1.5\">\n <KbdShortcut keys={['\u2318', 'Enter']} />\n <span>/</span>\n <KbdShortcut keys={['Ctrl', 'Enter']} />\n <span>{t('wms.backend.inventory.adjust.dialog.shortcutSave', 'to save')}</span>\n </p>\n <div className=\"flex w-full flex-col-reverse gap-2 sm:w-auto sm:flex-row\">\n <Button type=\"button\" variant=\"outline\" onClick={closeDialog} disabled={submitting}>\n {t('common.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={submitting}>\n {t('wms.backend.inventory.adjust.dialog.submit', 'Save adjustment')}\n </Button>\n </div>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.10.1-develop.7920.1.159653827a",
3
+ "version": "0.10.1-develop.7921.1.e5774a7073",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -266,16 +266,16 @@
266
266
  "zod": "^4.6.6"
267
267
  },
268
268
  "peerDependencies": {
269
- "@open-mercato/ai-assistant": "0.10.1-develop.7920.1.159653827a",
270
- "@open-mercato/shared": "0.10.1-develop.7920.1.159653827a",
271
- "@open-mercato/ui": "0.10.1-develop.7920.1.159653827a",
269
+ "@open-mercato/ai-assistant": "0.10.1-develop.7921.1.e5774a7073",
270
+ "@open-mercato/shared": "0.10.1-develop.7921.1.e5774a7073",
271
+ "@open-mercato/ui": "0.10.1-develop.7921.1.e5774a7073",
272
272
  "react": "^19.0.0",
273
273
  "react-dom": "^19.0.0"
274
274
  },
275
275
  "devDependencies": {
276
- "@open-mercato/ai-assistant": "0.10.1-develop.7920.1.159653827a",
277
- "@open-mercato/shared": "0.10.1-develop.7920.1.159653827a",
278
- "@open-mercato/ui": "0.10.1-develop.7920.1.159653827a",
276
+ "@open-mercato/ai-assistant": "0.10.1-develop.7921.1.e5774a7073",
277
+ "@open-mercato/shared": "0.10.1-develop.7921.1.e5774a7073",
278
+ "@open-mercato/ui": "0.10.1-develop.7921.1.e5774a7073",
279
279
  "@testing-library/dom": "^10.4.1",
280
280
  "@testing-library/jest-dom": "^7.0.1",
281
281
  "@testing-library/react": "^16.3.3",
@@ -9,7 +9,7 @@ import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuarde
9
9
  import { flashMutationError } from '../../lib/flashMutationError'
10
10
  import { ComboboxInput } from '@open-mercato/ui/backend/inputs/ComboboxInput'
11
11
  import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
12
- import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
12
+ import { raiseCrudError, readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'
13
13
  import { Button } from '@open-mercato/ui/primitives/button'
14
14
  import {
15
15
  Dialog,
@@ -461,6 +461,15 @@ export function AdjustInventoryDialog({
461
461
  },
462
462
  )
463
463
  if (!call.ok) {
464
+ const errorBody = await readJsonSafe<{ error?: string }>(call.response.clone(), null)
465
+ if (errorBody?.error === 'insufficient_stock') {
466
+ throw new Error(
467
+ t(
468
+ 'wms.backend.inventory.adjust.errors.insufficientStock',
469
+ 'The adjustment is larger than the available quantity in this location.',
470
+ ),
471
+ )
472
+ }
464
473
  await raiseCrudError(
465
474
  call.response,
466
475
  t('wms.backend.inventory.adjust.errors.submit', 'Failed to adjust inventory.'),
@@ -344,6 +344,7 @@
344
344
  "wms.backend.inventory.adjust.dialog.submit": "Korrektur speichern",
345
345
  "wms.backend.inventory.adjust.dialog.title": "Bestand anpassen",
346
346
  "wms.backend.inventory.adjust.errors.deltaZero": "Das Bestandsdelta darf nicht Null sein.",
347
+ "wms.backend.inventory.adjust.errors.insufficientStock": "Die Korrektur übersteigt die an diesem Lagerplatz verfügbare Menge.",
347
348
  "wms.backend.inventory.adjust.errors.lot": "Das Inventarlos konnte nicht aufgelöst werden.",
348
349
  "wms.backend.inventory.adjust.errors.previewBalance": "Die Balance-Vorschau konnte nicht geladen werden.",
349
350
  "wms.backend.inventory.adjust.errors.submit": "Der Lagerbestand konnte nicht angepasst werden.",
@@ -344,6 +344,7 @@
344
344
  "wms.backend.inventory.adjust.dialog.submit": "Save adjustment",
345
345
  "wms.backend.inventory.adjust.dialog.title": "Adjust inventory",
346
346
  "wms.backend.inventory.adjust.errors.deltaZero": "Inventory delta must be non-zero.",
347
+ "wms.backend.inventory.adjust.errors.insufficientStock": "The adjustment is larger than the available quantity in this location.",
347
348
  "wms.backend.inventory.adjust.errors.lot": "Failed to resolve inventory lot.",
348
349
  "wms.backend.inventory.adjust.errors.previewBalance": "Failed to load balance preview.",
349
350
  "wms.backend.inventory.adjust.errors.submit": "Failed to adjust inventory.",
@@ -344,6 +344,7 @@
344
344
  "wms.backend.inventory.adjust.dialog.submit": "Guardar ajuste",
345
345
  "wms.backend.inventory.adjust.dialog.title": "Ajustar inventario",
346
346
  "wms.backend.inventory.adjust.errors.deltaZero": "El delta de inventario debe ser distinto de cero.",
347
+ "wms.backend.inventory.adjust.errors.insufficientStock": "El ajuste supera la cantidad disponible en esta ubicación.",
347
348
  "wms.backend.inventory.adjust.errors.lot": "No se pudo resolver el lote de inventario.",
348
349
  "wms.backend.inventory.adjust.errors.previewBalance": "No se pudo cargar la vista previa del saldo.",
349
350
  "wms.backend.inventory.adjust.errors.submit": "No se pudo ajustar el inventario.",
@@ -344,6 +344,7 @@
344
344
  "wms.backend.inventory.adjust.dialog.submit": "조정 저장",
345
345
  "wms.backend.inventory.adjust.dialog.title": "재고 조정",
346
346
  "wms.backend.inventory.adjust.errors.deltaZero": "재고 델타는 0이 아니어야 합니다.",
347
+ "wms.backend.inventory.adjust.errors.insufficientStock": "조정 수량이 이 위치의 가용 수량보다 큽니다.",
347
348
  "wms.backend.inventory.adjust.errors.lot": "재고 로트를 해결하지 못했습니다.",
348
349
  "wms.backend.inventory.adjust.errors.previewBalance": "미리보기 로드 밸런싱에 실패했습니다.",
349
350
  "wms.backend.inventory.adjust.errors.submit": "인벤토리 조정에 실패했습니다.",
@@ -344,6 +344,7 @@
344
344
  "wms.backend.inventory.adjust.dialog.submit": "Zapisz korektę",
345
345
  "wms.backend.inventory.adjust.dialog.title": "Korekta stanu",
346
346
  "wms.backend.inventory.adjust.errors.deltaZero": "Delta stanu magazynowego nie może być równa zero.",
347
+ "wms.backend.inventory.adjust.errors.insufficientStock": "Korekta przekracza ilość dostępną w tej lokalizacji.",
347
348
  "wms.backend.inventory.adjust.errors.lot": "Nie udało się rozpoznać partii magazynowej.",
348
349
  "wms.backend.inventory.adjust.errors.previewBalance": "Nie udało się załadować podglądu salda.",
349
350
  "wms.backend.inventory.adjust.errors.submit": "Nie udało się zaksięgować korekty.",