@open-mercato/core 0.6.4-develop.4299.1.af24e08431 → 0.6.4-develop.4310.1.0be8773280
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/modules/attachments/lib/pdfProcessing.js +1 -1
- package/dist/modules/attachments/lib/pdfProcessing.js.map +2 -2
- package/dist/modules/attachments/lib/textExtraction.js +1 -1
- package/dist/modules/attachments/lib/textExtraction.js.map +1 -1
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +16 -3
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +4 -0
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +21 -5
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -5
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +48 -32
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +18 -3
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js +21 -3
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +18 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -3
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/jest.config.cjs +3 -0
- package/package.json +18 -18
- package/src/modules/attachments/lib/pdfProcessing.ts +1 -2
- package/src/modules/attachments/lib/textExtraction.ts +1 -1
- package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +20 -3
- package/src/modules/customers/api/companies/[id]/route.ts +4 -0
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +25 -5
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +25 -5
- package/src/modules/customers/commands/companies.ts +51 -34
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +21 -3
- package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.tsx +36 -3
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +21 -2
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +21 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/attachments/lib/pdfProcessing.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'fs/promises'\nimport path from 'path'\nimport { createRequire } from 'module'\n\nconst moduleRequire = createRequire(path.join(process.cwd(), 'package.json'))\nconst pdfJsPackageRoot = path.dirname(moduleRequire.resolve('pdfjs-dist/package.json'))\nconst cMapUrl = `${path.join(pdfJsPackageRoot, 'cmaps')}${path.sep}`\nconst standardFontDataUrl = `${path.join(pdfJsPackageRoot, 'standard_fonts')}${path.sep}`\n\nconst MIN_RENDER_SCALE = 2\nconst MAX_RENDER_SCALE = 4\nconst MAX_RENDER_DIMENSION = 2200\nconst MAX_RENDER_PIXELS = 8_000_000\n\ntype PdfPageProxyLike = {\n cleanup: () => void\n getTextContent: () => Promise<{ items?: Array<{ str?: string }> }>\n getViewport: (args: { scale: number }) => { width: number; height: number }\n render: (args: { canvasContext: unknown; viewport: { width: number; height: number } }) => { promise: Promise<void> }\n}\n\ntype PdfCanvasFactoryLike = {\n create: (width: number, height: number) => {\n canvas: { toBuffer: (mimeType: string) => Buffer | Uint8Array }\n context: unknown\n }\n destroy: (canvasAndContext: {\n canvas: { toBuffer: (mimeType: string) => Buffer | Uint8Array } | null\n context: unknown\n }) => void\n}\n\ntype PdfDocumentProxyLike = {\n numPages: number\n canvasFactory: PdfCanvasFactoryLike\n getPage: (pageNumber: number) => Promise<PdfPageProxyLike>\n
|
|
5
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAE9B,MAAM,gBAAgB,cAAc,KAAK,KAAK,QAAQ,IAAI,GAAG,cAAc,CAAC;AAC5E,MAAM,mBAAmB,KAAK,QAAQ,cAAc,QAAQ,yBAAyB,CAAC;AACtF,MAAM,UAAU,GAAG,KAAK,KAAK,kBAAkB,OAAO,CAAC,GAAG,KAAK,GAAG;AAClE,MAAM,sBAAsB,GAAG,KAAK,KAAK,kBAAkB,gBAAgB,CAAC,GAAG,KAAK,GAAG;AAEvF,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,uBAAuB;AAC7B,MAAM,oBAAoB;
|
|
4
|
+
"sourcesContent": ["import fs from 'fs/promises'\nimport path from 'path'\nimport { createRequire } from 'module'\n\nconst moduleRequire = createRequire(path.join(process.cwd(), 'package.json'))\nconst pdfJsPackageRoot = path.dirname(moduleRequire.resolve('pdfjs-dist/package.json'))\nconst cMapUrl = `${path.join(pdfJsPackageRoot, 'cmaps')}${path.sep}`\nconst standardFontDataUrl = `${path.join(pdfJsPackageRoot, 'standard_fonts')}${path.sep}`\n\nconst MIN_RENDER_SCALE = 2\nconst MAX_RENDER_SCALE = 4\nconst MAX_RENDER_DIMENSION = 2200\nconst MAX_RENDER_PIXELS = 8_000_000\n\ntype PdfPageProxyLike = {\n cleanup: () => void\n getTextContent: () => Promise<{ items?: Array<{ str?: string }> }>\n getViewport: (args: { scale: number }) => { width: number; height: number }\n render: (args: { canvasContext: unknown; viewport: { width: number; height: number } }) => { promise: Promise<void> }\n}\n\ntype PdfCanvasFactoryLike = {\n create: (width: number, height: number) => {\n canvas: { toBuffer: (mimeType: string) => Buffer | Uint8Array }\n context: unknown\n }\n destroy: (canvasAndContext: {\n canvas: { toBuffer: (mimeType: string) => Buffer | Uint8Array } | null\n context: unknown\n }) => void\n}\n\ntype PdfDocumentProxyLike = {\n numPages: number\n canvasFactory: PdfCanvasFactoryLike\n getPage: (pageNumber: number) => Promise<PdfPageProxyLike>\n}\n\nexport type PdfPageOcrInput = {\n pageNumber: number\n extractedText: string | null\n imageBuffer: Buffer | null\n}\n\nexport type PdfOcrPreparationResult = {\n pageCount: number\n pages: PdfPageOcrInput[]\n}\n\nfunction normalizePdfText(rawText: string): string | null {\n const normalized = rawText.replace(/\\s+/g, ' ').trim()\n return normalized.length > 0 ? normalized : null\n}\n\nfunction extractPdfTextContent(items: Array<{ str?: string }> | undefined): string | null {\n if (!Array.isArray(items) || items.length === 0) return null\n const collected = items\n .map((item) => (typeof item?.str === 'string' ? item.str : ''))\n .filter((value) => value.length > 0)\n .join(' ')\n return normalizePdfText(collected)\n}\n\nfunction resolvePdfRenderScale(page: PdfPageProxyLike): number {\n const baseViewport = page.getViewport({ scale: 1 })\n const baseLargestDimension = Math.max(baseViewport.width, baseViewport.height)\n let scale = Math.min(\n MAX_RENDER_SCALE,\n Math.max(MIN_RENDER_SCALE, MAX_RENDER_DIMENSION / Math.max(baseLargestDimension, 1)),\n )\n\n let viewport = page.getViewport({ scale })\n const pixelCount = viewport.width * viewport.height\n if (pixelCount > MAX_RENDER_PIXELS) {\n scale *= Math.sqrt(MAX_RENDER_PIXELS / pixelCount)\n viewport = page.getViewport({ scale })\n }\n\n return Math.max(1, scale)\n}\n\nasync function renderPdfPageToImageBuffer(\n page: PdfPageProxyLike,\n canvasFactory: PdfCanvasFactoryLike,\n): Promise<Buffer> {\n const viewport = page.getViewport({ scale: resolvePdfRenderScale(page) })\n const canvasAndContext = canvasFactory.create(viewport.width, viewport.height)\n\n try {\n const renderTask = page.render({\n canvasContext: canvasAndContext.context,\n viewport,\n })\n await renderTask.promise\n const imageBuffer = canvasAndContext.canvas.toBuffer('image/png')\n return Buffer.isBuffer(imageBuffer) ? imageBuffer : Buffer.from(imageBuffer)\n } finally {\n canvasFactory.destroy(canvasAndContext)\n }\n}\n\nexport async function preparePdfPagesForOcr(filePath: string): Promise<PdfOcrPreparationResult> {\n const { getDocument } = await import('pdfjs-dist/legacy/build/pdf.mjs')\n const data = new Uint8Array(await fs.readFile(filePath))\n const loadingTask = getDocument({\n data,\n cMapUrl,\n cMapPacked: true,\n standardFontDataUrl,\n })\n\n const pdfDocument = (await loadingTask.promise) as unknown as PdfDocumentProxyLike\n\n try {\n const pages: PdfPageOcrInput[] = []\n\n for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber += 1) {\n const page = await pdfDocument.getPage(pageNumber)\n\n try {\n const textContent = await page.getTextContent()\n const extractedText = extractPdfTextContent(textContent.items)\n\n if (extractedText) {\n pages.push({\n pageNumber,\n extractedText,\n imageBuffer: null,\n })\n continue\n }\n\n pages.push({\n pageNumber,\n extractedText: null,\n imageBuffer: await renderPdfPageToImageBuffer(page, pdfDocument.canvasFactory),\n })\n } finally {\n page.cleanup()\n }\n }\n\n return {\n pageCount: pdfDocument.numPages,\n pages,\n }\n } finally {\n await loadingTask.destroy()\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/attachments/lib/textExtraction.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'fs/promises'\nimport path from 'path'\nimport { createRequire } from 'module'\n\n// NOTE: child_process is intentionally NOT imported here.\n// This module MUST NOT shell out to any external binary for content extraction.\n// All extraction must use pure-JS libraries. See HUNT-PARSER-01.\n\nconst moduleRequire = createRequire(path.join(process.cwd(), 'package.json'))\nconst pdfJsPackageRoot = path.dirname(moduleRequire.resolve('pdfjs-dist/package.json'))\nconst PDF_CMAP_URL = `${path.join(pdfJsPackageRoot, 'cmaps')}${path.sep}`\nconst PDF_STANDARD_FONT_DATA_URL = `${path.join(pdfJsPackageRoot, 'standard_fonts')}${path.sep}`\n\ntype ExtractParams = {\n filePath: string\n mimeType?: string | null\n}\n\nfunction isImage(mimeType?: string | null, filePath?: string | null): boolean {\n const normalized = (mimeType || '').toLowerCase()\n if (normalized.startsWith('image/')) return true\n if (filePath) {\n const ext = path.extname(filePath).toLowerCase()\n return ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.tiff'].includes(ext)\n }\n return false\n}\n\nfunction isPlainText(mimeType: string, ext: string): boolean {\n return mimeType.startsWith('text/')\n || ext === '.txt'\n || ext === '.md'\n || ext === '.csv'\n || ext === '.log'\n}\n\nfunction isPdf(mimeType: string, ext: string): boolean {\n return mimeType === 'application/pdf' || ext === '.pdf'\n}\n\nfunction isDocx(mimeType: string, ext: string): boolean {\n // mammoth supports only Open XML .docx, not legacy binary .doc files.\n return (\n mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'\n || ext === '.docx'\n )\n}\n\nasync function extractPlainText(filePath: string): Promise<string | null> {\n try {\n const text = await fs.readFile(filePath, 'utf8')\n const trimmed = text.trim()\n return trimmed.length > 0 ? trimmed : null\n } catch {\n return null\n }\n}\n\nasync function extractPdfText(filePath: string): Promise<string | null> {\n try {\n const { getDocument } = await import('pdfjs-dist/legacy/build/pdf.mjs')\n const data = new Uint8Array(await fs.readFile(filePath))\n const loadingTask = getDocument({\n data,\n cMapUrl: PDF_CMAP_URL,\n cMapPacked: true,\n standardFontDataUrl: PDF_STANDARD_FONT_DATA_URL,\n })\n const pdfDocument = await loadingTask.promise\n const textParts: string[] = []\n try {\n for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber += 1) {\n const page = await pdfDocument.getPage(pageNumber)\n try {\n const textContent = await page.getTextContent()\n const items = (textContent as any).items as Array<{ str?: string }> | undefined\n if (Array.isArray(items)) {\n const pageText = items\n .map((item) => (typeof item?.str === 'string' ? item.str : ''))\n .filter((s) => s.length > 0)\n .join(' ')\n if (pageText.trim()) textParts.push(pageText.trim())\n }\n } finally {\n page.cleanup()\n }\n }\n } finally {\n await
|
|
4
|
+
"sourcesContent": ["import fs from 'fs/promises'\nimport path from 'path'\nimport { createRequire } from 'module'\n\n// NOTE: child_process is intentionally NOT imported here.\n// This module MUST NOT shell out to any external binary for content extraction.\n// All extraction must use pure-JS libraries. See HUNT-PARSER-01.\n\nconst moduleRequire = createRequire(path.join(process.cwd(), 'package.json'))\nconst pdfJsPackageRoot = path.dirname(moduleRequire.resolve('pdfjs-dist/package.json'))\nconst PDF_CMAP_URL = `${path.join(pdfJsPackageRoot, 'cmaps')}${path.sep}`\nconst PDF_STANDARD_FONT_DATA_URL = `${path.join(pdfJsPackageRoot, 'standard_fonts')}${path.sep}`\n\ntype ExtractParams = {\n filePath: string\n mimeType?: string | null\n}\n\nfunction isImage(mimeType?: string | null, filePath?: string | null): boolean {\n const normalized = (mimeType || '').toLowerCase()\n if (normalized.startsWith('image/')) return true\n if (filePath) {\n const ext = path.extname(filePath).toLowerCase()\n return ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.tiff'].includes(ext)\n }\n return false\n}\n\nfunction isPlainText(mimeType: string, ext: string): boolean {\n return mimeType.startsWith('text/')\n || ext === '.txt'\n || ext === '.md'\n || ext === '.csv'\n || ext === '.log'\n}\n\nfunction isPdf(mimeType: string, ext: string): boolean {\n return mimeType === 'application/pdf' || ext === '.pdf'\n}\n\nfunction isDocx(mimeType: string, ext: string): boolean {\n // mammoth supports only Open XML .docx, not legacy binary .doc files.\n return (\n mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'\n || ext === '.docx'\n )\n}\n\nasync function extractPlainText(filePath: string): Promise<string | null> {\n try {\n const text = await fs.readFile(filePath, 'utf8')\n const trimmed = text.trim()\n return trimmed.length > 0 ? trimmed : null\n } catch {\n return null\n }\n}\n\nasync function extractPdfText(filePath: string): Promise<string | null> {\n try {\n const { getDocument } = await import('pdfjs-dist/legacy/build/pdf.mjs')\n const data = new Uint8Array(await fs.readFile(filePath))\n const loadingTask = getDocument({\n data,\n cMapUrl: PDF_CMAP_URL,\n cMapPacked: true,\n standardFontDataUrl: PDF_STANDARD_FONT_DATA_URL,\n })\n const pdfDocument = await loadingTask.promise\n const textParts: string[] = []\n try {\n for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber += 1) {\n const page = await pdfDocument.getPage(pageNumber)\n try {\n const textContent = await page.getTextContent()\n const items = (textContent as any).items as Array<{ str?: string }> | undefined\n if (Array.isArray(items)) {\n const pageText = items\n .map((item) => (typeof item?.str === 'string' ? item.str : ''))\n .filter((s) => s.length > 0)\n .join(' ')\n if (pageText.trim()) textParts.push(pageText.trim())\n }\n } finally {\n page.cleanup()\n }\n }\n } finally {\n await loadingTask.destroy()\n }\n const result = textParts.join('\\n').trim()\n return result.length > 0 ? result : null\n } catch {\n return null\n }\n}\n\nasync function extractDocxText(filePath: string): Promise<string | null> {\n try {\n const mammoth = await import('mammoth')\n const result = await mammoth.extractRawText({ path: filePath })\n const trimmed = result.value.trim()\n return trimmed.length > 0 ? trimmed : null\n } catch {\n return null\n }\n}\n\nexport async function extractAttachmentContent(params: ExtractParams): Promise<string | null> {\n const { filePath, mimeType } = params\n if (!filePath) return null\n if (isImage(mimeType, filePath)) return null\n\n const normalized = (mimeType || '').toLowerCase()\n const ext = path.extname(filePath).toLowerCase()\n\n if (isPlainText(normalized, ext)) {\n return extractPlainText(filePath)\n }\n\n if (isPdf(normalized, ext)) {\n return extractPdfText(filePath)\n }\n\n if (isDocx(normalized, ext)) {\n return extractDocxText(filePath)\n }\n\n // XLSX, PPTX, MSG and other Office formats: no safe pure-JS extractor available yet.\n // Return null rather than shelling out to an external binary.\n return null\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useRouter } from "next/navigation";
|
|
5
5
|
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
|
|
6
|
-
import { LoadingMessage, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
6
|
+
import { LoadingMessage, ErrorMessage, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
|
|
7
7
|
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
8
8
|
import { updateCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
9
9
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
@@ -29,6 +29,7 @@ function EditExchangeRatePage({ params }) {
|
|
|
29
29
|
const [exchangeRate, setExchangeRate] = React.useState(null);
|
|
30
30
|
const [loading, setLoading] = React.useState(true);
|
|
31
31
|
const [error, setError] = React.useState(null);
|
|
32
|
+
const [isNotFound, setIsNotFound] = React.useState(false);
|
|
32
33
|
const loadOptions = React.useCallback(
|
|
33
34
|
(query) => loadCurrencyOptions(apiCall, query),
|
|
34
35
|
[]
|
|
@@ -39,8 +40,10 @@ function EditExchangeRatePage({ params }) {
|
|
|
39
40
|
const response = await apiCall(`/api/currencies/exchange-rates?id=${params?.id}`);
|
|
40
41
|
if (response.ok && response.result && response.result.items.length > 0) {
|
|
41
42
|
setExchangeRate(response.result.items[0]);
|
|
43
|
+
} else if (response.ok) {
|
|
44
|
+
setIsNotFound(true);
|
|
42
45
|
} else {
|
|
43
|
-
setError(t("exchangeRates.form.errors.
|
|
46
|
+
setError(t("exchangeRates.form.errors.load"));
|
|
44
47
|
}
|
|
45
48
|
} catch (err) {
|
|
46
49
|
setError(t("exchangeRates.form.errors.load"));
|
|
@@ -57,8 +60,18 @@ function EditExchangeRatePage({ params }) {
|
|
|
57
60
|
if (loading) {
|
|
58
61
|
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("exchangeRates.form.loading") }) }) });
|
|
59
62
|
}
|
|
63
|
+
if (isNotFound) {
|
|
64
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
65
|
+
RecordNotFoundState,
|
|
66
|
+
{
|
|
67
|
+
label: t("exchangeRates.form.errors.notFound"),
|
|
68
|
+
backHref: "/backend/exchange-rates",
|
|
69
|
+
backLabel: t("exchangeRates.form.actions.backToList", "Back to exchange rates")
|
|
70
|
+
}
|
|
71
|
+
) }) });
|
|
72
|
+
}
|
|
60
73
|
if (error || !exchangeRate) {
|
|
61
|
-
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(ErrorMessage, { label: error
|
|
74
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(ErrorMessage, { label: error ?? t("exchangeRates.form.errors.load") }) }) });
|
|
62
75
|
}
|
|
63
76
|
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
64
77
|
CrudForm,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/currencies/backend/exchange-rates/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n loadCurrencyOptions,\n exchangeRateGroups,\n validateExchangeRateForm,\n buildExchangeRatePayload,\n} from '../../../lib/exchangeRateFormConfig'\n\n/**\n * Formats a Date object to YYYY-MM-DDTHH:MM format in local timezone\n * for use with datetime-local input\n */\nfunction formatDateTimeLocal(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n return `${year}-${month}-${day}T${hours}:${minutes}`\n}\n\ntype ExchangeRateData = {\n id: string\n fromCurrencyCode: string\n toCurrencyCode: string\n rate: string\n date: string\n source: string | null\n type: string | null\n isActive: boolean\n organizationId: string\n tenantId: string\n}\n\nexport default function EditExchangeRatePage({ params }: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n\n const [exchangeRate, setExchangeRate] = React.useState<ExchangeRateData | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n const loadOptions = React.useCallback(\n (query?: string) => loadCurrencyOptions(apiCall, query),\n []\n )\n\n // Load exchange rate data\n React.useEffect(() => {\n async function loadExchangeRate() {\n try {\n const response = await apiCall<{ items: ExchangeRateData[] }>(`/api/currencies/exchange-rates?id=${params?.id}`)\n if (response.ok && response.result && response.result.items.length > 0) {\n setExchangeRate(response.result.items[0])\n } else {\n setError(t('exchangeRates.form.errors.
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { LoadingMessage, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n loadCurrencyOptions,\n exchangeRateGroups,\n validateExchangeRateForm,\n buildExchangeRatePayload,\n} from '../../../lib/exchangeRateFormConfig'\n\n/**\n * Formats a Date object to YYYY-MM-DDTHH:MM format in local timezone\n * for use with datetime-local input\n */\nfunction formatDateTimeLocal(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n return `${year}-${month}-${day}T${hours}:${minutes}`\n}\n\ntype ExchangeRateData = {\n id: string\n fromCurrencyCode: string\n toCurrencyCode: string\n rate: string\n date: string\n source: string | null\n type: string | null\n isActive: boolean\n organizationId: string\n tenantId: string\n}\n\nexport default function EditExchangeRatePage({ params }: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n\n const [exchangeRate, setExchangeRate] = React.useState<ExchangeRateData | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n const loadOptions = React.useCallback(\n (query?: string) => loadCurrencyOptions(apiCall, query),\n []\n )\n\n // Load exchange rate data\n React.useEffect(() => {\n async function loadExchangeRate() {\n try {\n const response = await apiCall<{ items: ExchangeRateData[] }>(`/api/currencies/exchange-rates?id=${params?.id}`)\n if (response.ok && response.result && response.result.items.length > 0) {\n setExchangeRate(response.result.items[0])\n } else if (response.ok) {\n setIsNotFound(true)\n } else {\n setError(t('exchangeRates.form.errors.load'))\n }\n } catch (err) {\n setError(t('exchangeRates.form.errors.load'))\n } finally {\n setLoading(false)\n }\n }\n loadExchangeRate()\n }, [params, t])\n\n const groups = React.useMemo(\n () => exchangeRateGroups(t, loadOptions),\n [t, loadOptions]\n )\n\n if (loading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('exchangeRates.form.loading')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('exchangeRates.form.errors.notFound')}\n backHref=\"/backend/exchange-rates\"\n backLabel={t('exchangeRates.form.actions.backToList', 'Back to exchange rates')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !exchangeRate) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error ?? t('exchangeRates.form.errors.load')} />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <CrudForm\n title={t('exchangeRates.edit.title')}\n backHref=\"/backend/exchange-rates\"\n versionHistory={{ resourceKind: 'currencies.exchange_rate', resourceId: exchangeRate.id }}\n fields={[]}\n groups={groups}\n initialValues={{\n fromCurrencyCode: exchangeRate.fromCurrencyCode,\n toCurrencyCode: exchangeRate.toCurrencyCode,\n rate: parseFloat(exchangeRate.rate),\n date: formatDateTimeLocal(new Date(exchangeRate.date)),\n source: exchangeRate.source || '',\n type: exchangeRate.type || '',\n isActive: exchangeRate.isActive,\n }}\n submitLabel={t('exchangeRates.form.action.save')}\n cancelHref=\"/backend/exchange-rates\"\n onSubmit={async (values) => {\n const validated = validateExchangeRateForm(values, t)\n const payload = {\n id: exchangeRate.id,\n ...buildExchangeRatePayload(values, validated),\n }\n\n await updateCrud('currencies/exchange-rates', payload)\n\n flash(t('exchangeRates.flash.updated'), 'success')\n router.push('/backend/exchange-rates')\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -768,6 +768,8 @@ async function GET(_req, ctx) {
|
|
|
768
768
|
organizationId: company.organizationId,
|
|
769
769
|
tenantId: company.tenantId,
|
|
770
770
|
isActive: company.isActive,
|
|
771
|
+
temperature: company.temperature ?? null,
|
|
772
|
+
renewalQuarter: company.renewalQuarter ?? null,
|
|
771
773
|
createdAt: company.createdAt.toISOString(),
|
|
772
774
|
updatedAt: company.updatedAt.toISOString()
|
|
773
775
|
},
|
|
@@ -944,6 +946,8 @@ const companyDetailResponseSchema = z.object({
|
|
|
944
946
|
organizationId: z.string().uuid().nullable().optional(),
|
|
945
947
|
tenantId: z.string().uuid().nullable().optional(),
|
|
946
948
|
isActive: z.boolean().optional(),
|
|
949
|
+
temperature: z.string().nullable().optional(),
|
|
950
|
+
renewalQuarter: z.string().nullable().optional(),
|
|
947
951
|
createdAt: z.string(),
|
|
948
952
|
updatedAt: z.string()
|
|
949
953
|
}),
|