@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.js +70 -57
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/catalog/acl.js +30 -5
- package/dist/modules/catalog/acl.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +17 -5
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/commands/offers.js +26 -7
- package/dist/modules/catalog/commands/offers.js.map +2 -2
- package/dist/modules/catalog/commands/prices.js +41 -26
- package/dist/modules/catalog/commands/prices.js.map +2 -2
- package/dist/modules/catalog/commands/productUnitConversions.js +7 -1
- package/dist/modules/catalog/commands/productUnitConversions.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +2 -0
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/shared.js +58 -11
- package/dist/modules/catalog/commands/shared.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +18 -5
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +17 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -1
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +28 -6
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/catalog/acl.ts +30 -5
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +21 -5
- package/src/modules/catalog/commands/offers.ts +26 -7
- package/src/modules/catalog/commands/prices.ts +41 -26
- package/src/modules/catalog/commands/productUnitConversions.ts +7 -1
- package/src/modules/catalog/commands/products.ts +2 -0
- package/src/modules/catalog/commands/shared.ts +70 -6
- package/src/modules/catalog/commands/variants.ts +18 -5
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +21 -2
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +28 -1
- package/src/modules/sales/i18n/de.json +3 -0
- package/src/modules/sales/i18n/en.json +3 -0
- package/src/modules/sales/i18n/es.json +3 -0
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
}
|