@open-mercato/core 0.6.4-develop.4000.1.450e315cec → 0.6.4-develop.4011.1.4f3ed9ae3e

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 (47) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/backend/users/[id]/edit/page.js +70 -57
  3. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  4. package/dist/modules/catalog/acl.js +30 -5
  5. package/dist/modules/catalog/acl.js.map +2 -2
  6. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +17 -5
  7. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  8. package/dist/modules/catalog/commands/offers.js +26 -7
  9. package/dist/modules/catalog/commands/offers.js.map +2 -2
  10. package/dist/modules/catalog/commands/prices.js +41 -26
  11. package/dist/modules/catalog/commands/prices.js.map +2 -2
  12. package/dist/modules/catalog/commands/productUnitConversions.js +7 -1
  13. package/dist/modules/catalog/commands/productUnitConversions.js.map +2 -2
  14. package/dist/modules/catalog/commands/products.js +2 -0
  15. package/dist/modules/catalog/commands/products.js.map +2 -2
  16. package/dist/modules/catalog/commands/shared.js +58 -11
  17. package/dist/modules/catalog/commands/shared.js.map +2 -2
  18. package/dist/modules/catalog/commands/variants.js +18 -5
  19. package/dist/modules/catalog/commands/variants.js.map +2 -2
  20. package/dist/modules/resources/backend/resources/resources/[id]/page.js +17 -2
  21. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  22. package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -1
  23. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  24. package/package.json +7 -7
  25. package/src/modules/auth/backend/users/[id]/edit/page.tsx +28 -6
  26. package/src/modules/auth/i18n/de.json +1 -0
  27. package/src/modules/auth/i18n/en.json +1 -0
  28. package/src/modules/auth/i18n/es.json +1 -0
  29. package/src/modules/auth/i18n/pl.json +1 -0
  30. package/src/modules/catalog/acl.ts +30 -5
  31. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +21 -5
  32. package/src/modules/catalog/commands/offers.ts +26 -7
  33. package/src/modules/catalog/commands/prices.ts +41 -26
  34. package/src/modules/catalog/commands/productUnitConversions.ts +7 -1
  35. package/src/modules/catalog/commands/products.ts +2 -0
  36. package/src/modules/catalog/commands/shared.ts +70 -6
  37. package/src/modules/catalog/commands/variants.ts +18 -5
  38. package/src/modules/catalog/i18n/de.json +1 -0
  39. package/src/modules/catalog/i18n/en.json +1 -0
  40. package/src/modules/catalog/i18n/es.json +1 -0
  41. package/src/modules/catalog/i18n/pl.json +1 -0
  42. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +21 -2
  43. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +28 -1
  44. package/src/modules/sales/i18n/de.json +3 -0
  45. package/src/modules/sales/i18n/en.json +3 -0
  46. package/src/modules/sales/i18n/es.json +3 -0
  47. package/src/modules/sales/i18n/pl.json +3 -0
@@ -10,6 +10,7 @@ import {
10
10
  } from "../data/validators.js";
11
11
  import {
12
12
  cloneJson,
13
+ commandActorScope,
13
14
  ensureOrganizationScope,
14
15
  ensureSameScope,
15
16
  ensureTenantScope,
@@ -68,7 +69,10 @@ const createOfferCommand = {
68
69
  ensureTenantScope(ctx, parsed.tenantId);
69
70
  ensureOrganizationScope(ctx, parsed.organizationId);
70
71
  const em = ctx.container.resolve("em").fork();
71
- const product = await requireProduct(em, parsed.productId);
72
+ const product = await requireProduct(em, parsed.productId, {
73
+ tenantId: parsed.tenantId,
74
+ organizationId: parsed.organizationId
75
+ });
72
76
  if (product.organizationId !== parsed.organizationId || product.tenantId !== parsed.tenantId) {
73
77
  throw new CrudHttpError(403, { error: "Cross-tenant relation forbidden" });
74
78
  }
@@ -185,9 +189,15 @@ const updateOfferCommand = {
185
189
  await em.populate(record, ["product"]);
186
190
  ensureTenantScope(ctx, record.tenantId);
187
191
  ensureOrganizationScope(ctx, record.organizationId);
188
- let productEntity = typeof record.product === "string" ? await requireProduct(em, record.product) : record.product;
192
+ let productEntity = typeof record.product === "string" ? await requireProduct(em, record.product, {
193
+ tenantId: record.tenantId,
194
+ organizationId: record.organizationId
195
+ }) : record.product;
189
196
  if (parsed.productId && parsed.productId !== record.product.id) {
190
- const nextProduct = await requireProduct(em, parsed.productId);
197
+ const nextProduct = await requireProduct(em, parsed.productId, {
198
+ tenantId: record.tenantId,
199
+ organizationId: record.organizationId
200
+ });
191
201
  ensureSameScope(nextProduct, record.organizationId, record.tenantId);
192
202
  productEntity = nextProduct;
193
203
  }
@@ -278,9 +288,15 @@ const updateOfferCommand = {
278
288
  const before = payload?.before;
279
289
  if (!before) return;
280
290
  const em = ctx.container.resolve("em").fork();
281
- const record = await requireOffer(em, before.id).catch(() => null);
291
+ const record = await requireOffer(em, before.id, {
292
+ tenantId: before.tenantId,
293
+ organizationId: before.organizationId
294
+ }).catch(() => null);
282
295
  if (!record) {
283
- const product = await requireProduct(em, before.productId);
296
+ const product = await requireProduct(em, before.productId, {
297
+ tenantId: before.tenantId,
298
+ organizationId: before.organizationId
299
+ });
284
300
  ensureSameScope(product, before.organizationId, before.tenantId);
285
301
  const restored = em.create(CatalogOffer, {
286
302
  id: before.id,
@@ -339,7 +355,7 @@ const deleteOfferCommand = {
339
355
  async execute(input, ctx) {
340
356
  const parsed = { id: requireId(input, "Offer id is required.") };
341
357
  const em = ctx.container.resolve("em").fork();
342
- const record = await requireOffer(em, parsed.id);
358
+ const record = await requireOffer(em, parsed.id, commandActorScope(ctx));
343
359
  ensureTenantScope(ctx, record.tenantId);
344
360
  ensureOrganizationScope(ctx, record.organizationId);
345
361
  const baseEm = ctx.container.resolve("em");
@@ -391,7 +407,10 @@ const deleteOfferCommand = {
391
407
  const em = ctx.container.resolve("em").fork();
392
408
  const existing = await em.findOne(CatalogOffer, { id: before.id });
393
409
  if (existing) return;
394
- const product = await requireProduct(em, before.productId);
410
+ const product = await requireProduct(em, before.productId, {
411
+ tenantId: before.tenantId,
412
+ organizationId: before.organizationId
413
+ });
395
414
  ensureSameScope(product, before.organizationId, before.tenantId);
396
415
  const restored = em.create(CatalogOffer, {
397
416
  id: before.id,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/catalog/commands/offers.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CatalogOffer } from '../data/entities'\nimport {\n offerCreateSchema,\n offerUpdateSchema,\n type OfferCreateInput,\n type OfferUpdateInput,\n} from '../data/validators'\nimport {\n cloneJson,\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n emitCatalogQueryIndexEvent,\n extractUndoPayload,\n requireOffer,\n requireProduct,\n} from './shared'\nimport { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { E } from '#generated/entities.ids.generated'\n\ntype OfferSnapshot = {\n id: string\n productId: string\n organizationId: string\n tenantId: string\n channelId: string\n title: string\n description: string | null\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n metadata: Record<string, unknown> | null\n isActive: boolean\n createdAt: string\n updatedAt: string\n custom: Record<string, unknown> | null\n}\n\ntype OfferUndoPayload = {\n before?: OfferSnapshot | null\n after?: OfferSnapshot | null\n}\n\nconst OFFER_CHANGE_KEYS = [\n 'channelId',\n 'title',\n 'description',\n 'defaultMediaId',\n 'defaultMediaUrl',\n 'metadata',\n 'isActive',\n] as const satisfies readonly string[]\n\nasync function loadOfferSnapshot(em: EntityManager, id: string): Promise<OfferSnapshot | null> {\n const record = await em.findOne(\n CatalogOffer,\n { id },\n { populate: ['product'], strategy: 'select-in' },\n )\n if (!record) return null\n const productId =\n typeof record.product === 'string' ? record.product : record.product?.id ?? null\n if (!productId) return null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_offer,\n recordId: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n return {\n id: record.id,\n productId,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n channelId: record.channelId,\n title: record.title,\n description: record.description ?? null,\n defaultMediaId: record.defaultMediaId ?? null,\n defaultMediaUrl: record.defaultMediaUrl ?? null,\n metadata: record.metadata ? cloneJson(record.metadata) : null,\n isActive: record.isActive,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n custom: Object.keys(custom).length ? custom : null,\n }\n}\n\nconst createOfferCommand: CommandHandler<OfferCreateInput, { offerId: string }> = {\n id: 'catalog.offers.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(offerCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const product = await requireProduct(em, parsed.productId)\n if (\n product.organizationId !== parsed.organizationId ||\n product.tenantId !== parsed.tenantId\n ) {\n throw new CrudHttpError(403, { error: 'Cross-tenant relation forbidden' })\n }\n const conflict = await em.findOne(CatalogOffer, {\n product,\n channelId: parsed.channelId,\n deletedAt: null,\n })\n if (conflict) {\n throw new CrudHttpError(400, {\n error: 'This product already has an offer in this channel.',\n details: { offerId: conflict.id },\n })\n }\n const now = new Date()\n const record = em.create(CatalogOffer, {\n product,\n organizationId: product.organizationId,\n tenantId: product.tenantId,\n channelId: parsed.channelId,\n title: parsed.title?.trim().length ? parsed.title.trim() : product.title,\n description:\n parsed.description && parsed.description.trim().length\n ? parsed.description.trim()\n : product.description ?? null,\n defaultMediaId: parsed.defaultMediaId ?? null,\n defaultMediaUrl: parsed.defaultMediaUrl ?? null,\n metadata: parsed.metadata ? cloneJson(parsed.metadata) : null,\n isActive: parsed.isActive !== false,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n try {\n await em.flush()\n } catch (err) {\n handleUniqueOfferError(err)\n }\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n action: 'created',\n })\n return { offerId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadOfferSnapshot(em, result.offerId)\n },\n buildLog: async ({ snapshots }) => {\n const after = snapshots.after as OfferSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.offers.create', 'Create catalog offer'),\n resourceKind: 'catalog.offer',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies OfferUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OfferUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogOffer, { id: after.id })\n if (!record) return\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n em.remove(record)\n await em.flush()\n const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst updateOfferCommand: CommandHandler<OfferUpdateInput, { offerId: string }> = {\n id: 'catalog.offers.update',\n async prepare(input, ctx) {\n const id = requireId(input, 'Offer id is required.')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadOfferSnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(offerUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogOffer, { id: parsed.id, deletedAt: null })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog offer not found' })\n await em.populate(record, ['product'])\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n let productEntity =\n typeof record.product === 'string'\n ? await requireProduct(em, record.product)\n : record.product\n if (parsed.productId && parsed.productId !== record.product.id) {\n const nextProduct = await requireProduct(em, parsed.productId)\n ensureSameScope(nextProduct, record.organizationId, record.tenantId)\n productEntity = nextProduct\n }\n const nextChannelId = parsed.channelId ?? record.channelId\n const conflict = await em.findOne(CatalogOffer, {\n product: typeof productEntity === 'string' ? productEntity : productEntity.id,\n channelId: nextChannelId,\n deletedAt: null,\n id: { $ne: record.id },\n })\n if (conflict) {\n throw new CrudHttpError(400, {\n error: 'This product already has an offer in this channel.',\n details: { offerId: conflict.id },\n })\n }\n record.product = productEntity\n record.channelId = nextChannelId\n if (parsed.title !== undefined) {\n record.title =\n parsed.title && parsed.title.trim().length ? parsed.title.trim() : productEntity.title\n }\n if (parsed.description !== undefined) {\n record.description =\n parsed.description && parsed.description.trim().length\n ? parsed.description.trim()\n : productEntity.description ?? null\n }\n if (parsed.defaultMediaId !== undefined) {\n record.defaultMediaId = parsed.defaultMediaId ?? null\n }\n if (parsed.defaultMediaUrl !== undefined) {\n record.defaultMediaUrl = parsed.defaultMediaUrl ?? null\n }\n if (parsed.metadata !== undefined) {\n record.metadata = parsed.metadata ? cloneJson(parsed.metadata) : null\n }\n if (parsed.isActive !== undefined) {\n record.isActive = parsed.isActive\n }\n try {\n await em.flush()\n } catch (err) {\n handleUniqueOfferError(err)\n }\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n action: 'updated',\n })\n return { offerId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadOfferSnapshot(em, result.offerId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as OfferSnapshot | undefined\n const after = snapshots.after as OfferSnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.offers.update', 'Update catalog offer'),\n resourceKind: 'catalog.offer',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n OFFER_CHANGE_KEYS,\n ),\n payload: {\n undo: { before, after } satisfies OfferUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OfferUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await requireOffer(em, before.id).catch(() => null)\n if (!record) {\n const product = await requireProduct(em, before.productId)\n ensureSameScope(product, before.organizationId, before.tenantId)\n const restored = em.create(CatalogOffer, {\n id: before.id,\n product,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n channelId: before.channelId,\n title: before.title,\n description: before.description ?? null,\n defaultMediaId: before.defaultMediaId ?? null,\n defaultMediaUrl: before.defaultMediaUrl ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(restored)\n } else {\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n record.channelId = before.channelId\n record.title = before.title\n record.description = before.description ?? null\n record.defaultMediaId = before.defaultMediaId ?? null\n record.defaultMediaUrl = before.defaultMediaUrl ?? null\n record.metadata = before.metadata ? cloneJson(before.metadata) : null\n record.isActive = before.isActive\n record.updatedAt = new Date(before.updatedAt)\n }\n await em.flush()\n const resetValues = buildCustomFieldResetMap(before.custom ?? undefined, payload?.after?.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst deleteOfferCommand: CommandHandler<{ id?: string }, { offerId: string }> = {\n id: 'catalog.offers.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Offer id is required.')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadOfferSnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const parsed = { id: requireId(input, 'Offer id is required.') }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await requireOffer(em, parsed.id)\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const baseEm = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadOfferSnapshot(baseEm, parsed.id)\n em.remove(record)\n await em.flush()\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_offer,\n recordId: parsed.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n action: 'deleted',\n })\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: parsed.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: resetValues,\n })\n }\n }\n return { offerId: parsed.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as OfferSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.offers.delete', 'Delete catalog offer'),\n resourceKind: 'catalog.offer',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies OfferUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OfferUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(CatalogOffer, { id: before.id })\n if (existing) return\n const product = await requireProduct(em, before.productId)\n ensureSameScope(product, before.organizationId, before.tenantId)\n const restored = em.create(CatalogOffer, {\n id: before.id,\n product,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n channelId: before.channelId,\n title: before.title,\n description: before.description ?? null,\n defaultMediaId: before.defaultMediaId ?? null,\n defaultMediaUrl: before.defaultMediaUrl ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(restored)\n await em.flush()\n if (before.custom && Object.keys(before.custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: before.custom,\n })\n }\n },\n}\n\nregisterCommand(createOfferCommand)\nregisterCommand(updateOfferCommand)\nregisterCommand(deleteOfferCommand)\n\nfunction handleUniqueOfferError(err: unknown): never {\n if (err instanceof UniqueConstraintViolationException) {\n throw new CrudHttpError(400, { error: 'This product already has an offer in this channel.' })\n }\n throw err\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { buildChanges, requireId, parseWithCustomFields, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CatalogOffer } from '../data/entities'\nimport {\n offerCreateSchema,\n offerUpdateSchema,\n type OfferCreateInput,\n type OfferUpdateInput,\n} from '../data/validators'\nimport {\n cloneJson,\n commandActorScope,\n ensureOrganizationScope,\n ensureSameScope,\n ensureTenantScope,\n emitCatalogQueryIndexEvent,\n extractUndoPayload,\n requireOffer,\n requireProduct,\n} from './shared'\nimport { loadCustomFieldSnapshot, buildCustomFieldResetMap } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { E } from '#generated/entities.ids.generated'\n\ntype OfferSnapshot = {\n id: string\n productId: string\n organizationId: string\n tenantId: string\n channelId: string\n title: string\n description: string | null\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n metadata: Record<string, unknown> | null\n isActive: boolean\n createdAt: string\n updatedAt: string\n custom: Record<string, unknown> | null\n}\n\ntype OfferUndoPayload = {\n before?: OfferSnapshot | null\n after?: OfferSnapshot | null\n}\n\nconst OFFER_CHANGE_KEYS = [\n 'channelId',\n 'title',\n 'description',\n 'defaultMediaId',\n 'defaultMediaUrl',\n 'metadata',\n 'isActive',\n] as const satisfies readonly string[]\n\nasync function loadOfferSnapshot(em: EntityManager, id: string): Promise<OfferSnapshot | null> {\n const record = await em.findOne(\n CatalogOffer,\n { id },\n { populate: ['product'], strategy: 'select-in' },\n )\n if (!record) return null\n const productId =\n typeof record.product === 'string' ? record.product : record.product?.id ?? null\n if (!productId) return null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_offer,\n recordId: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n return {\n id: record.id,\n productId,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n channelId: record.channelId,\n title: record.title,\n description: record.description ?? null,\n defaultMediaId: record.defaultMediaId ?? null,\n defaultMediaUrl: record.defaultMediaUrl ?? null,\n metadata: record.metadata ? cloneJson(record.metadata) : null,\n isActive: record.isActive,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n custom: Object.keys(custom).length ? custom : null,\n }\n}\n\nconst createOfferCommand: CommandHandler<OfferCreateInput, { offerId: string }> = {\n id: 'catalog.offers.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(offerCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const product = await requireProduct(em, parsed.productId, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n })\n if (\n product.organizationId !== parsed.organizationId ||\n product.tenantId !== parsed.tenantId\n ) {\n throw new CrudHttpError(403, { error: 'Cross-tenant relation forbidden' })\n }\n const conflict = await em.findOne(CatalogOffer, {\n product,\n channelId: parsed.channelId,\n deletedAt: null,\n })\n if (conflict) {\n throw new CrudHttpError(400, {\n error: 'This product already has an offer in this channel.',\n details: { offerId: conflict.id },\n })\n }\n const now = new Date()\n const record = em.create(CatalogOffer, {\n product,\n organizationId: product.organizationId,\n tenantId: product.tenantId,\n channelId: parsed.channelId,\n title: parsed.title?.trim().length ? parsed.title.trim() : product.title,\n description:\n parsed.description && parsed.description.trim().length\n ? parsed.description.trim()\n : product.description ?? null,\n defaultMediaId: parsed.defaultMediaId ?? null,\n defaultMediaUrl: parsed.defaultMediaUrl ?? null,\n metadata: parsed.metadata ? cloneJson(parsed.metadata) : null,\n isActive: parsed.isActive !== false,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n try {\n await em.flush()\n } catch (err) {\n handleUniqueOfferError(err)\n }\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n action: 'created',\n })\n return { offerId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadOfferSnapshot(em, result.offerId)\n },\n buildLog: async ({ snapshots }) => {\n const after = snapshots.after as OfferSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.offers.create', 'Create catalog offer'),\n resourceKind: 'catalog.offer',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies OfferUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OfferUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogOffer, { id: after.id })\n if (!record) return\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n em.remove(record)\n await em.flush()\n const resetValues = buildCustomFieldResetMap(undefined, after.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst updateOfferCommand: CommandHandler<OfferUpdateInput, { offerId: string }> = {\n id: 'catalog.offers.update',\n async prepare(input, ctx) {\n const id = requireId(input, 'Offer id is required.')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadOfferSnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(offerUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await em.findOne(CatalogOffer, { id: parsed.id, deletedAt: null })\n if (!record) throw new CrudHttpError(404, { error: 'Catalog offer not found' })\n await em.populate(record, ['product'])\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n let productEntity =\n typeof record.product === 'string'\n ? await requireProduct(em, record.product, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n : record.product\n if (parsed.productId && parsed.productId !== record.product.id) {\n const nextProduct = await requireProduct(em, parsed.productId, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n ensureSameScope(nextProduct, record.organizationId, record.tenantId)\n productEntity = nextProduct\n }\n const nextChannelId = parsed.channelId ?? record.channelId\n const conflict = await em.findOne(CatalogOffer, {\n product: typeof productEntity === 'string' ? productEntity : productEntity.id,\n channelId: nextChannelId,\n deletedAt: null,\n id: { $ne: record.id },\n })\n if (conflict) {\n throw new CrudHttpError(400, {\n error: 'This product already has an offer in this channel.',\n details: { offerId: conflict.id },\n })\n }\n record.product = productEntity\n record.channelId = nextChannelId\n if (parsed.title !== undefined) {\n record.title =\n parsed.title && parsed.title.trim().length ? parsed.title.trim() : productEntity.title\n }\n if (parsed.description !== undefined) {\n record.description =\n parsed.description && parsed.description.trim().length\n ? parsed.description.trim()\n : productEntity.description ?? null\n }\n if (parsed.defaultMediaId !== undefined) {\n record.defaultMediaId = parsed.defaultMediaId ?? null\n }\n if (parsed.defaultMediaUrl !== undefined) {\n record.defaultMediaUrl = parsed.defaultMediaUrl ?? null\n }\n if (parsed.metadata !== undefined) {\n record.metadata = parsed.metadata ? cloneJson(parsed.metadata) : null\n }\n if (parsed.isActive !== undefined) {\n record.isActive = parsed.isActive\n }\n try {\n await em.flush()\n } catch (err) {\n handleUniqueOfferError(err)\n }\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n values: custom,\n })\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_offer,\n recordId: record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n action: 'updated',\n })\n return { offerId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadOfferSnapshot(em, result.offerId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as OfferSnapshot | undefined\n const after = snapshots.after as OfferSnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.offers.update', 'Update catalog offer'),\n resourceKind: 'catalog.offer',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n OFFER_CHANGE_KEYS,\n ),\n payload: {\n undo: { before, after } satisfies OfferUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OfferUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await requireOffer(em, before.id, {\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n }).catch(() => null)\n if (!record) {\n const product = await requireProduct(em, before.productId, {\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n })\n ensureSameScope(product, before.organizationId, before.tenantId)\n const restored = em.create(CatalogOffer, {\n id: before.id,\n product,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n channelId: before.channelId,\n title: before.title,\n description: before.description ?? null,\n defaultMediaId: before.defaultMediaId ?? null,\n defaultMediaUrl: before.defaultMediaUrl ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(restored)\n } else {\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n record.channelId = before.channelId\n record.title = before.title\n record.description = before.description ?? null\n record.defaultMediaId = before.defaultMediaId ?? null\n record.defaultMediaUrl = before.defaultMediaUrl ?? null\n record.metadata = before.metadata ? cloneJson(before.metadata) : null\n record.isActive = before.isActive\n record.updatedAt = new Date(before.updatedAt)\n }\n await em.flush()\n const resetValues = buildCustomFieldResetMap(before.custom ?? undefined, payload?.after?.custom ?? undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: resetValues,\n })\n }\n },\n}\n\nconst deleteOfferCommand: CommandHandler<{ id?: string }, { offerId: string }> = {\n id: 'catalog.offers.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Offer id is required.')\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadOfferSnapshot(em, id)\n if (snapshot) {\n ensureTenantScope(ctx, snapshot.tenantId)\n ensureOrganizationScope(ctx, snapshot.organizationId)\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const parsed = { id: requireId(input, 'Offer id is required.') }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const record = await requireOffer(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const baseEm = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadOfferSnapshot(baseEm, parsed.id)\n em.remove(record)\n await em.flush()\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_offer,\n recordId: parsed.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n action: 'deleted',\n })\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const resetValues = buildCustomFieldResetMap(snapshot.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: parsed.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: resetValues,\n })\n }\n }\n return { offerId: parsed.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as OfferSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('catalog.audit.offers.delete', 'Delete catalog offer'),\n resourceKind: 'catalog.offer',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies OfferUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OfferUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(CatalogOffer, { id: before.id })\n if (existing) return\n const product = await requireProduct(em, before.productId, {\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n })\n ensureSameScope(product, before.organizationId, before.tenantId)\n const restored = em.create(CatalogOffer, {\n id: before.id,\n product,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n channelId: before.channelId,\n title: before.title,\n description: before.description ?? null,\n defaultMediaId: before.defaultMediaId ?? null,\n defaultMediaUrl: before.defaultMediaUrl ?? null,\n metadata: before.metadata ? cloneJson(before.metadata) : null,\n isActive: before.isActive,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(restored)\n await em.flush()\n if (before.custom && Object.keys(before.custom).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine'),\n entityId: E.catalog.catalog_offer,\n recordId: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n values: before.custom,\n })\n }\n },\n}\n\nregisterCommand(createOfferCommand)\nregisterCommand(updateOfferCommand)\nregisterCommand(deleteOfferCommand)\n\nfunction handleUniqueOfferError(err: unknown): never {\n if (err instanceof UniqueConstraintViolationException) {\n throw new CrudHttpError(400, { error: 'This product already has an offer in this channel.' })\n }\n throw err\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -11,6 +11,7 @@ import {
11
11
  } from "../data/validators.js";
12
12
  import {
13
13
  cloneJson,
14
+ commandActorScope,
14
15
  ensureOrganizationScope,
15
16
  ensureSameScope,
16
17
  ensureSameTenant,
@@ -53,22 +54,23 @@ const PRICE_CHANGE_KEYS = [
53
54
  "endsAt"
54
55
  ];
55
56
  async function resolveSnapshotAssociations(em, snapshot) {
57
+ const scope = { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId };
56
58
  let variant = null;
57
59
  if (snapshot.variantId) {
58
- variant = await requireVariant(em, snapshot.variantId);
60
+ variant = await requireVariant(em, snapshot.variantId, scope);
59
61
  }
60
62
  let product = null;
61
63
  if (snapshot.productId) {
62
- product = await requireProduct(em, snapshot.productId);
64
+ product = await requireProduct(em, snapshot.productId, scope);
63
65
  } else if (variant) {
64
- product = typeof variant.product === "string" ? await requireProduct(em, variant.product) : variant.product;
66
+ product = typeof variant.product === "string" ? await requireProduct(em, variant.product, scope) : variant.product;
65
67
  }
66
68
  if (!product) {
67
69
  throw new CrudHttpError(400, { error: "Price snapshot missing product association." });
68
70
  }
69
71
  let offer = null;
70
72
  if (snapshot.offerId) {
71
- offer = await requireOffer(em, snapshot.offerId);
73
+ offer = await requireOffer(em, snapshot.offerId, scope);
72
74
  }
73
75
  return { variant, product, offer };
74
76
  }
@@ -174,14 +176,18 @@ const createPriceCommand = {
174
176
  async execute(rawInput, ctx) {
175
177
  const { parsed, custom } = parseWithCustomFields(priceCreateSchema, rawInput);
176
178
  const em = ctx.container.resolve("em").fork();
179
+ const actorScope = commandActorScope(ctx);
177
180
  let variant = null;
178
181
  let product = null;
179
182
  if (parsed.variantId) {
180
- variant = await requireVariant(em, parsed.variantId);
181
- product = typeof variant.product === "string" ? await requireProduct(em, variant.product) : variant.product;
183
+ variant = await requireVariant(em, parsed.variantId, actorScope);
184
+ product = typeof variant.product === "string" ? await requireProduct(em, variant.product, {
185
+ tenantId: variant.tenantId,
186
+ organizationId: variant.organizationId
187
+ }) : variant.product;
182
188
  }
183
189
  if (parsed.productId) {
184
- const explicitProduct = await requireProduct(em, parsed.productId);
190
+ const explicitProduct = await requireProduct(em, parsed.productId, actorScope);
185
191
  if (product && explicitProduct.id !== product.id) {
186
192
  throw new CrudHttpError(400, { error: "Variant does not belong to the provided product." });
187
193
  }
@@ -193,13 +199,20 @@ const createPriceCommand = {
193
199
  const scopeSource = variant ?? product;
194
200
  ensureTenantScope(ctx, scopeSource.tenantId);
195
201
  ensureOrganizationScope(ctx, scopeSource.organizationId);
196
- const priceKind = await requirePriceKind(em, parsed.priceKindId);
202
+ const scopeSourceScope = {
203
+ tenantId: scopeSource.tenantId,
204
+ organizationId: scopeSource.organizationId
205
+ };
206
+ const priceKind = await requirePriceKind(em, parsed.priceKindId, scopeSourceScope);
197
207
  ensureSameTenant(priceKind, scopeSource.tenantId);
198
208
  let offer = null;
199
209
  if (parsed.offerId) {
200
- offer = await requireOffer(em, parsed.offerId);
210
+ offer = await requireOffer(em, parsed.offerId, scopeSourceScope);
201
211
  ensureSameScope(offer, scopeSource.organizationId, scopeSource.tenantId);
202
- const offerProduct = typeof offer.product === "string" ? await requireProduct(em, offer.product) : offer.product;
212
+ const offerProduct = typeof offer.product === "string" ? await requireProduct(em, offer.product, {
213
+ tenantId: offer.tenantId,
214
+ organizationId: offer.organizationId
215
+ }) : offer.product;
203
216
  if (product && offerProduct.id !== product.id) {
204
217
  throw new CrudHttpError(400, { error: "Offer does not belong to the selected product." });
205
218
  }
@@ -347,17 +360,18 @@ const updatePriceCommand = {
347
360
  { tenantId: parsed.tenantId, organizationId: parsed.organizationId }
348
361
  );
349
362
  if (!record) throw new CrudHttpError(404, { error: "Catalog price not found" });
363
+ const recordScope = { tenantId: record.tenantId, organizationId: record.organizationId };
350
364
  const currentVariantRef = record.variant;
351
365
  let targetVariant = null;
352
366
  if (typeof currentVariantRef === "string") {
353
- targetVariant = await requireVariant(em, currentVariantRef);
367
+ targetVariant = await requireVariant(em, currentVariantRef, recordScope);
354
368
  } else if (currentVariantRef) {
355
369
  targetVariant = currentVariantRef;
356
370
  }
357
371
  const currentProductRef = record.product ?? (targetVariant ? targetVariant.product : null);
358
372
  let targetProduct = null;
359
373
  if (typeof currentProductRef === "string") {
360
- targetProduct = await requireProduct(em, currentProductRef);
374
+ targetProduct = await requireProduct(em, currentProductRef, recordScope);
361
375
  } else if (currentProductRef) {
362
376
  targetProduct = currentProductRef;
363
377
  }
@@ -365,18 +379,18 @@ const updatePriceCommand = {
365
379
  if (!parsed.variantId) {
366
380
  targetVariant = null;
367
381
  } else {
368
- targetVariant = await requireVariant(em, parsed.variantId);
369
- targetProduct = typeof targetVariant.product === "string" ? await requireProduct(em, targetVariant.product) : targetVariant.product;
382
+ targetVariant = await requireVariant(em, parsed.variantId, recordScope);
383
+ targetProduct = typeof targetVariant.product === "string" ? await requireProduct(em, targetVariant.product, recordScope) : targetVariant.product;
370
384
  }
371
385
  }
372
386
  if (targetVariant && targetVariant?.product === void 0) {
373
- targetVariant = await requireVariant(em, targetVariant.id);
387
+ targetVariant = await requireVariant(em, targetVariant.id, recordScope);
374
388
  }
375
389
  if (parsed.productId !== void 0) {
376
390
  if (!parsed.productId) {
377
391
  targetProduct = null;
378
392
  } else {
379
- const explicitProduct = await requireProduct(em, parsed.productId);
393
+ const explicitProduct = await requireProduct(em, parsed.productId, recordScope);
380
394
  if (targetVariant) {
381
395
  const variantProductId = typeof targetVariant.product === "string" ? targetVariant.product : targetVariant.product.id;
382
396
  if (variantProductId !== explicitProduct.id) {
@@ -390,20 +404,20 @@ const updatePriceCommand = {
390
404
  throw new CrudHttpError(400, { error: "Price must remain associated with a product or variant." });
391
405
  }
392
406
  if (!targetProduct && targetVariant) {
393
- targetProduct = typeof targetVariant.product === "string" ? await requireProduct(em, targetVariant.product) : targetVariant.product;
407
+ targetProduct = typeof targetVariant.product === "string" ? await requireProduct(em, targetVariant.product, recordScope) : targetVariant.product;
394
408
  }
395
409
  if (!targetProduct) {
396
410
  throw new CrudHttpError(400, { error: "Unable to resolve product for price." });
397
411
  }
398
412
  let targetOffer = null;
399
413
  if (record.offer) {
400
- targetOffer = typeof record.offer === "string" ? await requireOffer(em, record.offer) : record.offer;
414
+ targetOffer = typeof record.offer === "string" ? await requireOffer(em, record.offer, recordScope) : record.offer;
401
415
  }
402
416
  if (parsed.offerId !== void 0) {
403
417
  if (!parsed.offerId) {
404
418
  targetOffer = null;
405
419
  } else {
406
- const explicitOffer = await requireOffer(em, parsed.offerId);
420
+ const explicitOffer = await requireOffer(em, parsed.offerId, recordScope);
407
421
  ensureSameScope(explicitOffer, targetProduct.organizationId, targetProduct.tenantId);
408
422
  const offerProductId = typeof explicitOffer.product === "string" ? explicitOffer.product : explicitOffer.product.id;
409
423
  if (offerProductId !== targetProduct.id) {
@@ -416,13 +430,13 @@ const updatePriceCommand = {
416
430
  ensureOrganizationScope(ctx, targetProduct.organizationId);
417
431
  let targetPriceKind = null;
418
432
  if (record.priceKind) {
419
- targetPriceKind = typeof record.priceKind === "string" ? await requirePriceKind(em, record.priceKind) : record.priceKind;
433
+ targetPriceKind = typeof record.priceKind === "string" ? await requirePriceKind(em, record.priceKind, recordScope) : record.priceKind;
420
434
  }
421
435
  if (parsed.priceKindId !== void 0) {
422
436
  if (!parsed.priceKindId) {
423
437
  throw new CrudHttpError(400, { error: "Price kind is required." });
424
438
  }
425
- targetPriceKind = await requirePriceKind(em, parsed.priceKindId);
439
+ targetPriceKind = await requirePriceKind(em, parsed.priceKindId, recordScope);
426
440
  }
427
441
  if (!targetPriceKind) {
428
442
  throw new CrudHttpError(400, { error: "Price kind is required." });
@@ -740,21 +754,22 @@ registerCommand(createPriceCommand);
740
754
  registerCommand(updatePriceCommand);
741
755
  registerCommand(deletePriceCommand);
742
756
  async function resolvePriceRecordAssociations(em, record) {
743
- const variant = record.variant ? typeof record.variant === "string" ? await requireVariant(em, record.variant) : record.variant : null;
757
+ const scope = { tenantId: record.tenantId, organizationId: record.organizationId };
758
+ const variant = record.variant ? typeof record.variant === "string" ? await requireVariant(em, record.variant, scope) : record.variant : null;
744
759
  if (record.product) {
745
- const product = typeof record.product === "string" ? await requireProduct(em, record.product) : record.product;
760
+ const product = typeof record.product === "string" ? await requireProduct(em, record.product, scope) : record.product;
746
761
  return { product, variant };
747
762
  }
748
763
  if (variant?.product) {
749
764
  const productRef = variant.product;
750
- const product = typeof productRef === "string" ? await requireProduct(em, productRef) : productRef;
765
+ const product = typeof productRef === "string" ? await requireProduct(em, productRef, scope) : productRef;
751
766
  return { product, variant };
752
767
  }
753
768
  if (record.offer) {
754
- const offer = typeof record.offer === "string" ? await requireOffer(em, record.offer) : record.offer;
769
+ const offer = typeof record.offer === "string" ? await requireOffer(em, record.offer, scope) : record.offer;
755
770
  const productRef = offer?.product ?? null;
756
771
  if (productRef) {
757
- const product = typeof productRef === "string" ? await requireProduct(em, productRef) : productRef;
772
+ const product = typeof productRef === "string" ? await requireProduct(em, productRef, scope) : productRef;
758
773
  return { product, variant };
759
774
  }
760
775
  }