@open-mercato/core 0.7.1-develop.7131.1.20abf9e885 → 0.7.1-develop.7136.1.0f76137a1d

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.
Files changed (73) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
  3. package/dist/modules/communication_channels/api/post/test-seed/route.js +40 -2
  4. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
  5. package/dist/modules/communication_channels/lib/access-control.js +6 -1
  6. package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
  7. package/dist/modules/communication_channels/lib/system-user.js +8 -3
  8. package/dist/modules/communication_channels/lib/system-user.js.map +2 -2
  9. package/dist/modules/warranty_claims/api/ai/assess/route.js +20 -18
  10. package/dist/modules/warranty_claims/api/ai/assess/route.js.map +2 -2
  11. package/dist/modules/warranty_claims/api/credit-memo/route.js +11 -12
  12. package/dist/modules/warranty_claims/api/credit-memo/route.js.map +2 -2
  13. package/dist/modules/warranty_claims/api/events/route.js +1 -1
  14. package/dist/modules/warranty_claims/api/events/route.js.map +2 -2
  15. package/dist/modules/warranty_claims/api/portal/attachments/route.js +24 -27
  16. package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
  17. package/dist/modules/warranty_claims/api/portal/claims/[id]/route.js +8 -10
  18. package/dist/modules/warranty_claims/api/portal/claims/[id]/route.js.map +2 -2
  19. package/dist/modules/warranty_claims/api/portal/claims/[id]/shared.js +4 -9
  20. package/dist/modules/warranty_claims/api/portal/claims/[id]/shared.js.map +2 -2
  21. package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js +3 -3
  22. package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js.map +2 -2
  23. package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js +3 -3
  24. package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js.map +2 -2
  25. package/dist/modules/warranty_claims/api/portal/claims/route.js +4 -9
  26. package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
  27. package/dist/modules/warranty_claims/api/portal/events/route.js +12 -13
  28. package/dist/modules/warranty_claims/api/portal/events/route.js.map +2 -2
  29. package/dist/modules/warranty_claims/api/receiving/route.js +14 -15
  30. package/dist/modules/warranty_claims/api/receiving/route.js.map +2 -2
  31. package/dist/modules/warranty_claims/api/registrations/route.js +9 -4
  32. package/dist/modules/warranty_claims/api/registrations/route.js.map +2 -2
  33. package/dist/modules/warranty_claims/api/replacement-order/route.js +11 -12
  34. package/dist/modules/warranty_claims/api/replacement-order/route.js.map +2 -2
  35. package/dist/modules/warranty_claims/api/return-label/route.js +20 -19
  36. package/dist/modules/warranty_claims/api/return-label/route.js.map +2 -2
  37. package/dist/modules/warranty_claims/api/risk/route.js +2 -1
  38. package/dist/modules/warranty_claims/api/risk/route.js.map +2 -2
  39. package/dist/modules/warranty_claims/api/sales-return/route.js +11 -12
  40. package/dist/modules/warranty_claims/api/sales-return/route.js.map +2 -2
  41. package/dist/modules/warranty_claims/api/troubleshooting-guides/route.js +22 -1
  42. package/dist/modules/warranty_claims/api/troubleshooting-guides/route.js.map +2 -2
  43. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js +2 -1
  44. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js.map +2 -2
  45. package/dist/modules/warranty_claims/commands/shared.js +2 -2
  46. package/dist/modules/warranty_claims/commands/shared.js.map +2 -2
  47. package/dist/modules/warranty_claims/lib/portalAuthGuard.js +31 -0
  48. package/dist/modules/warranty_claims/lib/portalAuthGuard.js.map +7 -0
  49. package/package.json +7 -7
  50. package/src/helpers/integration/communicationChannelsFixtures.ts +13 -0
  51. package/src/modules/communication_channels/api/post/test-seed/route.ts +47 -2
  52. package/src/modules/communication_channels/lib/access-control.ts +28 -0
  53. package/src/modules/communication_channels/lib/system-user.ts +40 -22
  54. package/src/modules/warranty_claims/api/ai/assess/route.ts +23 -17
  55. package/src/modules/warranty_claims/api/credit-memo/route.ts +14 -13
  56. package/src/modules/warranty_claims/api/events/route.ts +1 -1
  57. package/src/modules/warranty_claims/api/portal/attachments/route.ts +29 -27
  58. package/src/modules/warranty_claims/api/portal/claims/[id]/route.ts +9 -10
  59. package/src/modules/warranty_claims/api/portal/claims/[id]/shared.ts +5 -9
  60. package/src/modules/warranty_claims/api/portal/claims/[id]/submit/route.ts +3 -3
  61. package/src/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.ts +3 -3
  62. package/src/modules/warranty_claims/api/portal/claims/route.ts +5 -9
  63. package/src/modules/warranty_claims/api/portal/events/route.ts +13 -13
  64. package/src/modules/warranty_claims/api/receiving/route.ts +17 -15
  65. package/src/modules/warranty_claims/api/registrations/route.ts +9 -3
  66. package/src/modules/warranty_claims/api/replacement-order/route.ts +14 -13
  67. package/src/modules/warranty_claims/api/return-label/route.ts +21 -17
  68. package/src/modules/warranty_claims/api/risk/route.ts +3 -1
  69. package/src/modules/warranty_claims/api/sales-return/route.ts +14 -13
  70. package/src/modules/warranty_claims/api/troubleshooting-guides/route.ts +23 -1
  71. package/src/modules/warranty_claims/api/vendor-recovery-suggestions/route.ts +3 -1
  72. package/src/modules/warranty_claims/commands/shared.ts +7 -1
  73. package/src/modules/warranty_claims/lib/portalAuthGuard.ts +30 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/warranty_claims/api/registrations/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { buildIlikeTerm } from '@open-mercato/shared/lib/db/buildIlikeTerm'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/warranty_claim_registration'\nimport { WarrantyClaimRegistration } from '../../data/entities'\nimport { assertOrderBelongsToCustomer } from '../../lib/orderOwnership'\nimport { emitWarrantyClaimsEvent } from '../../events'\nimport {\n registrationCreateSchema,\n registrationUpdateSchema,\n registrationCoverageTypeSchema,\n registrationSourceSchema,\n type RegistrationCreateInput,\n type RegistrationUpdateInput,\n} from '../../data/validators'\nimport { addWarrantyMonths } from '../../lib/warrantyPreview'\nimport {\n createPagedListResponseSchema,\n createWarrantyClaimsCrudOpenApi,\n defaultOkResponseSchema,\n} from '../openapi'\n\nconst rawBodySchema = z.object({}).passthrough()\nconst uuid = z.string().uuid()\n\nconst expiryWindowSchema = z.enum(['expired', 'expiring_30d', 'active'])\n\nconst EXPIRING_WINDOW_MS = 30 * 24 * 60 * 60 * 1000\n\nconst listSchema = z\n .object({\n id: uuid.optional(),\n serialNumber: z.string().trim().max(191).optional(),\n customerId: uuid.optional(),\n coverageType: registrationCoverageTypeSchema.optional(),\n source: registrationSourceSchema.optional(),\n expiry: expiryWindowSchema.optional(),\n search: z.string().trim().max(300).optional(),\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(20),\n sortField: z.enum(['serialNumber', 'productName', 'sku', 'warrantyExpiresAt', 'updatedAt', 'createdAt']).optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\ntype RegistrationListQuery = z.infer<typeof listSchema>\ntype RawRegistrationInput = z.infer<typeof rawBodySchema>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['warranty_claims.registration.view'] },\n POST: { requireAuth: true, requireFeatures: ['warranty_claims.registration.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['warranty_claims.registration.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['warranty_claims.registration.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nfunction scopeFromContext(ctx: CrudCtx): { organizationId: string; tenantId: string } {\n const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n const tenantId = ctx.auth?.tenantId ?? null\n if (!organizationId || !tenantId) {\n throw new CrudHttpError(400, { error: '[internal] warranty registration scope is missing' })\n }\n return { organizationId, tenantId }\n}\n\nfunction parseCreateInput(input: RawRegistrationInput, ctx: CrudCtx): RegistrationCreateInput {\n return registrationCreateSchema.parse({\n ...input,\n ...scopeFromContext(ctx),\n })\n}\n\nfunction parseUpdateInput(input: RawRegistrationInput, ctx: CrudCtx): RegistrationUpdateInput {\n return registrationUpdateSchema.parse({\n ...input,\n ...scopeFromContext(ctx),\n })\n}\n\nfunction hasOwn(input: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(input, key)\n}\n\nasync function assertRegistrationSerialUnique(\n em: EntityManager,\n scope: { organizationId: string; tenantId: string },\n serialNumber: string | null | undefined,\n excludeId: string | null,\n): Promise<void> {\n if (!serialNumber) return\n const where: FilterQuery<WarrantyClaimRegistration> = {\n serialNumber,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n }\n if (excludeId) where.id = { $ne: excludeId }\n const existing = await em.count(WarrantyClaimRegistration, where)\n if (existing > 0) {\n throw new CrudHttpError(400, { error: 'warranty_claims.errors.duplicateSerial' })\n }\n}\n\nfunction parseDate(value: string | Date | null | undefined): Date | null {\n if (value === null || value === undefined) return null\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\nfunction resolveWarrantyExpiresAt(input: RegistrationCreateInput): Date | null {\n if (hasOwn(input, 'warrantyExpiresAt')) return parseDate(input.warrantyExpiresAt)\n const purchaseDate = parseDate(input.purchaseDate)\n return purchaseDate && input.warrantyMonths !== null && input.warrantyMonths !== undefined\n ? addWarrantyMonths(purchaseDate, input.warrantyMonths)\n : null\n}\n\nfunction resolveUpdatedWarrantyExpiresAt(\n entity: WarrantyClaimRegistration,\n input: RegistrationUpdateInput,\n): Date | null | undefined {\n if (hasOwn(input, 'warrantyExpiresAt')) return parseDate(input.warrantyExpiresAt)\n if (!hasOwn(input, 'purchaseDate') && !hasOwn(input, 'warrantyMonths')) return undefined\n const purchaseDate = hasOwn(input, 'purchaseDate') ? parseDate(input.purchaseDate) : entity.purchaseDate ?? null\n const warrantyMonths = hasOwn(input, 'warrantyMonths') ? input.warrantyMonths ?? null : entity.warrantyMonths ?? null\n return purchaseDate && warrantyMonths !== null ? addWarrantyMonths(purchaseDate, warrantyMonths) : null\n}\n\nfunction toRegistrationEntityData(input: RegistrationCreateInput): Record<string, unknown> {\n return {\n serialNumber: input.serialNumber ?? null,\n productId: input.productId ?? null,\n variantId: input.variantId ?? null,\n sku: input.sku ?? null,\n productName: input.productName ?? null,\n customerId: input.customerId ?? null,\n orderId: input.orderId ?? null,\n purchaseDate: parseDate(input.purchaseDate),\n warrantyMonths: input.warrantyMonths ?? null,\n warrantyExpiresAt: resolveWarrantyExpiresAt(input),\n coverageType: input.coverageType ?? null,\n source: input.source ?? null,\n proofAttachmentId: input.proofAttachmentId ?? null,\n notes: input.notes ?? null,\n }\n}\n\nfunction applyRegistrationUpdate(entity: WarrantyClaimRegistration, input: RegistrationUpdateInput): void {\n if (hasOwn(input, 'serialNumber')) entity.serialNumber = input.serialNumber ?? null\n if (hasOwn(input, 'productId')) entity.productId = input.productId ?? null\n if (hasOwn(input, 'variantId')) entity.variantId = input.variantId ?? null\n if (hasOwn(input, 'sku')) entity.sku = input.sku ?? null\n if (hasOwn(input, 'productName')) entity.productName = input.productName ?? null\n if (hasOwn(input, 'customerId')) entity.customerId = input.customerId ?? null\n if (hasOwn(input, 'orderId')) entity.orderId = input.orderId ?? null\n if (hasOwn(input, 'purchaseDate')) entity.purchaseDate = parseDate(input.purchaseDate)\n if (hasOwn(input, 'warrantyMonths')) entity.warrantyMonths = input.warrantyMonths ?? null\n const warrantyExpiresAt = resolveUpdatedWarrantyExpiresAt(entity, input)\n if (warrantyExpiresAt !== undefined) entity.warrantyExpiresAt = warrantyExpiresAt\n if (hasOwn(input, 'coverageType')) entity.coverageType = input.coverageType ?? null\n if (hasOwn(input, 'source')) entity.source = input.source ?? null\n if (hasOwn(input, 'proofAttachmentId')) entity.proofAttachmentId = input.proofAttachmentId ?? null\n if (hasOwn(input, 'notes')) entity.notes = input.notes ?? null\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\nexport async function emitRegistrationCreatedEvent(entity: unknown): Promise<void> {\n const record = toRecord(entity)\n const registrationId = typeof record.id === 'string' ? record.id : null\n const tenantId = typeof record.tenantId === 'string' ? record.tenantId : null\n const organizationId = typeof record.organizationId === 'string' ? record.organizationId : null\n if (!registrationId || !tenantId || !organizationId) return\n await emitWarrantyClaimsEvent('warranty_claims.registration.created', {\n registrationId,\n tenantId,\n organizationId,\n }, { persistent: true, tenantId, organizationId })\n}\n\nfunction readString(record: Record<string, unknown>, snakeKey: string, camelKey: string): string | null {\n const value = record[snakeKey] ?? record[camelKey]\n return typeof value === 'string' ? value : null\n}\n\nfunction readNumber(record: Record<string, unknown>, snakeKey: string, camelKey: string): number | null {\n const value = record[snakeKey] ?? record[camelKey]\n if (typeof value === 'number') return Number.isFinite(value) ? value : null\n if (typeof value === 'string') {\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : null\n }\n return null\n}\n\nfunction toIso(value: unknown): string | null {\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'string') {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toISOString()\n }\n return null\n}\n\nfunction transformRegistrationItem(item: unknown): unknown {\n const record = toRecord(item)\n if (!Object.keys(record).length) return item\n return {\n id: readString(record, 'id', 'id'),\n organizationId: readString(record, 'organization_id', 'organizationId'),\n tenantId: readString(record, 'tenant_id', 'tenantId'),\n serialNumber: readString(record, 'serial_number', 'serialNumber'),\n productId: readString(record, 'product_id', 'productId'),\n variantId: readString(record, 'variant_id', 'variantId'),\n sku: readString(record, 'sku', 'sku'),\n productName: readString(record, 'product_name', 'productName'),\n customerId: readString(record, 'customer_id', 'customerId'),\n orderId: readString(record, 'order_id', 'orderId'),\n purchaseDate: toIso(record.purchase_date ?? record.purchaseDate),\n warrantyMonths: readNumber(record, 'warranty_months', 'warrantyMonths'),\n warrantyExpiresAt: toIso(record.warranty_expires_at ?? record.warrantyExpiresAt),\n coverageType: readString(record, 'coverage_type', 'coverageType'),\n source: readString(record, 'source', 'source'),\n proofAttachmentId: readString(record, 'proof_attachment_id', 'proofAttachmentId'),\n notes: readString(record, 'notes', 'notes'),\n createdAt: toIso(record.created_at ?? record.createdAt),\n updatedAt: toIso(record.updated_at ?? record.updatedAt),\n deletedAt: toIso(record.deleted_at ?? record.deletedAt),\n }\n}\n\nconst crud = makeCrudRoute<RawRegistrationInput, RawRegistrationInput, RegistrationListQuery>({\n metadata: routeMetadata,\n orm: {\n entity: WarrantyClaimRegistration,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: { entityType: E.warranty_claims.warranty_claim_registration },\n list: {\n schema: listSchema,\n entityId: E.warranty_claims.warranty_claim_registration,\n fields: [\n F.id,\n F.organization_id,\n F.tenant_id,\n F.serial_number,\n F.product_id,\n F.variant_id,\n F.sku,\n F.product_name,\n F.customer_id,\n F.order_id,\n F.purchase_date,\n F.warranty_months,\n F.warranty_expires_at,\n F.coverage_type,\n F.source,\n F.proof_attachment_id,\n F.notes,\n F.created_at,\n F.updated_at,\n F.deleted_at,\n ],\n sortFieldMap: {\n serialNumber: F.serial_number,\n productName: F.product_name,\n sku: F.sku,\n warrantyExpiresAt: F.warranty_expires_at,\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n },\n buildFilters: async (query) => {\n const filters: Record<string, unknown> = {}\n if (query.id) filters.id = { $eq: query.id }\n if (query.serialNumber) filters.serial_number = { $eq: query.serialNumber }\n if (query.customerId) filters.customer_id = { $eq: query.customerId }\n if (query.coverageType) filters.coverage_type = { $eq: query.coverageType }\n if (query.source) filters.source = { $eq: query.source }\n if (query.expiry) {\n const now = new Date()\n if (query.expiry === 'expired') {\n filters.warranty_expires_at = { $lt: now }\n } else if (query.expiry === 'expiring_30d') {\n filters.warranty_expires_at = { $gte: now, $lte: new Date(now.getTime() + EXPIRING_WINDOW_MS) }\n } else {\n filters.warranty_expires_at = { $gte: now }\n }\n }\n if (query.search) {\n const pattern = buildIlikeTerm(query.search)\n filters.$or = [\n { serial_number: { $ilike: pattern } },\n { sku: { $ilike: pattern } },\n { product_name: { $ilike: pattern } },\n ]\n }\n return filters\n },\n transformItem: transformRegistrationItem,\n },\n create: {\n schema: rawBodySchema,\n mapToEntity: (input, ctx) => toRegistrationEntityData(parseCreateInput(input, ctx)),\n },\n hooks: {\n beforeCreate: async (input, ctx) => {\n const scope = scopeFromContext(ctx)\n const result = registrationCreateSchema.safeParse({ ...input, ...scope })\n if (!result.success) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n await assertOrderBelongsToCustomer(em, scope, result.data.orderId ?? null, result.data.customerId ?? null)\n await assertRegistrationSerialUnique(em, scope, result.data.serialNumber ?? null, null)\n },\n beforeUpdate: async (input, ctx) => {\n const scope = scopeFromContext(ctx)\n const result = registrationUpdateSchema.safeParse({ ...input, ...scope })\n if (!result.success) return\n const parsed = result.data\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await findOneWithDecryption(\n em,\n WarrantyClaimRegistration,\n {\n id: parsed.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {},\n scope,\n )\n if (!existing) return\n const effectiveCustomerId = hasOwn(parsed, 'customerId') ? (parsed.customerId ?? null) : (existing.customerId ?? null)\n const effectiveOrderId = hasOwn(parsed, 'orderId') ? (parsed.orderId ?? null) : (existing.orderId ?? null)\n await assertOrderBelongsToCustomer(em, scope, effectiveOrderId, effectiveCustomerId)\n if (hasOwn(parsed, 'serialNumber') && (parsed.serialNumber ?? null) !== (existing.serialNumber ?? null)) {\n await assertRegistrationSerialUnique(em, scope, parsed.serialNumber ?? null, existing.id)\n }\n },\n afterCreate: async (entity) => {\n await emitRegistrationCreatedEvent(entity)\n },\n },\n update: {\n schema: rawBodySchema,\n getId: (input) => {\n const id = input.id\n return typeof id === 'string' ? id : ''\n },\n applyToEntity: (entity, input, ctx) => {\n applyRegistrationUpdate(entity as WarrantyClaimRegistration, parseUpdateInput(input, ctx))\n },\n response: () => ({ ok: true }),\n },\n del: { idFrom: 'query', softDelete: true, response: () => ({ ok: true }) },\n})\n\nexport const GET = crud.GET\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst registrationListItemSchema = z.object({\n id: z.string().uuid().nullable(),\n organizationId: z.string().uuid().nullable(),\n tenantId: z.string().uuid().nullable(),\n serialNumber: z.string().nullable(),\n productId: z.string().uuid().nullable(),\n variantId: z.string().uuid().nullable(),\n sku: z.string().nullable(),\n productName: z.string().nullable(),\n customerId: z.string().uuid().nullable(),\n orderId: z.string().uuid().nullable(),\n purchaseDate: z.string().nullable(),\n warrantyMonths: z.number().nullable(),\n warrantyExpiresAt: z.string().nullable(),\n coverageType: registrationCoverageTypeSchema.nullable(),\n source: registrationSourceSchema.nullable(),\n proofAttachmentId: z.string().uuid().nullable(),\n notes: z.string().nullable(),\n createdAt: z.string().nullable(),\n updatedAt: z.string().nullable(),\n}).passthrough()\n\nexport const openApi = createWarrantyClaimsCrudOpenApi({\n resourceName: 'WarrantyRegistration',\n pluralName: 'WarrantyRegistrations',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(registrationListItemSchema),\n create: {\n schema: registrationCreateSchema,\n responseSchema: z.object({ id: z.string().uuid() }),\n description: 'Creates a product warranty registration for entitlement resolution.',\n },\n update: {\n schema: registrationUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates a product warranty registration.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Soft-deletes a product warranty registration.',\n },\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { buildIlikeTerm } from '@open-mercato/shared/lib/db/buildIlikeTerm'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/warranty_claim_registration'\nimport { WarrantyClaimRegistration } from '../../data/entities'\nimport { assertOrderBelongsToCustomer } from '../../lib/orderOwnership'\nimport { emitWarrantyClaimsEvent } from '../../events'\nimport {\n registrationCreateSchema,\n registrationUpdateSchema,\n registrationCoverageTypeSchema,\n registrationSourceSchema,\n type RegistrationCreateInput,\n type RegistrationUpdateInput,\n} from '../../data/validators'\nimport { addWarrantyMonths } from '../../lib/warrantyPreview'\nimport {\n createPagedListResponseSchema,\n createWarrantyClaimsCrudOpenApi,\n defaultOkResponseSchema,\n} from '../openapi'\n\nconst rawBodySchema = z.object({}).passthrough()\nconst uuid = z.string().uuid()\n\nconst expiryWindowSchema = z.enum(['expired', 'expiring_30d', 'active'])\n\nconst EXPIRING_WINDOW_MS = 30 * 24 * 60 * 60 * 1000\n\nconst listSchema = z\n .object({\n id: uuid.optional(),\n serialNumber: z.string().trim().max(191).optional(),\n customerId: uuid.optional(),\n coverageType: registrationCoverageTypeSchema.optional(),\n source: registrationSourceSchema.optional(),\n expiry: expiryWindowSchema.optional(),\n search: z.string().trim().max(300).optional(),\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(20),\n sortField: z.enum(['serialNumber', 'productName', 'sku', 'warrantyExpiresAt', 'updatedAt', 'createdAt']).optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\ntype RegistrationListQuery = z.infer<typeof listSchema>\ntype RawRegistrationInput = z.infer<typeof rawBodySchema>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['warranty_claims.registration.view'] },\n POST: { requireAuth: true, requireFeatures: ['warranty_claims.registration.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['warranty_claims.registration.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['warranty_claims.registration.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nfunction scopeFromContext(ctx: CrudCtx): { organizationId: string; tenantId: string } {\n const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n const tenantId = ctx.auth?.tenantId ?? null\n if (!organizationId || !tenantId) {\n throw new CrudHttpError(400, { error: '[internal] warranty registration scope is missing' })\n }\n return { organizationId, tenantId }\n}\n\nfunction parseCreateInput(input: RawRegistrationInput, ctx: CrudCtx): RegistrationCreateInput {\n return registrationCreateSchema.parse({\n ...input,\n ...scopeFromContext(ctx),\n })\n}\n\nfunction parseUpdateInput(input: RawRegistrationInput, ctx: CrudCtx): RegistrationUpdateInput {\n return registrationUpdateSchema.parse({\n ...input,\n ...scopeFromContext(ctx),\n })\n}\n\nfunction hasOwn(input: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(input, key)\n}\n\nasync function assertRegistrationSerialUnique(\n em: EntityManager,\n scope: { organizationId: string; tenantId: string },\n serialNumber: string | null | undefined,\n excludeId: string | null,\n translate: (key: string, fallback?: string) => string,\n): Promise<void> {\n if (!serialNumber) return\n const where: FilterQuery<WarrantyClaimRegistration> = {\n serialNumber,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n }\n if (excludeId) where.id = { $ne: excludeId }\n const existing = await em.count(WarrantyClaimRegistration, where)\n if (existing > 0) {\n throw new CrudHttpError(400, {\n error: translate('warranty_claims.errors.duplicateSerial', 'A registration with this serial number already exists.'),\n })\n }\n}\n\nfunction parseDate(value: string | Date | null | undefined): Date | null {\n if (value === null || value === undefined) return null\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\nfunction resolveWarrantyExpiresAt(input: RegistrationCreateInput): Date | null {\n if (hasOwn(input, 'warrantyExpiresAt')) return parseDate(input.warrantyExpiresAt)\n const purchaseDate = parseDate(input.purchaseDate)\n return purchaseDate && input.warrantyMonths !== null && input.warrantyMonths !== undefined\n ? addWarrantyMonths(purchaseDate, input.warrantyMonths)\n : null\n}\n\nfunction resolveUpdatedWarrantyExpiresAt(\n entity: WarrantyClaimRegistration,\n input: RegistrationUpdateInput,\n): Date | null | undefined {\n if (hasOwn(input, 'warrantyExpiresAt')) return parseDate(input.warrantyExpiresAt)\n if (!hasOwn(input, 'purchaseDate') && !hasOwn(input, 'warrantyMonths')) return undefined\n const purchaseDate = hasOwn(input, 'purchaseDate') ? parseDate(input.purchaseDate) : entity.purchaseDate ?? null\n const warrantyMonths = hasOwn(input, 'warrantyMonths') ? input.warrantyMonths ?? null : entity.warrantyMonths ?? null\n return purchaseDate && warrantyMonths !== null ? addWarrantyMonths(purchaseDate, warrantyMonths) : null\n}\n\nfunction toRegistrationEntityData(input: RegistrationCreateInput): Record<string, unknown> {\n return {\n serialNumber: input.serialNumber ?? null,\n productId: input.productId ?? null,\n variantId: input.variantId ?? null,\n sku: input.sku ?? null,\n productName: input.productName ?? null,\n customerId: input.customerId ?? null,\n orderId: input.orderId ?? null,\n purchaseDate: parseDate(input.purchaseDate),\n warrantyMonths: input.warrantyMonths ?? null,\n warrantyExpiresAt: resolveWarrantyExpiresAt(input),\n coverageType: input.coverageType ?? null,\n source: input.source ?? null,\n proofAttachmentId: input.proofAttachmentId ?? null,\n notes: input.notes ?? null,\n }\n}\n\nfunction applyRegistrationUpdate(entity: WarrantyClaimRegistration, input: RegistrationUpdateInput): void {\n if (hasOwn(input, 'serialNumber')) entity.serialNumber = input.serialNumber ?? null\n if (hasOwn(input, 'productId')) entity.productId = input.productId ?? null\n if (hasOwn(input, 'variantId')) entity.variantId = input.variantId ?? null\n if (hasOwn(input, 'sku')) entity.sku = input.sku ?? null\n if (hasOwn(input, 'productName')) entity.productName = input.productName ?? null\n if (hasOwn(input, 'customerId')) entity.customerId = input.customerId ?? null\n if (hasOwn(input, 'orderId')) entity.orderId = input.orderId ?? null\n if (hasOwn(input, 'purchaseDate')) entity.purchaseDate = parseDate(input.purchaseDate)\n if (hasOwn(input, 'warrantyMonths')) entity.warrantyMonths = input.warrantyMonths ?? null\n const warrantyExpiresAt = resolveUpdatedWarrantyExpiresAt(entity, input)\n if (warrantyExpiresAt !== undefined) entity.warrantyExpiresAt = warrantyExpiresAt\n if (hasOwn(input, 'coverageType')) entity.coverageType = input.coverageType ?? null\n if (hasOwn(input, 'source')) entity.source = input.source ?? null\n if (hasOwn(input, 'proofAttachmentId')) entity.proofAttachmentId = input.proofAttachmentId ?? null\n if (hasOwn(input, 'notes')) entity.notes = input.notes ?? null\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\nexport async function emitRegistrationCreatedEvent(entity: unknown): Promise<void> {\n const record = toRecord(entity)\n const registrationId = typeof record.id === 'string' ? record.id : null\n const tenantId = typeof record.tenantId === 'string' ? record.tenantId : null\n const organizationId = typeof record.organizationId === 'string' ? record.organizationId : null\n if (!registrationId || !tenantId || !organizationId) return\n await emitWarrantyClaimsEvent('warranty_claims.registration.created', {\n registrationId,\n tenantId,\n organizationId,\n }, { persistent: true, tenantId, organizationId })\n}\n\nfunction readString(record: Record<string, unknown>, snakeKey: string, camelKey: string): string | null {\n const value = record[snakeKey] ?? record[camelKey]\n return typeof value === 'string' ? value : null\n}\n\nfunction readNumber(record: Record<string, unknown>, snakeKey: string, camelKey: string): number | null {\n const value = record[snakeKey] ?? record[camelKey]\n if (typeof value === 'number') return Number.isFinite(value) ? value : null\n if (typeof value === 'string') {\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : null\n }\n return null\n}\n\nfunction toIso(value: unknown): string | null {\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'string') {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toISOString()\n }\n return null\n}\n\nfunction transformRegistrationItem(item: unknown): unknown {\n const record = toRecord(item)\n if (!Object.keys(record).length) return item\n return {\n id: readString(record, 'id', 'id'),\n organizationId: readString(record, 'organization_id', 'organizationId'),\n tenantId: readString(record, 'tenant_id', 'tenantId'),\n serialNumber: readString(record, 'serial_number', 'serialNumber'),\n productId: readString(record, 'product_id', 'productId'),\n variantId: readString(record, 'variant_id', 'variantId'),\n sku: readString(record, 'sku', 'sku'),\n productName: readString(record, 'product_name', 'productName'),\n customerId: readString(record, 'customer_id', 'customerId'),\n orderId: readString(record, 'order_id', 'orderId'),\n purchaseDate: toIso(record.purchase_date ?? record.purchaseDate),\n warrantyMonths: readNumber(record, 'warranty_months', 'warrantyMonths'),\n warrantyExpiresAt: toIso(record.warranty_expires_at ?? record.warrantyExpiresAt),\n coverageType: readString(record, 'coverage_type', 'coverageType'),\n source: readString(record, 'source', 'source'),\n proofAttachmentId: readString(record, 'proof_attachment_id', 'proofAttachmentId'),\n notes: readString(record, 'notes', 'notes'),\n createdAt: toIso(record.created_at ?? record.createdAt),\n updatedAt: toIso(record.updated_at ?? record.updatedAt),\n deletedAt: toIso(record.deleted_at ?? record.deletedAt),\n }\n}\n\nconst crud = makeCrudRoute<RawRegistrationInput, RawRegistrationInput, RegistrationListQuery>({\n metadata: routeMetadata,\n orm: {\n entity: WarrantyClaimRegistration,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: { entityType: E.warranty_claims.warranty_claim_registration },\n list: {\n schema: listSchema,\n entityId: E.warranty_claims.warranty_claim_registration,\n fields: [\n F.id,\n F.organization_id,\n F.tenant_id,\n F.serial_number,\n F.product_id,\n F.variant_id,\n F.sku,\n F.product_name,\n F.customer_id,\n F.order_id,\n F.purchase_date,\n F.warranty_months,\n F.warranty_expires_at,\n F.coverage_type,\n F.source,\n F.proof_attachment_id,\n F.notes,\n F.created_at,\n F.updated_at,\n F.deleted_at,\n ],\n sortFieldMap: {\n serialNumber: F.serial_number,\n productName: F.product_name,\n sku: F.sku,\n warrantyExpiresAt: F.warranty_expires_at,\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n },\n buildFilters: async (query) => {\n const filters: Record<string, unknown> = {}\n if (query.id) filters.id = { $eq: query.id }\n if (query.serialNumber) filters.serial_number = { $eq: query.serialNumber }\n if (query.customerId) filters.customer_id = { $eq: query.customerId }\n if (query.coverageType) filters.coverage_type = { $eq: query.coverageType }\n if (query.source) filters.source = { $eq: query.source }\n if (query.expiry) {\n const now = new Date()\n if (query.expiry === 'expired') {\n filters.warranty_expires_at = { $lt: now }\n } else if (query.expiry === 'expiring_30d') {\n filters.warranty_expires_at = { $gte: now, $lte: new Date(now.getTime() + EXPIRING_WINDOW_MS) }\n } else {\n filters.warranty_expires_at = { $gte: now }\n }\n }\n if (query.search) {\n const pattern = buildIlikeTerm(query.search)\n filters.$or = [\n { serial_number: { $ilike: pattern } },\n { sku: { $ilike: pattern } },\n { product_name: { $ilike: pattern } },\n ]\n }\n return filters\n },\n transformItem: transformRegistrationItem,\n },\n create: {\n schema: rawBodySchema,\n mapToEntity: (input, ctx) => toRegistrationEntityData(parseCreateInput(input, ctx)),\n },\n hooks: {\n beforeCreate: async (input, ctx) => {\n const scope = scopeFromContext(ctx)\n const result = registrationCreateSchema.safeParse({ ...input, ...scope })\n if (!result.success) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { translate } = await resolveTranslations()\n await assertOrderBelongsToCustomer(em, scope, result.data.orderId ?? null, result.data.customerId ?? null)\n await assertRegistrationSerialUnique(em, scope, result.data.serialNumber ?? null, null, translate)\n },\n beforeUpdate: async (input, ctx) => {\n const scope = scopeFromContext(ctx)\n const result = registrationUpdateSchema.safeParse({ ...input, ...scope })\n if (!result.success) return\n const parsed = result.data\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await findOneWithDecryption(\n em,\n WarrantyClaimRegistration,\n {\n id: parsed.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {},\n scope,\n )\n if (!existing) return\n const effectiveCustomerId = hasOwn(parsed, 'customerId') ? (parsed.customerId ?? null) : (existing.customerId ?? null)\n const effectiveOrderId = hasOwn(parsed, 'orderId') ? (parsed.orderId ?? null) : (existing.orderId ?? null)\n await assertOrderBelongsToCustomer(em, scope, effectiveOrderId, effectiveCustomerId)\n if (hasOwn(parsed, 'serialNumber') && (parsed.serialNumber ?? null) !== (existing.serialNumber ?? null)) {\n const { translate } = await resolveTranslations()\n await assertRegistrationSerialUnique(em, scope, parsed.serialNumber ?? null, existing.id, translate)\n }\n },\n afterCreate: async (entity) => {\n await emitRegistrationCreatedEvent(entity)\n },\n },\n update: {\n schema: rawBodySchema,\n getId: (input) => {\n const id = input.id\n return typeof id === 'string' ? id : ''\n },\n applyToEntity: (entity, input, ctx) => {\n applyRegistrationUpdate(entity as WarrantyClaimRegistration, parseUpdateInput(input, ctx))\n },\n response: () => ({ ok: true }),\n },\n del: { idFrom: 'query', softDelete: true, response: () => ({ ok: true }) },\n})\n\nexport const GET = crud.GET\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst registrationListItemSchema = z.object({\n id: z.string().uuid().nullable(),\n organizationId: z.string().uuid().nullable(),\n tenantId: z.string().uuid().nullable(),\n serialNumber: z.string().nullable(),\n productId: z.string().uuid().nullable(),\n variantId: z.string().uuid().nullable(),\n sku: z.string().nullable(),\n productName: z.string().nullable(),\n customerId: z.string().uuid().nullable(),\n orderId: z.string().uuid().nullable(),\n purchaseDate: z.string().nullable(),\n warrantyMonths: z.number().nullable(),\n warrantyExpiresAt: z.string().nullable(),\n coverageType: registrationCoverageTypeSchema.nullable(),\n source: registrationSourceSchema.nullable(),\n proofAttachmentId: z.string().uuid().nullable(),\n notes: z.string().nullable(),\n createdAt: z.string().nullable(),\n updatedAt: z.string().nullable(),\n}).passthrough()\n\nexport const openApi = createWarrantyClaimsCrudOpenApi({\n resourceName: 'WarrantyRegistration',\n pluralName: 'WarrantyRegistrations',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(registrationListItemSchema),\n create: {\n schema: registrationCreateSchema,\n responseSchema: z.object({ id: z.string().uuid() }),\n description: 'Creates a product warranty registration for entitlement resolution.',\n },\n update: {\n schema: registrationUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Updates a product warranty registration.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Soft-deletes a product warranty registration.',\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,6 +6,7 @@ import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/d
6
6
  import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
7
7
  import { getCommandInterceptorHttpRejection } from "@open-mercato/shared/lib/commands/errors";
8
8
  import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
9
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
9
10
  import { runRouteMutationGuards } from "@open-mercato/shared/lib/crud/route-mutation-guard";
10
11
  import { withScopedPayload } from "@open-mercato/shared/lib/api/scoped";
11
12
  import {
@@ -29,22 +30,19 @@ const errorResponseSchema = z.object({
29
30
  const metadata = {
30
31
  POST: { requireAuth: true, requireFeatures: ["warranty_claims.claim.manage", "sales.orders.manage"] }
31
32
  };
32
- function translateKey(key) {
33
- return key;
34
- }
35
33
  function toRecord(value) {
36
34
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
37
35
  }
38
- async function resolveActionContext(req) {
36
+ async function resolveActionContext(req, translate) {
39
37
  const container = await createRequestContainer();
40
38
  const auth = await getAuthFromRequest(req);
41
39
  if (!auth || !auth.tenantId) {
42
- throw new CrudHttpError(401, { error: "warranty_claims.errors.unauthorized" });
40
+ throw new CrudHttpError(401, { error: translate("warranty_claims.errors.unauthorized", "Unauthorized") });
43
41
  }
44
42
  const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
45
43
  const organizationId = scope?.selectedId ?? auth.orgId ?? null;
46
44
  if (!organizationId) {
47
- throw new CrudHttpError(400, { error: "warranty_claims.errors.organization_required" });
45
+ throw new CrudHttpError(400, { error: translate("warranty_claims.errors.organization_required", "Organization context is required.") });
48
46
  }
49
47
  return {
50
48
  ctx: {
@@ -57,7 +55,7 @@ async function resolveActionContext(req) {
57
55
  },
58
56
  tenantId: auth.tenantId,
59
57
  organizationId,
60
- translate: translateKey
58
+ translate
61
59
  };
62
60
  }
63
61
  function toReplacementOrderRequest(payload) {
@@ -74,7 +72,7 @@ function toCommandInput(input, context) {
74
72
  async function runGuard(req, context, input) {
75
73
  const userId = context.ctx.auth?.sub;
76
74
  if (!userId) {
77
- throw new CrudHttpError(401, { error: "warranty_claims.errors.unauthorized" });
75
+ throw new CrudHttpError(401, { error: context.translate("warranty_claims.errors.unauthorized", "Unauthorized") });
78
76
  }
79
77
  return runRouteMutationGuards({
80
78
  container: context.ctx.container,
@@ -93,8 +91,9 @@ async function runGuard(req, context, input) {
93
91
  });
94
92
  }
95
93
  async function POST(req) {
94
+ const { translate } = await resolveTranslations();
96
95
  try {
97
- const context = await resolveActionContext(req);
96
+ const context = await resolveActionContext(req, translate);
98
97
  const requestInput = toReplacementOrderRequest(toRecord(await readJsonSafe(req, {})));
99
98
  const guarded = await runGuard(req, context, requestInput);
100
99
  if (!guarded.ok) {
@@ -106,7 +105,7 @@ async function POST(req) {
106
105
  "warranty_claims.claim.create_replacement_order",
107
106
  { input: toCommandInput(guardedInput, context), ctx: context.ctx }
108
107
  );
109
- if (!result) throw new CrudHttpError(400, { error: "warranty_claims.errors.save_failed" });
108
+ if (!result) throw new CrudHttpError(400, { error: translate("warranty_claims.errors.save_failed", "Failed to save warranty claim.") });
110
109
  await guarded.runAfterSuccess();
111
110
  return NextResponse.json({
112
111
  replacementOrderId: result.replacementOrderId,
@@ -119,10 +118,10 @@ async function POST(req) {
119
118
  return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status });
120
119
  }
121
120
  if (err instanceof z.ZodError) {
122
- return NextResponse.json({ error: "warranty_claims.errors.invalidInput" }, { status: 400 });
121
+ return NextResponse.json({ error: translate("warranty_claims.errors.invalidInput", "Invalid input") }, { status: 400 });
123
122
  }
124
123
  logger.error("warranty_claims.replacement-order.post failed", { err });
125
- return NextResponse.json({ error: "warranty_claims.errors.save_failed" }, { status: 500 });
124
+ return NextResponse.json({ error: translate("warranty_claims.errors.save_failed", "Failed to save warranty claim.") }, { status: 500 });
126
125
  }
127
126
  }
128
127
  const openApi = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/warranty_claims/api/replacement-order/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'\nimport { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport {\n claimCreateReplacementOrderSchema,\n type ClaimCreateReplacementOrderInput,\n} from '../../data/validators'\nimport { WARRANTY_CLAIM_RESOURCE_KIND } from '../../commands/shared'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('warranty_claims')\n\ntype ActionRouteContext = {\n ctx: CommandRuntimeContext\n tenantId: string\n organizationId: string\n translate: (key: string, fallback?: string) => string\n}\n\ntype ReplacementOrderCommandResult = {\n claimId: string\n replacementOrderId: string\n replacementOrderUpdatedAt: string | null\n skippedLineIds: string[]\n pricing: 'zero' | 'original'\n}\n\nconst replacementOrderRequestSchema = z\n .object({\n claimId: z.string().uuid(),\n pricing: z.enum(['zero', 'original']).optional(),\n updatedAt: z.string().datetime().nullable().optional(),\n })\n .strict()\n\ntype ReplacementOrderRequest = z.infer<typeof replacementOrderRequestSchema>\n\nconst replacementOrderResponseSchema = z.object({\n replacementOrderId: z.string().uuid(),\n skippedLineIds: z.array(z.string().uuid()),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['warranty_claims.claim.manage', 'sales.orders.manage'] },\n}\n\nfunction translateKey(key: string): string {\n return key\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\nasync function resolveActionContext(req: Request): Promise<ActionRouteContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: 'warranty_claims.errors.unauthorized' })\n }\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = scope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, { error: 'warranty_claims.errors.organization_required' })\n }\n return {\n ctx: {\n container,\n auth,\n organizationScope: scope,\n selectedOrganizationId: organizationId,\n organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),\n request: req,\n },\n tenantId: auth.tenantId,\n organizationId,\n translate: translateKey,\n }\n}\n\nfunction toReplacementOrderRequest(payload: Record<string, unknown>): ReplacementOrderRequest {\n return replacementOrderRequestSchema.parse(payload)\n}\n\nfunction toCommandInput(\n input: ReplacementOrderRequest,\n context: ActionRouteContext,\n): ClaimCreateReplacementOrderInput {\n const scopedPayload = withScopedPayload({\n id: input.claimId,\n pricing: input.pricing,\n updatedAt: input.updatedAt,\n }, context.ctx, context.translate)\n return claimCreateReplacementOrderSchema.parse(scopedPayload)\n}\n\nasync function runGuard(\n req: Request,\n context: ActionRouteContext,\n input: ReplacementOrderRequest,\n): Promise<RouteMutationGuardResult> {\n const userId = context.ctx.auth?.sub\n if (!userId) {\n throw new CrudHttpError(401, { error: 'warranty_claims.errors.unauthorized' })\n }\n return runRouteMutationGuards({\n container: context.ctx.container,\n req,\n auth: {\n userId,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n },\n input: {\n resourceKind: WARRANTY_CLAIM_RESOURCE_KIND,\n resourceId: input.claimId,\n operation: 'custom',\n mutationPayload: { ...input },\n },\n })\n}\n\nexport async function POST(req: Request) {\n try {\n const context = await resolveActionContext(req)\n const requestInput = toReplacementOrderRequest(toRecord(await readJsonSafe(req, {})))\n const guarded = await runGuard(req, context, requestInput)\n if (!guarded.ok) {\n return guarded.response\n }\n const guardedInput = guarded.modifiedPayload\n ? toReplacementOrderRequest(guarded.modifiedPayload)\n : requestInput\n const commandBus = context.ctx.container.resolve('commandBus') as CommandBus\n const { result } = await commandBus.execute<ClaimCreateReplacementOrderInput, ReplacementOrderCommandResult>(\n 'warranty_claims.claim.create_replacement_order',\n { input: toCommandInput(guardedInput, context), ctx: context.ctx },\n )\n if (!result) throw new CrudHttpError(400, { error: 'warranty_claims.errors.save_failed' })\n await guarded.runAfterSuccess()\n return NextResponse.json({\n replacementOrderId: result.replacementOrderId,\n skippedLineIds: result.skippedLineIds,\n })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n const interceptorRejection = getCommandInterceptorHttpRejection(err)\n if (interceptorRejection) {\n return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })\n }\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'warranty_claims.errors.invalidInput' }, { status: 400 })\n }\n logger.error('warranty_claims.replacement-order.post failed', { err })\n return NextResponse.json({ error: 'warranty_claims.errors.save_failed' }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Warranty Claims',\n summary: 'Create a replacement sales order from a warranty claim',\n methods: {\n POST: {\n summary: 'Create and link a replacement order from eligible replace-disposition claim lines',\n description: 'Zero pricing is the default. Original pricing copies the source order lines\\' pre-discount unit prices.',\n requestBody: { contentType: 'application/json', schema: replacementOrderRequestSchema },\n responses: [\n {\n status: 200,\n description: 'Replacement order created and linked; ineligible or unresolvable claim lines are reported as skipped',\n schema: replacementOrderResponseSchema,\n },\n { status: 400, description: 'Invalid request or claim is not eligible for replacement-order creation', schema: errorResponseSchema },\n { status: 401, description: 'Authentication required', schema: errorResponseSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorResponseSchema },\n { status: 409, description: 'Optimistic lock conflict', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'\nimport { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport {\n claimCreateReplacementOrderSchema,\n type ClaimCreateReplacementOrderInput,\n} from '../../data/validators'\nimport { WARRANTY_CLAIM_RESOURCE_KIND } from '../../commands/shared'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('warranty_claims')\n\ntype ActionRouteContext = {\n ctx: CommandRuntimeContext\n tenantId: string\n organizationId: string\n translate: (key: string, fallback?: string) => string\n}\n\ntype ReplacementOrderCommandResult = {\n claimId: string\n replacementOrderId: string\n replacementOrderUpdatedAt: string | null\n skippedLineIds: string[]\n pricing: 'zero' | 'original'\n}\n\nconst replacementOrderRequestSchema = z\n .object({\n claimId: z.string().uuid(),\n pricing: z.enum(['zero', 'original']).optional(),\n updatedAt: z.string().datetime().nullable().optional(),\n })\n .strict()\n\ntype ReplacementOrderRequest = z.infer<typeof replacementOrderRequestSchema>\n\nconst replacementOrderResponseSchema = z.object({\n replacementOrderId: z.string().uuid(),\n skippedLineIds: z.array(z.string().uuid()),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['warranty_claims.claim.manage', 'sales.orders.manage'] },\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\nasync function resolveActionContext(\n req: Request,\n translate: ActionRouteContext['translate'],\n): Promise<ActionRouteContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: translate('warranty_claims.errors.unauthorized', 'Unauthorized') })\n }\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = scope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, { error: translate('warranty_claims.errors.organization_required', 'Organization context is required.') })\n }\n return {\n ctx: {\n container,\n auth,\n organizationScope: scope,\n selectedOrganizationId: organizationId,\n organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),\n request: req,\n },\n tenantId: auth.tenantId,\n organizationId,\n translate,\n }\n}\n\nfunction toReplacementOrderRequest(payload: Record<string, unknown>): ReplacementOrderRequest {\n return replacementOrderRequestSchema.parse(payload)\n}\n\nfunction toCommandInput(\n input: ReplacementOrderRequest,\n context: ActionRouteContext,\n): ClaimCreateReplacementOrderInput {\n const scopedPayload = withScopedPayload({\n id: input.claimId,\n pricing: input.pricing,\n updatedAt: input.updatedAt,\n }, context.ctx, context.translate)\n return claimCreateReplacementOrderSchema.parse(scopedPayload)\n}\n\nasync function runGuard(\n req: Request,\n context: ActionRouteContext,\n input: ReplacementOrderRequest,\n): Promise<RouteMutationGuardResult> {\n const userId = context.ctx.auth?.sub\n if (!userId) {\n throw new CrudHttpError(401, { error: context.translate('warranty_claims.errors.unauthorized', 'Unauthorized') })\n }\n return runRouteMutationGuards({\n container: context.ctx.container,\n req,\n auth: {\n userId,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n },\n input: {\n resourceKind: WARRANTY_CLAIM_RESOURCE_KIND,\n resourceId: input.claimId,\n operation: 'custom',\n mutationPayload: { ...input },\n },\n })\n}\n\nexport async function POST(req: Request) {\n const { translate } = await resolveTranslations()\n try {\n const context = await resolveActionContext(req, translate)\n const requestInput = toReplacementOrderRequest(toRecord(await readJsonSafe(req, {})))\n const guarded = await runGuard(req, context, requestInput)\n if (!guarded.ok) {\n return guarded.response\n }\n const guardedInput = guarded.modifiedPayload\n ? toReplacementOrderRequest(guarded.modifiedPayload)\n : requestInput\n const commandBus = context.ctx.container.resolve('commandBus') as CommandBus\n const { result } = await commandBus.execute<ClaimCreateReplacementOrderInput, ReplacementOrderCommandResult>(\n 'warranty_claims.claim.create_replacement_order',\n { input: toCommandInput(guardedInput, context), ctx: context.ctx },\n )\n if (!result) throw new CrudHttpError(400, { error: translate('warranty_claims.errors.save_failed', 'Failed to save warranty claim.') })\n await guarded.runAfterSuccess()\n return NextResponse.json({\n replacementOrderId: result.replacementOrderId,\n skippedLineIds: result.skippedLineIds,\n })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n const interceptorRejection = getCommandInterceptorHttpRejection(err)\n if (interceptorRejection) {\n return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })\n }\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })\n }\n logger.error('warranty_claims.replacement-order.post failed', { err })\n return NextResponse.json({ error: translate('warranty_claims.errors.save_failed', 'Failed to save warranty claim.') }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Warranty Claims',\n summary: 'Create a replacement sales order from a warranty claim',\n methods: {\n POST: {\n summary: 'Create and link a replacement order from eligible replace-disposition claim lines',\n description: 'Zero pricing is the default. Original pricing copies the source order lines\\' pre-discount unit prices.',\n requestBody: { contentType: 'application/json', schema: replacementOrderRequestSchema },\n responses: [\n {\n status: 200,\n description: 'Replacement order created and linked; ineligible or unresolvable claim lines are reported as skipped',\n schema: replacementOrderResponseSchema,\n },\n { status: 400, description: 'Invalid request or claim is not eligible for replacement-order creation', schema: errorResponseSchema },\n { status: 401, description: 'Authentication required', schema: errorResponseSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorResponseSchema },\n { status: 409, description: 'Optimistic lock conflict', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,6 +6,7 @@ import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/d
6
6
  import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
7
7
  import { getCommandInterceptorHttpRejection } from "@open-mercato/shared/lib/commands/errors";
8
8
  import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
9
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
9
10
  import { runRouteMutationGuards } from "@open-mercato/shared/lib/crud/route-mutation-guard";
10
11
  import { withScopedPayload } from "@open-mercato/shared/lib/api/scoped";
11
12
  import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
@@ -41,22 +42,19 @@ const returnLabelResponseSchema = z.discriminatedUnion("status", [
41
42
  const metadata = {
42
43
  POST: { requireAuth: true, requireFeatures: ["warranty_claims.claim.manage"] }
43
44
  };
44
- function translateKey(key) {
45
- return key;
46
- }
47
45
  function toRecord(value) {
48
46
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
49
47
  }
50
- async function resolveActionContext(req) {
48
+ async function resolveActionContext(req, translate) {
51
49
  const container = await createRequestContainer();
52
50
  const auth = await getAuthFromRequest(req);
53
51
  if (!auth || !auth.tenantId) {
54
- throw new CrudHttpError(401, { error: "warranty_claims.errors.unauthorized" });
52
+ throw new CrudHttpError(401, { error: translate("warranty_claims.errors.unauthorized", "Unauthorized") });
55
53
  }
56
54
  const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
57
55
  const organizationId = scope?.selectedId ?? auth.orgId ?? null;
58
56
  if (!organizationId) {
59
- throw new CrudHttpError(400, { error: "warranty_claims.errors.organization_required" });
57
+ throw new CrudHttpError(400, { error: translate("warranty_claims.errors.organization_required", "Organization context is required.") });
60
58
  }
61
59
  return {
62
60
  ctx: {
@@ -69,7 +67,7 @@ async function resolveActionContext(req) {
69
67
  },
70
68
  tenantId: auth.tenantId,
71
69
  organizationId,
72
- translate: translateKey
70
+ translate
73
71
  };
74
72
  }
75
73
  function toReturnLabelRequest(payload) {
@@ -98,7 +96,7 @@ function toSetReturnLabelInput(input, context) {
98
96
  async function runGuard(req, context, input) {
99
97
  const userId = context.ctx.auth?.sub;
100
98
  if (!userId) {
101
- throw new CrudHttpError(401, { error: "warranty_claims.errors.unauthorized" });
99
+ throw new CrudHttpError(401, { error: context.translate("warranty_claims.errors.unauthorized", "Unauthorized") });
102
100
  }
103
101
  return runRouteMutationGuards({
104
102
  container: context.ctx.container,
@@ -119,7 +117,7 @@ async function runGuard(req, context, input) {
119
117
  async function loadClaimAndLines(context, claimId) {
120
118
  const scope = { tenantId: context.tenantId, organizationId: context.organizationId };
121
119
  const em = context.ctx.container.resolve("em").fork();
122
- const claim = await requireScopedClaim(em, claimId, scope);
120
+ const claim = await requireScopedClaim(em, claimId, scope, {}, context.translate("warranty_claims.errors.notFound", "Claim not found."));
123
121
  const lines = await findWithDecryption(
124
122
  em,
125
123
  WarrantyClaimLine,
@@ -129,17 +127,17 @@ async function loadClaimAndLines(context, claimId) {
129
127
  );
130
128
  return { claim, lines };
131
129
  }
132
- function assertGeneratableStatus(claim) {
130
+ function assertGeneratableStatus(claim, translate) {
133
131
  if (claim.status !== "approved" && claim.status !== "awaiting_return") {
134
- throw new CrudHttpError(400, { error: "warranty_claims.errors.returnLabelInvalidStatus" });
132
+ throw new CrudHttpError(400, { error: translate("warranty_claims.errors.returnLabelInvalidStatus", "Return labels can only be created for approved claims that are awaiting return.") });
135
133
  }
136
134
  }
137
- async function executeSetReturnLabel(commandBus, input, ctx) {
135
+ async function executeSetReturnLabel(commandBus, input, ctx, translate) {
138
136
  const { result } = await commandBus.execute(
139
137
  "warranty_claims.claim.set_return_label",
140
138
  { input, ctx }
141
139
  );
142
- if (!result) throw new CrudHttpError(400, { error: "warranty_claims.errors.save_failed" });
140
+ if (!result) throw new CrudHttpError(400, { error: translate("warranty_claims.errors.save_failed", "Failed to save warranty claim.") });
143
141
  return {
144
142
  status: "created",
145
143
  labelUrl: result.labelUrl,
@@ -154,8 +152,9 @@ function firstTranslatableIssueKey(err) {
154
152
  return keyed ?? "warranty_claims.errors.invalidInput";
155
153
  }
156
154
  async function POST(req) {
155
+ const { translate } = await resolveTranslations();
157
156
  try {
158
- const context = await resolveActionContext(req);
157
+ const context = await resolveActionContext(req, translate);
159
158
  const requestInput = toReturnLabelRequest(toRecord(await readJsonSafe(req, {})));
160
159
  const guarded = await runGuard(req, context, requestInput);
161
160
  if (!guarded.ok) {
@@ -167,13 +166,14 @@ async function POST(req) {
167
166
  const response2 = await executeSetReturnLabel(
168
167
  commandBus,
169
168
  toSetReturnLabelInput(guardedInput, context),
170
- context.ctx
169
+ context.ctx,
170
+ translate
171
171
  );
172
172
  await guarded.runAfterSuccess();
173
173
  return NextResponse.json(response2);
174
174
  }
175
175
  const { claim, lines } = await loadClaimAndLines(context, guardedInput.claimId);
176
- assertGeneratableStatus(claim);
176
+ assertGeneratableStatus(claim, translate);
177
177
  await enforceWarrantyClaimOptimisticLock(
178
178
  context.ctx,
179
179
  claim,
@@ -197,7 +197,8 @@ async function POST(req) {
197
197
  trackingNumber: result.trackingNumber,
198
198
  carrier: result.carrier
199
199
  }, context),
200
- context.ctx
200
+ context.ctx,
201
+ translate
201
202
  );
202
203
  await guarded.runAfterSuccess();
203
204
  return NextResponse.json(response);
@@ -208,10 +209,10 @@ async function POST(req) {
208
209
  return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status });
209
210
  }
210
211
  if (err instanceof z.ZodError) {
211
- return NextResponse.json({ error: firstTranslatableIssueKey(err) }, { status: 400 });
212
+ return NextResponse.json({ error: translate(firstTranslatableIssueKey(err), "Invalid input") }, { status: 400 });
212
213
  }
213
214
  logger.error("warranty_claims.return-label.post failed", { err });
214
- return NextResponse.json({ error: "warranty_claims.errors.save_failed" }, { status: 500 });
215
+ return NextResponse.json({ error: translate("warranty_claims.errors.save_failed", "Failed to save warranty claim.") }, { status: 500 });
215
216
  }
216
217
  }
217
218
  const openApi = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/warranty_claims/api/return-label/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'\nimport { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { WarrantyClaim, WarrantyClaimLine } from '../../data/entities'\nimport { claimSetReturnLabelSchema, type ClaimSetReturnLabelInput } from '../../data/validators'\nimport type { WarrantyReturnLabelProvider } from '../../services/returnLabelProvider'\nimport {\n WARRANTY_CLAIM_RESOURCE_KIND,\n enforceWarrantyClaimOptimisticLock,\n requireScopedClaim,\n} from '../../commands/shared'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('warranty_claims')\n\ntype ActionRouteContext = {\n ctx: CommandRuntimeContext\n tenantId: string\n organizationId: string\n translate: (key: string, fallback?: string) => string\n}\n\ntype ReturnLabelCreatedResponse = {\n status: 'created'\n labelUrl: string | null\n trackingNumber: string | null\n carrier: string | null\n}\ntype ReturnLabelCommandResult = Omit<ReturnLabelCreatedResponse, 'status'> & { claimId: string }\n\nconst uuid = z.string().uuid()\nconst returnLabelText = (max: number) => z.string().trim().min(1).max(max).optional()\nconst optimisticLockTokenSchema = z.string().datetime().nullable().optional()\n\nconst returnLabelRequestSchema = z\n .object({\n claimId: uuid,\n manual: z.boolean().optional(),\n labelUrl: returnLabelText(2048),\n trackingNumber: returnLabelText(191),\n carrier: returnLabelText(120),\n updatedAt: optimisticLockTokenSchema,\n })\n .strict()\n\ntype ReturnLabelRequest = z.infer<typeof returnLabelRequestSchema>\n\nconst returnLabelResponseSchema = z.discriminatedUnion('status', [\n z.object({\n status: z.literal('created'),\n labelUrl: z.string().nullable(),\n trackingNumber: z.string().nullable(),\n carrier: z.string().nullable(),\n }),\n z.object({ status: z.literal('notConfigured') }),\n])\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['warranty_claims.claim.manage'] },\n}\n\nfunction translateKey(key: string): string {\n return key\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\nasync function resolveActionContext(req: Request): Promise<ActionRouteContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: 'warranty_claims.errors.unauthorized' })\n }\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = scope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, { error: 'warranty_claims.errors.organization_required' })\n }\n return {\n ctx: {\n container,\n auth,\n organizationScope: scope,\n selectedOrganizationId: organizationId,\n organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),\n request: req,\n },\n tenantId: auth.tenantId,\n organizationId,\n translate: translateKey,\n }\n}\n\nfunction toReturnLabelRequest(payload: Record<string, unknown>): ReturnLabelRequest {\n return returnLabelRequestSchema.parse({\n claimId: payload.claimId ?? payload.id,\n manual: payload.manual,\n labelUrl: payload.labelUrl,\n trackingNumber: payload.trackingNumber,\n carrier: payload.carrier,\n updatedAt: payload.updatedAt,\n })\n}\n\nfunction isManualRequest(input: ReturnLabelRequest): boolean {\n return input.manual === true\n || input.labelUrl !== undefined\n || input.trackingNumber !== undefined\n || input.carrier !== undefined\n}\n\nfunction toSetReturnLabelInput(\n input: ReturnLabelRequest,\n context: ActionRouteContext,\n): ClaimSetReturnLabelInput {\n const scopedPayload = withScopedPayload({\n id: input.claimId,\n labelUrl: input.labelUrl,\n trackingNumber: input.trackingNumber,\n carrier: input.carrier,\n updatedAt: input.updatedAt,\n }, context.ctx, context.translate)\n return claimSetReturnLabelSchema.parse(scopedPayload)\n}\n\nasync function runGuard(\n req: Request,\n context: ActionRouteContext,\n input: ReturnLabelRequest,\n): Promise<RouteMutationGuardResult> {\n const userId = context.ctx.auth?.sub\n if (!userId) {\n throw new CrudHttpError(401, { error: 'warranty_claims.errors.unauthorized' })\n }\n return runRouteMutationGuards({\n container: context.ctx.container,\n req,\n auth: {\n userId,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n },\n input: {\n resourceKind: WARRANTY_CLAIM_RESOURCE_KIND,\n resourceId: input.claimId,\n operation: 'custom',\n mutationPayload: { ...input },\n },\n })\n}\n\nasync function loadClaimAndLines(\n context: ActionRouteContext,\n claimId: string,\n): Promise<{ claim: WarrantyClaim; lines: WarrantyClaimLine[] }> {\n const scope = { tenantId: context.tenantId, organizationId: context.organizationId }\n const em = (context.ctx.container.resolve('em') as EntityManager).fork()\n const claim = await requireScopedClaim(em, claimId, scope)\n const lines = await findWithDecryption(\n em,\n WarrantyClaimLine,\n { claim: claim.id, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n {},\n scope,\n )\n return { claim, lines }\n}\n\nfunction assertGeneratableStatus(claim: WarrantyClaim): void {\n if (claim.status !== 'approved' && claim.status !== 'awaiting_return') {\n throw new CrudHttpError(400, { error: 'warranty_claims.errors.returnLabelInvalidStatus' })\n }\n}\n\nasync function executeSetReturnLabel(\n commandBus: CommandBus,\n input: ClaimSetReturnLabelInput,\n ctx: CommandRuntimeContext,\n): Promise<ReturnLabelCreatedResponse> {\n const { result } = await commandBus.execute<ClaimSetReturnLabelInput, ReturnLabelCommandResult>(\n 'warranty_claims.claim.set_return_label',\n { input, ctx },\n )\n if (!result) throw new CrudHttpError(400, { error: 'warranty_claims.errors.save_failed' })\n return {\n status: 'created',\n labelUrl: result.labelUrl,\n trackingNumber: result.trackingNumber,\n carrier: result.carrier,\n }\n}\n\nexport function firstTranslatableIssueKey(err: z.ZodError): string {\n const keyed = err.issues.find(\n (issue) => typeof issue.message === 'string' && issue.message.startsWith('warranty_claims.'),\n )?.message\n return keyed ?? 'warranty_claims.errors.invalidInput'\n}\n\nexport async function POST(req: Request) {\n try {\n const context = await resolveActionContext(req)\n const requestInput = toReturnLabelRequest(toRecord(await readJsonSafe(req, {})))\n const guarded = await runGuard(req, context, requestInput)\n if (!guarded.ok) {\n return guarded.response\n }\n const guardedInput = guarded.modifiedPayload ? toReturnLabelRequest(guarded.modifiedPayload) : requestInput\n const commandBus = context.ctx.container.resolve('commandBus') as CommandBus\n\n if (isManualRequest(guardedInput)) {\n const response = await executeSetReturnLabel(\n commandBus,\n toSetReturnLabelInput(guardedInput, context),\n context.ctx,\n )\n await guarded.runAfterSuccess()\n return NextResponse.json(response)\n }\n\n const { claim, lines } = await loadClaimAndLines(context, guardedInput.claimId)\n assertGeneratableStatus(claim)\n await enforceWarrantyClaimOptimisticLock(\n context.ctx,\n claim,\n WARRANTY_CLAIM_RESOURCE_KIND,\n guardedInput.updatedAt ?? undefined,\n )\n\n const provider = context.ctx.container.resolve<WarrantyReturnLabelProvider>('warrantyReturnLabelProvider')\n const result = await provider.createReturnLabel(\n { claim, lines },\n { tenantId: context.tenantId, organizationId: context.organizationId },\n context.ctx.container,\n )\n\n if (result.status === 'notConfigured') {\n return NextResponse.json({ status: 'notConfigured' })\n }\n\n const response = await executeSetReturnLabel(\n commandBus,\n toSetReturnLabelInput({\n ...guardedInput,\n labelUrl: result.labelUrl,\n trackingNumber: result.trackingNumber,\n carrier: result.carrier,\n }, context),\n context.ctx,\n )\n await guarded.runAfterSuccess()\n return NextResponse.json(response)\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n const interceptorRejection = getCommandInterceptorHttpRejection(err)\n if (interceptorRejection) {\n return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })\n }\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: firstTranslatableIssueKey(err) }, { status: 400 })\n }\n logger.error('warranty_claims.return-label.post failed', { err })\n return NextResponse.json({ error: 'warranty_claims.errors.save_failed' }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Warranty Claims',\n summary: 'Create or record a return label for a warranty claim',\n methods: {\n POST: {\n summary: 'Generate a carrier return label or record manual label details',\n requestBody: { contentType: 'application/json', schema: returnLabelRequestSchema },\n responses: [\n {\n status: 200,\n description: 'Return label created or provider not configured',\n schema: returnLabelResponseSchema,\n },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'\nimport { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { WarrantyClaim, WarrantyClaimLine } from '../../data/entities'\nimport { claimSetReturnLabelSchema, type ClaimSetReturnLabelInput } from '../../data/validators'\nimport type { WarrantyReturnLabelProvider } from '../../services/returnLabelProvider'\nimport {\n WARRANTY_CLAIM_RESOURCE_KIND,\n enforceWarrantyClaimOptimisticLock,\n requireScopedClaim,\n} from '../../commands/shared'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('warranty_claims')\n\ntype ActionRouteContext = {\n ctx: CommandRuntimeContext\n tenantId: string\n organizationId: string\n translate: (key: string, fallback?: string) => string\n}\n\ntype ReturnLabelCreatedResponse = {\n status: 'created'\n labelUrl: string | null\n trackingNumber: string | null\n carrier: string | null\n}\ntype ReturnLabelCommandResult = Omit<ReturnLabelCreatedResponse, 'status'> & { claimId: string }\n\nconst uuid = z.string().uuid()\nconst returnLabelText = (max: number) => z.string().trim().min(1).max(max).optional()\nconst optimisticLockTokenSchema = z.string().datetime().nullable().optional()\n\nconst returnLabelRequestSchema = z\n .object({\n claimId: uuid,\n manual: z.boolean().optional(),\n labelUrl: returnLabelText(2048),\n trackingNumber: returnLabelText(191),\n carrier: returnLabelText(120),\n updatedAt: optimisticLockTokenSchema,\n })\n .strict()\n\ntype ReturnLabelRequest = z.infer<typeof returnLabelRequestSchema>\n\nconst returnLabelResponseSchema = z.discriminatedUnion('status', [\n z.object({\n status: z.literal('created'),\n labelUrl: z.string().nullable(),\n trackingNumber: z.string().nullable(),\n carrier: z.string().nullable(),\n }),\n z.object({ status: z.literal('notConfigured') }),\n])\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['warranty_claims.claim.manage'] },\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\nasync function resolveActionContext(\n req: Request,\n translate: ActionRouteContext['translate'],\n): Promise<ActionRouteContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: translate('warranty_claims.errors.unauthorized', 'Unauthorized') })\n }\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = scope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, { error: translate('warranty_claims.errors.organization_required', 'Organization context is required.') })\n }\n return {\n ctx: {\n container,\n auth,\n organizationScope: scope,\n selectedOrganizationId: organizationId,\n organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),\n request: req,\n },\n tenantId: auth.tenantId,\n organizationId,\n translate,\n }\n}\n\nfunction toReturnLabelRequest(payload: Record<string, unknown>): ReturnLabelRequest {\n return returnLabelRequestSchema.parse({\n claimId: payload.claimId ?? payload.id,\n manual: payload.manual,\n labelUrl: payload.labelUrl,\n trackingNumber: payload.trackingNumber,\n carrier: payload.carrier,\n updatedAt: payload.updatedAt,\n })\n}\n\nfunction isManualRequest(input: ReturnLabelRequest): boolean {\n return input.manual === true\n || input.labelUrl !== undefined\n || input.trackingNumber !== undefined\n || input.carrier !== undefined\n}\n\nfunction toSetReturnLabelInput(\n input: ReturnLabelRequest,\n context: ActionRouteContext,\n): ClaimSetReturnLabelInput {\n const scopedPayload = withScopedPayload({\n id: input.claimId,\n labelUrl: input.labelUrl,\n trackingNumber: input.trackingNumber,\n carrier: input.carrier,\n updatedAt: input.updatedAt,\n }, context.ctx, context.translate)\n return claimSetReturnLabelSchema.parse(scopedPayload)\n}\n\nasync function runGuard(\n req: Request,\n context: ActionRouteContext,\n input: ReturnLabelRequest,\n): Promise<RouteMutationGuardResult> {\n const userId = context.ctx.auth?.sub\n if (!userId) {\n throw new CrudHttpError(401, { error: context.translate('warranty_claims.errors.unauthorized', 'Unauthorized') })\n }\n return runRouteMutationGuards({\n container: context.ctx.container,\n req,\n auth: {\n userId,\n tenantId: context.tenantId,\n organizationId: context.organizationId,\n },\n input: {\n resourceKind: WARRANTY_CLAIM_RESOURCE_KIND,\n resourceId: input.claimId,\n operation: 'custom',\n mutationPayload: { ...input },\n },\n })\n}\n\nasync function loadClaimAndLines(\n context: ActionRouteContext,\n claimId: string,\n): Promise<{ claim: WarrantyClaim; lines: WarrantyClaimLine[] }> {\n const scope = { tenantId: context.tenantId, organizationId: context.organizationId }\n const em = (context.ctx.container.resolve('em') as EntityManager).fork()\n const claim = await requireScopedClaim(em, claimId, scope, {}, context.translate('warranty_claims.errors.notFound', 'Claim not found.'))\n const lines = await findWithDecryption(\n em,\n WarrantyClaimLine,\n { claim: claim.id, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n {},\n scope,\n )\n return { claim, lines }\n}\n\nfunction assertGeneratableStatus(claim: WarrantyClaim, translate: ActionRouteContext['translate']): void {\n if (claim.status !== 'approved' && claim.status !== 'awaiting_return') {\n throw new CrudHttpError(400, { error: translate('warranty_claims.errors.returnLabelInvalidStatus', 'Return labels can only be created for approved claims that are awaiting return.') })\n }\n}\n\nasync function executeSetReturnLabel(\n commandBus: CommandBus,\n input: ClaimSetReturnLabelInput,\n ctx: CommandRuntimeContext,\n translate: ActionRouteContext['translate'],\n): Promise<ReturnLabelCreatedResponse> {\n const { result } = await commandBus.execute<ClaimSetReturnLabelInput, ReturnLabelCommandResult>(\n 'warranty_claims.claim.set_return_label',\n { input, ctx },\n )\n if (!result) throw new CrudHttpError(400, { error: translate('warranty_claims.errors.save_failed', 'Failed to save warranty claim.') })\n return {\n status: 'created',\n labelUrl: result.labelUrl,\n trackingNumber: result.trackingNumber,\n carrier: result.carrier,\n }\n}\n\nexport function firstTranslatableIssueKey(err: z.ZodError): string {\n const keyed = err.issues.find(\n (issue) => typeof issue.message === 'string' && issue.message.startsWith('warranty_claims.'),\n )?.message\n return keyed ?? 'warranty_claims.errors.invalidInput'\n}\n\nexport async function POST(req: Request) {\n const { translate } = await resolveTranslations()\n try {\n const context = await resolveActionContext(req, translate)\n const requestInput = toReturnLabelRequest(toRecord(await readJsonSafe(req, {})))\n const guarded = await runGuard(req, context, requestInput)\n if (!guarded.ok) {\n return guarded.response\n }\n const guardedInput = guarded.modifiedPayload ? toReturnLabelRequest(guarded.modifiedPayload) : requestInput\n const commandBus = context.ctx.container.resolve('commandBus') as CommandBus\n\n if (isManualRequest(guardedInput)) {\n const response = await executeSetReturnLabel(\n commandBus,\n toSetReturnLabelInput(guardedInput, context),\n context.ctx,\n translate,\n )\n await guarded.runAfterSuccess()\n return NextResponse.json(response)\n }\n\n const { claim, lines } = await loadClaimAndLines(context, guardedInput.claimId)\n assertGeneratableStatus(claim, translate)\n await enforceWarrantyClaimOptimisticLock(\n context.ctx,\n claim,\n WARRANTY_CLAIM_RESOURCE_KIND,\n guardedInput.updatedAt ?? undefined,\n )\n\n const provider = context.ctx.container.resolve<WarrantyReturnLabelProvider>('warrantyReturnLabelProvider')\n const result = await provider.createReturnLabel(\n { claim, lines },\n { tenantId: context.tenantId, organizationId: context.organizationId },\n context.ctx.container,\n )\n\n if (result.status === 'notConfigured') {\n return NextResponse.json({ status: 'notConfigured' })\n }\n\n const response = await executeSetReturnLabel(\n commandBus,\n toSetReturnLabelInput({\n ...guardedInput,\n labelUrl: result.labelUrl,\n trackingNumber: result.trackingNumber,\n carrier: result.carrier,\n }, context),\n context.ctx,\n translate,\n )\n await guarded.runAfterSuccess()\n return NextResponse.json(response)\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n const interceptorRejection = getCommandInterceptorHttpRejection(err)\n if (interceptorRejection) {\n return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })\n }\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: translate(firstTranslatableIssueKey(err), 'Invalid input') }, { status: 400 })\n }\n logger.error('warranty_claims.return-label.post failed', { err })\n return NextResponse.json({ error: translate('warranty_claims.errors.save_failed', 'Failed to save warranty claim.') }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Warranty Claims',\n summary: 'Create or record a return label for a warranty claim',\n methods: {\n POST: {\n summary: 'Generate a carrier return label or record manual label details',\n requestBody: { contentType: 'application/json', schema: returnLabelRequestSchema },\n responses: [\n {\n status: 200,\n description: 'Return label created or provider not configured',\n schema: returnLabelResponseSchema,\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["response"]
7
7
  }
@@ -48,6 +48,7 @@ async function resolveRiskContext(req) {
48
48
  tenantId: auth.tenantId,
49
49
  organizationId,
50
50
  scope: { tenantId: auth.tenantId, organizationId },
51
+ translate,
51
52
  em
52
53
  };
53
54
  }
@@ -56,7 +57,7 @@ async function GET(req) {
56
57
  const context = await resolveRiskContext(req);
57
58
  const url = new URL(req.url);
58
59
  const query = querySchema.parse(Object.fromEntries(url.searchParams));
59
- const claim = await requireScopedClaim(context.em, query.claimId, context.scope);
60
+ const claim = await requireScopedClaim(context.em, query.claimId, context.scope, {}, context.translate("warranty_claims.errors.notFound", "Claim not found."));
60
61
  const lines = await findWithDecryption(
61
62
  context.em,
62
63
  WarrantyClaimLine,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/warranty_claims/api/risk/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { WarrantyClaimLine } from '../../data/entities'\nimport { requireScopedClaim, type WarrantyClaimScope } from '../../commands/shared'\nimport { evaluateClaimRisk } from '../../lib/risk'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('warranty_claims')\n\nconst querySchema = z.object({\n claimId: z.string().uuid(),\n}).strict()\n\nconst riskSignalSchema = z.object({\n id: z.enum(['duplicate_serial', 'duplicate_order_claim', 'outside_return_window', 'over_quantity_claim', 'repeat_claimer', 'value_velocity']),\n level: z.enum(['low', 'medium', 'high']),\n messageKey: z.string(),\n params: z.record(z.string(), z.union([z.string(), z.number()])).optional(),\n relatedClaimNumbers: z.array(z.string()).optional(),\n})\n\nconst responseSchema = z.object({\n ok: z.literal(true),\n result: z.object({\n level: z.enum(['none', 'low', 'medium', 'high']),\n signals: z.array(riskSignalSchema),\n }),\n})\n\ntype RiskRouteContext = {\n tenantId: string\n organizationId: string\n scope: WarrantyClaimScope\n em: EntityManager\n}\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['warranty_claims.claim.view'] },\n}\n\nasync function resolveRiskContext(req: Request): Promise<RiskRouteContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n const { translate } = await resolveTranslations()\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: translate('warranty_claims.errors.unauthorized', 'Unauthorized') })\n }\n const organizationScope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = organizationScope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, { error: translate('warranty_claims.errors.organization_required', 'Organization context is required') })\n }\n const em = container.resolve('em') as EntityManager\n return {\n tenantId: auth.tenantId,\n organizationId,\n scope: { tenantId: auth.tenantId, organizationId },\n em,\n }\n}\n\nexport async function GET(req: Request) {\n try {\n const context = await resolveRiskContext(req)\n const url = new URL(req.url)\n const query = querySchema.parse(Object.fromEntries(url.searchParams))\n const claim = await requireScopedClaim(context.em, query.claimId, context.scope)\n const lines = await findWithDecryption(\n context.em,\n WarrantyClaimLine,\n { claim: claim.id, tenantId: context.tenantId, organizationId: context.organizationId, deletedAt: null },\n { orderBy: { lineNo: 'ASC' } },\n context.scope,\n )\n const result = await evaluateClaimRisk(context.em, claim, lines)\n return NextResponse.json({ ok: true, result })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n const { translate } = await resolveTranslations()\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })\n }\n logger.error('warranty_claims.risk.get failed', { err })\n return NextResponse.json({ error: translate('warranty_claims.errors.load_failed', 'Failed to load warranty claim data') }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Warranty Claims',\n summary: 'Evaluate warranty claim risk',\n methods: {\n GET: {\n summary: 'Evaluate deterministic risk signals for a claim',\n query: querySchema,\n responses: [\n {\n status: 200,\n description: 'Risk assessment',\n schema: responseSchema,\n },\n ],\n },\n },\n}\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC,SAAS,0CAA0C;AACnD,SAAS,eAAe,uBAAuB;AAC/C,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;AAEpC,SAAS,yBAAyB;AAClC,SAAS,0BAAmD;AAC5D,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,iBAAiB;AAE7C,MAAM,cAAc,EAAE,OAAO;AAAA,EAC3B,SAAS,EAAE,OAAO,EAAE,KAAK;AAC3B,CAAC,EAAE,OAAO;AAEV,MAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,IAAI,EAAE,KAAK,CAAC,oBAAoB,yBAAyB,yBAAyB,uBAAuB,kBAAkB,gBAAgB,CAAC;AAAA,EAC5I,OAAO,EAAE,KAAK,CAAC,OAAO,UAAU,MAAM,CAAC;AAAA,EACvC,YAAY,EAAE,OAAO;AAAA,EACrB,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA,EACzE,qBAAqB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AACpD,CAAC;AAED,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,IAAI,EAAE,QAAQ,IAAI;AAAA,EAClB,QAAQ,EAAE,OAAO;AAAA,IACf,OAAO,EAAE,KAAK,CAAC,QAAQ,OAAO,UAAU,MAAM,CAAC;AAAA,IAC/C,SAAS,EAAE,MAAM,gBAAgB;AAAA,EACnC,CAAC;AACH,CAAC;AASM,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,4BAA4B,EAAE;AAC5E;AAEA,eAAe,mBAAmB,KAAyC;AACzE,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,QAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,MAAI,CAAC,QAAQ,CAAC,KAAK,UAAU;AAC3B,UAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,uCAAuC,cAAc,EAAE,CAAC;AAAA,EAC1G;AACA,QAAM,oBAAoB,MAAM,mCAAmC,EAAE,WAAW,MAAM,SAAS,IAAI,CAAC;AACpG,QAAM,iBAAiB,mBAAmB,cAAc,KAAK,SAAS;AACtE,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,gDAAgD,kCAAkC,EAAE,CAAC;AAAA,EACvI;AACA,QAAM,KAAK,UAAU,QAAQ,IAAI;AACjC,SAAO;AAAA,IACL,UAAU,KAAK;AAAA,IACf;AAAA,IACA,OAAO,EAAE,UAAU,KAAK,UAAU,eAAe;AAAA,IACjD;AAAA,EACF;AACF;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,UAAU,MAAM,mBAAmB,GAAG;AAC5C,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,QAAQ,YAAY,MAAM,OAAO,YAAY,IAAI,YAAY,CAAC;AACpE,UAAM,QAAQ,MAAM,mBAAmB,QAAQ,IAAI,MAAM,SAAS,QAAQ,KAAK;AAC/E,UAAM,QAAQ,MAAM;AAAA,MAClB,QAAQ;AAAA,MACR;AAAA,MACA,EAAE,OAAO,MAAM,IAAI,UAAU,QAAQ,UAAU,gBAAgB,QAAQ,gBAAgB,WAAW,KAAK;AAAA,MACvG,EAAE,SAAS,EAAE,QAAQ,MAAM,EAAE;AAAA,MAC7B,QAAQ;AAAA,IACV;AACA,UAAM,SAAS,MAAM,kBAAkB,QAAQ,IAAI,OAAO,KAAK;AAC/D,WAAO,aAAa,KAAK,EAAE,IAAI,MAAM,OAAO,CAAC;AAAA,EAC/C,SAAS,KAAK;AACZ,QAAI,gBAAgB,GAAG,EAAG,QAAO,aAAa,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC;AACnF,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,QAAI,eAAe,EAAE,UAAU;AAC7B,aAAO,aAAa,KAAK,EAAE,OAAO,UAAU,uCAAuC,eAAe,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACxH;AACA,WAAO,MAAM,mCAAmC,EAAE,IAAI,CAAC;AACvD,WAAO,aAAa,KAAK,EAAE,OAAO,UAAU,sCAAsC,oCAAoC,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC5I;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,OAAO;AAAA,MACP,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { WarrantyClaimLine } from '../../data/entities'\nimport { requireScopedClaim, type WarrantyClaimScope } from '../../commands/shared'\nimport { evaluateClaimRisk } from '../../lib/risk'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('warranty_claims')\n\nconst querySchema = z.object({\n claimId: z.string().uuid(),\n}).strict()\n\nconst riskSignalSchema = z.object({\n id: z.enum(['duplicate_serial', 'duplicate_order_claim', 'outside_return_window', 'over_quantity_claim', 'repeat_claimer', 'value_velocity']),\n level: z.enum(['low', 'medium', 'high']),\n messageKey: z.string(),\n params: z.record(z.string(), z.union([z.string(), z.number()])).optional(),\n relatedClaimNumbers: z.array(z.string()).optional(),\n})\n\nconst responseSchema = z.object({\n ok: z.literal(true),\n result: z.object({\n level: z.enum(['none', 'low', 'medium', 'high']),\n signals: z.array(riskSignalSchema),\n }),\n})\n\ntype RiskRouteContext = {\n tenantId: string\n organizationId: string\n scope: WarrantyClaimScope\n translate: (key: string, fallback?: string) => string\n em: EntityManager\n}\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['warranty_claims.claim.view'] },\n}\n\nasync function resolveRiskContext(req: Request): Promise<RiskRouteContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n const { translate } = await resolveTranslations()\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: translate('warranty_claims.errors.unauthorized', 'Unauthorized') })\n }\n const organizationScope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = organizationScope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, { error: translate('warranty_claims.errors.organization_required', 'Organization context is required') })\n }\n const em = container.resolve('em') as EntityManager\n return {\n tenantId: auth.tenantId,\n organizationId,\n scope: { tenantId: auth.tenantId, organizationId },\n translate,\n em,\n }\n}\n\nexport async function GET(req: Request) {\n try {\n const context = await resolveRiskContext(req)\n const url = new URL(req.url)\n const query = querySchema.parse(Object.fromEntries(url.searchParams))\n const claim = await requireScopedClaim(context.em, query.claimId, context.scope, {}, context.translate('warranty_claims.errors.notFound', 'Claim not found.'))\n const lines = await findWithDecryption(\n context.em,\n WarrantyClaimLine,\n { claim: claim.id, tenantId: context.tenantId, organizationId: context.organizationId, deletedAt: null },\n { orderBy: { lineNo: 'ASC' } },\n context.scope,\n )\n const result = await evaluateClaimRisk(context.em, claim, lines)\n return NextResponse.json({ ok: true, result })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n const { translate } = await resolveTranslations()\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })\n }\n logger.error('warranty_claims.risk.get failed', { err })\n return NextResponse.json({ error: translate('warranty_claims.errors.load_failed', 'Failed to load warranty claim data') }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Warranty Claims',\n summary: 'Evaluate warranty claim risk',\n methods: {\n GET: {\n summary: 'Evaluate deterministic risk signals for a claim',\n query: querySchema,\n responses: [\n {\n status: 200,\n description: 'Risk assessment',\n schema: responseSchema,\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }