@open-mercato/core 0.4.5-develop-636d33c995 → 0.4.5-develop-3d8e759e45
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/catalog/backend/catalog/categories/[id]/edit/page.js +17 -2
- package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +15 -0
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +30 -0
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/catalog/inbox-actions.js +51 -0
- package/dist/modules/catalog/inbox-actions.js.map +7 -0
- package/dist/modules/catalog/lib/messageObjectPreviews.js +146 -0
- package/dist/modules/catalog/lib/messageObjectPreviews.js.map +7 -0
- package/dist/modules/catalog/message-objects.js +95 -0
- package/dist/modules/catalog/message-objects.js.map +7 -0
- package/dist/modules/currencies/backend/currencies/[id]/page.js +21 -0
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/lib/messageObjectPreviews.js +51 -0
- package/dist/modules/currencies/lib/messageObjectPreviews.js.map +7 -0
- package/dist/modules/currencies/message-objects.js +41 -0
- package/dist/modules/currencies/message-objects.js.map +7 -0
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +20 -0
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +12 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +20 -0
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyHighlights.js +18 -14
- package/dist/modules/customers/components/detail/CompanyHighlights.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonHighlights.js +18 -14
- package/dist/modules/customers/components/detail/PersonHighlights.js.map +2 -2
- package/dist/modules/customers/inbox-actions.js +230 -0
- package/dist/modules/customers/inbox-actions.js.map +7 -0
- package/dist/modules/customers/lib/messageObjectPreviews.js +41 -5
- package/dist/modules/customers/lib/messageObjectPreviews.js.map +2 -2
- package/dist/modules/customers/message-objects.js +31 -11
- package/dist/modules/customers/message-objects.js.map +2 -2
- package/dist/modules/inbox_ops/api/emails/[id]/route.js +40 -1
- package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/extract/route.js +87 -0
- package/dist/modules/inbox_ops/api/extract/route.js.map +7 -0
- package/dist/modules/inbox_ops/api/proposals/[id]/translate/route.js +6 -1
- package/dist/modules/inbox_ops/api/proposals/[id]/translate/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +40 -14
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +161 -79
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js +109 -62
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js.map +3 -3
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +36 -14
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/ActionCard.js +65 -10
- package/dist/modules/inbox_ops/components/proposals/ActionCard.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +58 -10
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
- package/dist/modules/inbox_ops/lib/constants.js.map +2 -2
- package/dist/modules/inbox_ops/lib/contactValidation.js +40 -0
- package/dist/modules/inbox_ops/lib/contactValidation.js.map +7 -0
- package/dist/modules/inbox_ops/lib/executionEngine.js +31 -826
- package/dist/modules/inbox_ops/lib/executionEngine.js.map +3 -3
- package/dist/modules/inbox_ops/lib/executionHelpers.js +368 -0
- package/dist/modules/inbox_ops/lib/executionHelpers.js.map +7 -0
- package/dist/modules/inbox_ops/lib/extractionPrompt.js +28 -35
- package/dist/modules/inbox_ops/lib/extractionPrompt.js.map +3 -3
- package/dist/modules/inbox_ops/lib/inbox-actions-generated.d.js +1 -0
- package/dist/modules/inbox_ops/lib/inbox-actions-generated.d.js.map +7 -0
- package/dist/modules/inbox_ops/lib/translationProvider.js +15 -10
- package/dist/modules/inbox_ops/lib/translationProvider.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/extractionWorker.js +16 -16
- package/dist/modules/inbox_ops/subscribers/extractionWorker.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +3 -0
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/objects-panel.js +6 -1
- package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js +4 -1
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
- package/dist/modules/messages/frontend/messages/view/[token]/page.js +1 -0
- package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -7
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/resources/lib/messageObjectPreviews.js +43 -0
- package/dist/modules/resources/lib/messageObjectPreviews.js.map +7 -0
- package/dist/modules/resources/message-objects.js +37 -0
- package/dist/modules/resources/message-objects.js.map +7 -0
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +19 -0
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +23 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/quotes/[id]/page.js +1 -1
- package/dist/modules/sales/backend/sales/quotes/[id]/page.js.map +2 -2
- package/dist/modules/sales/inbox-actions.js +278 -0
- package/dist/modules/sales/inbox-actions.js.map +7 -0
- package/dist/modules/sales/lib/messageObjectPreviews.js +49 -4
- package/dist/modules/sales/lib/messageObjectPreviews.js.map +2 -2
- package/dist/modules/sales/message-objects.js +44 -2
- package/dist/modules/sales/message-objects.js.map +2 -2
- package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +59 -30
- package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +2 -2
- package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +1 -1
- package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +1 -1
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +8 -30
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-availability/page.js +13 -0
- package/dist/modules/staff/backend/staff/my-availability/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +8 -31
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +32 -10
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +14 -1
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +14 -1
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/components/TeamForm.js +4 -2
- package/dist/modules/staff/components/TeamForm.js.map +2 -2
- package/dist/modules/staff/components/TeamRoleForm.js +4 -2
- package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
- package/dist/modules/staff/lib/messageObjectPreviews.js +111 -2
- package/dist/modules/staff/lib/messageObjectPreviews.js.map +2 -2
- package/dist/modules/staff/message-objects.js +79 -8
- package/dist/modules/staff/message-objects.js.map +2 -2
- package/jest.config.cjs +1 -0
- package/jest.mocks/inbox-actions.generated.js +5 -0
- package/package.json +2 -2
- package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +19 -5
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +14 -0
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +40 -0
- package/src/modules/catalog/inbox-actions.ts +60 -0
- package/src/modules/catalog/lib/messageObjectPreviews.ts +176 -0
- package/src/modules/catalog/message-objects.ts +102 -0
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +20 -0
- package/src/modules/currencies/lib/messageObjectPreviews.ts +65 -0
- package/src/modules/currencies/message-objects.ts +40 -0
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +19 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +13 -0
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +19 -0
- package/src/modules/customers/components/detail/CompanyHighlights.tsx +14 -9
- package/src/modules/customers/components/detail/PersonHighlights.tsx +14 -9
- package/src/modules/customers/inbox-actions.ts +285 -0
- package/src/modules/customers/lib/messageObjectPreviews.ts +43 -3
- package/src/modules/customers/message-objects.ts +31 -11
- package/src/modules/inbox_ops/api/emails/[id]/route.ts +44 -0
- package/src/modules/inbox_ops/api/extract/route.ts +94 -0
- package/src/modules/inbox_ops/api/proposals/[id]/translate/route.ts +6 -1
- package/src/modules/inbox_ops/api/proposals/counts/route.ts +2 -0
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +43 -13
- package/src/modules/inbox_ops/backend/inbox-ops/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +176 -81
- package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.tsx +122 -68
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +36 -14
- package/src/modules/inbox_ops/components/proposals/ActionCard.tsx +91 -7
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +64 -12
- package/src/modules/inbox_ops/lib/constants.ts +9 -0
- package/src/modules/inbox_ops/lib/contactValidation.ts +54 -0
- package/src/modules/inbox_ops/lib/executionEngine.ts +47 -1060
- package/src/modules/inbox_ops/lib/executionHelpers.ts +527 -0
- package/src/modules/inbox_ops/lib/extractionPrompt.ts +45 -34
- package/src/modules/inbox_ops/lib/inbox-actions-generated.d.ts +11 -0
- package/src/modules/inbox_ops/lib/translationProvider.ts +16 -10
- package/src/modules/inbox_ops/subscribers/extractionWorker.ts +16 -18
- package/src/modules/messages/commands/messages.ts +4 -0
- package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +8 -1
- package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +3 -0
- package/src/modules/messages/frontend/messages/view/[token]/page.tsx +1 -0
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +20 -4
- package/src/modules/resources/lib/messageObjectPreviews.ts +55 -0
- package/src/modules/resources/message-objects.ts +36 -0
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +18 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -0
- package/src/modules/sales/backend/sales/quotes/[id]/page.tsx +1 -1
- package/src/modules/sales/inbox-actions.ts +359 -0
- package/src/modules/sales/lib/messageObjectPreviews.ts +54 -4
- package/src/modules/sales/message-objects.ts +44 -2
- package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +72 -34
- package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +1 -1
- package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +7 -29
- package/src/modules/staff/backend/staff/my-availability/page.tsx +14 -0
- package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +8 -30
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +28 -7
- package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +12 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +12 -0
- package/src/modules/staff/components/TeamForm.tsx +3 -0
- package/src/modules/staff/components/TeamRoleForm.tsx +3 -0
- package/src/modules/staff/lib/messageObjectPreviews.ts +133 -2
- package/src/modules/staff/message-objects.ts +79 -8
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +0 -51
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +0 -7
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +0 -35
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +0 -7
- package/dist/modules/customers/widgets/messages/index.js +0 -7
- package/dist/modules/customers/widgets/messages/index.js.map +0 -7
- package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +0 -51
- package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +0 -7
- package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +0 -34
- package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +0 -7
- package/dist/modules/staff/widgets/messages/index.js +0 -7
- package/dist/modules/staff/widgets/messages/index.js.map +0 -7
- package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +0 -57
- package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +0 -49
- package/src/modules/customers/widgets/messages/index.ts +0 -2
- package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +0 -57
- package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +0 -44
- package/src/modules/staff/widgets/messages/index.ts +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { generateText } from 'ai'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import {
|
|
4
4
|
resolveOpenCodeModel,
|
|
@@ -8,7 +8,7 @@ import { createStructuredModel, resolveExtractionProviderId, withTimeout } from
|
|
|
8
8
|
|
|
9
9
|
const LANGUAGE_NAMES: Record<string, string> = { en: 'English', de: 'German', es: 'Spanish', pl: 'Polish' }
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const translationResultSchema = z.object({
|
|
12
12
|
summary: z.string(),
|
|
13
13
|
actions: z.record(z.string(), z.string()),
|
|
14
14
|
})
|
|
@@ -35,20 +35,26 @@ export async function translateProposalContent(input: {
|
|
|
35
35
|
|
|
36
36
|
const timeoutMs = parseInt(process.env.INBOX_OPS_TRANSLATION_TIMEOUT_MS || '30000', 10)
|
|
37
37
|
|
|
38
|
+
const actionIds = Object.keys(input.actionDescriptions)
|
|
39
|
+
|
|
38
40
|
const result = await withTimeout(
|
|
39
|
-
|
|
41
|
+
generateText({
|
|
40
42
|
model,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
system: `You are a professional translator. Translate the provided content from ${sourceLang} to ${targetLang}. Preserve proper nouns, numbers, dates, currencies, product names, and company names exactly as they appear. Maintain the same tone and meaning. Respond ONLY with valid JSON, no markdown fences.`,
|
|
44
|
+
prompt: `Translate and return JSON with this exact shape:
|
|
45
|
+
{"summary": "translated summary", "actions": {"action-id-1": "translated description", ...}}
|
|
46
|
+
|
|
47
|
+
Content to translate:
|
|
48
|
+
${JSON.stringify({ summary: input.summary, actions: input.actionDescriptions })}
|
|
49
|
+
|
|
50
|
+
Action IDs to preserve exactly: ${JSON.stringify(actionIds)}`,
|
|
47
51
|
temperature: 0,
|
|
48
52
|
}),
|
|
49
53
|
timeoutMs,
|
|
50
54
|
`Translation timed out after ${timeoutMs}ms`,
|
|
51
55
|
)
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
const text = result.text.replace(/^```(?:json)?\s*/, '').replace(/\s*```$/, '').trim()
|
|
58
|
+
const parsed = translationResultSchema.parse(JSON.parse(text))
|
|
59
|
+
return parsed
|
|
54
60
|
}
|
|
@@ -160,7 +160,7 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
160
160
|
const maxTextSize = parseInt(process.env.INBOX_OPS_MAX_TEXT_SIZE || '204800', 10)
|
|
161
161
|
const truncatedText = fullText.slice(0, maxTextSize)
|
|
162
162
|
|
|
163
|
-
const systemPrompt = buildExtractionSystemPrompt(contactMatches, catalogProducts, undefined, workingLanguage)
|
|
163
|
+
const systemPrompt = await buildExtractionSystemPrompt(contactMatches, catalogProducts, undefined, workingLanguage)
|
|
164
164
|
const userPrompt = buildExtractionUserPrompt(truncatedText)
|
|
165
165
|
|
|
166
166
|
let extractionResult: ReturnType<typeof extractionOutputSchema.parse>
|
|
@@ -269,22 +269,20 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
269
269
|
|
|
270
270
|
action.payloadJson = JSON.stringify(enriched)
|
|
271
271
|
|
|
272
|
-
// Discrepancy descriptions are stored in the DB and rendered on the proposal review page.
|
|
273
|
-
// Not i18n keys — the proposal UI displays them as-is for operator guidance.
|
|
274
272
|
for (const warning of warnings) {
|
|
275
273
|
if (warning === 'no_channel_resolved') {
|
|
276
274
|
enrichmentDiscrepancies.push({
|
|
277
275
|
actionIndex,
|
|
278
276
|
type: 'other',
|
|
279
277
|
severity: 'error',
|
|
280
|
-
description: '
|
|
278
|
+
description: 'inbox_ops.discrepancy.desc.no_channel',
|
|
281
279
|
})
|
|
282
280
|
} else if (warning === 'no_currency_resolved') {
|
|
283
281
|
enrichmentDiscrepancies.push({
|
|
284
282
|
actionIndex,
|
|
285
283
|
type: 'currency_mismatch',
|
|
286
284
|
severity: 'warning',
|
|
287
|
-
description: '
|
|
285
|
+
description: 'inbox_ops.discrepancy.desc.no_currency',
|
|
288
286
|
})
|
|
289
287
|
}
|
|
290
288
|
}
|
|
@@ -317,7 +315,7 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
317
315
|
actionIndex,
|
|
318
316
|
type: 'product_not_found',
|
|
319
317
|
severity: 'error',
|
|
320
|
-
description:
|
|
318
|
+
description: 'inbox_ops.discrepancy.desc.product_not_matched',
|
|
321
319
|
foundValue: productName,
|
|
322
320
|
})
|
|
323
321
|
const nameKey = productName.toLowerCase().trim()
|
|
@@ -328,7 +326,7 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
328
326
|
const currencyCode = typeof parsedPayload.currencyCode === 'string' ? parsedPayload.currencyCode : undefined
|
|
329
327
|
autoProductActions.push({
|
|
330
328
|
actionType: 'create_product',
|
|
331
|
-
description:
|
|
329
|
+
description: 'inbox_ops.action.desc.create_product',
|
|
332
330
|
confidence: 0.9,
|
|
333
331
|
requiredFeature: REQUIRED_FEATURES_MAP.create_product,
|
|
334
332
|
payloadJson: JSON.stringify({
|
|
@@ -412,7 +410,7 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
412
410
|
proposalId: proposalId,
|
|
413
411
|
sortOrder: combinedProposedActions.length + index,
|
|
414
412
|
actionType: 'draft_reply',
|
|
415
|
-
description:
|
|
413
|
+
description: 'inbox_ops.action.desc.draft_reply',
|
|
416
414
|
payload: {
|
|
417
415
|
to: reply.to,
|
|
418
416
|
toName: reply.toName,
|
|
@@ -468,8 +466,8 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
468
466
|
createDiscrepancy(em, proposalId, allActions, {
|
|
469
467
|
type: 'unknown_contact',
|
|
470
468
|
severity: 'warning',
|
|
471
|
-
description:
|
|
472
|
-
foundValue: match.participant.email
|
|
469
|
+
description: 'inbox_ops.discrepancy.desc.no_matching_contact',
|
|
470
|
+
foundValue: `${match.participant.name} (${match.participant.email})`,
|
|
473
471
|
}, scope),
|
|
474
472
|
)
|
|
475
473
|
}
|
|
@@ -483,8 +481,8 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
483
481
|
createDiscrepancy(em, proposalId, allActions, {
|
|
484
482
|
type: 'unknown_contact',
|
|
485
483
|
severity: 'warning',
|
|
486
|
-
description:
|
|
487
|
-
foundValue: participant.email
|
|
484
|
+
description: 'inbox_ops.discrepancy.desc.no_matching_contact',
|
|
485
|
+
foundValue: `${participant.name} (${participant.email})`,
|
|
488
486
|
}, scope),
|
|
489
487
|
)
|
|
490
488
|
}
|
|
@@ -505,7 +503,7 @@ export default async function handle(payload: EmailReceivedPayload, ctx: Resolve
|
|
|
505
503
|
actionIndex,
|
|
506
504
|
type: 'unknown_contact',
|
|
507
505
|
severity: 'error',
|
|
508
|
-
description:
|
|
506
|
+
description: 'inbox_ops.discrepancy.desc.draft_reply_no_contact',
|
|
509
507
|
foundValue: toEmail,
|
|
510
508
|
}, scope),
|
|
511
509
|
)
|
|
@@ -606,7 +604,7 @@ function buildContactActionsForUnmatchedParticipants(
|
|
|
606
604
|
})
|
|
607
605
|
.map((m) => ({
|
|
608
606
|
actionType: 'create_contact' as const,
|
|
609
|
-
description:
|
|
607
|
+
description: 'inbox_ops.action.desc.create_contact',
|
|
610
608
|
confidence: 0.9,
|
|
611
609
|
requiredFeature: REQUIRED_FEATURES_MAP.create_contact,
|
|
612
610
|
payloadJson: JSON.stringify({
|
|
@@ -647,7 +645,7 @@ function buildLinkContactActionsForMatchedParticipants(
|
|
|
647
645
|
})
|
|
648
646
|
.map((m) => ({
|
|
649
647
|
actionType: 'link_contact' as const,
|
|
650
|
-
description:
|
|
648
|
+
description: 'inbox_ops.action.desc.link_contact',
|
|
651
649
|
confidence: 0.95,
|
|
652
650
|
requiredFeature: REQUIRED_FEATURES_MAP.link_contact,
|
|
653
651
|
payloadJson: JSON.stringify({
|
|
@@ -701,7 +699,7 @@ function buildContactActionsForUnmatchedLlmParticipants(
|
|
|
701
699
|
})
|
|
702
700
|
.map((p) => ({
|
|
703
701
|
actionType: 'create_contact' as const,
|
|
704
|
-
description:
|
|
702
|
+
description: 'inbox_ops.action.desc.create_contact',
|
|
705
703
|
confidence: 0.85,
|
|
706
704
|
requiredFeature: REQUIRED_FEATURES_MAP.create_contact,
|
|
707
705
|
payloadJson: JSON.stringify({
|
|
@@ -749,8 +747,8 @@ async function detectDuplicateOrders(
|
|
|
749
747
|
discrepancies.push({
|
|
750
748
|
type: 'duplicate_order',
|
|
751
749
|
severity: 'error',
|
|
752
|
-
description:
|
|
753
|
-
expectedValue:
|
|
750
|
+
description: 'inbox_ops.discrepancy.desc.duplicate_order_reference',
|
|
751
|
+
expectedValue: existing.orderNumber || existing.id,
|
|
754
752
|
foundValue: customerReference,
|
|
755
753
|
actionIndex: action.index,
|
|
756
754
|
})
|
|
@@ -477,6 +477,10 @@ const replyMessageCommand: CommandHandler<unknown, { id: string; externalEmail:
|
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
|
+
|
|
481
|
+
if (recipientIds.size === 0 && original.senderUserId === input.userId) {
|
|
482
|
+
recipientIds.add(input.userId)
|
|
483
|
+
}
|
|
480
484
|
}
|
|
481
485
|
if (recipientIds.size === 0) throw new Error('No recipients available for reply')
|
|
482
486
|
|
|
@@ -5,6 +5,7 @@ import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
|
5
5
|
import {
|
|
6
6
|
getMessageUiComponentRegistry,
|
|
7
7
|
} from '../../utils/typeUiRegistry'
|
|
8
|
+
import { getMessageObjectType } from '../../../lib/message-objects-registry'
|
|
8
9
|
import type { MessageAction, MessageDetail } from '../types'
|
|
9
10
|
import { toObjectAction } from '../utils'
|
|
10
11
|
|
|
@@ -28,11 +29,16 @@ export function MessageDetailObjectsSection(props: ObjectsPanelProps) {
|
|
|
28
29
|
const componentKey = `${item.entityModule}:${item.entityType}`
|
|
29
30
|
const DetailComponent = messageUiRegistry.objectDetailComponents[componentKey] ?? null
|
|
30
31
|
const objectActions = props.objectActionsByObjectId.get(item.id)
|
|
32
|
+
const objectType = getMessageObjectType(item.entityModule, item.entityType)
|
|
31
33
|
|
|
32
34
|
if (DetailComponent) {
|
|
33
|
-
const
|
|
35
|
+
const storedActions: MessageObjectAction[] = objectActions
|
|
34
36
|
? Array.from(objectActions.entries()).map(([actionId, action]) => toObjectAction(actionId, action))
|
|
35
37
|
: []
|
|
38
|
+
const typeDefinitionActions: MessageObjectAction[] = storedActions.length === 0
|
|
39
|
+
? (objectType?.actions ?? [])
|
|
40
|
+
: []
|
|
41
|
+
const actions = storedActions.length > 0 ? storedActions : typeDefinitionActions
|
|
36
42
|
|
|
37
43
|
return (
|
|
38
44
|
<DetailComponent
|
|
@@ -49,6 +55,7 @@ export function MessageDetailObjectsSection(props: ObjectsPanelProps) {
|
|
|
49
55
|
actionTakenAt={props.detail.actionTakenAt ? new Date(props.detail.actionTakenAt) : null}
|
|
50
56
|
actionTakenByUserId={props.detail.actionTakenByUserId ?? null}
|
|
51
57
|
actions={actions}
|
|
58
|
+
icon={objectType?.icon}
|
|
52
59
|
onAction={async (actionId, payload) => {
|
|
53
60
|
const action = objectActions?.get(actionId)
|
|
54
61
|
if (!action) return
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
4
4
|
import { MarkdownContent } from '@open-mercato/ui/backend/markdown/MarkdownContent'
|
|
5
5
|
import { getMessageUiComponentRegistry } from '../../utils/typeUiRegistry'
|
|
6
|
+
import { getMessageObjectType } from '../../../lib/message-objects-registry'
|
|
6
7
|
import type { MessageDetail, MessageDetailObject } from '../types'
|
|
7
8
|
import { formatDateTime } from '../utils'
|
|
8
9
|
|
|
@@ -38,6 +39,7 @@ export function MessageDetailThreadSection({ detail }: { detail: MessageDetail }
|
|
|
38
39
|
const componentKey = `${obj.entityModule}:${obj.entityType}`
|
|
39
40
|
const PreviewComponent = messageUiRegistry.objectPreviewComponents[componentKey]
|
|
40
41
|
?? messageUiRegistry.objectPreviewComponents['messages:default']
|
|
42
|
+
const objectType = getMessageObjectType(obj.entityModule, obj.entityType)
|
|
41
43
|
if (!PreviewComponent) return null
|
|
42
44
|
|
|
43
45
|
return (
|
|
@@ -51,6 +53,7 @@ export function MessageDetailThreadSection({ detail }: { detail: MessageDetail }
|
|
|
51
53
|
actionRequired={obj.actionRequired}
|
|
52
54
|
actionType={obj.actionType ?? undefined}
|
|
53
55
|
actionLabel={obj.actionLabel ?? undefined}
|
|
56
|
+
icon={objectType?.icon}
|
|
54
57
|
/>
|
|
55
58
|
</div>
|
|
56
59
|
)
|
|
@@ -375,6 +375,7 @@ export default function MessageTokenPage({ params }: { params: { token: string }
|
|
|
375
375
|
actionTaken={data.actionTaken ?? null}
|
|
376
376
|
actionTakenAt={data.actionTakenAt ? new Date(data.actionTakenAt) : null}
|
|
377
377
|
actionTakenByUserId={data.actionTakenByUserId ?? null}
|
|
378
|
+
icon={objectType?.icon}
|
|
378
379
|
onAction={async () => {
|
|
379
380
|
return
|
|
380
381
|
}}
|
|
@@ -12,6 +12,7 @@ import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
|
12
12
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
13
13
|
import { ActivitiesSection, NotesSection, type SectionAction, type TagOption } from '@open-mercato/ui/backend/detail'
|
|
14
14
|
import { VersionHistoryAction } from '@open-mercato/ui/backend/version-history'
|
|
15
|
+
import { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'
|
|
15
16
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
16
17
|
import { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'
|
|
17
18
|
import { buildResourceScheduleItems } from '@open-mercato/core/modules/resources/lib/resourceSchedule'
|
|
@@ -490,10 +491,25 @@ export default function ResourcesResourceDetailPage({ params }: { params?: { id?
|
|
|
490
491
|
backHref="/backend/resources/resources"
|
|
491
492
|
backLabel={t('resources.resources.detail.back', 'Back to resources')}
|
|
492
493
|
utilityActions={(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
494
|
+
<>
|
|
495
|
+
{resourceId ? (
|
|
496
|
+
<SendObjectMessageDialog
|
|
497
|
+
object={{
|
|
498
|
+
entityModule: 'resources',
|
|
499
|
+
entityType: 'resource',
|
|
500
|
+
entityId: resourceId,
|
|
501
|
+
previewData: {
|
|
502
|
+
title: resourceTitle,
|
|
503
|
+
},
|
|
504
|
+
}}
|
|
505
|
+
viewHref={`/backend/resources/resources/${resourceId}`}
|
|
506
|
+
/>
|
|
507
|
+
) : null}
|
|
508
|
+
<VersionHistoryAction
|
|
509
|
+
config={resourceId ? { resourceKind: 'resources.resource', resourceId, includeRelated: true } : null}
|
|
510
|
+
t={t}
|
|
511
|
+
/>
|
|
512
|
+
</>
|
|
497
513
|
)}
|
|
498
514
|
title={resourceTitle}
|
|
499
515
|
subtitle={t('resources.resources.detail.subtitle', 'Resource profile and activity')}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
2
|
+
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
3
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
4
|
+
import type { ObjectPreviewData } from '@open-mercato/shared/modules/messages/types'
|
|
5
|
+
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
6
|
+
import { ResourcesResource } from '../data/entities'
|
|
7
|
+
|
|
8
|
+
type PreviewContext = {
|
|
9
|
+
tenantId: string
|
|
10
|
+
organizationId?: string | null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function resolveEm() {
|
|
14
|
+
const { resolve } = await createRequestContainer()
|
|
15
|
+
return resolve('em') as EntityManager
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function loadResourcePreview(
|
|
19
|
+
entityId: string,
|
|
20
|
+
ctx: PreviewContext,
|
|
21
|
+
): Promise<ObjectPreviewData> {
|
|
22
|
+
const { t } = await resolveTranslations()
|
|
23
|
+
const defaultTitle = t('resources.messageObjects.resource.title')
|
|
24
|
+
|
|
25
|
+
if (!ctx.organizationId) {
|
|
26
|
+
return { title: defaultTitle, subtitle: entityId }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const em = await resolveEm()
|
|
30
|
+
const entity = await findOneWithDecryption(
|
|
31
|
+
em,
|
|
32
|
+
ResourcesResource,
|
|
33
|
+
{
|
|
34
|
+
id: entityId,
|
|
35
|
+
tenantId: ctx.tenantId,
|
|
36
|
+
organizationId: ctx.organizationId,
|
|
37
|
+
deletedAt: null,
|
|
38
|
+
},
|
|
39
|
+
undefined,
|
|
40
|
+
{ tenantId: ctx.tenantId, organizationId: ctx.organizationId },
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!entity) {
|
|
44
|
+
return {
|
|
45
|
+
title: defaultTitle,
|
|
46
|
+
subtitle: entityId,
|
|
47
|
+
status: t('customers.messageObjects.notFound'),
|
|
48
|
+
statusColor: 'gray',
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
title: entity.name,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { MessageObjectTypeDefinition } from '@open-mercato/shared/modules/messages/types'
|
|
2
|
+
import { MessageObjectDetail, MessageObjectPreview } from '@open-mercato/ui/backend/messages'
|
|
3
|
+
|
|
4
|
+
const objectMessageTypes = ['default', 'messages.defaultWithObjects']
|
|
5
|
+
|
|
6
|
+
export const messageObjectTypes: MessageObjectTypeDefinition[] = [
|
|
7
|
+
{
|
|
8
|
+
module: 'resources',
|
|
9
|
+
entityType: 'resource',
|
|
10
|
+
messageTypes: objectMessageTypes,
|
|
11
|
+
entityId: 'resources:resources_resource',
|
|
12
|
+
optionLabelField: 'name',
|
|
13
|
+
optionSubtitleField: 'description',
|
|
14
|
+
labelKey: 'resources.messageObjects.resource.title',
|
|
15
|
+
icon: 'package',
|
|
16
|
+
PreviewComponent: MessageObjectPreview,
|
|
17
|
+
DetailComponent: MessageObjectDetail,
|
|
18
|
+
actions: [
|
|
19
|
+
{
|
|
20
|
+
id: 'view',
|
|
21
|
+
labelKey: 'common.view',
|
|
22
|
+
variant: 'outline',
|
|
23
|
+
href: '/backend/resources/resources/{entityId}',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
loadPreview: async (entityId, ctx) => {
|
|
27
|
+
if (typeof window !== 'undefined') {
|
|
28
|
+
return { title: 'Resource', subtitle: entityId }
|
|
29
|
+
}
|
|
30
|
+
const { loadResourcePreview } = await import('./lib/messageObjectPreviews')
|
|
31
|
+
return loadResourcePreview(entityId, ctx)
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
export default messageObjectTypes
|
|
@@ -12,6 +12,7 @@ import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
|
12
12
|
import { useChannelFields, buildChannelPayload, type ChannelFormValues } from '@open-mercato/core/modules/sales/components/channels/channelFormFields'
|
|
13
13
|
import { E } from '#generated/entities.ids.generated'
|
|
14
14
|
import { SalesChannelOffersPanel } from '@open-mercato/core/modules/sales/components/channels/SalesChannelOffersPanel'
|
|
15
|
+
import { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'
|
|
15
16
|
|
|
16
17
|
type ChannelApiResponse = {
|
|
17
18
|
items?: Array<Record<string, unknown>>
|
|
@@ -126,6 +127,23 @@ export default function EditChannelPage({ params }: { params?: { channelId?: str
|
|
|
126
127
|
<CrudForm<ChannelFormValues>
|
|
127
128
|
title={t('sales.channels.form.editTitle', 'Edit channel')}
|
|
128
129
|
versionHistory={{ resourceKind: 'sales.channel', resourceId: channelId ? String(channelId) : '' }}
|
|
130
|
+
extraActions={channelId ? (
|
|
131
|
+
<SendObjectMessageDialog
|
|
132
|
+
object={{
|
|
133
|
+
entityModule: 'sales',
|
|
134
|
+
entityType: 'channel',
|
|
135
|
+
entityId: channelId,
|
|
136
|
+
previewData: {
|
|
137
|
+
title: initialValues?.name ?? '',
|
|
138
|
+
metadata: {
|
|
139
|
+
[t('sales.channels.form.contactEmail')]: initialValues?.contactEmail ?? '-',
|
|
140
|
+
[t('sales.channels.form.websiteUrl')]: initialValues?.websiteUrl ?? '-',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
}}
|
|
144
|
+
viewHref={`/backend/sales/channels/${channelId}/edit`}
|
|
145
|
+
/>
|
|
146
|
+
) : undefined}
|
|
129
147
|
entityId={E.sales.sales_channel}
|
|
130
148
|
fields={fields}
|
|
131
149
|
groups={[
|
|
@@ -63,6 +63,16 @@ import { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '@op
|
|
|
63
63
|
import { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'
|
|
64
64
|
import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
|
|
65
65
|
|
|
66
|
+
function formatMessageAmount(amount: number | null | undefined, currency: string | null | undefined): string | null {
|
|
67
|
+
if (typeof amount !== 'number' || !Number.isFinite(amount)) return null
|
|
68
|
+
if (!currency) return amount.toLocaleString()
|
|
69
|
+
try {
|
|
70
|
+
return new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(amount)
|
|
71
|
+
} catch {
|
|
72
|
+
return `${amount.toLocaleString()} ${currency}`
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
function CurrencyInlineEditor({
|
|
67
77
|
label,
|
|
68
78
|
value,
|
|
@@ -1844,9 +1854,11 @@ function StatusInlineEditor({
|
|
|
1844
1854
|
export default function SalesDocumentDetailPage({
|
|
1845
1855
|
params,
|
|
1846
1856
|
initialKind,
|
|
1857
|
+
includeAmountInMessageMetadata,
|
|
1847
1858
|
}: {
|
|
1848
1859
|
params: { id: string }
|
|
1849
1860
|
initialKind?: 'order' | 'quote'
|
|
1861
|
+
includeAmountInMessageMetadata?: boolean
|
|
1850
1862
|
}) {
|
|
1851
1863
|
const t = useT()
|
|
1852
1864
|
const router = useRouter()
|
|
@@ -2729,6 +2741,11 @@ export default function SalesDocumentDetailPage({
|
|
|
2729
2741
|
: null
|
|
2730
2742
|
const contactEmail = resolveCustomerEmail(customerSnapshot) ?? metadataEmail ?? record?.contactEmail ?? null
|
|
2731
2743
|
const statusDisplay = record?.status ? statusDictionaryMap[record.status] ?? null : null
|
|
2744
|
+
const previewAmount = formatMessageAmount(record?.grandTotalGrossAmount ?? null, record?.currencyCode ?? null)
|
|
2745
|
+
const messagePreviewMetadata: Record<string, string> = {}
|
|
2746
|
+
if (includeAmountInMessageMetadata && previewAmount) {
|
|
2747
|
+
messagePreviewMetadata[t('sales.documents.detail.totals.grandTotalGross')] = previewAmount
|
|
2748
|
+
}
|
|
2732
2749
|
const contactRecordId = customerSnapshot?.contact?.id ?? customerSnapshot?.customer?.id ?? record?.customerEntityId ?? null
|
|
2733
2750
|
const resolveAdjustmentLabel = React.useCallback(
|
|
2734
2751
|
(row: AdjustmentRowData) => {
|
|
@@ -4434,7 +4451,13 @@ export default function SalesDocumentDetailPage({
|
|
|
4434
4451
|
entityId: record.id,
|
|
4435
4452
|
sourceEntityType: kind === 'order' ? 'sales.order' : 'sales.quote',
|
|
4436
4453
|
sourceEntityId: record.id,
|
|
4454
|
+
previewData: {
|
|
4455
|
+
title: number,
|
|
4456
|
+
status: statusDisplay?.label ?? record?.status ?? undefined,
|
|
4457
|
+
metadata: Object.keys(messagePreviewMetadata).length > 0 ? messagePreviewMetadata : undefined,
|
|
4458
|
+
},
|
|
4437
4459
|
}}
|
|
4460
|
+
viewHref={`/backend/sales/${kind === 'order' ? 'orders' : 'quotes'}/${record.id}`}
|
|
4438
4461
|
defaultValues={{
|
|
4439
4462
|
sourceEntityType: kind === 'order' ? 'sales.order' : 'sales.quote',
|
|
4440
4463
|
sourceEntityId: record.id,
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
import SalesDocumentDetailPage from '../../documents/[id]/page'
|
|
4
4
|
|
|
5
5
|
export default function SalesQuoteDetailPage(props: { params: { id: string } }) {
|
|
6
|
-
return <SalesDocumentDetailPage {...props} initialKind="quote" />
|
|
6
|
+
return <SalesDocumentDetailPage {...props} initialKind="quote" includeAmountInMessageMetadata />
|
|
7
7
|
}
|