@open-mercato/core 0.7.1-develop.7130.1.fef2396fd8 → 0.7.1-develop.7135.1.19bf969756
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/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +5 -0
- package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +5 -0
- package/dist/modules/auth/api/profile/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +40 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/lib/access-control.js +6 -1
- package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
- package/dist/modules/communication_channels/lib/system-user.js +8 -3
- package/dist/modules/communication_channels/lib/system-user.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +13 -0
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +9 -0
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/route.js +5 -0
- package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js +5 -0
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/cancel/route.js +5 -0
- package/dist/modules/customers/api/interactions/cancel/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/complete/route.js +5 -0
- package/dist/modules/customers/api/interactions/complete/route.js.map +2 -2
- package/dist/modules/customers/api/labels/assign/route.js +5 -0
- package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
- package/dist/modules/customers/api/labels/route.js +5 -0
- package/dist/modules/customers/api/labels/route.js.map +2 -2
- package/dist/modules/customers/api/labels/unassign/route.js +5 -0
- package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +9 -0
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/route.js +5 -0
- package/dist/modules/customers/api/people/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/pipeline-stages/reorder/route.js +5 -0
- package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
- package/dist/modules/customers/api/pipeline-stages/route.js +13 -0
- package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
- package/dist/modules/customers/api/pipelines/route.js +13 -0
- package/dist/modules/customers/api/pipelines/route.js.map +2 -2
- package/dist/modules/customers/api/settings/address-format/route.js +5 -0
- package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
- package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js +5 -0
- package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js.map +2 -2
- package/dist/modules/customers/api/settings/stuck-threshold/route.js +5 -0
- package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +2 -2
- package/dist/modules/customers/api/tags/assign/route.js +5 -0
- package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
- package/dist/modules/customers/api/tags/unassign/route.js +5 -0
- package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +13 -0
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +9 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +5 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +5 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +5 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +2 -2
- package/dist/modules/directory/api/organization-branding/route.js +5 -0
- package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
- package/dist/modules/eudr/api/plots/import/route.js.map +2 -2
- package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +2 -2
- package/dist/modules/feature_toggles/api/overrides/route.js +5 -0
- package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +5 -0
- package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/archive/route.js +5 -0
- package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/read/route.js +5 -0
- package/dist/modules/messages/api/[id]/conversation/read/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/route.js +5 -0
- package/dist/modules/messages/api/[id]/conversation/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/forward/route.js +5 -0
- package/dist/modules/messages/api/[id]/forward/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/reply/route.js +5 -0
- package/dist/modules/messages/api/[id]/reply/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +9 -0
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/token/[token]/route.js +5 -0
- package/dist/modules/messages/api/token/[token]/route.js.map +2 -2
- package/dist/modules/resources/api/resources/tags/assign/route.js +5 -0
- package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
- package/dist/modules/resources/api/resources/tags/unassign/route.js +5 -0
- package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js +5 -0
- package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/convert/route.js +5 -0
- package/dist/modules/sales/api/quotes/convert/route.js.map +2 -2
- package/dist/modules/sales/api/settings/document-numbers/route.js +5 -0
- package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
- package/dist/modules/sales/api/settings/order-editing/route.js +5 -0
- package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/accept/route.js +5 -0
- package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/reject/route.js +5 -0
- package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/self/route.js +5 -0
- package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/assign/route.js +5 -0
- package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/unassign/route.js +5 -0
- package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +5 -0
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js +9 -0
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/ai/assess/route.js +25 -18
- package/dist/modules/warranty_claims/api/ai/assess/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/assign/route.js +5 -0
- package/dist/modules/warranty_claims/api/assign/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/credit-memo/route.js +16 -12
- package/dist/modules/warranty_claims/api/credit-memo/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/events/route.js +6 -1
- package/dist/modules/warranty_claims/api/events/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js +24 -27
- package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/route.js +8 -10
- package/dist/modules/warranty_claims/api/portal/claims/[id]/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/shared.js +4 -9
- package/dist/modules/warranty_claims/api/portal/claims/[id]/shared.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js +8 -3
- package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js +8 -3
- package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js +9 -9
- package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/events/route.js +17 -13
- package/dist/modules/warranty_claims/api/portal/events/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/receiving/route.js +19 -15
- package/dist/modules/warranty_claims/api/receiving/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/registrations/route.js +9 -4
- package/dist/modules/warranty_claims/api/registrations/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/replacement-order/route.js +16 -12
- package/dist/modules/warranty_claims/api/replacement-order/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/return-label/route.js +25 -19
- package/dist/modules/warranty_claims/api/return-label/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/risk/route.js +2 -1
- package/dist/modules/warranty_claims/api/risk/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/sales-return/route.js +16 -12
- package/dist/modules/warranty_claims/api/sales-return/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/settings-general/route.js +5 -0
- package/dist/modules/warranty_claims/api/settings-general/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/submit/route.js +5 -0
- package/dist/modules/warranty_claims/api/submit/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/transition/route.js +5 -0
- package/dist/modules/warranty_claims/api/transition/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/troubleshooting-guides/route.js +22 -1
- package/dist/modules/warranty_claims/api/troubleshooting-guides/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/vendor-recovery/route.js +5 -0
- package/dist/modules/warranty_claims/api/vendor-recovery/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js +2 -1
- package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js.map +2 -2
- package/dist/modules/warranty_claims/commands/shared.js +2 -2
- package/dist/modules/warranty_claims/commands/shared.js.map +2 -2
- package/dist/modules/warranty_claims/lib/portalAuthGuard.js +31 -0
- package/dist/modules/warranty_claims/lib/portalAuthGuard.js.map +7 -0
- package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js +5 -0
- package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js.map +2 -2
- package/package.json +7 -7
- package/src/helpers/integration/communicationChannelsFixtures.ts +13 -0
- package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +5 -0
- package/src/modules/auth/api/profile/route.ts +5 -0
- package/src/modules/communication_channels/api/post/test-seed/route.ts +47 -2
- package/src/modules/communication_channels/lib/access-control.ts +28 -0
- package/src/modules/communication_channels/lib/system-user.ts +40 -22
- package/src/modules/customers/api/activities/route.ts +13 -0
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +9 -0
- package/src/modules/customers/api/dictionaries/[kind]/route.ts +5 -0
- package/src/modules/customers/api/dictionaries/kind-settings/route.ts +5 -0
- package/src/modules/customers/api/interactions/cancel/route.ts +5 -0
- package/src/modules/customers/api/interactions/complete/route.ts +5 -0
- package/src/modules/customers/api/labels/assign/route.ts +5 -0
- package/src/modules/customers/api/labels/route.ts +5 -0
- package/src/modules/customers/api/labels/unassign/route.ts +5 -0
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +9 -0
- package/src/modules/customers/api/people/[id]/companies/route.ts +5 -0
- package/src/modules/customers/api/pipeline-stages/reorder/route.ts +5 -0
- package/src/modules/customers/api/pipeline-stages/route.ts +13 -0
- package/src/modules/customers/api/pipelines/route.ts +13 -0
- package/src/modules/customers/api/settings/address-format/route.ts +5 -0
- package/src/modules/customers/api/settings/dictionary-sort-modes/route.ts +5 -0
- package/src/modules/customers/api/settings/stuck-threshold/route.ts +5 -0
- package/src/modules/customers/api/tags/assign/route.ts +5 -0
- package/src/modules/customers/api/tags/unassign/route.ts +5 -0
- package/src/modules/customers/api/todos/route.ts +13 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +9 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +5 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +5 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +5 -0
- package/src/modules/directory/api/organization-branding/route.ts +5 -0
- package/src/modules/eudr/api/plots/import/route.ts +7 -0
- package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +7 -0
- package/src/modules/feature_toggles/api/overrides/route.ts +5 -0
- package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +5 -0
- package/src/modules/messages/api/[id]/conversation/archive/route.ts +5 -0
- package/src/modules/messages/api/[id]/conversation/read/route.ts +5 -0
- package/src/modules/messages/api/[id]/conversation/route.ts +5 -0
- package/src/modules/messages/api/[id]/forward/route.ts +5 -0
- package/src/modules/messages/api/[id]/reply/route.ts +5 -0
- package/src/modules/messages/api/[id]/route.ts +9 -0
- package/src/modules/messages/api/token/[token]/route.ts +5 -0
- package/src/modules/resources/api/resources/tags/assign/route.ts +5 -0
- package/src/modules/resources/api/resources/tags/unassign/route.ts +5 -0
- package/src/modules/sales/api/quotes/accept/route.ts +5 -0
- package/src/modules/sales/api/quotes/convert/route.ts +5 -0
- package/src/modules/sales/api/settings/document-numbers/route.ts +5 -0
- package/src/modules/sales/api/settings/order-editing/route.ts +5 -0
- package/src/modules/staff/api/leave-requests/accept/route.ts +5 -0
- package/src/modules/staff/api/leave-requests/reject/route.ts +5 -0
- package/src/modules/staff/api/team-members/self/route.ts +5 -0
- package/src/modules/staff/api/team-members/tags/assign/route.ts +5 -0
- package/src/modules/staff/api/team-members/tags/unassign/route.ts +5 -0
- package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +5 -0
- package/src/modules/translations/api/[entityType]/[entityId]/route.ts +9 -0
- package/src/modules/warranty_claims/api/ai/assess/route.ts +28 -17
- package/src/modules/warranty_claims/api/assign/route.ts +5 -0
- package/src/modules/warranty_claims/api/credit-memo/route.ts +19 -13
- package/src/modules/warranty_claims/api/events/route.ts +6 -1
- package/src/modules/warranty_claims/api/portal/attachments/route.ts +29 -27
- package/src/modules/warranty_claims/api/portal/claims/[id]/route.ts +9 -10
- package/src/modules/warranty_claims/api/portal/claims/[id]/shared.ts +5 -9
- package/src/modules/warranty_claims/api/portal/claims/[id]/submit/route.ts +8 -3
- package/src/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.ts +8 -3
- package/src/modules/warranty_claims/api/portal/claims/route.ts +10 -9
- package/src/modules/warranty_claims/api/portal/events/route.ts +18 -13
- package/src/modules/warranty_claims/api/receiving/route.ts +22 -15
- package/src/modules/warranty_claims/api/registrations/route.ts +9 -3
- package/src/modules/warranty_claims/api/replacement-order/route.ts +19 -13
- package/src/modules/warranty_claims/api/return-label/route.ts +26 -17
- package/src/modules/warranty_claims/api/risk/route.ts +3 -1
- package/src/modules/warranty_claims/api/sales-return/route.ts +19 -13
- package/src/modules/warranty_claims/api/settings-general/route.ts +5 -0
- package/src/modules/warranty_claims/api/submit/route.ts +5 -0
- package/src/modules/warranty_claims/api/transition/route.ts +5 -0
- package/src/modules/warranty_claims/api/troubleshooting-guides/route.ts +23 -1
- package/src/modules/warranty_claims/api/vendor-recovery/route.ts +5 -0
- package/src/modules/warranty_claims/api/vendor-recovery-suggestions/route.ts +3 -1
- package/src/modules/warranty_claims/commands/shared.ts +7 -1
- package/src/modules/warranty_claims/lib/portalAuthGuard.ts +30 -0
- package/src/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.ts +5 -0
|
@@ -5,7 +5,9 @@ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
|
5
5
|
import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
|
|
6
6
|
import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
7
7
|
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
8
|
+
import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
|
|
8
9
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
10
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
11
|
import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
|
|
10
12
|
import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
|
|
11
13
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
@@ -54,24 +56,23 @@ export const metadata = {
|
|
|
54
56
|
POST: { requireAuth: true, requireFeatures: ['warranty_claims.claim.manage', 'sales.returns.create'] },
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
function translateKey(key: string): string {
|
|
58
|
-
return key
|
|
59
|
-
}
|
|
60
|
-
|
|
61
59
|
function toRecord(value: unknown): Record<string, unknown> {
|
|
62
60
|
return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
async function resolveActionContext(
|
|
63
|
+
async function resolveActionContext(
|
|
64
|
+
req: Request,
|
|
65
|
+
translate: ActionRouteContext['translate'],
|
|
66
|
+
): Promise<ActionRouteContext> {
|
|
66
67
|
const container = await createRequestContainer()
|
|
67
68
|
const auth = await getAuthFromRequest(req)
|
|
68
69
|
if (!auth || !auth.tenantId) {
|
|
69
|
-
throw new CrudHttpError(401, { error: 'warranty_claims.errors.unauthorized' })
|
|
70
|
+
throw new CrudHttpError(401, { error: translate('warranty_claims.errors.unauthorized', 'Unauthorized') })
|
|
70
71
|
}
|
|
71
72
|
const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })
|
|
72
73
|
const organizationId = scope?.selectedId ?? auth.orgId ?? null
|
|
73
74
|
if (!organizationId) {
|
|
74
|
-
throw new CrudHttpError(400, { error: 'warranty_claims.errors.organization_required' })
|
|
75
|
+
throw new CrudHttpError(400, { error: translate('warranty_claims.errors.organization_required', 'Organization context is required.') })
|
|
75
76
|
}
|
|
76
77
|
return {
|
|
77
78
|
ctx: {
|
|
@@ -84,7 +85,7 @@ async function resolveActionContext(req: Request): Promise<ActionRouteContext> {
|
|
|
84
85
|
},
|
|
85
86
|
tenantId: auth.tenantId,
|
|
86
87
|
organizationId,
|
|
87
|
-
translate
|
|
88
|
+
translate,
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
@@ -110,7 +111,7 @@ async function runGuard(
|
|
|
110
111
|
): Promise<RouteMutationGuardResult> {
|
|
111
112
|
const userId = context.ctx.auth?.sub
|
|
112
113
|
if (!userId) {
|
|
113
|
-
throw new CrudHttpError(401, { error: 'warranty_claims.errors.unauthorized' })
|
|
114
|
+
throw new CrudHttpError(401, { error: context.translate('warranty_claims.errors.unauthorized', 'Unauthorized') })
|
|
114
115
|
}
|
|
115
116
|
return runRouteMutationGuards({
|
|
116
117
|
container: context.ctx.container,
|
|
@@ -130,8 +131,9 @@ async function runGuard(
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
export async function POST(req: Request) {
|
|
134
|
+
const { translate } = await resolveTranslations()
|
|
133
135
|
try {
|
|
134
|
-
const context = await resolveActionContext(req)
|
|
136
|
+
const context = await resolveActionContext(req, translate)
|
|
135
137
|
const requestInput = toSalesReturnRequest(toRecord(await readJsonSafe(req, {})))
|
|
136
138
|
const guarded = await runGuard(req, context, requestInput)
|
|
137
139
|
if (!guarded.ok) {
|
|
@@ -143,16 +145,20 @@ export async function POST(req: Request) {
|
|
|
143
145
|
'warranty_claims.claim.create_sales_return',
|
|
144
146
|
{ input: toCommandInput(guardedInput, context), ctx: context.ctx },
|
|
145
147
|
)
|
|
146
|
-
if (!result) throw new CrudHttpError(400, { error: 'warranty_claims.errors.save_failed' })
|
|
148
|
+
if (!result) throw new CrudHttpError(400, { error: translate('warranty_claims.errors.save_failed', 'Failed to save warranty claim.') })
|
|
147
149
|
await guarded.runAfterSuccess()
|
|
148
150
|
return NextResponse.json({ salesReturnId: result.salesReturnId, skippedLineIds: result.skippedLineIds })
|
|
149
151
|
} catch (err) {
|
|
150
152
|
if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
|
|
153
|
+
const interceptorRejection = getCommandInterceptorHttpRejection(err)
|
|
154
|
+
if (interceptorRejection) {
|
|
155
|
+
return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
|
|
156
|
+
}
|
|
151
157
|
if (err instanceof z.ZodError) {
|
|
152
|
-
return NextResponse.json({ error: 'warranty_claims.errors.invalidInput' }, { status: 400 })
|
|
158
|
+
return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
|
|
153
159
|
}
|
|
154
160
|
logger.error('warranty_claims.sales-return.post failed', { err })
|
|
155
|
-
return NextResponse.json({ error: 'warranty_claims.errors.save_failed' }, { status: 500 })
|
|
161
|
+
return NextResponse.json({ error: translate('warranty_claims.errors.save_failed', 'Failed to save warranty claim.') }, { status: 500 })
|
|
156
162
|
}
|
|
157
163
|
}
|
|
158
164
|
|
|
@@ -7,6 +7,7 @@ import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/d
|
|
|
7
7
|
import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
8
8
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
9
|
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
10
|
+
import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
|
|
10
11
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
11
12
|
import { runRouteMutationGuards } from '@open-mercato/shared/lib/crud/route-mutation-guard'
|
|
12
13
|
import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
|
|
@@ -165,6 +166,10 @@ export async function PUT(req: Request) {
|
|
|
165
166
|
})
|
|
166
167
|
} catch (err) {
|
|
167
168
|
if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
|
|
169
|
+
const interceptorRejection = getCommandInterceptorHttpRejection(err)
|
|
170
|
+
if (interceptorRejection) {
|
|
171
|
+
return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
|
|
172
|
+
}
|
|
168
173
|
const { translate } = await resolveTranslations()
|
|
169
174
|
if (err instanceof z.ZodError) {
|
|
170
175
|
return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
|
|
@@ -6,6 +6,7 @@ import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/d
|
|
|
6
6
|
import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
7
7
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
8
8
|
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
9
|
+
import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
|
|
9
10
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
10
11
|
import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
|
|
11
12
|
import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
|
|
@@ -118,6 +119,10 @@ export async function POST(req: Request) {
|
|
|
118
119
|
return NextResponse.json({ ok: true, claimId: result?.claimId ?? commandInput.id })
|
|
119
120
|
} catch (err) {
|
|
120
121
|
if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
|
|
122
|
+
const interceptorRejection = getCommandInterceptorHttpRejection(err)
|
|
123
|
+
if (interceptorRejection) {
|
|
124
|
+
return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
|
|
125
|
+
}
|
|
121
126
|
const { translate } = await resolveTranslations()
|
|
122
127
|
if (err instanceof z.ZodError) {
|
|
123
128
|
return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
|
|
@@ -6,6 +6,7 @@ import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/d
|
|
|
6
6
|
import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
7
7
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
8
8
|
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
9
|
+
import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
|
|
9
10
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
10
11
|
import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
|
|
11
12
|
import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
|
|
@@ -116,6 +117,10 @@ export async function POST(req: Request) {
|
|
|
116
117
|
return NextResponse.json({ ok: true, claimId: result?.claimId ?? commandInput.id })
|
|
117
118
|
} catch (err) {
|
|
118
119
|
if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
|
|
120
|
+
const interceptorRejection = getCommandInterceptorHttpRejection(err)
|
|
121
|
+
if (interceptorRejection) {
|
|
122
|
+
return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
|
|
123
|
+
}
|
|
119
124
|
const { translate } = await resolveTranslations()
|
|
120
125
|
if (err instanceof z.ZodError) {
|
|
121
126
|
return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
|
|
@@ -2,6 +2,7 @@ import { z } from 'zod'
|
|
|
2
2
|
import type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'
|
|
3
3
|
import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
|
|
4
4
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
5
6
|
import { parseBooleanFromUnknown } from '@open-mercato/shared/lib/boolean'
|
|
6
7
|
import { buildIlikeTerm } from '@open-mercato/shared/lib/db/buildIlikeTerm'
|
|
7
8
|
import { applyIdsFilter } from '../../lib/apiIdsFilter'
|
|
@@ -122,11 +123,24 @@ function toEntitySteps(value: unknown): Record<string, unknown> | null {
|
|
|
122
123
|
if (value === undefined || value === null) return null
|
|
123
124
|
const parsed = parseGuideSteps(value)
|
|
124
125
|
if (!parsed) {
|
|
125
|
-
throw new CrudHttpError(400, { error: '
|
|
126
|
+
throw new CrudHttpError(400, { error: '[internal] troubleshooting steps reached the entity mapper unvalidated' })
|
|
126
127
|
}
|
|
127
128
|
return { prompt: parsed.prompt, options: parsed.options }
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
async function assertParsableGuideSteps(input: object): Promise<void> {
|
|
132
|
+
if (!hasOwn(input, 'steps')) return
|
|
133
|
+
const value = (input as { steps?: unknown }).steps
|
|
134
|
+
if (value === undefined || value === null || parseGuideSteps(value)) return
|
|
135
|
+
const { translate } = await resolveTranslations()
|
|
136
|
+
throw new CrudHttpError(400, {
|
|
137
|
+
error: translate(
|
|
138
|
+
'warranty_claims.errors.invalidTroubleshootingSteps',
|
|
139
|
+
'Troubleshooting steps must include a prompt and valid option branches.',
|
|
140
|
+
),
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
130
144
|
function toTroubleshootingGuideEntityData(input: TroubleshootingGuideCreateInput): Record<string, unknown> {
|
|
131
145
|
return {
|
|
132
146
|
claimType: input.claimType ?? null,
|
|
@@ -238,6 +252,14 @@ const crud = makeCrudRoute<RawTroubleshootingGuideInput, RawTroubleshootingGuide
|
|
|
238
252
|
schema: rawBodySchema,
|
|
239
253
|
mapToEntity: (input, ctx) => toTroubleshootingGuideEntityData(parseCreateInput(input, ctx)),
|
|
240
254
|
},
|
|
255
|
+
hooks: {
|
|
256
|
+
beforeCreate: async (input) => {
|
|
257
|
+
await assertParsableGuideSteps(input)
|
|
258
|
+
},
|
|
259
|
+
beforeUpdate: async (input) => {
|
|
260
|
+
await assertParsableGuideSteps(input)
|
|
261
|
+
},
|
|
262
|
+
},
|
|
241
263
|
update: {
|
|
242
264
|
schema: rawBodySchema,
|
|
243
265
|
getId: (input) => {
|
|
@@ -6,6 +6,7 @@ import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/d
|
|
|
6
6
|
import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
7
7
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
8
8
|
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
9
|
+
import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
|
|
9
10
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
10
11
|
import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
|
|
11
12
|
import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
|
|
@@ -120,6 +121,10 @@ export async function POST(req: Request) {
|
|
|
120
121
|
return NextResponse.json({ ok: true, claimId: createdClaimId })
|
|
121
122
|
} catch (err) {
|
|
122
123
|
if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
|
|
124
|
+
const interceptorRejection = getCommandInterceptorHttpRejection(err)
|
|
125
|
+
if (interceptorRejection) {
|
|
126
|
+
return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
|
|
127
|
+
}
|
|
123
128
|
const { translate } = await resolveTranslations()
|
|
124
129
|
if (err instanceof z.ZodError) {
|
|
125
130
|
return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
|
|
@@ -43,6 +43,7 @@ type SuggestionsRouteContext = {
|
|
|
43
43
|
tenantId: string
|
|
44
44
|
organizationId: string
|
|
45
45
|
scope: WarrantyClaimScope
|
|
46
|
+
translate: (key: string, fallback?: string) => string
|
|
46
47
|
em: EntityManager
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -79,6 +80,7 @@ async function resolveSuggestionsContext(req: Request): Promise<SuggestionsRoute
|
|
|
79
80
|
tenantId: auth.tenantId,
|
|
80
81
|
organizationId,
|
|
81
82
|
scope: { tenantId: auth.tenantId, organizationId },
|
|
83
|
+
translate,
|
|
82
84
|
em,
|
|
83
85
|
}
|
|
84
86
|
}
|
|
@@ -88,7 +90,7 @@ export async function GET(req: Request) {
|
|
|
88
90
|
const context = await resolveSuggestionsContext(req)
|
|
89
91
|
const url = new URL(req.url)
|
|
90
92
|
const query = querySchema.parse(Object.fromEntries(url.searchParams))
|
|
91
|
-
const claim = await requireScopedClaim(context.em, query.claimId, context.scope)
|
|
93
|
+
const claim = await requireScopedClaim(context.em, query.claimId, context.scope, {}, context.translate('warranty_claims.errors.notFound', 'Claim not found.'))
|
|
92
94
|
if (claim.claimType !== 'warranty' || (claim.status !== 'resolved' && claim.status !== 'closed')) {
|
|
93
95
|
return NextResponse.json({ ok: true, result: { claimId: claim.id, suggestions: [] } })
|
|
94
96
|
}
|
|
@@ -80,14 +80,20 @@ export async function loadScopedClaim(
|
|
|
80
80
|
)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* `notFoundMessage` is passed to `assertFound` verbatim, so request-scoped callers
|
|
85
|
+
* must hand in an already-translated sentence; the key default only suits the
|
|
86
|
+
* command surface, which runs without a request locale.
|
|
87
|
+
*/
|
|
83
88
|
export async function requireScopedClaim(
|
|
84
89
|
em: EntityManager,
|
|
85
90
|
id: string,
|
|
86
91
|
scope: WarrantyClaimScope,
|
|
87
92
|
options: FindOneOptions<WarrantyClaim> = {},
|
|
93
|
+
notFoundMessage = 'warranty_claims.errors.notFound',
|
|
88
94
|
): Promise<WarrantyClaim> {
|
|
89
95
|
const claim = await loadScopedClaim(em, id, scope, options)
|
|
90
|
-
return assertFound(claim,
|
|
96
|
+
return assertFound(claim, notFoundMessage)
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
export function appendClaimEvent(
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
3
|
+
import { getCustomerAuthFromRequest, type CustomerAuthContext } from '@open-mercato/core/modules/customer_accounts/lib/customerAuth'
|
|
4
|
+
|
|
5
|
+
export type LinkedCustomerAuthContext = CustomerAuthContext & { customerEntityId: string }
|
|
6
|
+
|
|
7
|
+
export async function resolveLinkedCustomerAuth(req: Request): Promise<LinkedCustomerAuthContext | Response> {
|
|
8
|
+
const auth = await getCustomerAuthFromRequest(req)
|
|
9
|
+
if (!auth) {
|
|
10
|
+
const { translate } = await resolveTranslations()
|
|
11
|
+
return NextResponse.json(
|
|
12
|
+
{ ok: false, error: translate('warranty_claims.errors.unauthorized', 'Unauthorized') },
|
|
13
|
+
{ status: 401 },
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
if (!auth.customerEntityId) {
|
|
17
|
+
const { translate } = await resolveTranslations()
|
|
18
|
+
return NextResponse.json(
|
|
19
|
+
{
|
|
20
|
+
ok: false,
|
|
21
|
+
error: translate(
|
|
22
|
+
'warranty_claims.errors.customerAccountNotLinked',
|
|
23
|
+
'Customer account is not linked to a customer record',
|
|
24
|
+
),
|
|
25
|
+
},
|
|
26
|
+
{ status: 403 },
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
return auth as LinkedCustomerAuthContext
|
|
30
|
+
}
|
|
@@ -17,6 +17,7 @@ import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
|
17
17
|
import { salesOrderWarehouseAssignBodySchema } from '../../../../data/validators'
|
|
18
18
|
import { loadSalesOrderWarehouseAssignmentView } from '../../../../lib/salesOrderWarehouseAssignment'
|
|
19
19
|
import { executeWmsCustomPostRoute } from '../../../inventory/helpers'
|
|
20
|
+
import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
|
|
20
21
|
|
|
21
22
|
const logger = createLogger('wms')
|
|
22
23
|
|
|
@@ -241,6 +242,10 @@ export async function DELETE(
|
|
|
241
242
|
}
|
|
242
243
|
return NextResponse.json(intercepted.body, { status: intercepted.statusCode })
|
|
243
244
|
} catch (error) {
|
|
245
|
+
const interceptorRejection = getCommandInterceptorHttpRejection(error)
|
|
246
|
+
if (interceptorRejection) {
|
|
247
|
+
return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
|
|
248
|
+
}
|
|
244
249
|
if (error instanceof CrudHttpError) {
|
|
245
250
|
return NextResponse.json(error.body, { status: error.status })
|
|
246
251
|
}
|