@open-mercato/core 0.9.1-develop.7499.1.fcec456e4e → 0.9.1-develop.7515.1.e2712c8b00

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 (89) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/audit_logs/components/AuditLogsActions.js +1 -1
  3. package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
  4. package/dist/modules/auth/frontend/reset.js +7 -3
  5. package/dist/modules/auth/frontend/reset.js.map +2 -2
  6. package/dist/modules/business_rules/api/rules/route.js +12 -1
  7. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  8. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +17 -2
  9. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  10. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +3 -2
  11. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  12. package/dist/modules/catalog/backend/catalog/products/create/page.js +1 -0
  13. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  14. package/dist/modules/catalog/components/products/productFormUtils.js +9 -0
  15. package/dist/modules/catalog/components/products/productFormUtils.js.map +2 -2
  16. package/dist/modules/customers/backend/customers/companies/page.js +32 -32
  17. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  18. package/dist/modules/customers/backend/customers/deals/page.js +22 -22
  19. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  20. package/dist/modules/customers/backend/customers/people/page.js +34 -34
  21. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  22. package/dist/modules/ecommerce/search.js +1 -2
  23. package/dist/modules/ecommerce/search.js.map +2 -2
  24. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +4 -7
  25. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
  26. package/dist/modules/shipping_carriers/lib/shipping-service.js +29 -11
  27. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
  28. package/dist/modules/shipping_carriers/lib/status-sync.js +2 -2
  29. package/dist/modules/shipping_carriers/lib/status-sync.js.map +2 -2
  30. package/dist/modules/shipping_carriers/workers/webhook-processor.js +60 -33
  31. package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +3 -3
  32. package/dist/modules/staff/backend/staff/time-tracking/entries/page.js +10 -7
  33. package/dist/modules/staff/backend/staff/time-tracking/entries/page.js.map +2 -2
  34. package/dist/modules/warranty_claims/commands/claim-lines.js +89 -68
  35. package/dist/modules/warranty_claims/commands/claim-lines.js.map +2 -2
  36. package/dist/modules/warranty_claims/commands/claims.js +14 -13
  37. package/dist/modules/warranty_claims/commands/claims.js.map +2 -2
  38. package/dist/modules/warranty_claims/commands/shared.js +8 -2
  39. package/dist/modules/warranty_claims/commands/shared.js.map +2 -2
  40. package/dist/modules/wms/api/interceptors.js +3 -0
  41. package/dist/modules/wms/api/interceptors.js.map +2 -2
  42. package/dist/modules/wms/commands/configuration.js +16 -16
  43. package/dist/modules/wms/commands/configuration.js.map +2 -2
  44. package/dist/modules/wms/events.js +1 -0
  45. package/dist/modules/wms/events.js.map +2 -2
  46. package/dist/modules/wms/lib/catalogInventoryProfileIntent.js +9 -0
  47. package/dist/modules/wms/lib/catalogInventoryProfileIntent.js.map +2 -2
  48. package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js +11 -3
  49. package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js.map +2 -2
  50. package/package.json +7 -7
  51. package/src/modules/audit_logs/components/AuditLogsActions.tsx +1 -1
  52. package/src/modules/auth/frontend/reset.tsx +8 -3
  53. package/src/modules/business_rules/api/rules/route.ts +11 -0
  54. package/src/modules/business_rules/i18n/de.json +1 -0
  55. package/src/modules/business_rules/i18n/en.json +1 -0
  56. package/src/modules/business_rules/i18n/es.json +1 -0
  57. package/src/modules/business_rules/i18n/ko.json +1 -0
  58. package/src/modules/business_rules/i18n/pl.json +1 -0
  59. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +20 -1
  60. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +2 -1
  61. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1 -0
  62. package/src/modules/catalog/components/products/productFormUtils.ts +9 -0
  63. package/src/modules/customers/backend/customers/companies/page.tsx +32 -32
  64. package/src/modules/customers/backend/customers/deals/page.tsx +22 -22
  65. package/src/modules/customers/backend/customers/people/page.tsx +34 -34
  66. package/src/modules/customers/i18n/de.json +12 -0
  67. package/src/modules/customers/i18n/en.json +12 -0
  68. package/src/modules/customers/i18n/es.json +12 -0
  69. package/src/modules/customers/i18n/ko.json +12 -0
  70. package/src/modules/customers/i18n/pl.json +12 -0
  71. package/src/modules/ecommerce/i18n/de.json +2 -1
  72. package/src/modules/ecommerce/i18n/en.json +2 -1
  73. package/src/modules/ecommerce/i18n/es.json +2 -1
  74. package/src/modules/ecommerce/i18n/ko.json +2 -1
  75. package/src/modules/ecommerce/i18n/pl.json +2 -1
  76. package/src/modules/ecommerce/search.ts +0 -1
  77. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +4 -7
  78. package/src/modules/shipping_carriers/lib/shipping-service.ts +29 -11
  79. package/src/modules/shipping_carriers/lib/status-sync.ts +2 -2
  80. package/src/modules/shipping_carriers/workers/webhook-processor.ts +71 -39
  81. package/src/modules/staff/backend/staff/time-tracking/entries/page.tsx +20 -14
  82. package/src/modules/warranty_claims/commands/claim-lines.ts +107 -66
  83. package/src/modules/warranty_claims/commands/claims.ts +14 -13
  84. package/src/modules/warranty_claims/commands/shared.ts +7 -1
  85. package/src/modules/wms/api/interceptors.ts +9 -0
  86. package/src/modules/wms/commands/configuration.ts +28 -16
  87. package/src/modules/wms/events.ts +1 -0
  88. package/src/modules/wms/lib/catalogInventoryProfileIntent.ts +9 -0
  89. package/src/modules/wms/widgets/injection/catalog-inventory-profile/widget.ts +13 -4
@@ -1,10 +1,11 @@
1
1
  import { randomUUID } from "crypto";
2
- import { assertFound } from "@open-mercato/shared/lib/crud/errors";
2
+ import { CrudHttpError, assertFound } from "@open-mercato/shared/lib/crud/errors";
3
3
  import { invalidateCrudCache } from "@open-mercato/shared/lib/crud/cache";
4
4
  import { enforceCommandOptimisticLockWithGuards } from "@open-mercato/shared/lib/crud/optimistic-lock-command";
5
5
  import { withAtomicFlush } from "@open-mercato/shared/lib/commands/flush";
6
6
  import { emitCrudSideEffects, flushCrudSideEffects } from "@open-mercato/shared/lib/commands/helpers";
7
7
  import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
8
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
8
9
  import {
9
10
  WarrantyClaim,
10
11
  WarrantyClaimEvent,
@@ -26,6 +27,10 @@ async function enforceWarrantyClaimOptimisticLock(ctx, record, resourceKind = WA
26
27
  request: ctx.request ?? null
27
28
  });
28
29
  }
30
+ async function throwUndoRefusal(key, fallback) {
31
+ const { translate } = await resolveTranslations();
32
+ throw new CrudHttpError(409, { error: translate(key, fallback), code: key });
33
+ }
29
34
  async function loadScopedClaim(em, id, scope, options = {}) {
30
35
  return findOneWithDecryption(
31
36
  em,
@@ -157,6 +162,7 @@ export {
157
162
  extractUndoPayload,
158
163
  loadScopedClaim,
159
164
  reconcileVendorRecoverySourceClaim,
160
- requireScopedClaim
165
+ requireScopedClaim,
166
+ throwUndoRefusal
161
167
  };
162
168
  //# sourceMappingURL=shared.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/warranty_claims/commands/shared.ts"],
4
- "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { FindOneOptions } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { assertFound } from '@open-mercato/shared/lib/crud/errors'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { emitCrudSideEffects, flushCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport {\n WarrantyClaim,\n WarrantyClaimEvent,\n WarrantyClaimLine,\n} from '../data/entities'\nimport type {\n WarrantyClaimEventKind,\n WarrantyClaimEventVisibility,\n} from '../data/validators'\nimport { computeHeaderRollups } from '../lib/stateMachine'\n\nexport { assertFound } from '@open-mercato/shared/lib/crud/errors'\nexport { ensureOrganizationScope, ensureSameScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nexport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\n\nexport const WARRANTY_CLAIM_RESOURCE_KIND = 'warranty_claims.claim'\nexport const WARRANTY_CLAIM_LINE_RESOURCE_KIND = 'warranty_claims.claim_line'\n\nexport type WarrantyClaimScope = {\n organizationId: string\n tenantId: string\n}\n\nexport type VersionedRecord = {\n id: string\n updatedAt?: Date | string | null\n}\n\nexport type ResolverContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport type AppendClaimEventInput = {\n visibility?: WarrantyClaimEventVisibility\n body?: string | null\n payload?: Record<string, unknown> | null\n actorUserId?: string | null\n actorCustomerId?: string | null\n}\n\nexport async function enforceWarrantyClaimOptimisticLock(\n ctx: CommandRuntimeContext,\n record: VersionedRecord | null | undefined,\n resourceKind = WARRANTY_CLAIM_RESOURCE_KIND,\n expected?: string | Date | null,\n): Promise<void> {\n if (!record) return\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind,\n resourceId: record.id,\n current: record.updatedAt ?? null,\n expected,\n request: ctx.request ?? null,\n })\n}\n\nexport async function loadScopedClaim(\n em: EntityManager,\n id: string,\n scope: WarrantyClaimScope,\n options: FindOneOptions<WarrantyClaim> = {},\n): Promise<WarrantyClaim | null> {\n return findOneWithDecryption(\n em,\n WarrantyClaim,\n { id, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n options,\n scope,\n )\n}\n\n/**\n * `notFoundMessage` is passed to `assertFound` verbatim, so request-scoped callers\n * must hand in an already-translated sentence; the key default only suits the\n * command surface, which runs without a request locale.\n */\nexport async function requireScopedClaim(\n em: EntityManager,\n id: string,\n scope: WarrantyClaimScope,\n options: FindOneOptions<WarrantyClaim> = {},\n notFoundMessage = 'warranty_claims.errors.notFound',\n): Promise<WarrantyClaim> {\n const claim = await loadScopedClaim(em, id, scope, options)\n return assertFound(claim, notFoundMessage)\n}\n\nexport function appendClaimEvent(\n em: EntityManager,\n claim: WarrantyClaim,\n kind: WarrantyClaimEventKind,\n input: AppendClaimEventInput = {},\n): WarrantyClaimEvent {\n const event = em.create(WarrantyClaimEvent, {\n id: randomUUID(),\n claim,\n organizationId: claim.organizationId,\n tenantId: claim.tenantId,\n kind,\n visibility: input.visibility ?? 'internal',\n body: input.body ?? null,\n payload: input.payload ?? null,\n actorUserId: input.actorUserId ?? null,\n actorCustomerId: input.actorCustomerId ?? null,\n createdAt: new Date(),\n })\n em.persist(event)\n return event\n}\n\nexport async function reconcileVendorRecoverySourceClaim(\n ctx: ResolverContext,\n input: { claimId: string; tenantId: string; organizationId: string },\n): Promise<void> {\n const em = (ctx.resolve('em') as EntityManager).fork()\n const scope = { tenantId: input.tenantId, organizationId: input.organizationId }\n const recoveryClaim = await findOneWithDecryption(\n em,\n WarrantyClaim,\n { id: input.claimId, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n {},\n scope,\n )\n if (!recoveryClaim || recoveryClaim.claimType !== 'vendor_recovery' || !recoveryClaim.sourceClaimId) return\n\n const sourceClaim = await findOneWithDecryption(\n em,\n WarrantyClaim,\n { id: recoveryClaim.sourceClaimId, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n {},\n scope,\n )\n if (!sourceClaim) return\n\n const resolvedChildren = await findWithDecryption(\n em,\n WarrantyClaim,\n {\n sourceClaimId: sourceClaim.id,\n claimType: 'vendor_recovery',\n status: { $in: ['resolved', 'closed'] },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {},\n scope,\n )\n const childLines = resolvedChildren.length\n ? await findWithDecryption(\n em,\n WarrantyClaimLine,\n {\n claim: { $in: resolvedChildren.map((child) => child.id) },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {},\n scope,\n )\n : []\n const recoveredTotal = computeHeaderRollups(childLines).totalApprovedAmount\n await withAtomicFlush(\n em,\n [\n () => {\n sourceClaim.totalRecoveredAmount = String(recoveredTotal)\n sourceClaim.updatedAt = new Date()\n },\n ],\n { transaction: true, label: 'warranty_claims.vendor_recovery.reconciliation' },\n )\n\n const dataEngine = ctx.resolve<DataEngine>('dataEngine')\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: sourceClaim,\n identifiers: {\n id: sourceClaim.id,\n organizationId: sourceClaim.organizationId,\n tenantId: sourceClaim.tenantId,\n },\n indexer: { entityType: 'warranty_claims:warranty_claim' },\n events: {\n module: 'warranty_claims',\n entity: 'claim',\n persistent: true,\n buildPayload: () => ({\n id: sourceClaim.id,\n organizationId: sourceClaim.organizationId,\n tenantId: sourceClaim.tenantId,\n claimType: sourceClaim.claimType,\n status: sourceClaim.status,\n }),\n },\n })\n await flushCrudSideEffects(dataEngine)\n await invalidateCrudCache(\n ctx as unknown as Parameters<typeof invalidateCrudCache>[0],\n 'warranty_claims.claim',\n { id: sourceClaim.id, organizationId: sourceClaim.organizationId, tenantId: sourceClaim.tenantId },\n input.tenantId,\n 'warranty_claims.vendor_recovery.reconciliation',\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { FindOneOptions } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError, assertFound } from '@open-mercato/shared/lib/crud/errors'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { emitCrudSideEffects, flushCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n WarrantyClaim,\n WarrantyClaimEvent,\n WarrantyClaimLine,\n} from '../data/entities'\nimport type {\n WarrantyClaimEventKind,\n WarrantyClaimEventVisibility,\n} from '../data/validators'\nimport { computeHeaderRollups } from '../lib/stateMachine'\n\nexport { assertFound } from '@open-mercato/shared/lib/crud/errors'\nexport { ensureOrganizationScope, ensureSameScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nexport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\n\nexport const WARRANTY_CLAIM_RESOURCE_KIND = 'warranty_claims.claim'\nexport const WARRANTY_CLAIM_LINE_RESOURCE_KIND = 'warranty_claims.claim_line'\n\nexport type WarrantyClaimScope = {\n organizationId: string\n tenantId: string\n}\n\nexport type VersionedRecord = {\n id: string\n updatedAt?: Date | string | null\n}\n\nexport type ResolverContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport type AppendClaimEventInput = {\n visibility?: WarrantyClaimEventVisibility\n body?: string | null\n payload?: Record<string, unknown> | null\n actorUserId?: string | null\n actorCustomerId?: string | null\n}\n\nexport async function enforceWarrantyClaimOptimisticLock(\n ctx: CommandRuntimeContext,\n record: VersionedRecord | null | undefined,\n resourceKind = WARRANTY_CLAIM_RESOURCE_KIND,\n expected?: string | Date | null,\n): Promise<void> {\n if (!record) return\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind,\n resourceId: record.id,\n current: record.updatedAt ?? null,\n expected,\n request: ctx.request ?? null,\n })\n}\n\nexport async function throwUndoRefusal(key: string, fallback: string): Promise<never> {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, { error: translate(key, fallback), code: key })\n}\n\nexport async function loadScopedClaim(\n em: EntityManager,\n id: string,\n scope: WarrantyClaimScope,\n options: FindOneOptions<WarrantyClaim> = {},\n): Promise<WarrantyClaim | null> {\n return findOneWithDecryption(\n em,\n WarrantyClaim,\n { id, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n options,\n scope,\n )\n}\n\n/**\n * `notFoundMessage` is passed to `assertFound` verbatim, so request-scoped callers\n * must hand in an already-translated sentence; the key default only suits the\n * command surface, which runs without a request locale.\n */\nexport async function requireScopedClaim(\n em: EntityManager,\n id: string,\n scope: WarrantyClaimScope,\n options: FindOneOptions<WarrantyClaim> = {},\n notFoundMessage = 'warranty_claims.errors.notFound',\n): Promise<WarrantyClaim> {\n const claim = await loadScopedClaim(em, id, scope, options)\n return assertFound(claim, notFoundMessage)\n}\n\nexport function appendClaimEvent(\n em: EntityManager,\n claim: WarrantyClaim,\n kind: WarrantyClaimEventKind,\n input: AppendClaimEventInput = {},\n): WarrantyClaimEvent {\n const event = em.create(WarrantyClaimEvent, {\n id: randomUUID(),\n claim,\n organizationId: claim.organizationId,\n tenantId: claim.tenantId,\n kind,\n visibility: input.visibility ?? 'internal',\n body: input.body ?? null,\n payload: input.payload ?? null,\n actorUserId: input.actorUserId ?? null,\n actorCustomerId: input.actorCustomerId ?? null,\n createdAt: new Date(),\n })\n em.persist(event)\n return event\n}\n\nexport async function reconcileVendorRecoverySourceClaim(\n ctx: ResolverContext,\n input: { claimId: string; tenantId: string; organizationId: string },\n): Promise<void> {\n const em = (ctx.resolve('em') as EntityManager).fork()\n const scope = { tenantId: input.tenantId, organizationId: input.organizationId }\n const recoveryClaim = await findOneWithDecryption(\n em,\n WarrantyClaim,\n { id: input.claimId, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n {},\n scope,\n )\n if (!recoveryClaim || recoveryClaim.claimType !== 'vendor_recovery' || !recoveryClaim.sourceClaimId) return\n\n const sourceClaim = await findOneWithDecryption(\n em,\n WarrantyClaim,\n { id: recoveryClaim.sourceClaimId, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n {},\n scope,\n )\n if (!sourceClaim) return\n\n const resolvedChildren = await findWithDecryption(\n em,\n WarrantyClaim,\n {\n sourceClaimId: sourceClaim.id,\n claimType: 'vendor_recovery',\n status: { $in: ['resolved', 'closed'] },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {},\n scope,\n )\n const childLines = resolvedChildren.length\n ? await findWithDecryption(\n em,\n WarrantyClaimLine,\n {\n claim: { $in: resolvedChildren.map((child) => child.id) },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n {},\n scope,\n )\n : []\n const recoveredTotal = computeHeaderRollups(childLines).totalApprovedAmount\n await withAtomicFlush(\n em,\n [\n () => {\n sourceClaim.totalRecoveredAmount = String(recoveredTotal)\n sourceClaim.updatedAt = new Date()\n },\n ],\n { transaction: true, label: 'warranty_claims.vendor_recovery.reconciliation' },\n )\n\n const dataEngine = ctx.resolve<DataEngine>('dataEngine')\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: sourceClaim,\n identifiers: {\n id: sourceClaim.id,\n organizationId: sourceClaim.organizationId,\n tenantId: sourceClaim.tenantId,\n },\n indexer: { entityType: 'warranty_claims:warranty_claim' },\n events: {\n module: 'warranty_claims',\n entity: 'claim',\n persistent: true,\n buildPayload: () => ({\n id: sourceClaim.id,\n organizationId: sourceClaim.organizationId,\n tenantId: sourceClaim.tenantId,\n claimType: sourceClaim.claimType,\n status: sourceClaim.status,\n }),\n },\n })\n await flushCrudSideEffects(dataEngine)\n await invalidateCrudCache(\n ctx as unknown as Parameters<typeof invalidateCrudCache>[0],\n 'warranty_claims.claim',\n { id: sourceClaim.id, organizationId: sourceClaim.organizationId, tenantId: sourceClaim.tenantId },\n input.tenantId,\n 'warranty_claims.vendor_recovery.reconciliation',\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["assertFound"]
7
7
  }
@@ -1,3 +1,4 @@
1
+ import { E } from "../../../generated/entities.ids.generated.js";
1
2
  import {
2
3
  decodeCatalogInventoryProfileIntent,
3
4
  WMS_CATALOG_PROFILE_HEADER
@@ -26,6 +27,7 @@ const interceptors = [
26
27
  const rawHeader = request.headers[WMS_CATALOG_PROFILE_HEADER];
27
28
  if (!rawHeader) return { ok: true };
28
29
  const intent = decodeCatalogInventoryProfileIntent(rawHeader);
30
+ if (intent?.sourceEntityId !== E.catalog.catalog_product) return { ok: true };
29
31
  return {
30
32
  ok: true,
31
33
  metadata: { intent, target: "product" }
@@ -58,6 +60,7 @@ const interceptors = [
58
60
  const rawHeader = request.headers[WMS_CATALOG_PROFILE_HEADER];
59
61
  if (!rawHeader) return { ok: true };
60
62
  const intent = decodeCatalogInventoryProfileIntent(rawHeader);
63
+ if (intent?.sourceEntityId !== E.catalog.catalog_product_variant) return { ok: true };
61
64
  return {
62
65
  ok: true,
63
66
  metadata: { intent, target: "variant" }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/wms/api/interceptors.ts"],
4
- "sourcesContent": ["import type { ApiInterceptor } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport {\n decodeCatalogInventoryProfileIntent,\n WMS_CATALOG_PROFILE_HEADER,\n} from '../lib/catalogInventoryProfileIntent'\nimport {\n syncCatalogInventoryProfile,\n} from '../lib/catalogInventoryProfileSync'\n\nfunction resolveRecordId(\n requestBody: Record<string, unknown> | undefined,\n responseBody: Record<string, unknown> | undefined,\n): string | null {\n const responseId = responseBody?.id\n if (typeof responseId === 'string' && responseId.trim().length > 0) {\n return responseId\n }\n\n const requestId = requestBody?.id\n if (typeof requestId === 'string' && requestId.trim().length > 0) {\n return requestId\n }\n\n return null\n}\n\nexport const interceptors: ApiInterceptor[] = [\n {\n id: 'wms.catalog-products.inventory-profile-sync',\n targetRoute: 'catalog/products',\n methods: ['POST', 'PUT'],\n priority: 120,\n async before(request) {\n const rawHeader = request.headers[WMS_CATALOG_PROFILE_HEADER]\n if (!rawHeader) return { ok: true }\n\n const intent = decodeCatalogInventoryProfileIntent(rawHeader)\n return {\n ok: true,\n metadata: { intent, target: 'product' },\n }\n },\n async after(request, response, context) {\n if (response.statusCode >= 400) return {}\n\n const metadata = context.metadata as\n | { intent?: ReturnType<typeof decodeCatalogInventoryProfileIntent>; target?: 'product' | 'variant' }\n | undefined\n if (!metadata?.intent) return {}\n\n const recordId = resolveRecordId(request.body, response.body)\n if (!recordId) return {}\n\n await syncCatalogInventoryProfile({\n intent: metadata.intent,\n target: 'product',\n recordId,\n organizationId: context.organizationId,\n tenantId: context.tenantId,\n userId: context.userId,\n container: context.container,\n })\n\n return {}\n },\n },\n {\n id: 'wms.catalog-variants.inventory-profile-sync',\n targetRoute: 'catalog/variants',\n methods: ['POST', 'PUT'],\n priority: 120,\n async before(request) {\n const rawHeader = request.headers[WMS_CATALOG_PROFILE_HEADER]\n if (!rawHeader) return { ok: true }\n\n const intent = decodeCatalogInventoryProfileIntent(rawHeader)\n return {\n ok: true,\n metadata: { intent, target: 'variant' },\n }\n },\n async after(request, response, context) {\n if (response.statusCode >= 400) return {}\n\n const metadata = context.metadata as\n | { intent?: ReturnType<typeof decodeCatalogInventoryProfileIntent>; target?: 'product' | 'variant' }\n | undefined\n if (!metadata?.intent) return {}\n\n const recordId = resolveRecordId(request.body, response.body)\n if (!recordId) return {}\n\n await syncCatalogInventoryProfile({\n intent: metadata.intent,\n target: 'variant',\n recordId,\n organizationId: context.organizationId,\n tenantId: context.tenantId,\n userId: context.userId,\n container: context.container,\n })\n\n return {}\n },\n },\n]\n\nexport default interceptors\n"],
5
- "mappings": "AACA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OACK;AAEP,SAAS,gBACP,aACA,cACe;AACf,QAAM,aAAa,cAAc;AACjC,MAAI,OAAO,eAAe,YAAY,WAAW,KAAK,EAAE,SAAS,GAAG;AAClE,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,aAAa;AAC/B,MAAI,OAAO,cAAc,YAAY,UAAU,KAAK,EAAE,SAAS,GAAG;AAChE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,MAAM,eAAiC;AAAA,EAC5C;AAAA,IACE,IAAI;AAAA,IACJ,aAAa;AAAA,IACb,SAAS,CAAC,QAAQ,KAAK;AAAA,IACvB,UAAU;AAAA,IACV,MAAM,OAAO,SAAS;AACpB,YAAM,YAAY,QAAQ,QAAQ,0BAA0B;AAC5D,UAAI,CAAC,UAAW,QAAO,EAAE,IAAI,KAAK;AAElC,YAAM,SAAS,oCAAoC,SAAS;AAC5D,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU,EAAE,QAAQ,QAAQ,UAAU;AAAA,MACxC;AAAA,IACF;AAAA,IACA,MAAM,MAAM,SAAS,UAAU,SAAS;AACtC,UAAI,SAAS,cAAc,IAAK,QAAO,CAAC;AAExC,YAAM,WAAW,QAAQ;AAGzB,UAAI,CAAC,UAAU,OAAQ,QAAO,CAAC;AAE/B,YAAM,WAAW,gBAAgB,QAAQ,MAAM,SAAS,IAAI;AAC5D,UAAI,CAAC,SAAU,QAAO,CAAC;AAEvB,YAAM,4BAA4B;AAAA,QAChC,QAAQ,SAAS;AAAA,QACjB,QAAQ;AAAA,QACR;AAAA,QACA,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,QAClB,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,MACrB,CAAC;AAED,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,aAAa;AAAA,IACb,SAAS,CAAC,QAAQ,KAAK;AAAA,IACvB,UAAU;AAAA,IACV,MAAM,OAAO,SAAS;AACpB,YAAM,YAAY,QAAQ,QAAQ,0BAA0B;AAC5D,UAAI,CAAC,UAAW,QAAO,EAAE,IAAI,KAAK;AAElC,YAAM,SAAS,oCAAoC,SAAS;AAC5D,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU,EAAE,QAAQ,QAAQ,UAAU;AAAA,MACxC;AAAA,IACF;AAAA,IACA,MAAM,MAAM,SAAS,UAAU,SAAS;AACtC,UAAI,SAAS,cAAc,IAAK,QAAO,CAAC;AAExC,YAAM,WAAW,QAAQ;AAGzB,UAAI,CAAC,UAAU,OAAQ,QAAO,CAAC;AAE/B,YAAM,WAAW,gBAAgB,QAAQ,MAAM,SAAS,IAAI;AAC5D,UAAI,CAAC,SAAU,QAAO,CAAC;AAEvB,YAAM,4BAA4B;AAAA,QAChC,QAAQ,SAAS;AAAA,QACjB,QAAQ;AAAA,QACR;AAAA,QACA,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,QAClB,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,MACrB,CAAC;AAED,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAO,uBAAQ;",
4
+ "sourcesContent": ["import type { ApiInterceptor } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n decodeCatalogInventoryProfileIntent,\n WMS_CATALOG_PROFILE_HEADER,\n} from '../lib/catalogInventoryProfileIntent'\nimport {\n syncCatalogInventoryProfile,\n} from '../lib/catalogInventoryProfileSync'\n\nfunction resolveRecordId(\n requestBody: Record<string, unknown> | undefined,\n responseBody: Record<string, unknown> | undefined,\n): string | null {\n const responseId = responseBody?.id\n if (typeof responseId === 'string' && responseId.trim().length > 0) {\n return responseId\n }\n\n const requestId = requestBody?.id\n if (typeof requestId === 'string' && requestId.trim().length > 0) {\n return requestId\n }\n\n return null\n}\n\nexport const interceptors: ApiInterceptor[] = [\n {\n id: 'wms.catalog-products.inventory-profile-sync',\n targetRoute: 'catalog/products',\n methods: ['POST', 'PUT'],\n priority: 120,\n async before(request) {\n const rawHeader = request.headers[WMS_CATALOG_PROFILE_HEADER]\n if (!rawHeader) return { ok: true }\n\n const intent = decodeCatalogInventoryProfileIntent(rawHeader)\n // CrudForm scopes `onBeforeSave` request headers around the whole\n // `onSubmit` callback, so a page whose submit handler also creates\n // other records (e.g. the product-create wizard implicitly creating\n // its default variant) can leak this header onto those unrelated\n // requests. Only honor an intent the product form itself computed.\n if (intent?.sourceEntityId !== E.catalog.catalog_product) return { ok: true }\n return {\n ok: true,\n metadata: { intent, target: 'product' },\n }\n },\n async after(request, response, context) {\n if (response.statusCode >= 400) return {}\n\n const metadata = context.metadata as\n | { intent?: ReturnType<typeof decodeCatalogInventoryProfileIntent>; target?: 'product' | 'variant' }\n | undefined\n if (!metadata?.intent) return {}\n\n const recordId = resolveRecordId(request.body, response.body)\n if (!recordId) return {}\n\n await syncCatalogInventoryProfile({\n intent: metadata.intent,\n target: 'product',\n recordId,\n organizationId: context.organizationId,\n tenantId: context.tenantId,\n userId: context.userId,\n container: context.container,\n })\n\n return {}\n },\n },\n {\n id: 'wms.catalog-variants.inventory-profile-sync',\n targetRoute: 'catalog/variants',\n methods: ['POST', 'PUT'],\n priority: 120,\n async before(request) {\n const rawHeader = request.headers[WMS_CATALOG_PROFILE_HEADER]\n if (!rawHeader) return { ok: true }\n\n const intent = decodeCatalogInventoryProfileIntent(rawHeader)\n // See the product interceptor's `before` for why this check exists.\n if (intent?.sourceEntityId !== E.catalog.catalog_product_variant) return { ok: true }\n return {\n ok: true,\n metadata: { intent, target: 'variant' },\n }\n },\n async after(request, response, context) {\n if (response.statusCode >= 400) return {}\n\n const metadata = context.metadata as\n | { intent?: ReturnType<typeof decodeCatalogInventoryProfileIntent>; target?: 'product' | 'variant' }\n | undefined\n if (!metadata?.intent) return {}\n\n const recordId = resolveRecordId(request.body, response.body)\n if (!recordId) return {}\n\n await syncCatalogInventoryProfile({\n intent: metadata.intent,\n target: 'variant',\n recordId,\n organizationId: context.organizationId,\n tenantId: context.tenantId,\n userId: context.userId,\n container: context.container,\n })\n\n return {}\n },\n },\n]\n\nexport default interceptors\n"],
5
+ "mappings": "AACA,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OACK;AAEP,SAAS,gBACP,aACA,cACe;AACf,QAAM,aAAa,cAAc;AACjC,MAAI,OAAO,eAAe,YAAY,WAAW,KAAK,EAAE,SAAS,GAAG;AAClE,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,aAAa;AAC/B,MAAI,OAAO,cAAc,YAAY,UAAU,KAAK,EAAE,SAAS,GAAG;AAChE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,MAAM,eAAiC;AAAA,EAC5C;AAAA,IACE,IAAI;AAAA,IACJ,aAAa;AAAA,IACb,SAAS,CAAC,QAAQ,KAAK;AAAA,IACvB,UAAU;AAAA,IACV,MAAM,OAAO,SAAS;AACpB,YAAM,YAAY,QAAQ,QAAQ,0BAA0B;AAC5D,UAAI,CAAC,UAAW,QAAO,EAAE,IAAI,KAAK;AAElC,YAAM,SAAS,oCAAoC,SAAS;AAM5D,UAAI,QAAQ,mBAAmB,EAAE,QAAQ,gBAAiB,QAAO,EAAE,IAAI,KAAK;AAC5E,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU,EAAE,QAAQ,QAAQ,UAAU;AAAA,MACxC;AAAA,IACF;AAAA,IACA,MAAM,MAAM,SAAS,UAAU,SAAS;AACtC,UAAI,SAAS,cAAc,IAAK,QAAO,CAAC;AAExC,YAAM,WAAW,QAAQ;AAGzB,UAAI,CAAC,UAAU,OAAQ,QAAO,CAAC;AAE/B,YAAM,WAAW,gBAAgB,QAAQ,MAAM,SAAS,IAAI;AAC5D,UAAI,CAAC,SAAU,QAAO,CAAC;AAEvB,YAAM,4BAA4B;AAAA,QAChC,QAAQ,SAAS;AAAA,QACjB,QAAQ;AAAA,QACR;AAAA,QACA,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,QAClB,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,MACrB,CAAC;AAED,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,aAAa;AAAA,IACb,SAAS,CAAC,QAAQ,KAAK;AAAA,IACvB,UAAU;AAAA,IACV,MAAM,OAAO,SAAS;AACpB,YAAM,YAAY,QAAQ,QAAQ,0BAA0B;AAC5D,UAAI,CAAC,UAAW,QAAO,EAAE,IAAI,KAAK;AAElC,YAAM,SAAS,oCAAoC,SAAS;AAE5D,UAAI,QAAQ,mBAAmB,EAAE,QAAQ,wBAAyB,QAAO,EAAE,IAAI,KAAK;AACpF,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU,EAAE,QAAQ,QAAQ,UAAU;AAAA,MACxC;AAAA,IACF;AAAA,IACA,MAAM,MAAM,SAAS,UAAU,SAAS;AACtC,UAAI,SAAS,cAAc,IAAK,QAAO,CAAC;AAExC,YAAM,WAAW,QAAQ;AAGzB,UAAI,CAAC,UAAU,OAAQ,QAAO,CAAC;AAE/B,YAAM,WAAW,gBAAgB,QAAQ,MAAM,SAAS,IAAI;AAC5D,UAAI,CAAC,SAAU,QAAO,CAAC;AAEvB,YAAM,4BAA4B;AAAA,QAChC,QAAQ,SAAS;AAAA,QACjB,QAAQ;AAAA,QACR;AAAA,QACA,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,QAClB,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,MACrB,CAAC;AAED,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAO,uBAAQ;",
6
6
  "names": []
7
7
  }
@@ -1185,6 +1185,16 @@ function restoreInventoryProfileFromSnapshot(em, before, record) {
1185
1185
  record.metadata = before.metadata;
1186
1186
  record.deletedAt = null;
1187
1187
  }
1188
+ function emitInventoryProfileEvent(eventId, profile) {
1189
+ void emitWmsEvent(eventId, {
1190
+ id: profile.id,
1191
+ profileId: profile.id,
1192
+ catalogProductId: profile.catalogProductId,
1193
+ catalogVariantId: profile.catalogVariantId ?? null,
1194
+ tenantId: profile.tenantId,
1195
+ organizationId: profile.organizationId
1196
+ }).catch(() => void 0);
1197
+ }
1188
1198
  const createProductInventoryProfileCommand = {
1189
1199
  id: "wms.inventoryProfiles.create",
1190
1200
  async execute(rawInput, ctx) {
@@ -1208,14 +1218,7 @@ const createProductInventoryProfileCommand = {
1208
1218
  metadata: toJsonValue(parsed.metadata)
1209
1219
  });
1210
1220
  await em.persist(profile).flush();
1211
- void emitWmsEvent("wms.inventory_profile.created", {
1212
- id: profile.id,
1213
- profileId: profile.id,
1214
- catalogProductId: profile.catalogProductId,
1215
- catalogVariantId: profile.catalogVariantId ?? null,
1216
- tenantId: profile.tenantId,
1217
- organizationId: profile.organizationId
1218
- }).catch(() => void 0);
1221
+ emitInventoryProfileEvent("wms.inventory_profile.created", profile);
1219
1222
  return { profileId: profile.id };
1220
1223
  },
1221
1224
  captureAfter: async (_input, result, ctx) => {
@@ -1244,6 +1247,7 @@ const createProductInventoryProfileCommand = {
1244
1247
  ensureOrganizationScope(ctx, record.organizationId);
1245
1248
  record.deletedAt = /* @__PURE__ */ new Date();
1246
1249
  await em.flush();
1250
+ emitInventoryProfileEvent("wms.inventory_profile.deleted", record);
1247
1251
  }
1248
1252
  };
1249
1253
  const updateProductInventoryProfileCommand = {
@@ -1278,14 +1282,7 @@ const updateProductInventoryProfileCommand = {
1278
1282
  if (parsed.safetyStock !== void 0) profile.safetyStock = toNumericString(parsed.safetyStock);
1279
1283
  if (parsed.metadata !== void 0) profile.metadata = toJsonValue(parsed.metadata);
1280
1284
  await em.flush();
1281
- void emitWmsEvent("wms.inventory_profile.updated", {
1282
- id: profile.id,
1283
- profileId: profile.id,
1284
- catalogProductId: profile.catalogProductId,
1285
- catalogVariantId: profile.catalogVariantId ?? null,
1286
- tenantId: profile.tenantId,
1287
- organizationId: profile.organizationId
1288
- }).catch(() => void 0);
1285
+ emitInventoryProfileEvent("wms.inventory_profile.updated", profile);
1289
1286
  return { profileId: profile.id };
1290
1287
  },
1291
1288
  captureAfter: async (_input, result, ctx) => {
@@ -1335,6 +1332,7 @@ const updateProductInventoryProfileCommand = {
1335
1332
  restoreInventoryProfileFromSnapshot(em, before, record);
1336
1333
  }
1337
1334
  await em.flush();
1335
+ emitInventoryProfileEvent("wms.inventory_profile.updated", before);
1338
1336
  }
1339
1337
  };
1340
1338
  const deleteProductInventoryProfileCommand = {
@@ -1351,6 +1349,7 @@ const deleteProductInventoryProfileCommand = {
1351
1349
  const profile = await loadProfile(em, ctx, profileId);
1352
1350
  profile.deletedAt = /* @__PURE__ */ new Date();
1353
1351
  await em.flush();
1352
+ emitInventoryProfileEvent("wms.inventory_profile.deleted", profile);
1354
1353
  return { profileId: profile.id };
1355
1354
  },
1356
1355
  buildLog: async ({ input, result, ctx, snapshots }) => {
@@ -1395,6 +1394,7 @@ const deleteProductInventoryProfileCommand = {
1395
1394
  restoreInventoryProfileFromSnapshot(em, before, record);
1396
1395
  }
1397
1396
  await em.flush();
1397
+ emitInventoryProfileEvent("wms.inventory_profile.created", before);
1398
1398
  }
1399
1399
  };
1400
1400
  function restoreInventoryLotFromSnapshot(_em, before, record) {