@open-mercato/sync-akeneo 0.10.1-develop.7599.1.22c2d6481d → 0.10.1-develop.7600.1.57704c3ffb

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.
@@ -1839,7 +1839,7 @@ async function createAkeneoImporter(client, scope) {
1839
1839
  });
1840
1840
  return true;
1841
1841
  } catch (error) {
1842
- if (isCrudHttpError(error) && error.status === 409) return false;
1842
+ if (isCrudHttpError(error) && (error.status === 409 || error.status === 404)) return false;
1843
1843
  throw error;
1844
1844
  }
1845
1845
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/sync_akeneo/lib/catalog-importer.ts"],
4
- "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { DataMapping } from '@open-mercato/core/modules/data_sync/lib/adapter'\nimport type { ExternalIdMappingService } from '@open-mercato/core/modules/data_sync/lib/id-mapping'\nimport { SyncExternalIdMapping } from '@open-mercato/core/modules/integrations/data/entities'\nimport {\n CatalogOffer,\n CatalogOptionSchemaTemplate,\n CatalogPriceKind,\n CatalogProduct,\n CatalogProductCategory,\n CatalogProductPrice,\n CatalogProductVariant,\n CatalogProductVariantRelation,\n} from '@open-mercato/core/modules/catalog/data/entities'\nimport { ensureCustomFieldDefinitions } from '@open-mercato/core/modules/entities/lib/field-definitions'\nimport { CustomFieldDef, CustomFieldEntityConfig } from '@open-mercato/core/modules/entities/data/entities'\nimport { normalizeEntityFieldsetConfig, type CustomFieldsetDefinition } from '@open-mercato/core/modules/entities/lib/fieldsets'\nimport { invalidateDefinitionsCache } from '@open-mercato/core/modules/entities/api/definitions.cache'\nimport { Attachment } from '@open-mercato/core/modules/attachments/data/entities'\nimport { buildAttachmentFileUrl, buildAttachmentImageUrl, slugifyAttachmentFileName } from '@open-mercato/core/modules/attachments/lib/imageUrls'\nimport type { AttachmentService } from '@open-mercato/core/modules/attachments'\nimport {\n isScopedAttachmentUploadError,\n type ScopedAttachmentUploadErrorCode,\n type ScopedAttachmentUploadService,\n} from '@open-mercato/core/modules/attachments/lib/scoped-upload-service'\nimport type { IntegrationLogService } from '@open-mercato/core/modules/integrations/lib/log-service'\nimport { attachmentCrudEvents, attachmentCrudIndexer } from '@open-mercato/core/modules/attachments/lib/crud'\nimport { emitCatalogQueryIndexEvent } from '@open-mercato/core/modules/catalog/commands/shared'\nimport { SalesChannel } from '@open-mercato/core/modules/sales/data/entities'\nimport type { CustomFieldDefinition } from '@open-mercato/shared/modules/entities'\nimport {\n buildAkeneoFieldsetCode,\n buildProductFieldMappings,\n dedupeStrings,\n labelFromLocalizedRecord,\n safeRecord,\n slugifyAkeneoCode,\n type AkeneoAttribute,\n type AkeneoCategory,\n type AkeneoCustomFieldKind,\n type AkeneoDataMapping,\n type AkeneoFamily,\n type AkeneoFamilyVariant,\n type AkeneoFieldsetMapping,\n type AkeneoProduct,\n type AkeneoProductMappingSettings,\n type AkeneoReconciliationSettings,\n type AkeneoValues,\n buildDefaultAkeneoMapping,\n} from './shared'\nimport { isAkeneoResponseTooLargeError, type AkeneoClient } from './client'\nimport { inferAkeneoProductMapping } from './inference'\nimport { normalizeMarkdownText } from './markdown'\n\ntype ImportScope = {\n organizationId: string\n tenantId: string\n}\n\nconst REJECTED_MEDIA_UPLOAD_CODES: ReadonlySet<ScopedAttachmentUploadErrorCode> = new Set([\n 'dangerous_executable',\n 'max_upload_size',\n 'active_content',\n])\n\ntype UpsertResult = {\n localId: string\n action: 'create' | 'update' | 'skip'\n}\n\ntype CustomFieldSyncItem = {\n externalId: string\n action: 'create' | 'update' | 'skip'\n data: Record<string, unknown>\n}\n\ntype ResolvedHierarchy = {\n rootExternalId: string\n family: string | null\n familyVariantCode: string | null\n rootValues: AkeneoValues\n leafValues: AkeneoValues\n mergedValues: AkeneoValues\n categories: string[]\n parentChain: string[]\n associationSource: AkeneoProduct\n axisCodes: string[]\n}\n\ntype DesiredOffer = {\n externalId: string\n channelCode: string\n channelId: string\n akeneoChannel: string | null\n title: string\n description: string | null\n prices: DesiredPrice[]\n}\n\ntype DesiredPrice = {\n externalId: string\n priceKindCode: string\n priceKindId: string\n channelId: string\n currencyCode: string\n amount: number\n variantId: string\n}\n\ntype MediaReference = {\n codeOrUrl: string\n fileNameHint: string | null\n mimeTypeHint: string | null\n}\n\ntype DesiredAsset = {\n externalId: string\n entityId: string\n recordId: string\n kind: 'image' | 'file'\n remote: MediaReference\n}\n\ntype AkeneoFieldsetPlan = {\n product: CustomFieldsetDefinition | null\n variant: CustomFieldsetDefinition | null\n}\n\nconst PRODUCT_ENTITY_ID = 'catalog:catalog_product'\nconst VARIANT_ENTITY_ID = 'catalog:catalog_product_variant'\n\nexport function readPreferredAkeneoValue(\n values: AkeneoValues | undefined | null,\n attributeCode: string,\n locale: string,\n channel: string | null,\n): unknown {\n const entries = Array.isArray(values?.[attributeCode]) ? values?.[attributeCode] ?? [] : []\n if (entries.length === 0) return null\n\n const normalize = (value: string | null | undefined) => (typeof value === 'string' && value.trim().length > 0 ? value.trim() : null)\n const wantedLocale = normalize(locale)\n const wantedChannel = normalize(channel)\n\n const eligibleEntries = entries.filter((entry) => {\n const entryLocale = normalize(entry.locale)\n const entryChannel = normalize(entry.scope)\n const localeMatches = wantedLocale ? entryLocale === wantedLocale || entryLocale === null : true\n const channelMatches = wantedChannel ? entryChannel === wantedChannel || entryChannel === null : true\n return localeMatches && channelMatches\n })\n\n const scored = eligibleEntries\n .map((entry) => {\n const entryLocale = normalize(entry.locale)\n const entryChannel = normalize(entry.scope)\n let score = 0\n if (wantedLocale && entryLocale === wantedLocale) score += 4\n else if (!wantedLocale && !entryLocale) score += 2\n else if (!entryLocale) score += 1\n if (wantedChannel && entryChannel === wantedChannel) score += 4\n else if (!wantedChannel && !entryChannel) score += 2\n else if (!entryChannel) score += 1\n return { score, entry }\n })\n .sort((left, right) => right.score - left.score)\n\n return scored[0]?.entry?.data ?? null\n}\n\nexport function readLayeredAkeneoValue(\n layers: AkeneoValues[],\n attributeCode: string,\n locale: string,\n channel: string | null,\n): unknown {\n for (const layer of layers) {\n const value = readPreferredAkeneoValue(layer, attributeCode, locale, channel)\n if (value !== null && value !== undefined && !(typeof value === 'string' && value.trim().length === 0)) {\n return value\n }\n }\n return null\n}\n\nfunction coerceString(value: unknown): string | null {\n if (typeof value === 'string' && value.trim().length > 0) return value.trim()\n if (typeof value === 'number' && Number.isFinite(value)) return String(value)\n return null\n}\n\nexport function normalizeAkeneoSelectValue(\n value: unknown,\n optionLabels: Map<string, string>,\n): string | null {\n if (Array.isArray(value)) {\n const labels = value\n .map((entry) => normalizeAkeneoSelectValue(entry, optionLabels))\n .filter((entry): entry is string => typeof entry === 'string' && entry.length > 0)\n return labels.length > 0 ? labels.join(', ') : null\n }\n\n const raw = coerceString(value)\n if (!raw) return null\n return optionLabels.get(raw) ?? raw\n}\n\nexport function filterAkeneoAttributeMappingsByAvailableAttributes<T extends { attributeCode: string }>(\n mappings: T[],\n availableAttributeCodes: string[],\n): T[] {\n const allowed = new Set(\n availableAttributeCodes\n .map((code) => code.trim())\n .filter((code) => code.length > 0),\n )\n if (allowed.size === 0) return []\n return mappings.filter((mapping) => allowed.has(mapping.attributeCode))\n}\n\ntype ExistingFieldsetDefinition = {\n key: string\n description: string | null\n fieldset: string | null\n fieldsets: string[]\n}\n\ntype DesiredFieldsetAssignment = {\n key: string\n fieldsets: string[]\n}\n\ntype EntityFieldsetAssignments = {\n fieldsets: CustomFieldsetDefinition[]\n fieldsetsByKey: Map<string, string[]>\n}\n\ntype ResolvedGlobalFieldsetAssignments = {\n product: EntityFieldsetAssignments\n variant: EntityFieldsetAssignments\n}\n\ntype AkeneoOptionSchemaMetadata = {\n familyCode: string | null\n familyVariantCode: string | null\n attributeCodes: string[]\n richAttributes: Record<string, Record<string, unknown>>\n}\n\nexport function resolveAkeneoFieldKeysToDetach(\n definitions: ExistingFieldsetDefinition[],\n desiredFieldKeys: string[],\n fieldsetCode: string | null,\n): string[] {\n if (!fieldsetCode) return []\n const desired = new Set(\n desiredFieldKeys\n .map((key) => normalizeFieldKey(key))\n .filter((key) => key.length > 0),\n )\n\n return definitions\n .filter((definition) => definition.fieldset === fieldsetCode || definition.fieldsets.includes(fieldsetCode))\n .filter((definition) => typeof definition.description === 'string' && definition.description.startsWith('Akeneo attribute '))\n .filter((definition) => !desired.has(normalizeFieldKey(definition.key)))\n .map((definition) => definition.key)\n}\n\nexport function resolveAkeneoFieldsetMemberships(\n currentFieldsets: string[],\n fieldsetCode: string | null,\n): string[] {\n return dedupeStrings([\n ...currentFieldsets\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n ...(fieldsetCode ? [fieldsetCode] : []),\n ])\n}\n\nfunction readConfiguredFieldsets(config: Record<string, unknown> | null | undefined): string[] {\n const configured = Array.isArray(config?.fieldsets)\n ? config.fieldsets.filter((entry): entry is string => typeof entry === 'string')\n : []\n const normalized = dedupeStrings(\n configured\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n )\n if (normalized.length > 0) return normalized\n const legacy = typeof config?.fieldset === 'string' ? config.fieldset.trim() : ''\n return legacy.length > 0 ? [legacy] : []\n}\n\nfunction clampString(value: string | null, maxLength: number): string | null {\n if (!value) return null\n return value.length > maxLength ? value.slice(0, maxLength).trim() : value\n}\n\nfunction coerceMetricAmount(value: unknown): number | null {\n const record = safeRecord(value)\n const amount = record?.amount\n if (typeof amount === 'string' && amount.trim().length > 0) {\n const numeric = Number(amount)\n return Number.isFinite(numeric) ? numeric : null\n }\n if (typeof amount === 'number' && Number.isFinite(amount)) return amount\n if (typeof value === 'number' && Number.isFinite(value)) return value\n return null\n}\n\nfunction coerceNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length > 0) {\n const numeric = Number(value)\n return Number.isFinite(numeric) ? numeric : null\n }\n return null\n}\n\nfunction coerceBoolean(value: unknown): boolean | null {\n if (typeof value === 'boolean') return value\n if (typeof value === 'string') {\n const lowered = value.trim().toLowerCase()\n if (lowered === 'true' || lowered === '1' || lowered === 'yes') return true\n if (lowered === 'false' || lowered === '0' || lowered === 'no') return false\n }\n return null\n}\n\nfunction mergeValueLayers(...layers: Array<AkeneoValues | undefined | null>): AkeneoValues {\n const merged: AkeneoValues = {}\n for (const layer of layers) {\n if (!layer) continue\n for (const [key, value] of Object.entries(layer)) {\n merged[key] = Array.isArray(value) ? value : []\n }\n }\n return merged\n}\n\nfunction normalizeFieldKey(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 100)\n}\n\nfunction readAkeneoOptionSchemaMetadata(value: unknown): AkeneoOptionSchemaMetadata | null {\n const parsedValue = typeof value === 'string'\n ? (() => {\n try {\n return JSON.parse(value) as unknown\n } catch {\n return null\n }\n })()\n : value\n const metadata = safeRecord(parsedValue)\n if (!metadata) return null\n\n const familyCode = typeof metadata.familyCode === 'string' && metadata.familyCode.trim().length > 0\n ? metadata.familyCode.trim()\n : null\n const familyVariantCode = typeof metadata.familyVariantCode === 'string' && metadata.familyVariantCode.trim().length > 0\n ? metadata.familyVariantCode.trim()\n : null\n const attributeCodes = Array.isArray(metadata.attributeCodes)\n ? dedupeStrings(metadata.attributeCodes.filter((entry): entry is string => typeof entry === 'string'))\n : []\n const richAttributes = safeRecord(metadata.richAttributes) ?? {}\n\n if (!familyCode && !familyVariantCode) return null\n if (attributeCodes.length === 0) return null\n\n return {\n familyCode,\n familyVariantCode,\n attributeCodes,\n richAttributes: Object.fromEntries(\n Object.entries(richAttributes)\n .filter(([, entry]) => Boolean(safeRecord(entry))),\n ) as Record<string, Record<string, unknown>>,\n }\n}\n\nfunction mapAkeneoAttributeInputType(attributeType: string): 'select' | 'text' | 'textarea' | 'number' | null {\n if (attributeType === 'pim_catalog_simpleselect' || attributeType === 'akeneo_reference_entity' || attributeType === 'akeneo_reference_entity_collection') {\n return 'select'\n }\n if (attributeType === 'pim_catalog_multiselect') return 'select'\n if (attributeType === 'pim_catalog_text') return 'text'\n if (attributeType === 'pim_catalog_textarea') return 'textarea'\n if (\n attributeType === 'pim_catalog_number'\n || attributeType === 'pim_catalog_metric'\n || attributeType === 'pim_catalog_price_collection'\n ) {\n return 'number'\n }\n return null\n}\n\nfunction mapAkeneoAttributeToCustomFieldKind(attribute: AkeneoAttribute, preferredKind?: AkeneoCustomFieldKind | null): AkeneoCustomFieldKind | null {\n if (preferredKind) return preferredKind\n if (attribute.type === 'pim_catalog_boolean') return 'boolean'\n if (attribute.type === 'pim_catalog_number') {\n return attribute.decimals_allowed === false ? 'integer' : 'float'\n }\n if (attribute.type === 'pim_catalog_metric') return 'float'\n if (\n attribute.type === 'pim_catalog_simpleselect'\n || attribute.type === 'pim_catalog_multiselect'\n || attribute.type === 'akeneo_reference_entity'\n || attribute.type === 'akeneo_reference_entity_collection'\n ) {\n return 'select'\n }\n if (attribute.type === 'pim_catalog_textarea') return 'multiline'\n if (attribute.type === 'pim_catalog_text') return 'text'\n if (attribute.type === 'pim_catalog_date') return 'text'\n return null\n}\n\nfunction buildValidationRules(attribute: AkeneoAttribute): Array<{ rule: string; param?: unknown }> {\n const rules: Array<{ rule: string; param?: unknown }> = []\n if (attribute.is_required_for_completeness) rules.push({ rule: 'required' })\n if (typeof attribute.max_characters === 'number' && Number.isFinite(attribute.max_characters)) {\n rules.push({ rule: 'maxLength', param: attribute.max_characters })\n }\n if (attribute.validation_rule === 'regexp' && typeof attribute.validation_regexp === 'string' && attribute.validation_regexp.trim().length > 0) {\n rules.push({ rule: 'pattern', param: attribute.validation_regexp.trim() })\n }\n const minimumValue = coerceNumber(attribute.minimum_value)\n if (minimumValue !== null) rules.push({ rule: 'min', param: minimumValue })\n const maximumValue = coerceNumber(attribute.maximum_value)\n if (maximumValue !== null) rules.push({ rule: 'max', param: maximumValue })\n return rules\n}\n\nfunction buildAttributeMetadata(attribute: AkeneoAttribute, locale: string): Record<string, unknown> {\n return {\n provider: 'akeneo',\n attributeCode: attribute.code,\n type: attribute.type,\n label: labelFromLocalizedRecord(attribute.labels ?? null, locale, attribute.code),\n groupCode: attribute.group ?? null,\n groupLabel: attribute.group_labels ? labelFromLocalizedRecord(attribute.group_labels, locale, attribute.group ?? 'Akeneo') : null,\n localizable: Boolean(attribute.localizable),\n scopable: Boolean(attribute.scopable),\n isRequiredForCompleteness: Boolean(attribute.is_required_for_completeness),\n unique: Boolean(attribute.unique),\n useableAsGridFilter: Boolean(attribute.useable_as_grid_filter),\n validationRule: attribute.validation_rule ?? null,\n validationRegexp: attribute.validation_regexp ?? null,\n decimalsAllowed: attribute.decimals_allowed ?? null,\n negativeAllowed: attribute.negative_allowed ?? null,\n minimumValue: attribute.minimum_value ?? null,\n maximumValue: attribute.maximum_value ?? null,\n metricFamily: attribute.metric_family ?? null,\n defaultMetricUnit: attribute.default_metric_unit ?? null,\n referenceDataName: attribute.reference_data_name ?? null,\n }\n}\n\nfunction familyRequiresAttribute(family: AkeneoFamily, attributeCode: string): boolean {\n const requirements = family.attribute_requirements\n if (!requirements || typeof requirements !== 'object') return false\n return Object.values(requirements).some((codes) => Array.isArray(codes) && codes.includes(attributeCode))\n}\n\nfunction resolvePriceVariantId(price: Pick<CatalogProductPrice, 'variant'>): string | null {\n const variant: unknown = price.variant\n if (typeof variant === 'string') return variant\n return price.variant?.id ?? null\n}\n\nfunction parsePriceCollection(value: unknown): Array<{ currencyCode: string; amount: number }> {\n if (!Array.isArray(value)) return []\n return value\n .map((entry) => {\n const record = safeRecord(entry)\n const currencyCode = typeof record?.currency === 'string' ? record.currency.trim().toUpperCase() : ''\n const amount = coerceNumber(record?.amount)\n if (!currencyCode || amount === null) return null\n return { currencyCode, amount }\n })\n .filter((entry): entry is { currencyCode: string; amount: number } => Boolean(entry))\n}\n\nfunction collectMediaReferences(value: unknown): MediaReference[] {\n const values = Array.isArray(value) ? value : value === null || value === undefined ? [] : [value]\n return values\n .map((entry) => {\n if (typeof entry === 'string' && entry.trim().length > 0) {\n return {\n codeOrUrl: entry.trim(),\n fileNameHint: null,\n mimeTypeHint: null,\n }\n }\n const record = safeRecord(entry)\n if (!record) return null\n const linkRecord = safeRecord(record._links)\n const downloadRecord = safeRecord(linkRecord?.download)\n const codeOrUrl = coerceString(record.code)\n ?? coerceString(record.download_link)\n ?? coerceString(record.href)\n ?? coerceString(downloadRecord?.href)\n if (!codeOrUrl) return null\n return {\n codeOrUrl,\n fileNameHint: coerceString(record.original_filename) ?? coerceString(record.file_path),\n mimeTypeHint: coerceString(record.mime_type),\n }\n })\n .filter((entry): entry is MediaReference => Boolean(entry))\n}\n\nexport function resolveAkeneoMediaTarget(params: {\n mappingTarget: 'product' | 'variant'\n attributeCode: string\n variantAttributeCodes: string[]\n productScopedValue: unknown\n variantScopedValue: unknown\n}): 'product' | 'variant' {\n const hasProductValue = params.productScopedValue !== null && params.productScopedValue !== undefined\n const hasVariantValue = params.variantScopedValue !== null && params.variantScopedValue !== undefined\n\n if (params.variantAttributeCodes.includes(params.attributeCode)) {\n return 'variant'\n }\n if (hasProductValue) {\n return 'product'\n }\n if (hasVariantValue) {\n return 'variant'\n }\n return params.mappingTarget\n}\n\nfunction resolveCustomFieldValue(value: unknown, attribute: AkeneoAttribute, kind: AkeneoCustomFieldKind): unknown {\n if (kind === 'boolean') return coerceBoolean(value)\n if (kind === 'integer') return coerceNumber(value) === null ? null : Math.trunc(Number(value))\n if (kind === 'float') return attribute.type === 'pim_catalog_metric' ? coerceMetricAmount(value) : coerceNumber(value)\n if (kind === 'multiline') return normalizeMarkdownText(coerceString(value))\n if (kind === 'text') {\n if (typeof value === 'string') return normalizeMarkdownText(value)\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n return value ? JSON.stringify(value) : null\n }\n if (kind === 'select') {\n if (Array.isArray(value)) {\n const items = value.map((entry) => coerceString(entry)).filter((entry): entry is string => Boolean(entry))\n return items.length > 0 ? items : null\n }\n return coerceString(value)\n }\n return null\n}\n\nfunction relationTypeFromAssociation(associationType: string): 'bundle' | 'grouped' {\n const normalized = associationType.trim().toLowerCase()\n return normalized.includes('pack') || normalized.includes('bundle') ? 'bundle' : 'grouped'\n}\n\nfunction titleizeCode(value: string): string {\n return value\n .trim()\n .replace(/[_-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n}\n\nfunction findFieldsetMapping(\n mappings: AkeneoFieldsetMapping[],\n target: 'product' | 'variant',\n sourceType: 'family' | 'familyVariant',\n sourceCode: string | null,\n): AkeneoFieldsetMapping | null {\n if (!sourceCode) return null\n return mappings.find((entry) => (\n entry.target === target\n && entry.sourceType === sourceType\n && entry.sourceCode === sourceCode\n )) ?? null\n}\n\nfunction applyFieldsetOverride(\n fallback: CustomFieldsetDefinition | null,\n override: AkeneoFieldsetMapping | null,\n): CustomFieldsetDefinition | null {\n if (!fallback || !override) return fallback\n return {\n ...fallback,\n code: override.fieldsetCode,\n label: override.fieldsetLabel,\n description: override.description ?? fallback.description,\n }\n}\n\nfunction collectFieldsetGroups(attributes: AkeneoAttribute[], locale: string): NonNullable<CustomFieldsetDefinition['groups']> | undefined {\n const groups = dedupeStrings(attributes.map((attribute) => attribute.group))\n .map((groupCode) => {\n const attribute = attributes.find((entry) => entry.group === groupCode)\n return {\n code: normalizeFieldKey(groupCode),\n title: attribute?.group_labels\n ? labelFromLocalizedRecord(attribute.group_labels, locale, groupCode)\n : titleizeCode(groupCode),\n }\n })\n .filter((group) => group.code.length > 0)\n return groups.length > 0 ? groups : undefined\n}\n\nfunction collectFieldsetGroupsFromSchemaMetadata(\n metadata: AkeneoOptionSchemaMetadata,\n): NonNullable<CustomFieldsetDefinition['groups']> | undefined {\n const groups = new Map<string, { code: string; title: string }>()\n for (const attributeCode of metadata.attributeCodes) {\n const attribute = safeRecord(metadata.richAttributes[attributeCode])\n const groupCode = typeof attribute?.groupCode === 'string' && attribute.groupCode.trim().length > 0\n ? attribute.groupCode.trim()\n : null\n if (!groupCode) continue\n const normalizedCode = normalizeFieldKey(groupCode)\n if (!normalizedCode || groups.has(normalizedCode)) continue\n const title = typeof attribute?.groupLabel === 'string' && attribute.groupLabel.trim().length > 0\n ? attribute.groupLabel.trim()\n : titleizeCode(groupCode)\n groups.set(normalizedCode, { code: normalizedCode, title })\n }\n return groups.size > 0 ? Array.from(groups.values()) : undefined\n}\n\nfunction buildFieldsetPlanFromOptionSchema(params: {\n schema: Pick<CatalogOptionSchemaTemplate, 'code' | 'name' | 'description'>\n metadata: AkeneoOptionSchemaMetadata\n locale: string\n fieldsetMappings: AkeneoFieldsetMapping[]\n}): { target: 'product' | 'variant'; fieldset: CustomFieldsetDefinition | null } {\n const target = params.metadata.familyVariantCode ? 'variant' : 'product'\n const sourceType = params.metadata.familyVariantCode ? 'familyVariant' : 'family'\n const sourceCode = params.metadata.familyVariantCode ?? params.metadata.familyCode\n const fallbackCode = buildAkeneoFieldsetCode(target, sourceCode)\n const override = findFieldsetMapping(params.fieldsetMappings, target, sourceType, sourceCode)\n const fallbackLabel = params.schema.name?.trim().length\n ? params.schema.name.trim()\n : titleizeCode(sourceCode ?? `Akeneo ${target}`)\n const fallbackDescription = params.schema.description?.trim().length\n ? params.schema.description.trim()\n : sourceType === 'familyVariant' && params.metadata.familyVariantCode\n ? `Akeneo family variant ${params.metadata.familyVariantCode}`\n : params.metadata.familyCode\n ? `Akeneo family ${params.metadata.familyCode}`\n : `Akeneo ${target} attributes`\n const fieldsetCode = override?.fieldsetCode ?? fallbackCode\n if (!fieldsetCode) {\n return { target, fieldset: null }\n }\n\n return {\n target,\n fieldset: {\n code: fieldsetCode,\n label: override?.fieldsetLabel ?? fallbackLabel,\n description: override?.description ?? fallbackDescription,\n groups: collectFieldsetGroupsFromSchemaMetadata(params.metadata),\n },\n }\n}\n\nfunction buildFieldsetPlan(params: {\n family: AkeneoFamily | null\n familyVariant: AkeneoFamilyVariant | null\n productAttributes: AkeneoAttribute[]\n variantAttributes: AkeneoAttribute[]\n locale: string\n fieldsetMappings: AkeneoFieldsetMapping[]\n}): AkeneoFieldsetPlan {\n const productFallbackCode = buildAkeneoFieldsetCode('product', params.family?.code ?? null)\n const variantFallbackCode = buildAkeneoFieldsetCode('variant', params.familyVariant?.code ?? params.family?.code ?? null)\n\n const productFallback = productFallbackCode && params.productAttributes.length > 0\n ? {\n code: productFallbackCode,\n label: labelFromLocalizedRecord(params.family?.labels ?? null, params.locale, params.family?.code ?? 'Akeneo product'),\n description: params.family\n ? `Akeneo family ${params.family.code}`\n : 'Akeneo-imported product attributes',\n groups: collectFieldsetGroups(params.productAttributes, params.locale),\n }\n : null\n const variantFallback = variantFallbackCode && params.variantAttributes.length > 0\n ? {\n code: variantFallbackCode,\n label: labelFromLocalizedRecord(\n params.familyVariant?.labels ?? params.family?.labels ?? null,\n params.locale,\n params.familyVariant?.code ?? params.family?.code ?? 'Akeneo variant',\n ),\n description: params.familyVariant?.code\n ? `Akeneo family variant ${params.familyVariant.code}`\n : params.family?.code\n ? `Akeneo variant attributes for family ${params.family.code}`\n : 'Akeneo-imported variant attributes',\n groups: collectFieldsetGroups(params.variantAttributes, params.locale),\n }\n : null\n\n return {\n product: applyFieldsetOverride(\n productFallback,\n findFieldsetMapping(params.fieldsetMappings, 'product', 'family', params.family?.code ?? null),\n ),\n variant: applyFieldsetOverride(\n variantFallback,\n findFieldsetMapping(params.fieldsetMappings, 'variant', 'familyVariant', params.familyVariant?.code ?? null)\n ?? findFieldsetMapping(params.fieldsetMappings, 'variant', 'family', params.family?.code ?? null),\n ),\n }\n}\n\nfunction dedupeCustomFieldMappings(items: Array<{ attributeCode: string; fieldKey: string; target: 'product' | 'variant'; kind?: AkeneoCustomFieldKind | null; skip?: boolean }>) {\n const seen = new Set<string>()\n return items.filter((item) => {\n const key = `${item.target}:${item.attributeCode}:${item.fieldKey}:${item.skip === true ? 'skip' : 'import'}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\nfunction dedupeMediaMappings(items: Array<{ attributeCode: string; target: 'product' | 'variant'; kind: 'image' | 'file' }>) {\n const seen = new Set<string>()\n return items.filter((item) => {\n const key = `${item.target}:${item.kind}:${item.attributeCode}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\nfunction collectValueScopes(layers: AkeneoValues[], attributeCode: string): Array<string | null> {\n const seen = new Set<string>()\n const scopes: Array<string | null> = []\n for (const layer of layers) {\n const entries = Array.isArray(layer?.[attributeCode]) ? layer[attributeCode] : []\n for (const entry of entries) {\n const scope = coerceString(entry?.scope)\n const key = scope ?? '__null__'\n if (seen.has(key)) continue\n seen.add(key)\n scopes.push(scope)\n }\n }\n return scopes\n}\n\nfunction resolveImportedAkeneoChannels(settings: AkeneoProductMappingSettings): string[] {\n return dedupeStrings([\n ...(settings.channels ?? []),\n settings.channel,\n ])\n}\n\nfunction shouldImportAkeneoChannel(settings: AkeneoProductMappingSettings, akeneoChannel: string | null): boolean {\n if (!akeneoChannel) return true\n if (settings.importAllChannels) return true\n const selectedChannels = resolveImportedAkeneoChannels(settings)\n if (selectedChannels.length === 0) return true\n return selectedChannels.includes(akeneoChannel)\n}\n\nexport async function createAkeneoImporter(client: AkeneoClient, scope: ImportScope) {\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const commandBus = container.resolve('commandBus') as CommandBus\n const dataEngine = container.resolve('dataEngine') as DataEngine\n const externalIdMappingService = container.resolve('externalIdMappingService') as ExternalIdMappingService\n let cacheService: { deleteByTags?: (tags: string[]) => Promise<void> } | null = null\n try {\n cacheService = container.resolve('cache') as { deleteByTags?: (tags: string[]) => Promise<void> }\n } catch {\n cacheService = null\n }\n const categoryCache = new Map<string, Promise<string | null>>()\n const optionSchemaCache = new Map<string, Promise<UpsertResult | null>>()\n const channelCache = new Map<string, Promise<{ id: string; code: string } | null>>()\n const priceKindCache = new Map<string, Promise<{ id: string; code: string; displayMode: string } | null>>()\n const customFieldSyncCache = new Map<string, Promise<CustomFieldSyncItem[]>>()\n const globalFieldsetAssignmentCache = new Map<string, Promise<ResolvedGlobalFieldsetAssignments>>()\n const preferredChannelCodeCache = new Map<string, Promise<string | null>>()\n const preferredPriceKindCodeCache = new Map<string, Promise<string | null>>()\n const attributeOptionLabelCache = new Map<string, Promise<Map<string, string>>>()\n const defaultProductSettings = buildDefaultAkeneoMapping('products').settings?.products\n\n function buildCommandContext(): CommandRuntimeContext {\n return {\n container,\n auth: null,\n organizationScope: {\n selectedId: scope.organizationId,\n filterIds: [scope.organizationId],\n allowedIds: [scope.organizationId],\n tenantId: scope.tenantId,\n },\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n }\n\n async function emitAttachmentCrudChange(\n action: 'created' | 'updated' | 'deleted',\n attachment: Attachment,\n ): Promise<void> {\n await emitCrudSideEffects({\n dataEngine,\n action,\n entity: attachment,\n identifiers: {\n id: attachment.id,\n organizationId: attachment.organizationId ?? null,\n tenantId: attachment.tenantId ?? null,\n },\n events: attachmentCrudEvents,\n indexer: attachmentCrudIndexer,\n })\n await dataEngine.flushOrmEntityChanges()\n }\n\n async function executeCommand<TResult>(commandId: string, input: Record<string, unknown>): Promise<TResult> {\n try {\n const executed = await commandBus.execute<Record<string, unknown>, TResult>(commandId, {\n input,\n ctx: buildCommandContext(),\n })\n return executed.result\n } catch (error) {\n const message = error instanceof Error ? error.message : JSON.stringify(error)\n throw new Error(`${commandId} failed: ${message}`)\n }\n }\n\n async function lookupProductBySku(sku: string | null): Promise<string | null> {\n if (!sku) return null\n const product = await findOneWithDecryption(\n em,\n CatalogProduct,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n sku,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n return product?.id ?? null\n }\n\n async function lookupVariantBySku(sku: string | null, productId?: string | null): Promise<string | null> {\n if (!sku) return null\n const variant = await findOneWithDecryption(\n em,\n CatalogProductVariant,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n ...(productId ? { product: productId } : {}),\n sku,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n return variant?.id ?? null\n }\n\n async function resolveExistingProductId(productExternalId: string, sku: string | null): Promise<string | null> {\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product', productExternalId, scope)\n if (mappedId) {\n const mappedProduct = await findOneWithDecryption(\n em,\n CatalogProduct,\n {\n id: mappedId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (mappedProduct) return mappedProduct.id\n }\n\n return lookupProductBySku(sku)\n }\n\n async function resolveExistingVariantId(\n variantExternalId: string,\n sku: string | null,\n productId: string,\n ): Promise<string | null> {\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_variant', variantExternalId, scope)\n if (mappedId) {\n const mappedVariant = await findOneWithDecryption(\n em,\n CatalogProductVariant,\n {\n id: mappedId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product: productId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (mappedVariant) return mappedVariant.id\n }\n\n return lookupVariantBySku(sku, productId)\n }\n\n async function resolveCategoryId(code: string | null | undefined, locale: string): Promise<string | null> {\n if (!code) return null\n if (!categoryCache.has(code)) {\n categoryCache.set(code, (async () => {\n const mapped = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_category', code, scope)\n if (mapped) return mapped\n\n const existing = await findOneWithDecryption(\n em,\n CatalogProductCategory,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n slug: slugifyAkeneoCode(code),\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (existing) {\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_category', existing.id, code, scope)\n return existing.id\n }\n\n const remote = await client.getCategory(code)\n if (!remote) return null\n const result = await upsertCategory(remote, locale)\n return result.localId\n })())\n }\n return categoryCache.get(code) ?? null\n }\n\n async function resolveChannel(code: string, options?: { createIfMissing?: boolean; label?: string | null }): Promise<{ id: string; code: string } | null> {\n const normalizedCode = code.trim().toLowerCase()\n if (!normalizedCode) return null\n const cacheKey = `${normalizedCode}:${options?.createIfMissing ? 'create' : 'read'}:${options?.label ?? ''}`\n if (!channelCache.has(cacheKey)) {\n channelCache.set(cacheKey, (async () => {\n const channel = await findOneWithDecryption(em, SalesChannel, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n code: normalizedCode,\n deletedAt: null,\n isActive: true,\n }, undefined, scope)\n if (channel) {\n return { id: channel.id, code: channel.code ?? normalizedCode }\n }\n if (!options?.createIfMissing) return null\n\n const created = await executeCommand<{ channelId: string }>('sales.channels.create', {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: options.label?.trim() || titleizeCode(normalizedCode),\n code: normalizedCode,\n metadata: {\n source: 'akeneo',\n autoCreatedBy: 'sync_akeneo',\n },\n isActive: true,\n })\n return {\n id: created.channelId,\n code: normalizedCode,\n }\n })())\n }\n return channelCache.get(cacheKey) ?? null\n }\n\n async function resolvePriceKind(code: string): Promise<{ id: string; code: string; displayMode: string } | null> {\n const normalizedCode = code.trim().toLowerCase()\n if (!normalizedCode) return null\n if (!priceKindCache.has(normalizedCode)) {\n priceKindCache.set(normalizedCode, (async () => {\n const priceKind = await findOneWithDecryption(\n em,\n CatalogPriceKind,\n {\n tenantId: scope.tenantId,\n code: normalizedCode,\n deletedAt: null,\n isActive: true,\n },\n undefined,\n scope,\n )\n return priceKind ? { id: priceKind.id, code: priceKind.code, displayMode: priceKind.displayMode } : null\n })())\n }\n return priceKindCache.get(normalizedCode) ?? null\n }\n\n async function resolvePreferredLocalChannelCode(): Promise<string | null> {\n const cacheKey = 'preferred'\n if (!preferredChannelCodeCache.has(cacheKey)) {\n preferredChannelCodeCache.set(cacheKey, (async () => {\n const channels = await findWithDecryption(em, SalesChannel, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n isActive: true,\n }, {\n orderBy: { createdAt: 'asc' },\n }, scope)\n const preferredCodes = ['web', 'online', 'ecommerce', 'default']\n for (const preferredCode of preferredCodes) {\n const match = channels.find((channel) => (channel.code ?? '').trim().toLowerCase() === preferredCode)\n if (match?.code) return match.code\n }\n return channels.find((channel) => typeof channel.code === 'string' && channel.code.trim().length > 0)?.code ?? null\n })())\n }\n return preferredChannelCodeCache.get(cacheKey) ?? null\n }\n\n async function resolvePreferredPriceKindCode(): Promise<string | null> {\n const cacheKey = 'preferred'\n if (!preferredPriceKindCodeCache.has(cacheKey)) {\n preferredPriceKindCodeCache.set(cacheKey, (async () => {\n const priceKinds = await findWithDecryption(em, CatalogPriceKind, {\n tenantId: scope.tenantId,\n deletedAt: null,\n isActive: true,\n }, {\n orderBy: { createdAt: 'asc' },\n }, scope)\n const preferredCodes = ['regular', 'sale', 'base', 'default']\n for (const preferredCode of preferredCodes) {\n const match = priceKinds.find((priceKind) => priceKind.code.trim().toLowerCase() === preferredCode)\n if (match) return match.code\n }\n return priceKinds[0]?.code ?? null\n })())\n }\n return preferredPriceKindCodeCache.get(cacheKey) ?? null\n }\n\n async function ensureEntityFieldsetConfig(entityId: string, fieldset: CustomFieldsetDefinition | null): Promise<void> {\n if (!fieldset) return\n let config = await findOneWithDecryption(em, CustomFieldEntityConfig, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n if (!config) {\n config = em.create(CustomFieldEntityConfig, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n }\n\n const existing = normalizeEntityFieldsetConfig(config.configJson ?? {})\n const remaining = existing.fieldsets.filter((entry) => entry.code !== fieldset.code)\n config.configJson = {\n fieldsets: [...remaining, fieldset],\n singleFieldsetPerRecord: true,\n }\n config.isActive = true\n config.deletedAt = null\n config.updatedAt = new Date()\n em.persist(config)\n await em.flush()\n }\n\n async function upsertCategory(category: AkeneoCategory, locale: string): Promise<UpsertResult> {\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_category', category.code, scope)\n const existingId = mappedId\n ?? (await findOneWithDecryption(\n em,\n CatalogProductCategory,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n slug: slugifyAkeneoCode(category.code),\n deletedAt: null,\n },\n undefined,\n scope,\n ))?.id\n ?? null\n\n const parentId = category.parent ? await resolveCategoryId(category.parent, locale) : null\n const input = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: labelFromLocalizedRecord(category.labels ?? null, locale, category.code),\n slug: slugifyAkeneoCode(category.code),\n description: undefined,\n parentId,\n isActive: true,\n }\n\n if (existingId) {\n await executeCommand('catalog.categories.update', {\n id: existingId,\n ...input,\n })\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_category', existingId, category.code, scope)\n return { localId: existingId, action: 'update' }\n }\n\n const created = await executeCommand<{ categoryId: string }>('catalog.categories.create', input)\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_category', created.categoryId, category.code, scope)\n return { localId: created.categoryId, action: 'create' }\n }\n\n async function buildOptionSchemaDefinition(attribute: AkeneoAttribute, family: AkeneoFamily, locale: string) {\n const inputType = mapAkeneoAttributeInputType(attribute.type)\n if (!inputType) return null\n\n const definition: Record<string, unknown> = {\n code: slugifyAkeneoCode(attribute.code),\n label: labelFromLocalizedRecord(attribute.labels ?? null, locale, attribute.code),\n description: typeof attribute.group === 'string' ? `Akeneo group: ${attribute.group}` : undefined,\n inputType,\n isRequired: familyRequiresAttribute(family, attribute.code),\n }\n\n if (attribute.type === 'pim_catalog_multiselect') {\n definition.isMultiple = true\n }\n\n if (inputType === 'select' && (attribute.type === 'pim_catalog_simpleselect' || attribute.type === 'pim_catalog_multiselect')) {\n const options = await client.listAttributeOptions(attribute.code).catch(() => [])\n definition.choices = options.map((option) => ({\n code: slugifyAkeneoCode(option.code),\n label: labelFromLocalizedRecord(option.labels ?? null, locale, option.code),\n }))\n }\n\n return definition\n }\n\n async function getAttributeOptionLabels(attributeCode: string, locale: string): Promise<Map<string, string>> {\n const cacheKey = `${attributeCode}:${locale}`\n if (!attributeOptionLabelCache.has(cacheKey)) {\n attributeOptionLabelCache.set(cacheKey, (async () => {\n const options = await client.listAttributeOptions(attributeCode).catch(() => [])\n return new Map(\n options.map((option) => [\n option.code,\n labelFromLocalizedRecord(option.labels ?? null, locale, option.code),\n ]),\n )\n })())\n }\n return attributeOptionLabelCache.get(cacheKey) ?? new Map<string, string>()\n }\n\n async function ensureOptionSchemaForFamily(\n family: AkeneoFamily,\n familyVariant: AkeneoFamilyVariant | null,\n includeTextAttributes: boolean,\n includeNumericAttributes: boolean,\n locale: string,\n attributeCodesOverride?: string[] | null,\n ): Promise<UpsertResult | null> {\n const requestedAttributeCodes = Array.isArray(attributeCodesOverride)\n ? dedupeStrings(attributeCodesOverride)\n : null\n const cacheKey = `${family.code}:${familyVariant?.code ?? 'family'}:${locale}:${includeTextAttributes}:${includeNumericAttributes}:${requestedAttributeCodes ? requestedAttributeCodes.join('|') : 'all'}`\n if (!optionSchemaCache.has(cacheKey)) {\n optionSchemaCache.set(cacheKey, (async () => {\n if (requestedAttributeCodes && requestedAttributeCodes.length === 0) {\n return null\n }\n const externalId = familyVariant?.code ?? family.code\n const schemaCode = slugifyAkeneoCode(`akeneo-${externalId}`)\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_option_schema', externalId, scope)\n const existing = mappedId\n ? await findOneWithDecryption(\n em,\n CatalogOptionSchemaTemplate,\n {\n id: mappedId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n : await findOneWithDecryption(\n em,\n CatalogOptionSchemaTemplate,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n code: schemaCode,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n const familyAttributes = Array.isArray(family.attributes) ? family.attributes : []\n const familyVariantAttributes = familyVariant?.variant_attribute_sets?.flatMap((set) => [\n ...(Array.isArray(set.attributes) ? set.attributes : []),\n ...(Array.isArray(set.axes) ? set.axes : []),\n ]) ?? []\n const attributeCodes = requestedAttributeCodes ?? dedupeStrings([...familyAttributes, ...familyVariantAttributes])\n const definitions: Record<string, unknown>[] = []\n const richAttributes: Record<string, unknown> = {}\n for (const code of attributeCodes) {\n const attribute = await client.getAttribute(code)\n if (!attribute) continue\n const inputType = mapAkeneoAttributeInputType(attribute.type)\n if (!inputType) continue\n if ((inputType === 'text' || inputType === 'textarea') && !includeTextAttributes) continue\n if (inputType === 'number' && !includeNumericAttributes) continue\n const definition = await buildOptionSchemaDefinition(attribute, family, locale)\n if (!definition) continue\n definitions.push(definition)\n richAttributes[code] = {\n ...buildAttributeMetadata(attribute, locale),\n validation: buildValidationRules(attribute),\n }\n if (definitions.length >= 64) break\n }\n\n const schemaInput = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: labelFromLocalizedRecord(family.labels ?? null, locale, family.code),\n code: schemaCode,\n description: familyVariant?.code ? `Akeneo family variant ${familyVariant.code}` : `Akeneo family ${family.code}`,\n schema: {\n version: 1,\n name: labelFromLocalizedRecord(family.labels ?? null, locale, family.code),\n description: familyVariant?.code ? `Akeneo family variant ${familyVariant.code}` : `Akeneo family ${family.code}`,\n options: definitions,\n },\n metadata: {\n source: 'akeneo',\n familyCode: family.code,\n familyVariantCode: familyVariant?.code ?? null,\n attributeCodes,\n richAttributes,\n attributeAsLabel: family.attribute_as_label ?? null,\n attributeAsImage: family.attribute_as_image ?? null,\n variantAxes: familyVariant?.variant_attribute_sets?.map((set) => ({\n level: set.level ?? null,\n axes: Array.isArray(set.axes) ? set.axes : [],\n attributes: Array.isArray(set.attributes) ? set.attributes : [],\n })) ?? [],\n },\n isActive: true,\n }\n\n if (existing) {\n await executeCommand('catalog.optionSchemas.update', {\n id: existing.id,\n ...schemaInput,\n })\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_option_schema', existing.id, externalId, scope)\n return { localId: existing.id, action: 'update' }\n }\n\n const created = await executeCommand<{ schemaId: string }>('catalog.optionSchemas.create', schemaInput)\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_option_schema', created.schemaId, externalId, scope)\n return { localId: created.schemaId, action: 'create' }\n })())\n }\n\n return optionSchemaCache.get(cacheKey) ?? null\n }\n\n async function syncMappedCustomFields(\n mapping: AkeneoDataMapping,\n locale: string,\n fieldsetPlan?: AkeneoFieldsetPlan | null,\n options?: { forceRefresh?: boolean },\n ): Promise<CustomFieldSyncItem[]> {\n const settings = mapping.settings?.products\n if (!settings || settings.customFieldMappings.length === 0) return []\n const cacheKey = JSON.stringify({\n customFieldMappings: settings.customFieldMappings.filter((mapping) => !mapping.skip),\n fieldsetPlan,\n locale,\n })\n if (options?.forceRefresh) {\n customFieldSyncCache.delete(cacheKey)\n globalFieldsetAssignmentCache.delete(JSON.stringify({\n customFieldMappings: settings.customFieldMappings.filter((entry) => !entry.skip),\n fieldsetMappings: settings.fieldsetMappings,\n }))\n }\n if (!customFieldSyncCache.has(cacheKey)) {\n customFieldSyncCache.set(cacheKey, (async () => {\n const productFields: Array<CustomFieldDefinition & { sourceMetadata?: Record<string, unknown> }> = []\n const variantFields: Array<CustomFieldDefinition & { sourceMetadata?: Record<string, unknown> }> = []\n const items: CustomFieldSyncItem[] = []\n const globalAssignments = await resolveGlobalFieldsetAssignments(settings)\n const existingDefinitions = await findWithDecryption(em, CustomFieldDef, {\n entityId: { $in: [PRODUCT_ENTITY_ID, VARIANT_ENTITY_ID] } as never,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n const existingFieldsetsByEntityAndKey = new Map<string, string[]>()\n for (const definition of existingDefinitions) {\n const config = safeRecord(definition.configJson)\n existingFieldsetsByEntityAndKey.set(\n `${definition.entityId}:${definition.key}`,\n readConfiguredFieldsets(config),\n )\n }\n\n for (const fieldMapping of settings.customFieldMappings) {\n if (fieldMapping.skip) continue\n const attribute = await client.getAttribute(fieldMapping.attributeCode)\n if (!attribute) continue\n const kind = mapAkeneoAttributeToCustomFieldKind(attribute, fieldMapping.kind)\n if (!kind) continue\n const entityId = fieldMapping.target === 'product' ? PRODUCT_ENTITY_ID : VARIANT_ENTITY_ID\n const normalizedKey = normalizeFieldKey(fieldMapping.fieldKey)\n const currentFieldsetCode = fieldMapping.target === 'product'\n ? fieldsetPlan?.product?.code ?? null\n : fieldsetPlan?.variant?.code ?? null\n const globalFieldsets = fieldMapping.target === 'product'\n ? globalAssignments.product.fieldsetsByKey.get(normalizedKey) ?? []\n : globalAssignments.variant.fieldsetsByKey.get(normalizedKey) ?? []\n const inheritedFieldsets = existingFieldsetsByEntityAndKey.get(`${entityId}:${normalizedKey}`) ?? []\n const effectiveFieldsets = dedupeStrings([\n ...globalFieldsets,\n ...inheritedFieldsets,\n ...(currentFieldsetCode ? [currentFieldsetCode] : []),\n ])\n const options = kind === 'select' && (attribute.type === 'pim_catalog_simpleselect' || attribute.type === 'pim_catalog_multiselect')\n ? await client.listAttributeOptions(attribute.code).catch(() => [])\n : []\n const field: CustomFieldDefinition & { sourceMetadata?: Record<string, unknown> } = {\n key: normalizedKey,\n kind,\n label: labelFromLocalizedRecord(attribute.labels ?? null, locale, fieldMapping.fieldKey),\n description: `Akeneo attribute ${fieldMapping.attributeCode}`,\n fieldset: effectiveFieldsets.length === 1 ? effectiveFieldsets[0] : undefined,\n fieldsets: effectiveFieldsets.length > 0 ? effectiveFieldsets : undefined,\n multi: attribute.type === 'pim_catalog_multiselect' || attribute.type === 'akeneo_reference_entity_collection',\n options: options.map((option) => ({\n value: option.code,\n label: labelFromLocalizedRecord(option.labels ?? null, locale, option.code),\n })),\n filterable: Boolean(attribute.useable_as_grid_filter),\n listVisible: false,\n editor: kind === 'multiline' ? 'markdown' : undefined,\n validation: buildValidationRules(attribute),\n group: attribute.group ? {\n code: normalizeFieldKey(attribute.group),\n title: attribute.group_labels ? labelFromLocalizedRecord(attribute.group_labels, locale, attribute.group) : attribute.group,\n } : undefined,\n sourceMetadata: buildAttributeMetadata(attribute, locale),\n }\n if (fieldMapping.target === 'product') productFields.push(field)\n else variantFields.push(field)\n items.push({\n externalId: `${fieldMapping.target}:${fieldMapping.attributeCode}`,\n action: 'update',\n data: {\n key: field.key,\n target: fieldMapping.target,\n attributeCode: fieldMapping.attributeCode,\n },\n })\n }\n\n const sets = []\n if (productFields.length > 0) {\n sets.push({\n entity: PRODUCT_ENTITY_ID,\n fields: productFields,\n source: 'akeneo',\n })\n }\n if (variantFields.length > 0) {\n sets.push({\n entity: VARIANT_ENTITY_ID,\n fields: variantFields,\n source: 'akeneo',\n })\n }\n\n if (sets.length > 0) {\n const productFieldAssignments = productFields.map((field) => ({\n key: field.key,\n fieldsets: resolveAkeneoFieldsetMemberships(\n existingFieldsetsByEntityAndKey.get(`${PRODUCT_ENTITY_ID}:${field.key}`) ?? [],\n fieldsetPlan?.product?.code ?? null,\n ),\n }))\n const variantFieldAssignments = variantFields.map((field) => ({\n key: field.key,\n fieldsets: resolveAkeneoFieldsetMemberships(\n existingFieldsetsByEntityAndKey.get(`${VARIANT_ENTITY_ID}:${field.key}`) ?? [],\n fieldsetPlan?.variant?.code ?? null,\n ),\n }))\n\n await ensureCustomFieldDefinitions(em, sets, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await Promise.all([\n ensureEntityFieldsetConfig(PRODUCT_ENTITY_ID, fieldsetPlan?.product ?? null),\n ensureEntityFieldsetConfig(VARIANT_ENTITY_ID, fieldsetPlan?.variant ?? null),\n ])\n await Promise.all([\n ensureAkeneoFieldsetAssignments(PRODUCT_ENTITY_ID, productFieldAssignments),\n ensureAkeneoFieldsetAssignments(VARIANT_ENTITY_ID, variantFieldAssignments),\n ])\n await Promise.all([\n reconcileAkeneoFieldsetAssignments(PRODUCT_ENTITY_ID, fieldsetPlan?.product?.code ?? null, productFields.map((field) => field.key)),\n reconcileAkeneoFieldsetAssignments(VARIANT_ENTITY_ID, fieldsetPlan?.variant?.code ?? null, variantFields.map((field) => field.key)),\n ])\n await invalidateDefinitionsCache(cacheService as never, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entityIds: [PRODUCT_ENTITY_ID, VARIANT_ENTITY_ID],\n })\n }\n\n return items\n })())\n }\n return customFieldSyncCache.get(cacheKey) ?? []\n }\n\n async function reconcileAkeneoFieldsetAssignments(\n entityId: string,\n fieldsetCode: string | null,\n desiredFieldKeys: string[],\n ): Promise<void> {\n if (!fieldsetCode) return\n\n const existingDefinitions = await findWithDecryption(em, CustomFieldDef, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n\n const keysToDetach = resolveAkeneoFieldKeysToDetach(\n existingDefinitions.map((definition) => {\n const config = safeRecord(definition.configJson)\n return {\n key: definition.key,\n description: typeof config?.description === 'string' ? config.description : null,\n fieldset: typeof config?.fieldset === 'string' ? config.fieldset : null,\n fieldsets: readConfiguredFieldsets(config),\n }\n }),\n desiredFieldKeys,\n fieldsetCode,\n )\n\n if (keysToDetach.length === 0) return\n\n for (const definition of existingDefinitions) {\n if (!keysToDetach.includes(definition.key)) continue\n const nextConfig = {\n ...(safeRecord(definition.configJson) ?? {}),\n }\n const remainingFieldsets = readConfiguredFieldsets(nextConfig).filter((entry) => entry !== fieldsetCode)\n if (remainingFieldsets.length === 0) {\n delete nextConfig.fieldset\n delete nextConfig.fieldsets\n } else if (remainingFieldsets.length === 1) {\n nextConfig.fieldset = remainingFieldsets[0]\n nextConfig.fieldsets = remainingFieldsets\n } else {\n delete nextConfig.fieldset\n nextConfig.fieldsets = remainingFieldsets\n }\n definition.configJson = nextConfig\n definition.updatedAt = new Date()\n }\n\n await em.flush()\n }\n\n async function ensureAkeneoFieldsetAssignments(\n entityId: string,\n assignments: DesiredFieldsetAssignment[],\n ): Promise<void> {\n const normalizedAssignments = assignments\n .map((assignment) => ({\n key: normalizeFieldKey(assignment.key),\n fieldsets: dedupeStrings(\n assignment.fieldsets\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n ),\n }))\n .filter((assignment) => assignment.key.length > 0 && assignment.fieldsets.length > 0)\n\n const normalizedKeys = normalizedAssignments.map((assignment) => assignment.key)\n if (normalizedKeys.length === 0) return\n\n const fieldsetsByKey = new Map(normalizedAssignments.map((assignment) => [assignment.key, assignment.fieldsets]))\n\n const existingDefinitions = await findWithDecryption(em, CustomFieldDef, {\n entityId,\n key: { $in: normalizedKeys } as never,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n\n let changed = false\n for (const definition of existingDefinitions) {\n const nextConfig = {\n ...(safeRecord(definition.configJson) ?? {}),\n }\n const nextFieldsets = fieldsetsByKey.get(definition.key) ?? []\n if (nextFieldsets.length === 0) continue\n\n const currentFieldsets = readConfiguredFieldsets(nextConfig)\n const currentPrimary = typeof nextConfig.fieldset === 'string' ? nextConfig.fieldset.trim() : ''\n const nextPrimary = nextFieldsets.length === 1 ? nextFieldsets[0] : ''\n const sameMemberships = currentFieldsets.length === nextFieldsets.length\n && currentFieldsets.every((entry, index) => entry === nextFieldsets[index])\n if (sameMemberships && currentPrimary === nextPrimary) continue\n\n if (nextFieldsets.length === 1) {\n nextConfig.fieldset = nextFieldsets[0]\n delete nextConfig.fieldsets\n } else {\n delete nextConfig.fieldset\n nextConfig.fieldsets = nextFieldsets\n }\n definition.configJson = nextConfig\n definition.updatedAt = new Date()\n changed = true\n }\n\n if (changed) {\n await em.flush()\n }\n }\n\n async function applyAkeneoManagedFieldsetAssignments(\n entityId: string,\n assignments: EntityFieldsetAssignments,\n ): Promise<void> {\n const dedupedFieldsets = new Map(assignments.fieldsets.map((fieldset) => [fieldset.code, fieldset]))\n await Promise.all(\n Array.from(dedupedFieldsets.values()).map((fieldset) => ensureEntityFieldsetConfig(entityId, fieldset)),\n )\n\n const definitions = await findWithDecryption(em, CustomFieldDef, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n\n let changed = false\n for (const definition of definitions) {\n const config = safeRecord(definition.configJson)\n const sourceMetadata = safeRecord(config?.sourceMetadata)\n const isAkeneoManaged = sourceMetadata?.provider === 'akeneo'\n || (typeof config?.description === 'string' && config.description.startsWith('Akeneo attribute '))\n if (!isAkeneoManaged) continue\n\n const nextConfig = {\n ...(config ?? {}),\n }\n const nextFieldsets = assignments.fieldsetsByKey.get(definition.key) ?? []\n const currentFieldsets = readConfiguredFieldsets(nextConfig)\n const currentPrimary = typeof nextConfig.fieldset === 'string' ? nextConfig.fieldset.trim() : ''\n const nextPrimary = nextFieldsets.length === 1 ? nextFieldsets[0] : ''\n const sameMemberships = currentFieldsets.length === nextFieldsets.length\n && currentFieldsets.every((entry, index) => entry === nextFieldsets[index])\n if (sameMemberships && currentPrimary === nextPrimary) continue\n\n if (nextFieldsets.length === 0) {\n delete nextConfig.fieldset\n delete nextConfig.fieldsets\n } else if (nextFieldsets.length === 1) {\n nextConfig.fieldset = nextFieldsets[0]\n delete nextConfig.fieldsets\n } else {\n delete nextConfig.fieldset\n nextConfig.fieldsets = nextFieldsets\n }\n\n definition.configJson = nextConfig\n definition.updatedAt = new Date()\n changed = true\n }\n\n if (changed) {\n await em.flush()\n await invalidateDefinitionsCache(cacheService as never, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entityIds: [entityId],\n })\n }\n }\n\n async function reconcileMappedCustomFieldFieldsets(mapping: AkeneoDataMapping): Promise<void> {\n const settings = mapping.settings?.products\n if (!settings || settings.customFieldMappings.length === 0) return\n\n const activeMappings = settings.customFieldMappings.filter((entry) => !entry.skip)\n if (activeMappings.length === 0) return\n\n globalFieldsetAssignmentCache.delete(JSON.stringify({\n customFieldMappings: settings.customFieldMappings.filter((entry) => !entry.skip),\n fieldsetMappings: settings.fieldsetMappings,\n }))\n em.clear()\n const globalAssignments = await resolveGlobalFieldsetAssignments(settings)\n const productAssignments = globalAssignments.product\n const variantAssignments = globalAssignments.variant\n\n if (productAssignments.fieldsets.length > 0 || productAssignments.fieldsetsByKey.size > 0) {\n await applyAkeneoManagedFieldsetAssignments(PRODUCT_ENTITY_ID, productAssignments)\n }\n if (variantAssignments.fieldsets.length > 0 || variantAssignments.fieldsetsByKey.size > 0) {\n await applyAkeneoManagedFieldsetAssignments(VARIANT_ENTITY_ID, variantAssignments)\n }\n }\n\n async function resolveGlobalFieldsetAssignments(\n settings: AkeneoProductMappingSettings,\n ): Promise<ResolvedGlobalFieldsetAssignments> {\n const activeMappings = settings.customFieldMappings.filter((entry) => !entry.skip)\n const cacheKey = JSON.stringify({\n customFieldMappings: activeMappings,\n fieldsetMappings: settings.fieldsetMappings,\n })\n if (!globalFieldsetAssignmentCache.has(cacheKey)) {\n globalFieldsetAssignmentCache.set(cacheKey, (async () => {\n const optionSchemas = await em.getConnection().execute<Array<{\n code: string\n name: string\n description: string | null\n metadata: unknown\n }>>(\n `\n select code, name, description, metadata\n from catalog_product_option_schemas\n where organization_id = ?\n and tenant_id = ?\n and deleted_at is null\n `,\n [scope.organizationId, scope.tenantId],\n )\n const akeneoSchemas: Array<{\n schema: {\n code: string\n name: string\n description: string | null\n }\n metadata: AkeneoOptionSchemaMetadata\n }> = []\n for (const schema of optionSchemas) {\n const metadata = readAkeneoOptionSchemaMetadata(schema.metadata)\n if (!metadata) continue\n akeneoSchemas.push({\n schema: {\n code: schema.code,\n name: schema.name,\n description: schema.description,\n },\n metadata,\n })\n }\n\n const productAssignments: EntityFieldsetAssignments = {\n fieldsets: [],\n fieldsetsByKey: new Map(),\n }\n const variantAssignments: EntityFieldsetAssignments = {\n fieldsets: [],\n fieldsetsByKey: new Map(),\n }\n\n const addFieldsetAssignment = (\n bucket: EntityFieldsetAssignments,\n fieldKey: string,\n fieldset: CustomFieldsetDefinition | null,\n ) => {\n if (!fieldset) return\n const normalizedKey = normalizeFieldKey(fieldKey)\n if (!normalizedKey) return\n const existing = bucket.fieldsetsByKey.get(normalizedKey) ?? []\n bucket.fieldsetsByKey.set(\n normalizedKey,\n resolveAkeneoFieldsetMemberships(existing, fieldset.code),\n )\n if (!bucket.fieldsets.some((entry) => entry.code === fieldset.code)) {\n bucket.fieldsets.push(fieldset)\n }\n }\n\n for (const { schema, metadata } of akeneoSchemas) {\n const fieldsetPlan = buildFieldsetPlanFromOptionSchema({\n schema,\n metadata,\n locale: settings.locale,\n fieldsetMappings: settings.fieldsetMappings,\n })\n if (!fieldsetPlan.fieldset) continue\n\n const schemaMappings = activeMappings.filter((entry) => (\n entry.target === fieldsetPlan.target\n && metadata.attributeCodes.includes(entry.attributeCode)\n ))\n if (schemaMappings.length === 0) continue\n\n const bucket = fieldsetPlan.target === 'product' ? productAssignments : variantAssignments\n for (const fieldMapping of schemaMappings) {\n addFieldsetAssignment(bucket, fieldMapping.fieldKey, fieldsetPlan.fieldset)\n }\n }\n\n return {\n product: productAssignments,\n variant: variantAssignments,\n }\n })())\n }\n\n return globalFieldsetAssignmentCache.get(cacheKey) ?? {\n product: { fieldsets: [], fieldsetsByKey: new Map() },\n variant: { fieldsets: [], fieldsetsByKey: new Map() },\n }\n }\n\n async function upsertAttributeFamily(\n family: AkeneoFamily,\n locale: string,\n includeTextAttributes: boolean,\n includeNumericAttributes: boolean,\n ): Promise<UpsertResult | null> {\n return ensureOptionSchemaForFamily(family, null, includeTextAttributes, includeNumericAttributes, locale)\n }\n\n async function resolveAutoLocalChannelCode(\n akeneoChannel: string | null,\n fallbackChannelCode: string | null,\n createIfMissing: boolean,\n ): Promise<string | null> {\n if (akeneoChannel) {\n const exact = await resolveChannel(akeneoChannel, {\n createIfMissing,\n label: titleizeCode(akeneoChannel),\n })\n if (exact) return exact.code\n\n const aliases = akeneoChannel.trim().toLowerCase() === 'ecommerce'\n ? ['web', 'online', 'default']\n : akeneoChannel.trim().toLowerCase() === 'web'\n ? ['ecommerce', 'online', 'default']\n : []\n for (const alias of aliases) {\n const match = await resolveChannel(alias)\n if (match) return match.code\n }\n }\n return fallbackChannelCode\n }\n\n async function resolveAutoPriceKindCode(attributeCode: string): Promise<string | null> {\n const normalizedCode = attributeCode.trim().toLowerCase()\n const preferredCode = normalizedCode.includes('sale')\n || normalizedCode.includes('promo')\n || normalizedCode.includes('special')\n || normalizedCode.includes('discount')\n ? 'sale'\n : 'regular'\n const preferred = await resolvePriceKind(preferredCode)\n if (preferred) return preferred.code\n return resolvePreferredPriceKindCode()\n }\n\n async function buildAutomaticPriceMappings(params: {\n hierarchy: ResolvedHierarchy\n settings: AkeneoProductMappingSettings\n priceAttributeCodes: string[]\n }): Promise<AkeneoProductMappingSettings['priceMappings']> {\n const fallbackChannelCode = await resolvePreferredLocalChannelCode()\n\n const mappings: AkeneoProductMappingSettings['priceMappings'] = []\n const selectedChannels = resolveImportedAkeneoChannels(params.settings)\n for (const attributeCode of dedupeStrings(params.priceAttributeCodes)) {\n const priceKindCode = await resolveAutoPriceKindCode(attributeCode)\n if (!priceKindCode) continue\n const scopes = collectValueScopes(\n [params.hierarchy.leafValues, params.hierarchy.mergedValues],\n attributeCode,\n )\n const effectiveScopes = scopes.length > 0\n ? scopes\n : [\n ...(selectedChannels.length > 0\n ? selectedChannels\n : [params.settings.channel ?? (params.settings.createMissingChannels ? 'default' : null)]),\n ]\n for (const akeneoChannel of effectiveScopes) {\n if (!shouldImportAkeneoChannel(params.settings, akeneoChannel)) continue\n const localChannelCode = await resolveAutoLocalChannelCode(\n akeneoChannel,\n fallbackChannelCode,\n params.settings.createMissingChannels,\n )\n if (!localChannelCode) continue\n mappings.push({\n attributeCode,\n priceKindCode,\n akeneoChannel,\n localChannelCode,\n })\n }\n }\n\n const seen = new Set<string>()\n return mappings.filter((mapping) => {\n const key = `${mapping.attributeCode}:${mapping.priceKindCode}:${mapping.akeneoChannel ?? ''}:${mapping.localChannelCode}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n async function resolveProductSettings(params: {\n mapping: AkeneoDataMapping\n hierarchy: ResolvedHierarchy\n family: AkeneoFamily | null\n familyVariant: AkeneoFamilyVariant | null\n }): Promise<{\n settings: AkeneoProductMappingSettings\n axisCodes: string[]\n variantAttributeCodes: string[]\n optionSchemaAttributeCodes: string[]\n fieldsetPlan: AkeneoFieldsetPlan\n }> {\n if (!defaultProductSettings) {\n throw new Error('Default Akeneo product mapping is not available')\n }\n\n const baseSettings = params.mapping.settings?.products ?? defaultProductSettings\n const attributeCodes = dedupeStrings([\n ...Object.keys(params.hierarchy.rootValues),\n ...Object.keys(params.hierarchy.leafValues),\n ...Object.keys(params.hierarchy.mergedValues),\n ...(Array.isArray(params.family?.attributes) ? params.family.attributes : []),\n ...(params.familyVariant?.variant_attribute_sets?.flatMap((set) => [\n ...(Array.isArray(set.axes) ? set.axes : []),\n ...(Array.isArray(set.attributes) ? set.attributes : []),\n ]) ?? []),\n ])\n const attributes = (\n await Promise.all(attributeCodes.map((code) => client.getAttribute(code)))\n ).filter((attribute): attribute is AkeneoAttribute => Boolean(attribute))\n\n const inferred = inferAkeneoProductMapping({\n attributes,\n family: params.family,\n familyVariant: params.familyVariant,\n fieldMap: baseSettings.fieldMap,\n explicitCustomFieldMappings: baseSettings.customFieldMappings,\n explicitMediaMappings: baseSettings.mediaMappings,\n })\n\n const priceMappings = baseSettings.priceMappings.length > 0\n ? baseSettings.priceMappings\n : await buildAutomaticPriceMappings({\n hierarchy: params.hierarchy,\n settings: baseSettings,\n priceAttributeCodes: inferred.autoPriceAttributeCodes,\n })\n\n const explicitCustomAttributeCodes = new Set(baseSettings.customFieldMappings.map((entry) => entry.attributeCode))\n const inferredCustomAttributeCodes = new Set(inferred.autoCustomFieldMappings.map((entry) => entry.attributeCode))\n const productAttributes = attributes.filter((attribute) => {\n if (!explicitCustomAttributeCodes.has(attribute.code) && !inferredCustomAttributeCodes.has(attribute.code)) return false\n return params.familyVariant\n ? !inferred.variantAttributeCodes.includes(attribute.code)\n : true\n })\n const variantAttributes = attributes.filter((attribute) => {\n if (!explicitCustomAttributeCodes.has(attribute.code) && !inferredCustomAttributeCodes.has(attribute.code)) return false\n return inferred.variantAttributeCodes.includes(attribute.code)\n })\n const fieldsetPlan = buildFieldsetPlan({\n family: params.family,\n familyVariant: params.familyVariant,\n productAttributes,\n variantAttributes,\n locale: baseSettings.locale,\n fieldsetMappings: baseSettings.fieldsetMappings,\n })\n const availableAttributeCodes = attributes.map((attribute) => attribute.code)\n\n return {\n settings: {\n ...baseSettings,\n fieldMap: inferred.fieldMap,\n customFieldMappings: filterAkeneoAttributeMappingsByAvailableAttributes(\n dedupeCustomFieldMappings([\n ...baseSettings.customFieldMappings,\n ...inferred.autoCustomFieldMappings,\n ]),\n availableAttributeCodes,\n ),\n mediaMappings: filterAkeneoAttributeMappingsByAvailableAttributes(\n dedupeMediaMappings([\n ...baseSettings.mediaMappings,\n ...inferred.autoMediaMappings,\n ]),\n availableAttributeCodes,\n ),\n fieldsetMappings: baseSettings.fieldsetMappings,\n priceMappings,\n },\n axisCodes: inferred.axisCodes,\n variantAttributeCodes: inferred.variantAttributeCodes,\n optionSchemaAttributeCodes: inferred.optionSchemaAttributeCodes,\n fieldsetPlan,\n }\n }\n\n async function resolveProductHierarchy(product: AkeneoProduct): Promise<ResolvedHierarchy> {\n if (!product.parent) {\n return {\n rootExternalId: product.uuid,\n family: product.family ?? null,\n familyVariantCode: null,\n rootValues: mergeValueLayers(product.values),\n leafValues: mergeValueLayers(product.values),\n mergedValues: mergeValueLayers(product.values),\n categories: Array.isArray(product.categories) ? product.categories : [],\n parentChain: [],\n associationSource: product,\n axisCodes: [],\n }\n }\n\n const chain: Array<{ code: string; values: AkeneoValues; categories: string[]; family?: string | null; familyVariant?: string | null }> = []\n let nextCode: string | null = product.parent\n while (nextCode) {\n const model = await client.getProductModel(nextCode)\n if (!model) break\n chain.unshift({\n code: model.code,\n values: mergeValueLayers(model.values),\n categories: Array.isArray(model.categories) ? model.categories : [],\n family: model.family ?? null,\n familyVariant: model.family_variant ?? null,\n })\n nextCode = model.parent ?? null\n }\n\n const root = chain[0]\n return {\n rootExternalId: root?.code ?? product.uuid,\n family: product.family ?? root?.family ?? null,\n familyVariantCode: chain[chain.length - 1]?.familyVariant ?? root?.familyVariant ?? null,\n rootValues: root?.values ?? mergeValueLayers(product.values),\n leafValues: mergeValueLayers(product.values),\n mergedValues: mergeValueLayers(\n ...chain.map((model) => model.values),\n product.values,\n ),\n categories: Array.from(new Set([\n ...chain.flatMap((model) => model.categories),\n ...(product.categories ?? []),\n ])),\n parentChain: chain.map((model) => model.code),\n associationSource: product,\n axisCodes: [],\n }\n }\n\n async function applyCustomFieldMappings(params: {\n mapping: AkeneoDataMapping\n hierarchy: ResolvedHierarchy\n product: AkeneoProduct\n localProductId: string\n localVariantId: string\n fieldsetPlan?: AkeneoFieldsetPlan | null\n }): Promise<void> {\n const settings = params.mapping.settings?.products\n if (!settings || settings.customFieldMappings.length === 0) return\n\n await syncMappedCustomFields(params.mapping, settings.locale, params.fieldsetPlan)\n\n const productCustomFields: Record<string, unknown> = {}\n const variantCustomFields: Record<string, unknown> = {}\n\n for (const fieldMapping of settings.customFieldMappings) {\n if (fieldMapping.skip) continue\n const attribute = await client.getAttribute(fieldMapping.attributeCode)\n if (!attribute) continue\n const kind = mapAkeneoAttributeToCustomFieldKind(attribute, fieldMapping.kind)\n if (!kind) continue\n const sourceLayers = fieldMapping.target === 'product'\n ? [params.hierarchy.rootValues, params.hierarchy.mergedValues]\n : [params.product.values ?? {}, params.hierarchy.mergedValues]\n const rawValue = readLayeredAkeneoValue(sourceLayers, fieldMapping.attributeCode, settings.locale, settings.channel ?? null)\n const value = resolveCustomFieldValue(rawValue, attribute, kind)\n if (value === null || value === undefined || (Array.isArray(value) && value.length === 0)) continue\n if (fieldMapping.target === 'product') {\n productCustomFields[normalizeFieldKey(fieldMapping.fieldKey)] = value\n } else {\n variantCustomFields[normalizeFieldKey(fieldMapping.fieldKey)] = value\n }\n }\n\n await Promise.all([\n setCustomFieldsIfAny({\n dataEngine,\n entityId: PRODUCT_ENTITY_ID,\n recordId: params.localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: productCustomFields,\n }),\n setCustomFieldsIfAny({\n dataEngine,\n entityId: VARIANT_ENTITY_ID,\n recordId: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: variantCustomFields,\n }),\n ])\n\n await Promise.all([\n params.fieldsetPlan?.product?.code\n ? executeCommand('catalog.products.update', {\n id: params.localProductId,\n customFieldsetCode: params.fieldsetPlan.product.code,\n })\n : Promise.resolve(),\n params.fieldsetPlan?.variant?.code\n ? executeCommand('catalog.variants.update', {\n id: params.localVariantId,\n customFieldsetCode: params.fieldsetPlan.variant.code,\n })\n : Promise.resolve(),\n ])\n\n if (Object.keys(productCustomFields).length > 0) {\n await emitCatalogQueryIndexEvent(buildCommandContext(), {\n entityType: PRODUCT_ENTITY_ID,\n recordId: params.localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n action: 'updated',\n })\n }\n\n if (Object.keys(variantCustomFields).length > 0) {\n await emitCatalogQueryIndexEvent(buildCommandContext(), {\n entityType: VARIANT_ENTITY_ID,\n recordId: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n action: 'updated',\n })\n }\n }\n\n async function upsertOffersAndPrices(params: {\n mapping: AkeneoDataMapping\n settings: AkeneoProductMappingSettings\n hierarchy: ResolvedHierarchy\n localProductId: string\n localVariantId: string\n resolvedProductTitle: string\n resolvedProductDescription: string | null\n variantExternalId: string\n }): Promise<void> {\n const desiredOffers = new Map<string, DesiredOffer>()\n for (const priceMapping of params.settings.priceMappings) {\n const channel = await resolveChannel(priceMapping.localChannelCode, {\n createIfMissing: params.settings.createMissingChannels,\n label: titleizeCode(priceMapping.localChannelCode),\n })\n const priceKind = await resolvePriceKind(priceMapping.priceKindCode)\n if (!channel || !priceKind) continue\n const akeneoChannel = priceMapping.akeneoChannel ?? params.settings.channel ?? null\n if (!shouldImportAkeneoChannel(params.settings, akeneoChannel)) continue\n const rawPrices = readLayeredAkeneoValue(\n [params.hierarchy.leafValues, params.hierarchy.mergedValues],\n priceMapping.attributeCode,\n params.settings.locale,\n akeneoChannel,\n )\n const entries = parsePriceCollection(rawPrices)\n if (entries.length === 0) continue\n const offerExternalId = `${params.hierarchy.rootExternalId}:offer:${channel.code}`\n const existingOffer = desiredOffers.get(offerExternalId)\n const title = coerceString(readLayeredAkeneoValue(\n [params.hierarchy.rootValues, params.hierarchy.mergedValues],\n params.settings.fieldMap.title,\n params.settings.locale,\n akeneoChannel,\n )) ?? params.resolvedProductTitle\n const description = clampString(\n normalizeMarkdownText(\n coerceString(readLayeredAkeneoValue(\n [params.hierarchy.rootValues, params.hierarchy.mergedValues],\n params.settings.fieldMap.description,\n params.settings.locale,\n akeneoChannel,\n )) ?? params.resolvedProductDescription,\n ),\n 4000,\n )\n const bucket = existingOffer ?? {\n externalId: offerExternalId,\n channelCode: channel.code,\n channelId: channel.id,\n akeneoChannel,\n title,\n description,\n prices: [],\n }\n for (const entry of entries) {\n bucket.prices.push({\n externalId: `${params.variantExternalId}:price:${priceKind.code}:${channel.code}:${entry.currencyCode}`,\n priceKindCode: priceKind.code,\n priceKindId: priceKind.id,\n channelId: channel.id,\n currencyCode: entry.currencyCode,\n amount: entry.amount,\n variantId: params.localVariantId,\n })\n }\n desiredOffers.set(offerExternalId, bucket)\n }\n\n const existingOffers = await findWithDecryption(\n em,\n CatalogOffer,\n {\n product: params.localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n const existingOfferByChannelId = new Map(existingOffers.map((offer) => [offer.channelId, offer]))\n const desiredOfferExternalIds = new Set(desiredOffers.keys())\n\n for (const offer of desiredOffers.values()) {\n const mappedOfferId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_offer', offer.externalId, scope)\n const existingOffer = mappedOfferId\n ? existingOffers.find((entry) => entry.id === mappedOfferId) ?? null\n : existingOfferByChannelId.get(offer.channelId) ?? null\n const input = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n productId: params.localProductId,\n channelId: offer.channelId,\n title: offer.title,\n description: offer.description ?? undefined,\n metadata: {\n source: 'akeneo',\n externalId: offer.externalId,\n channelCode: offer.channelCode,\n akeneoChannel: offer.akeneoChannel,\n },\n isActive: true,\n }\n const offerId = existingOffer\n ? (await executeCommand<{ offerId: string }>('catalog.offers.update', { id: existingOffer.id, ...input })).offerId\n : (await executeCommand<{ offerId: string }>('catalog.offers.create', input)).offerId\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_offer', offerId, offer.externalId, scope)\n\n const existingPrices = await findWithDecryption(\n em,\n CatalogProductPrice,\n {\n offer: offerId,\n variant: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n const desiredPriceExternalIds = new Set(offer.prices.map((price) => price.externalId))\n for (const price of offer.prices) {\n const mappedPriceId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_price', price.externalId, scope)\n const mappedPrice = mappedPriceId\n ? existingPrices.find((entry) => entry.id === mappedPriceId) ?? null\n : null\n const existingPrice = mappedPrice\n ?? existingPrices.find((entry) => (\n resolvePriceVariantId(entry) === price.variantId\n && entry.channelId === price.channelId\n && entry.currencyCode === price.currencyCode\n && entry.kind === price.priceKindCode\n && entry.minQuantity === 1\n ))\n ?? null\n const input = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n productId: params.localProductId,\n variantId: price.variantId,\n offerId,\n priceKindId: price.priceKindId,\n currencyCode: price.currencyCode,\n unitPriceNet: price.amount,\n unitPriceGross: price.amount,\n minQuantity: 1,\n channelId: price.channelId,\n metadata: {\n source: 'akeneo',\n externalId: price.externalId,\n priceKindCode: price.priceKindCode,\n },\n }\n const priceId = existingPrice\n ? (await executeCommand<{ priceId: string }>('catalog.prices.update', { id: existingPrice.id, ...input })).priceId\n : (await executeCommand<{ priceId: string }>('catalog.prices.create', input)).priceId\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_price', priceId, price.externalId, scope)\n }\n\n if (params.settings.reconciliation.deleteMissingPrices) {\n for (const existingPrice of existingPrices) {\n const externalId = await externalIdMappingService.lookupExternalId('sync_akeneo', 'catalog_product_price', existingPrice.id, scope)\n if (externalId && !desiredPriceExternalIds.has(externalId)) {\n await executeCommand('catalog.prices.delete', { id: existingPrice.id })\n }\n }\n }\n }\n\n if (params.settings.reconciliation.deleteMissingOffers) {\n for (const existingOffer of existingOffers) {\n const externalId = await externalIdMappingService.lookupExternalId('sync_akeneo', 'catalog_offer', existingOffer.id, scope)\n if (externalId && !desiredOfferExternalIds.has(externalId)) {\n const offerPrices = await findWithDecryption(\n em,\n CatalogProductPrice,\n { offer: existingOffer.id, organizationId: scope.organizationId, tenantId: scope.tenantId },\n undefined,\n scope,\n )\n const sharedWithOtherVariants = offerPrices.some((price) => {\n const priceVariantId = resolvePriceVariantId(price)\n return priceVariantId !== null && priceVariantId !== params.localVariantId\n })\n if (sharedWithOtherVariants) {\n for (const price of offerPrices) {\n if (resolvePriceVariantId(price) !== params.localVariantId) continue\n const priceExternalId = await externalIdMappingService.lookupExternalId('sync_akeneo', 'catalog_product_price', price.id, scope)\n if (priceExternalId) {\n await executeCommand('catalog.prices.delete', { id: price.id })\n }\n }\n continue\n }\n for (const price of offerPrices) {\n await executeCommand('catalog.prices.delete', { id: price.id })\n }\n await executeCommand('catalog.offers.delete', { id: existingOffer.id })\n }\n }\n }\n }\n\n async function recordRejectedMedia(asset: DesiredAsset, reason: string): Promise<void> {\n const integrationLogService = container.resolve('integrationLogService') as IntegrationLogService\n await integrationLogService.write({\n integrationId: 'sync_akeneo',\n level: 'warn',\n code: 'sync_akeneo.media_rejected',\n message: `Akeneo media ${asset.remote.codeOrUrl} was not imported: ${reason}`,\n scopeEntityType: asset.entityId,\n scopeEntityId: asset.recordId,\n payload: {\n externalId: asset.externalId,\n remoteCode: asset.remote.codeOrUrl,\n kind: asset.kind,\n reason,\n },\n }, scope)\n }\n\n async function upsertAsset(asset: DesiredAsset): Promise<string | null> {\n const existingAttachmentId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'attachment', asset.externalId, scope)\n if (existingAttachmentId) return existingAttachmentId\n\n let binary: Awaited<ReturnType<AkeneoClient['downloadMediaFile']>>\n try {\n binary = await client.downloadMediaFile(asset.remote.codeOrUrl)\n } catch (error) {\n if (!isAkeneoResponseTooLargeError(error)) throw error\n await recordRejectedMedia(asset, 'max_upload_size')\n return null\n }\n const fileName = asset.remote.fileNameHint ?? binary.fileName ?? `akeneo-${randomUUID().slice(0, 8)}`\n const uploadService = container.resolve('attachmentScopedUploadService') as ScopedAttachmentUploadService\n let attachment: Attachment\n try {\n attachment = await uploadService.upload({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n entityId: asset.entityId,\n recordId: asset.recordId,\n fileName,\n declaredMimeType: asset.remote.mimeTypeHint ?? binary.contentType,\n buffer: binary.buffer,\n })\n } catch (error) {\n if (!isScopedAttachmentUploadError(error)) throw error\n if (REJECTED_MEDIA_UPLOAD_CODES.has(error.code)) {\n await recordRejectedMedia(asset, error.code)\n return null\n }\n const { translate } = await resolveTranslations()\n throw new Error(translate(\n 'sync_akeneo.errors.mediaStorageRejected',\n 'Akeneo media {code} was rejected by attachment storage ({reason}).',\n { code: asset.remote.codeOrUrl, reason: error.code },\n ))\n }\n attachment.url = asset.kind === 'image'\n ? buildAttachmentImageUrl(attachment.id, { slug: slugifyAttachmentFileName(attachment.fileName) })\n : buildAttachmentFileUrl(attachment.id)\n attachment.storageMetadata = {\n ...(attachment.storageMetadata ?? {}),\n source: 'akeneo',\n externalId: asset.externalId,\n kind: asset.kind,\n remoteCode: asset.remote.codeOrUrl,\n }\n await em.flush()\n await emitAttachmentCrudChange('updated', attachment)\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'attachment', attachment.id, asset.externalId, scope)\n return attachment.id\n }\n\n async function releaseImportedAttachment(attachment: Attachment): Promise<boolean> {\n const attachmentService = container.resolve('attachmentService') as AttachmentService\n if (!attachmentService.releaseScoped) {\n throw new Error('[internal] attachmentService.releaseScoped is not available')\n }\n try {\n await attachmentService.releaseScoped({\n attachmentId: attachment.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n expectedOwner: { entityId: attachment.entityId, recordId: attachment.recordId },\n expectedAssignment: { type: attachment.entityId, id: attachment.recordId },\n expectedPartitionCode: attachment.partitionCode,\n })\n return true\n } catch (error) {\n if (isCrudHttpError(error) && error.status === 409) return false\n throw error\n }\n }\n\n async function reconcileAttachments(params: {\n entityId: string\n recordId: string\n desiredAssets: DesiredAsset[]\n reconciliation: AkeneoReconciliationSettings\n }): Promise<{ heroAttachmentId: string | null; heroAttachmentUrl: string | null }> {\n const desiredExternalIds = new Set(params.desiredAssets.map((asset) => asset.externalId))\n let heroAttachmentId: string | null = null\n for (const asset of params.desiredAssets) {\n const attachmentId = await upsertAsset(asset)\n if (!heroAttachmentId && attachmentId && asset.kind === 'image') heroAttachmentId = attachmentId\n }\n const heroAttachmentUrl = heroAttachmentId ? buildAttachmentImageUrl(heroAttachmentId) : null\n\n const existing = await findWithDecryption(em, Attachment, {\n entityId: params.entityId,\n recordId: params.recordId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }, undefined, scope)\n for (const attachment of existing) {\n const metadata = safeRecord(attachment.storageMetadata)\n const externalId = typeof metadata?.externalId === 'string' ? metadata.externalId : null\n const kind = metadata?.kind === 'image' || metadata?.kind === 'file' ? metadata.kind : null\n if (!externalId || !kind) continue\n const shouldDelete = kind === 'image'\n ? params.reconciliation.deleteMissingMedia\n : params.reconciliation.deleteMissingAttachments\n if (!shouldDelete || desiredExternalIds.has(externalId)) continue\n if (!(await releaseImportedAttachment(attachment))) continue\n await emitAttachmentCrudChange('deleted', attachment)\n }\n\n return {\n heroAttachmentId,\n heroAttachmentUrl,\n }\n }\n\n async function syncAssociations(params: {\n product: AkeneoProduct\n localVariantId: string\n localProductId: string\n settings: AkeneoProductMappingSettings\n }): Promise<void> {\n if (!params.settings.syncAssociations) return\n const existing = await findWithDecryption(em, CatalogProductVariantRelation, {\n parentVariant: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }, undefined, scope)\n\n const desired = new Map<string, {\n relationType: 'bundle' | 'grouped'\n childVariantId: string | null\n childProductId: string | null\n associationType: string\n minQuantity: number | null\n }>()\n\n const addDesired = async (associationType: string, externalCandidate: string | null, quantity: number | null, mode: 'product' | 'productModel') => {\n if (!externalCandidate) return\n let childVariantId: string | null = null\n let childProductId: string | null = null\n if (mode === 'product') {\n childVariantId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_variant', externalCandidate, scope)\n ?? await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_variant', `${externalCandidate}:default`, scope)\n ?? await lookupVariantBySku(externalCandidate)\n childProductId = childVariantId\n ? null\n : await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product', externalCandidate, scope)\n ?? await lookupProductBySku(externalCandidate)\n } else {\n childProductId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product', externalCandidate, scope)\n }\n if (!childVariantId && !childProductId) return\n const relationType = relationTypeFromAssociation(associationType)\n const key = `${relationType}:${childVariantId ?? childProductId}`\n desired.set(key, {\n relationType,\n childVariantId,\n childProductId,\n associationType,\n minQuantity: quantity,\n })\n }\n\n for (const [associationType, payload] of Object.entries(params.product.associations ?? {})) {\n for (const productIdentifier of payload.products ?? []) {\n await addDesired(associationType, productIdentifier, null, 'product')\n }\n for (const productModelCode of payload.product_models ?? []) {\n await addDesired(associationType, productModelCode, null, 'productModel')\n }\n }\n\n for (const [associationType, payload] of Object.entries(params.product.quantified_associations ?? {})) {\n for (const productEntry of payload.products ?? []) {\n await addDesired(associationType, coerceString(productEntry.uuid) ?? coerceString(productEntry.identifier), coerceNumber(productEntry.quantity), 'product')\n }\n for (const productModelEntry of payload.product_models ?? []) {\n await addDesired(associationType, coerceString(productModelEntry.code) ?? coerceString(productModelEntry.identifier), coerceNumber(productModelEntry.quantity), 'productModel')\n }\n }\n\n const desiredKeys = new Set(desired.keys())\n // Apply the create/update upserts and the stale-relation removals as a\n // single atomic unit so a product's relation set is never left partially\n // synced. `existing` is an in-memory array (already fetched above), so the\n // `.find()` lookups inside the phase do not run new `em` queries.\n await withAtomicFlush(em, [\n () => {\n for (const entry of desired.values()) {\n const existingRelation = existing.find((relation) => {\n const childVariantId = typeof relation.childVariant === 'string' ? relation.childVariant : relation.childVariant?.id ?? null\n const childProductId = typeof relation.childProduct === 'string' ? relation.childProduct : relation.childProduct?.id ?? null\n return relation.relationType === entry.relationType\n && childVariantId === entry.childVariantId\n && childProductId === entry.childProductId\n })\n if (existingRelation) {\n existingRelation.minQuantity = entry.minQuantity\n existingRelation.metadata = {\n source: 'akeneo',\n associationType: entry.associationType,\n }\n continue\n }\n const relation = em.create(CatalogProductVariantRelation, {\n parentVariant: em.getReference(CatalogProductVariant, params.localVariantId),\n childVariant: entry.childVariantId ? em.getReference(CatalogProductVariant, entry.childVariantId) : null,\n childProduct: entry.childProductId ? em.getReference(CatalogProduct, entry.childProductId) : null,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n relationType: entry.relationType,\n isRequired: false,\n minQuantity: entry.minQuantity,\n maxQuantity: null,\n position: 0,\n metadata: {\n source: 'akeneo',\n associationType: entry.associationType,\n },\n })\n em.persist(relation)\n }\n\n for (const relation of existing) {\n const metadata = safeRecord(relation.metadata)\n if (metadata?.source !== 'akeneo') continue\n const childVariantId = typeof relation.childVariant === 'string' ? relation.childVariant : relation.childVariant?.id ?? null\n const childProductId = typeof relation.childProduct === 'string' ? relation.childProduct : relation.childProduct?.id ?? null\n const key = `${relation.relationType}:${childVariantId ?? childProductId}`\n if (!desiredKeys.has(key)) {\n em.remove(relation)\n }\n }\n },\n ], { transaction: true })\n }\n\n async function upsertProduct(product: AkeneoProduct, mapping: AkeneoDataMapping): Promise<Array<{ externalId: string; action: 'create' | 'update' | 'skip'; data: Record<string, unknown> }>> {\n const family = product.family ? await client.getFamily(product.family) : null\n const hierarchy = await resolveProductHierarchy(product)\n const resolvedFamily = hierarchy.family ? await client.getFamily(hierarchy.family) : family\n const resolvedFamilyVariant = hierarchy.family && hierarchy.familyVariantCode\n ? await client.getFamilyVariant(hierarchy.family, hierarchy.familyVariantCode)\n : null\n const resolvedProductSettings = await resolveProductSettings({\n mapping,\n hierarchy,\n family: resolvedFamily,\n familyVariant: resolvedFamilyVariant,\n })\n const settings = resolvedProductSettings.settings\n const locale = settings.locale\n const channel = settings.channel ?? null\n hierarchy.axisCodes = resolvedProductSettings.axisCodes\n const productFieldsetCode = resolvedProductSettings.fieldsetPlan.product?.code ?? null\n const variantFieldsetCode = resolvedProductSettings.fieldsetPlan.variant?.code ?? null\n\n let optionSchemaId: string | null = null\n if (resolvedFamily && hierarchy.axisCodes.length > 0) {\n optionSchemaId = (await ensureOptionSchemaForFamily(\n resolvedFamily,\n resolvedFamilyVariant ?? null,\n true,\n true,\n locale,\n resolvedProductSettings.optionSchemaAttributeCodes,\n ))?.localId ?? null\n }\n const fieldMap = settings.fieldMap\n const derivedMapping: AkeneoDataMapping = {\n ...mapping,\n fields: buildProductFieldMappings(settings),\n settings: {\n ...(mapping.settings ?? {}),\n products: settings,\n },\n }\n\n const resolvedTitle = coerceString(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.title, locale, channel))\n ?? coerceString(product.identifier)\n ?? hierarchy.rootExternalId\n const resolvedSubtitle = coerceString(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.subtitle, locale, channel))\n const resolvedDescription = clampString(\n normalizeMarkdownText(\n coerceString(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.description, locale, channel)),\n ),\n 4000,\n )\n const resolvedSku = coerceString(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.sku, locale, channel))\n ?? coerceString(product.identifier)\n ?? product.uuid\n const resolvedBarcode = coerceString(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.barcode, locale, channel))\n const resolvedWeight = coerceMetricAmount(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.weight, locale, channel))\n ?? coerceMetricAmount(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.weight, locale, channel))\n const categoryIds = (\n await Promise.all(hierarchy.categories.map((code) => resolveCategoryId(code, locale)))\n ).filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n const productExternalId = hierarchy.rootExternalId\n const existingProductId = await resolveExistingProductId(\n productExternalId,\n product.parent ? null : resolvedSku,\n )\n\n const productInput = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: resolvedTitle,\n subtitle: resolvedSubtitle ?? undefined,\n description: resolvedDescription ?? undefined,\n sku: product.parent ? undefined : resolvedSku,\n productType: product.parent ? 'configurable' : 'simple',\n optionSchemaId,\n isConfigurable: Boolean(product.parent),\n isActive: product.enabled !== false,\n weightValue: resolvedWeight ?? undefined,\n categoryIds,\n metadata: {\n source: 'akeneo',\n externalId: productExternalId,\n sourceProductUuid: product.uuid,\n family: hierarchy.family,\n familyVariant: hierarchy.familyVariantCode,\n parentChain: hierarchy.parentChain,\n associations: product.associations ?? {},\n quantifiedAssociations: product.quantified_associations ?? {},\n updatedAt: product.updated ?? null,\n },\n customFieldsetCode: productFieldsetCode,\n }\n\n let localProductId: string\n let productAction: 'create' | 'update'\n if (existingProductId) {\n await executeCommand('catalog.products.update', {\n id: existingProductId,\n ...productInput,\n })\n localProductId = existingProductId\n productAction = 'update'\n } else {\n const created = await executeCommand<{ productId?: string; id?: string }>('catalog.products.create', productInput)\n localProductId = created.productId ?? created.id ?? ''\n if (!localProductId) {\n throw new Error(`Akeneo product ${product.uuid} did not return a local product id`)\n }\n productAction = 'create'\n }\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product', localProductId, productExternalId, scope)\n\n const variantExternalId = product.parent ? product.uuid : `${product.uuid}:default`\n const existingVariantId = await resolveExistingVariantId(variantExternalId, resolvedSku, localProductId)\n\n const optionValues =\n hierarchy.axisCodes.length > 0\n ? await (async () => {\n const values: Record<string, string> = {}\n for (const axis of hierarchy.axisCodes) {\n const rawValue = readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], axis, locale, channel)\n const optionLabels = await getAttributeOptionLabels(axis, locale)\n const normalizedValue = normalizeAkeneoSelectValue(rawValue, optionLabels)\n if (normalizedValue) {\n values[slugifyAkeneoCode(axis)] = normalizedValue\n }\n }\n return Object.keys(values).length > 0 ? values : undefined\n })()\n : undefined\n\n const existingDefaultVariant = await findOneWithDecryption(\n em,\n CatalogProductVariant,\n {\n product: localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n isDefault: true,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n const variantName = coerceString(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.variantName, locale, channel))\n ?? (optionValues && Object.values(optionValues).length > 0 ? Object.values(optionValues).join(' / ') : resolvedTitle)\n\n const variantInput = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n productId: localProductId,\n name: variantName,\n sku: resolvedSku,\n barcode: resolvedBarcode ?? undefined,\n isDefault: existingVariantId ? existingVariantId === existingDefaultVariant?.id : !existingDefaultVariant,\n isActive: product.enabled !== false,\n weightValue: resolvedWeight ?? undefined,\n optionValues: optionValues && Object.keys(optionValues).length > 0 ? optionValues : undefined,\n metadata: {\n source: 'akeneo',\n externalId: variantExternalId,\n sourceProductUuid: product.uuid,\n sourceParentCode: product.parent ?? null,\n associations: product.associations ?? {},\n quantifiedAssociations: product.quantified_associations ?? {},\n updatedAt: product.updated ?? null,\n },\n customFieldsetCode: variantFieldsetCode,\n }\n\n let localVariantId: string\n let variantAction: 'create' | 'update'\n if (existingVariantId) {\n await executeCommand('catalog.variants.update', {\n id: existingVariantId,\n ...variantInput,\n })\n localVariantId = existingVariantId\n variantAction = 'update'\n } else {\n const created = await executeCommand<{ variantId?: string; id?: string }>('catalog.variants.create', variantInput)\n localVariantId = created.variantId ?? created.id ?? ''\n if (!localVariantId) {\n throw new Error(`Akeneo variant ${variantExternalId} did not return a local variant id`)\n }\n variantAction = 'create'\n }\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_variant', localVariantId, variantExternalId, scope)\n\n await applyCustomFieldMappings({\n mapping: derivedMapping,\n hierarchy,\n product,\n localProductId,\n localVariantId,\n fieldsetPlan: resolvedProductSettings.fieldsetPlan,\n })\n await upsertOffersAndPrices({\n mapping: derivedMapping,\n settings,\n hierarchy,\n localProductId,\n localVariantId,\n resolvedProductTitle: resolvedTitle,\n resolvedProductDescription: resolvedDescription,\n variantExternalId,\n })\n\n const desiredAssets: DesiredAsset[] = []\n for (const mediaMapping of settings.mediaMappings) {\n const productScopedValue = readPreferredAkeneoValue(\n hierarchy.rootValues,\n mediaMapping.attributeCode,\n locale,\n channel,\n )\n const variantScopedValue = readPreferredAkeneoValue(\n hierarchy.leafValues,\n mediaMapping.attributeCode,\n locale,\n channel,\n )\n const effectiveTarget = resolveAkeneoMediaTarget({\n mappingTarget: mediaMapping.target,\n attributeCode: mediaMapping.attributeCode,\n variantAttributeCodes: resolvedProductSettings.variantAttributeCodes,\n productScopedValue,\n variantScopedValue,\n })\n const sourceLayers = effectiveTarget === 'product'\n ? [hierarchy.rootValues, hierarchy.mergedValues]\n : [hierarchy.leafValues, hierarchy.mergedValues]\n const rawValue = readLayeredAkeneoValue(sourceLayers, mediaMapping.attributeCode, locale, channel)\n const refs = collectMediaReferences(rawValue)\n refs.forEach((ref, index) => {\n desiredAssets.push({\n externalId: `${effectiveTarget}:${mediaMapping.kind}:${mediaMapping.attributeCode}:${ref.codeOrUrl}:${index}`,\n entityId: effectiveTarget === 'product' ? PRODUCT_ENTITY_ID : VARIANT_ENTITY_ID,\n recordId: effectiveTarget === 'product' ? localProductId : localVariantId,\n kind: mediaMapping.kind,\n remote: ref,\n })\n })\n }\n\n const assetsByTarget = new Map<string, DesiredAsset[]>()\n const pendingVariantHeroUpdates: Array<{\n variantId: string\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n }> = []\n const shouldMirrorVariantHeroToProduct = !product.parent && !hierarchy.familyVariantCode\n let mirroredProductHeroFromVariant: {\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n } | null = null\n for (const asset of desiredAssets) {\n const key = `${asset.entityId}:${asset.recordId}`\n const bucket = assetsByTarget.get(key) ?? []\n bucket.push(asset)\n assetsByTarget.set(key, bucket)\n }\n\n for (const assets of assetsByTarget.values()) {\n const firstAsset = assets[0]\n if (!firstAsset) continue\n const hero = await reconcileAttachments({\n entityId: firstAsset.entityId,\n recordId: firstAsset.recordId,\n desiredAssets: assets,\n reconciliation: settings.reconciliation,\n })\n if (firstAsset.entityId === PRODUCT_ENTITY_ID) {\n await executeCommand('catalog.products.update', {\n id: localProductId,\n defaultMediaId: hero.heroAttachmentId,\n defaultMediaUrl: hero.heroAttachmentUrl,\n })\n } else {\n pendingVariantHeroUpdates.push({\n variantId: localVariantId,\n defaultMediaId: hero.heroAttachmentId,\n defaultMediaUrl: hero.heroAttachmentUrl,\n })\n if (\n shouldMirrorVariantHeroToProduct\n && firstAsset.recordId === localVariantId\n && hero.heroAttachmentId\n && !mirroredProductHeroFromVariant\n ) {\n mirroredProductHeroFromVariant = {\n defaultMediaId: hero.heroAttachmentId,\n defaultMediaUrl: hero.heroAttachmentUrl,\n }\n }\n }\n }\n\n await syncAssociations({\n product,\n localVariantId,\n localProductId,\n settings,\n })\n\n for (const heroUpdate of pendingVariantHeroUpdates) {\n await em.getConnection().execute(\n `\n update catalog_product_variants\n set default_media_id = ?, default_media_url = ?, updated_at = now()\n where id = ? and organization_id = ? and tenant_id = ?\n `,\n [\n heroUpdate.defaultMediaId,\n heroUpdate.defaultMediaUrl,\n heroUpdate.variantId,\n scope.organizationId,\n scope.tenantId,\n ],\n )\n await emitCatalogQueryIndexEvent(buildCommandContext(), {\n entityType: VARIANT_ENTITY_ID,\n recordId: heroUpdate.variantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n action: 'updated',\n })\n }\n\n if (mirroredProductHeroFromVariant) {\n await executeCommand('catalog.products.update', {\n id: localProductId,\n defaultMediaId: mirroredProductHeroFromVariant.defaultMediaId,\n defaultMediaUrl: mirroredProductHeroFromVariant.defaultMediaUrl,\n })\n }\n\n return [\n {\n externalId: productExternalId,\n action: productAction,\n data: {\n localProductId,\n sku: resolvedSku,\n family: hierarchy.family,\n },\n },\n {\n externalId: variantExternalId,\n action: variantAction,\n data: {\n localVariantId,\n productId: localProductId,\n sku: resolvedSku,\n },\n },\n ]\n }\n\n async function deactivateMappedEntities(entityType: string, seenExternalIds: Set<string>, commandId: string): Promise<void> {\n const mappings = await findWithDecryption(em, SyncExternalIdMapping, {\n integrationId: 'sync_akeneo',\n internalEntityType: entityType,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n for (const mapping of mappings) {\n if (seenExternalIds.has(mapping.externalId)) continue\n await executeCommand(commandId, {\n id: mapping.internalEntityId,\n isActive: false,\n })\n }\n }\n\n async function reconcileCategories(seenExternalIds: Set<string>, locale: string, reconciliation: AkeneoReconciliationSettings): Promise<void> {\n if (!reconciliation.deactivateMissingCategories || seenExternalIds.size === 0) return\n await deactivateMappedEntities('catalog_product_category', seenExternalIds, 'catalog.categories.update')\n }\n\n async function reconcileAttributes(params: {\n seenFamilyExternalIds: Set<string>\n currentCustomFieldKeys: Set<string>\n reconciliation: AkeneoReconciliationSettings\n }): Promise<void> {\n if (!params.reconciliation.deactivateMissingAttributes) return\n if (params.seenFamilyExternalIds.size > 0) {\n await deactivateMappedEntities('catalog_option_schema', params.seenFamilyExternalIds, 'catalog.optionSchemas.update')\n }\n const defs = await findWithDecryption(em, CustomFieldDef, {\n entityId: { $in: [PRODUCT_ENTITY_ID, VARIANT_ENTITY_ID] },\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n for (const def of defs) {\n const sourceMetadata = safeRecord(def.configJson?.sourceMetadata)\n if (sourceMetadata?.provider !== 'akeneo') continue\n if (params.currentCustomFieldKeys.has(`${def.entityId}:${def.key}`)) continue\n def.isActive = false\n }\n await em.flush()\n }\n\n async function reconcileProducts(seenProductExternalIds: Set<string>, seenVariantExternalIds: Set<string>, reconciliation: AkeneoReconciliationSettings): Promise<void> {\n if (!reconciliation.deactivateMissingProducts) return\n if (seenProductExternalIds.size > 0) {\n await deactivateMappedEntities('catalog_product', seenProductExternalIds, 'catalog.products.update')\n }\n if (seenVariantExternalIds.size > 0) {\n await deactivateMappedEntities('catalog_product_variant', seenVariantExternalIds, 'catalog.variants.update')\n }\n }\n\n return {\n upsertCategory,\n upsertAttributeFamily,\n upsertProduct,\n syncMappedCustomFields,\n reconcileMappedCustomFieldFieldsets,\n reconcileCategories,\n reconcileAttributes,\n reconcileProducts,\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { DataMapping } from '@open-mercato/core/modules/data_sync/lib/adapter'\nimport type { ExternalIdMappingService } from '@open-mercato/core/modules/data_sync/lib/id-mapping'\nimport { SyncExternalIdMapping } from '@open-mercato/core/modules/integrations/data/entities'\nimport {\n CatalogOffer,\n CatalogOptionSchemaTemplate,\n CatalogPriceKind,\n CatalogProduct,\n CatalogProductCategory,\n CatalogProductPrice,\n CatalogProductVariant,\n CatalogProductVariantRelation,\n} from '@open-mercato/core/modules/catalog/data/entities'\nimport { ensureCustomFieldDefinitions } from '@open-mercato/core/modules/entities/lib/field-definitions'\nimport { CustomFieldDef, CustomFieldEntityConfig } from '@open-mercato/core/modules/entities/data/entities'\nimport { normalizeEntityFieldsetConfig, type CustomFieldsetDefinition } from '@open-mercato/core/modules/entities/lib/fieldsets'\nimport { invalidateDefinitionsCache } from '@open-mercato/core/modules/entities/api/definitions.cache'\nimport { Attachment } from '@open-mercato/core/modules/attachments/data/entities'\nimport { buildAttachmentFileUrl, buildAttachmentImageUrl, slugifyAttachmentFileName } from '@open-mercato/core/modules/attachments/lib/imageUrls'\nimport type { AttachmentService } from '@open-mercato/core/modules/attachments'\nimport {\n isScopedAttachmentUploadError,\n type ScopedAttachmentUploadErrorCode,\n type ScopedAttachmentUploadService,\n} from '@open-mercato/core/modules/attachments/lib/scoped-upload-service'\nimport type { IntegrationLogService } from '@open-mercato/core/modules/integrations/lib/log-service'\nimport { attachmentCrudEvents, attachmentCrudIndexer } from '@open-mercato/core/modules/attachments/lib/crud'\nimport { emitCatalogQueryIndexEvent } from '@open-mercato/core/modules/catalog/commands/shared'\nimport { SalesChannel } from '@open-mercato/core/modules/sales/data/entities'\nimport type { CustomFieldDefinition } from '@open-mercato/shared/modules/entities'\nimport {\n buildAkeneoFieldsetCode,\n buildProductFieldMappings,\n dedupeStrings,\n labelFromLocalizedRecord,\n safeRecord,\n slugifyAkeneoCode,\n type AkeneoAttribute,\n type AkeneoCategory,\n type AkeneoCustomFieldKind,\n type AkeneoDataMapping,\n type AkeneoFamily,\n type AkeneoFamilyVariant,\n type AkeneoFieldsetMapping,\n type AkeneoProduct,\n type AkeneoProductMappingSettings,\n type AkeneoReconciliationSettings,\n type AkeneoValues,\n buildDefaultAkeneoMapping,\n} from './shared'\nimport { isAkeneoResponseTooLargeError, type AkeneoClient } from './client'\nimport { inferAkeneoProductMapping } from './inference'\nimport { normalizeMarkdownText } from './markdown'\n\ntype ImportScope = {\n organizationId: string\n tenantId: string\n}\n\nconst REJECTED_MEDIA_UPLOAD_CODES: ReadonlySet<ScopedAttachmentUploadErrorCode> = new Set([\n 'dangerous_executable',\n 'max_upload_size',\n 'active_content',\n])\n\ntype UpsertResult = {\n localId: string\n action: 'create' | 'update' | 'skip'\n}\n\ntype CustomFieldSyncItem = {\n externalId: string\n action: 'create' | 'update' | 'skip'\n data: Record<string, unknown>\n}\n\ntype ResolvedHierarchy = {\n rootExternalId: string\n family: string | null\n familyVariantCode: string | null\n rootValues: AkeneoValues\n leafValues: AkeneoValues\n mergedValues: AkeneoValues\n categories: string[]\n parentChain: string[]\n associationSource: AkeneoProduct\n axisCodes: string[]\n}\n\ntype DesiredOffer = {\n externalId: string\n channelCode: string\n channelId: string\n akeneoChannel: string | null\n title: string\n description: string | null\n prices: DesiredPrice[]\n}\n\ntype DesiredPrice = {\n externalId: string\n priceKindCode: string\n priceKindId: string\n channelId: string\n currencyCode: string\n amount: number\n variantId: string\n}\n\ntype MediaReference = {\n codeOrUrl: string\n fileNameHint: string | null\n mimeTypeHint: string | null\n}\n\ntype DesiredAsset = {\n externalId: string\n entityId: string\n recordId: string\n kind: 'image' | 'file'\n remote: MediaReference\n}\n\ntype AkeneoFieldsetPlan = {\n product: CustomFieldsetDefinition | null\n variant: CustomFieldsetDefinition | null\n}\n\nconst PRODUCT_ENTITY_ID = 'catalog:catalog_product'\nconst VARIANT_ENTITY_ID = 'catalog:catalog_product_variant'\n\nexport function readPreferredAkeneoValue(\n values: AkeneoValues | undefined | null,\n attributeCode: string,\n locale: string,\n channel: string | null,\n): unknown {\n const entries = Array.isArray(values?.[attributeCode]) ? values?.[attributeCode] ?? [] : []\n if (entries.length === 0) return null\n\n const normalize = (value: string | null | undefined) => (typeof value === 'string' && value.trim().length > 0 ? value.trim() : null)\n const wantedLocale = normalize(locale)\n const wantedChannel = normalize(channel)\n\n const eligibleEntries = entries.filter((entry) => {\n const entryLocale = normalize(entry.locale)\n const entryChannel = normalize(entry.scope)\n const localeMatches = wantedLocale ? entryLocale === wantedLocale || entryLocale === null : true\n const channelMatches = wantedChannel ? entryChannel === wantedChannel || entryChannel === null : true\n return localeMatches && channelMatches\n })\n\n const scored = eligibleEntries\n .map((entry) => {\n const entryLocale = normalize(entry.locale)\n const entryChannel = normalize(entry.scope)\n let score = 0\n if (wantedLocale && entryLocale === wantedLocale) score += 4\n else if (!wantedLocale && !entryLocale) score += 2\n else if (!entryLocale) score += 1\n if (wantedChannel && entryChannel === wantedChannel) score += 4\n else if (!wantedChannel && !entryChannel) score += 2\n else if (!entryChannel) score += 1\n return { score, entry }\n })\n .sort((left, right) => right.score - left.score)\n\n return scored[0]?.entry?.data ?? null\n}\n\nexport function readLayeredAkeneoValue(\n layers: AkeneoValues[],\n attributeCode: string,\n locale: string,\n channel: string | null,\n): unknown {\n for (const layer of layers) {\n const value = readPreferredAkeneoValue(layer, attributeCode, locale, channel)\n if (value !== null && value !== undefined && !(typeof value === 'string' && value.trim().length === 0)) {\n return value\n }\n }\n return null\n}\n\nfunction coerceString(value: unknown): string | null {\n if (typeof value === 'string' && value.trim().length > 0) return value.trim()\n if (typeof value === 'number' && Number.isFinite(value)) return String(value)\n return null\n}\n\nexport function normalizeAkeneoSelectValue(\n value: unknown,\n optionLabels: Map<string, string>,\n): string | null {\n if (Array.isArray(value)) {\n const labels = value\n .map((entry) => normalizeAkeneoSelectValue(entry, optionLabels))\n .filter((entry): entry is string => typeof entry === 'string' && entry.length > 0)\n return labels.length > 0 ? labels.join(', ') : null\n }\n\n const raw = coerceString(value)\n if (!raw) return null\n return optionLabels.get(raw) ?? raw\n}\n\nexport function filterAkeneoAttributeMappingsByAvailableAttributes<T extends { attributeCode: string }>(\n mappings: T[],\n availableAttributeCodes: string[],\n): T[] {\n const allowed = new Set(\n availableAttributeCodes\n .map((code) => code.trim())\n .filter((code) => code.length > 0),\n )\n if (allowed.size === 0) return []\n return mappings.filter((mapping) => allowed.has(mapping.attributeCode))\n}\n\ntype ExistingFieldsetDefinition = {\n key: string\n description: string | null\n fieldset: string | null\n fieldsets: string[]\n}\n\ntype DesiredFieldsetAssignment = {\n key: string\n fieldsets: string[]\n}\n\ntype EntityFieldsetAssignments = {\n fieldsets: CustomFieldsetDefinition[]\n fieldsetsByKey: Map<string, string[]>\n}\n\ntype ResolvedGlobalFieldsetAssignments = {\n product: EntityFieldsetAssignments\n variant: EntityFieldsetAssignments\n}\n\ntype AkeneoOptionSchemaMetadata = {\n familyCode: string | null\n familyVariantCode: string | null\n attributeCodes: string[]\n richAttributes: Record<string, Record<string, unknown>>\n}\n\nexport function resolveAkeneoFieldKeysToDetach(\n definitions: ExistingFieldsetDefinition[],\n desiredFieldKeys: string[],\n fieldsetCode: string | null,\n): string[] {\n if (!fieldsetCode) return []\n const desired = new Set(\n desiredFieldKeys\n .map((key) => normalizeFieldKey(key))\n .filter((key) => key.length > 0),\n )\n\n return definitions\n .filter((definition) => definition.fieldset === fieldsetCode || definition.fieldsets.includes(fieldsetCode))\n .filter((definition) => typeof definition.description === 'string' && definition.description.startsWith('Akeneo attribute '))\n .filter((definition) => !desired.has(normalizeFieldKey(definition.key)))\n .map((definition) => definition.key)\n}\n\nexport function resolveAkeneoFieldsetMemberships(\n currentFieldsets: string[],\n fieldsetCode: string | null,\n): string[] {\n return dedupeStrings([\n ...currentFieldsets\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n ...(fieldsetCode ? [fieldsetCode] : []),\n ])\n}\n\nfunction readConfiguredFieldsets(config: Record<string, unknown> | null | undefined): string[] {\n const configured = Array.isArray(config?.fieldsets)\n ? config.fieldsets.filter((entry): entry is string => typeof entry === 'string')\n : []\n const normalized = dedupeStrings(\n configured\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n )\n if (normalized.length > 0) return normalized\n const legacy = typeof config?.fieldset === 'string' ? config.fieldset.trim() : ''\n return legacy.length > 0 ? [legacy] : []\n}\n\nfunction clampString(value: string | null, maxLength: number): string | null {\n if (!value) return null\n return value.length > maxLength ? value.slice(0, maxLength).trim() : value\n}\n\nfunction coerceMetricAmount(value: unknown): number | null {\n const record = safeRecord(value)\n const amount = record?.amount\n if (typeof amount === 'string' && amount.trim().length > 0) {\n const numeric = Number(amount)\n return Number.isFinite(numeric) ? numeric : null\n }\n if (typeof amount === 'number' && Number.isFinite(amount)) return amount\n if (typeof value === 'number' && Number.isFinite(value)) return value\n return null\n}\n\nfunction coerceNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length > 0) {\n const numeric = Number(value)\n return Number.isFinite(numeric) ? numeric : null\n }\n return null\n}\n\nfunction coerceBoolean(value: unknown): boolean | null {\n if (typeof value === 'boolean') return value\n if (typeof value === 'string') {\n const lowered = value.trim().toLowerCase()\n if (lowered === 'true' || lowered === '1' || lowered === 'yes') return true\n if (lowered === 'false' || lowered === '0' || lowered === 'no') return false\n }\n return null\n}\n\nfunction mergeValueLayers(...layers: Array<AkeneoValues | undefined | null>): AkeneoValues {\n const merged: AkeneoValues = {}\n for (const layer of layers) {\n if (!layer) continue\n for (const [key, value] of Object.entries(layer)) {\n merged[key] = Array.isArray(value) ? value : []\n }\n }\n return merged\n}\n\nfunction normalizeFieldKey(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 100)\n}\n\nfunction readAkeneoOptionSchemaMetadata(value: unknown): AkeneoOptionSchemaMetadata | null {\n const parsedValue = typeof value === 'string'\n ? (() => {\n try {\n return JSON.parse(value) as unknown\n } catch {\n return null\n }\n })()\n : value\n const metadata = safeRecord(parsedValue)\n if (!metadata) return null\n\n const familyCode = typeof metadata.familyCode === 'string' && metadata.familyCode.trim().length > 0\n ? metadata.familyCode.trim()\n : null\n const familyVariantCode = typeof metadata.familyVariantCode === 'string' && metadata.familyVariantCode.trim().length > 0\n ? metadata.familyVariantCode.trim()\n : null\n const attributeCodes = Array.isArray(metadata.attributeCodes)\n ? dedupeStrings(metadata.attributeCodes.filter((entry): entry is string => typeof entry === 'string'))\n : []\n const richAttributes = safeRecord(metadata.richAttributes) ?? {}\n\n if (!familyCode && !familyVariantCode) return null\n if (attributeCodes.length === 0) return null\n\n return {\n familyCode,\n familyVariantCode,\n attributeCodes,\n richAttributes: Object.fromEntries(\n Object.entries(richAttributes)\n .filter(([, entry]) => Boolean(safeRecord(entry))),\n ) as Record<string, Record<string, unknown>>,\n }\n}\n\nfunction mapAkeneoAttributeInputType(attributeType: string): 'select' | 'text' | 'textarea' | 'number' | null {\n if (attributeType === 'pim_catalog_simpleselect' || attributeType === 'akeneo_reference_entity' || attributeType === 'akeneo_reference_entity_collection') {\n return 'select'\n }\n if (attributeType === 'pim_catalog_multiselect') return 'select'\n if (attributeType === 'pim_catalog_text') return 'text'\n if (attributeType === 'pim_catalog_textarea') return 'textarea'\n if (\n attributeType === 'pim_catalog_number'\n || attributeType === 'pim_catalog_metric'\n || attributeType === 'pim_catalog_price_collection'\n ) {\n return 'number'\n }\n return null\n}\n\nfunction mapAkeneoAttributeToCustomFieldKind(attribute: AkeneoAttribute, preferredKind?: AkeneoCustomFieldKind | null): AkeneoCustomFieldKind | null {\n if (preferredKind) return preferredKind\n if (attribute.type === 'pim_catalog_boolean') return 'boolean'\n if (attribute.type === 'pim_catalog_number') {\n return attribute.decimals_allowed === false ? 'integer' : 'float'\n }\n if (attribute.type === 'pim_catalog_metric') return 'float'\n if (\n attribute.type === 'pim_catalog_simpleselect'\n || attribute.type === 'pim_catalog_multiselect'\n || attribute.type === 'akeneo_reference_entity'\n || attribute.type === 'akeneo_reference_entity_collection'\n ) {\n return 'select'\n }\n if (attribute.type === 'pim_catalog_textarea') return 'multiline'\n if (attribute.type === 'pim_catalog_text') return 'text'\n if (attribute.type === 'pim_catalog_date') return 'text'\n return null\n}\n\nfunction buildValidationRules(attribute: AkeneoAttribute): Array<{ rule: string; param?: unknown }> {\n const rules: Array<{ rule: string; param?: unknown }> = []\n if (attribute.is_required_for_completeness) rules.push({ rule: 'required' })\n if (typeof attribute.max_characters === 'number' && Number.isFinite(attribute.max_characters)) {\n rules.push({ rule: 'maxLength', param: attribute.max_characters })\n }\n if (attribute.validation_rule === 'regexp' && typeof attribute.validation_regexp === 'string' && attribute.validation_regexp.trim().length > 0) {\n rules.push({ rule: 'pattern', param: attribute.validation_regexp.trim() })\n }\n const minimumValue = coerceNumber(attribute.minimum_value)\n if (minimumValue !== null) rules.push({ rule: 'min', param: minimumValue })\n const maximumValue = coerceNumber(attribute.maximum_value)\n if (maximumValue !== null) rules.push({ rule: 'max', param: maximumValue })\n return rules\n}\n\nfunction buildAttributeMetadata(attribute: AkeneoAttribute, locale: string): Record<string, unknown> {\n return {\n provider: 'akeneo',\n attributeCode: attribute.code,\n type: attribute.type,\n label: labelFromLocalizedRecord(attribute.labels ?? null, locale, attribute.code),\n groupCode: attribute.group ?? null,\n groupLabel: attribute.group_labels ? labelFromLocalizedRecord(attribute.group_labels, locale, attribute.group ?? 'Akeneo') : null,\n localizable: Boolean(attribute.localizable),\n scopable: Boolean(attribute.scopable),\n isRequiredForCompleteness: Boolean(attribute.is_required_for_completeness),\n unique: Boolean(attribute.unique),\n useableAsGridFilter: Boolean(attribute.useable_as_grid_filter),\n validationRule: attribute.validation_rule ?? null,\n validationRegexp: attribute.validation_regexp ?? null,\n decimalsAllowed: attribute.decimals_allowed ?? null,\n negativeAllowed: attribute.negative_allowed ?? null,\n minimumValue: attribute.minimum_value ?? null,\n maximumValue: attribute.maximum_value ?? null,\n metricFamily: attribute.metric_family ?? null,\n defaultMetricUnit: attribute.default_metric_unit ?? null,\n referenceDataName: attribute.reference_data_name ?? null,\n }\n}\n\nfunction familyRequiresAttribute(family: AkeneoFamily, attributeCode: string): boolean {\n const requirements = family.attribute_requirements\n if (!requirements || typeof requirements !== 'object') return false\n return Object.values(requirements).some((codes) => Array.isArray(codes) && codes.includes(attributeCode))\n}\n\nfunction resolvePriceVariantId(price: Pick<CatalogProductPrice, 'variant'>): string | null {\n const variant: unknown = price.variant\n if (typeof variant === 'string') return variant\n return price.variant?.id ?? null\n}\n\nfunction parsePriceCollection(value: unknown): Array<{ currencyCode: string; amount: number }> {\n if (!Array.isArray(value)) return []\n return value\n .map((entry) => {\n const record = safeRecord(entry)\n const currencyCode = typeof record?.currency === 'string' ? record.currency.trim().toUpperCase() : ''\n const amount = coerceNumber(record?.amount)\n if (!currencyCode || amount === null) return null\n return { currencyCode, amount }\n })\n .filter((entry): entry is { currencyCode: string; amount: number } => Boolean(entry))\n}\n\nfunction collectMediaReferences(value: unknown): MediaReference[] {\n const values = Array.isArray(value) ? value : value === null || value === undefined ? [] : [value]\n return values\n .map((entry) => {\n if (typeof entry === 'string' && entry.trim().length > 0) {\n return {\n codeOrUrl: entry.trim(),\n fileNameHint: null,\n mimeTypeHint: null,\n }\n }\n const record = safeRecord(entry)\n if (!record) return null\n const linkRecord = safeRecord(record._links)\n const downloadRecord = safeRecord(linkRecord?.download)\n const codeOrUrl = coerceString(record.code)\n ?? coerceString(record.download_link)\n ?? coerceString(record.href)\n ?? coerceString(downloadRecord?.href)\n if (!codeOrUrl) return null\n return {\n codeOrUrl,\n fileNameHint: coerceString(record.original_filename) ?? coerceString(record.file_path),\n mimeTypeHint: coerceString(record.mime_type),\n }\n })\n .filter((entry): entry is MediaReference => Boolean(entry))\n}\n\nexport function resolveAkeneoMediaTarget(params: {\n mappingTarget: 'product' | 'variant'\n attributeCode: string\n variantAttributeCodes: string[]\n productScopedValue: unknown\n variantScopedValue: unknown\n}): 'product' | 'variant' {\n const hasProductValue = params.productScopedValue !== null && params.productScopedValue !== undefined\n const hasVariantValue = params.variantScopedValue !== null && params.variantScopedValue !== undefined\n\n if (params.variantAttributeCodes.includes(params.attributeCode)) {\n return 'variant'\n }\n if (hasProductValue) {\n return 'product'\n }\n if (hasVariantValue) {\n return 'variant'\n }\n return params.mappingTarget\n}\n\nfunction resolveCustomFieldValue(value: unknown, attribute: AkeneoAttribute, kind: AkeneoCustomFieldKind): unknown {\n if (kind === 'boolean') return coerceBoolean(value)\n if (kind === 'integer') return coerceNumber(value) === null ? null : Math.trunc(Number(value))\n if (kind === 'float') return attribute.type === 'pim_catalog_metric' ? coerceMetricAmount(value) : coerceNumber(value)\n if (kind === 'multiline') return normalizeMarkdownText(coerceString(value))\n if (kind === 'text') {\n if (typeof value === 'string') return normalizeMarkdownText(value)\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n return value ? JSON.stringify(value) : null\n }\n if (kind === 'select') {\n if (Array.isArray(value)) {\n const items = value.map((entry) => coerceString(entry)).filter((entry): entry is string => Boolean(entry))\n return items.length > 0 ? items : null\n }\n return coerceString(value)\n }\n return null\n}\n\nfunction relationTypeFromAssociation(associationType: string): 'bundle' | 'grouped' {\n const normalized = associationType.trim().toLowerCase()\n return normalized.includes('pack') || normalized.includes('bundle') ? 'bundle' : 'grouped'\n}\n\nfunction titleizeCode(value: string): string {\n return value\n .trim()\n .replace(/[_-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n}\n\nfunction findFieldsetMapping(\n mappings: AkeneoFieldsetMapping[],\n target: 'product' | 'variant',\n sourceType: 'family' | 'familyVariant',\n sourceCode: string | null,\n): AkeneoFieldsetMapping | null {\n if (!sourceCode) return null\n return mappings.find((entry) => (\n entry.target === target\n && entry.sourceType === sourceType\n && entry.sourceCode === sourceCode\n )) ?? null\n}\n\nfunction applyFieldsetOverride(\n fallback: CustomFieldsetDefinition | null,\n override: AkeneoFieldsetMapping | null,\n): CustomFieldsetDefinition | null {\n if (!fallback || !override) return fallback\n return {\n ...fallback,\n code: override.fieldsetCode,\n label: override.fieldsetLabel,\n description: override.description ?? fallback.description,\n }\n}\n\nfunction collectFieldsetGroups(attributes: AkeneoAttribute[], locale: string): NonNullable<CustomFieldsetDefinition['groups']> | undefined {\n const groups = dedupeStrings(attributes.map((attribute) => attribute.group))\n .map((groupCode) => {\n const attribute = attributes.find((entry) => entry.group === groupCode)\n return {\n code: normalizeFieldKey(groupCode),\n title: attribute?.group_labels\n ? labelFromLocalizedRecord(attribute.group_labels, locale, groupCode)\n : titleizeCode(groupCode),\n }\n })\n .filter((group) => group.code.length > 0)\n return groups.length > 0 ? groups : undefined\n}\n\nfunction collectFieldsetGroupsFromSchemaMetadata(\n metadata: AkeneoOptionSchemaMetadata,\n): NonNullable<CustomFieldsetDefinition['groups']> | undefined {\n const groups = new Map<string, { code: string; title: string }>()\n for (const attributeCode of metadata.attributeCodes) {\n const attribute = safeRecord(metadata.richAttributes[attributeCode])\n const groupCode = typeof attribute?.groupCode === 'string' && attribute.groupCode.trim().length > 0\n ? attribute.groupCode.trim()\n : null\n if (!groupCode) continue\n const normalizedCode = normalizeFieldKey(groupCode)\n if (!normalizedCode || groups.has(normalizedCode)) continue\n const title = typeof attribute?.groupLabel === 'string' && attribute.groupLabel.trim().length > 0\n ? attribute.groupLabel.trim()\n : titleizeCode(groupCode)\n groups.set(normalizedCode, { code: normalizedCode, title })\n }\n return groups.size > 0 ? Array.from(groups.values()) : undefined\n}\n\nfunction buildFieldsetPlanFromOptionSchema(params: {\n schema: Pick<CatalogOptionSchemaTemplate, 'code' | 'name' | 'description'>\n metadata: AkeneoOptionSchemaMetadata\n locale: string\n fieldsetMappings: AkeneoFieldsetMapping[]\n}): { target: 'product' | 'variant'; fieldset: CustomFieldsetDefinition | null } {\n const target = params.metadata.familyVariantCode ? 'variant' : 'product'\n const sourceType = params.metadata.familyVariantCode ? 'familyVariant' : 'family'\n const sourceCode = params.metadata.familyVariantCode ?? params.metadata.familyCode\n const fallbackCode = buildAkeneoFieldsetCode(target, sourceCode)\n const override = findFieldsetMapping(params.fieldsetMappings, target, sourceType, sourceCode)\n const fallbackLabel = params.schema.name?.trim().length\n ? params.schema.name.trim()\n : titleizeCode(sourceCode ?? `Akeneo ${target}`)\n const fallbackDescription = params.schema.description?.trim().length\n ? params.schema.description.trim()\n : sourceType === 'familyVariant' && params.metadata.familyVariantCode\n ? `Akeneo family variant ${params.metadata.familyVariantCode}`\n : params.metadata.familyCode\n ? `Akeneo family ${params.metadata.familyCode}`\n : `Akeneo ${target} attributes`\n const fieldsetCode = override?.fieldsetCode ?? fallbackCode\n if (!fieldsetCode) {\n return { target, fieldset: null }\n }\n\n return {\n target,\n fieldset: {\n code: fieldsetCode,\n label: override?.fieldsetLabel ?? fallbackLabel,\n description: override?.description ?? fallbackDescription,\n groups: collectFieldsetGroupsFromSchemaMetadata(params.metadata),\n },\n }\n}\n\nfunction buildFieldsetPlan(params: {\n family: AkeneoFamily | null\n familyVariant: AkeneoFamilyVariant | null\n productAttributes: AkeneoAttribute[]\n variantAttributes: AkeneoAttribute[]\n locale: string\n fieldsetMappings: AkeneoFieldsetMapping[]\n}): AkeneoFieldsetPlan {\n const productFallbackCode = buildAkeneoFieldsetCode('product', params.family?.code ?? null)\n const variantFallbackCode = buildAkeneoFieldsetCode('variant', params.familyVariant?.code ?? params.family?.code ?? null)\n\n const productFallback = productFallbackCode && params.productAttributes.length > 0\n ? {\n code: productFallbackCode,\n label: labelFromLocalizedRecord(params.family?.labels ?? null, params.locale, params.family?.code ?? 'Akeneo product'),\n description: params.family\n ? `Akeneo family ${params.family.code}`\n : 'Akeneo-imported product attributes',\n groups: collectFieldsetGroups(params.productAttributes, params.locale),\n }\n : null\n const variantFallback = variantFallbackCode && params.variantAttributes.length > 0\n ? {\n code: variantFallbackCode,\n label: labelFromLocalizedRecord(\n params.familyVariant?.labels ?? params.family?.labels ?? null,\n params.locale,\n params.familyVariant?.code ?? params.family?.code ?? 'Akeneo variant',\n ),\n description: params.familyVariant?.code\n ? `Akeneo family variant ${params.familyVariant.code}`\n : params.family?.code\n ? `Akeneo variant attributes for family ${params.family.code}`\n : 'Akeneo-imported variant attributes',\n groups: collectFieldsetGroups(params.variantAttributes, params.locale),\n }\n : null\n\n return {\n product: applyFieldsetOverride(\n productFallback,\n findFieldsetMapping(params.fieldsetMappings, 'product', 'family', params.family?.code ?? null),\n ),\n variant: applyFieldsetOverride(\n variantFallback,\n findFieldsetMapping(params.fieldsetMappings, 'variant', 'familyVariant', params.familyVariant?.code ?? null)\n ?? findFieldsetMapping(params.fieldsetMappings, 'variant', 'family', params.family?.code ?? null),\n ),\n }\n}\n\nfunction dedupeCustomFieldMappings(items: Array<{ attributeCode: string; fieldKey: string; target: 'product' | 'variant'; kind?: AkeneoCustomFieldKind | null; skip?: boolean }>) {\n const seen = new Set<string>()\n return items.filter((item) => {\n const key = `${item.target}:${item.attributeCode}:${item.fieldKey}:${item.skip === true ? 'skip' : 'import'}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\nfunction dedupeMediaMappings(items: Array<{ attributeCode: string; target: 'product' | 'variant'; kind: 'image' | 'file' }>) {\n const seen = new Set<string>()\n return items.filter((item) => {\n const key = `${item.target}:${item.kind}:${item.attributeCode}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\nfunction collectValueScopes(layers: AkeneoValues[], attributeCode: string): Array<string | null> {\n const seen = new Set<string>()\n const scopes: Array<string | null> = []\n for (const layer of layers) {\n const entries = Array.isArray(layer?.[attributeCode]) ? layer[attributeCode] : []\n for (const entry of entries) {\n const scope = coerceString(entry?.scope)\n const key = scope ?? '__null__'\n if (seen.has(key)) continue\n seen.add(key)\n scopes.push(scope)\n }\n }\n return scopes\n}\n\nfunction resolveImportedAkeneoChannels(settings: AkeneoProductMappingSettings): string[] {\n return dedupeStrings([\n ...(settings.channels ?? []),\n settings.channel,\n ])\n}\n\nfunction shouldImportAkeneoChannel(settings: AkeneoProductMappingSettings, akeneoChannel: string | null): boolean {\n if (!akeneoChannel) return true\n if (settings.importAllChannels) return true\n const selectedChannels = resolveImportedAkeneoChannels(settings)\n if (selectedChannels.length === 0) return true\n return selectedChannels.includes(akeneoChannel)\n}\n\nexport async function createAkeneoImporter(client: AkeneoClient, scope: ImportScope) {\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const commandBus = container.resolve('commandBus') as CommandBus\n const dataEngine = container.resolve('dataEngine') as DataEngine\n const externalIdMappingService = container.resolve('externalIdMappingService') as ExternalIdMappingService\n let cacheService: { deleteByTags?: (tags: string[]) => Promise<void> } | null = null\n try {\n cacheService = container.resolve('cache') as { deleteByTags?: (tags: string[]) => Promise<void> }\n } catch {\n cacheService = null\n }\n const categoryCache = new Map<string, Promise<string | null>>()\n const optionSchemaCache = new Map<string, Promise<UpsertResult | null>>()\n const channelCache = new Map<string, Promise<{ id: string; code: string } | null>>()\n const priceKindCache = new Map<string, Promise<{ id: string; code: string; displayMode: string } | null>>()\n const customFieldSyncCache = new Map<string, Promise<CustomFieldSyncItem[]>>()\n const globalFieldsetAssignmentCache = new Map<string, Promise<ResolvedGlobalFieldsetAssignments>>()\n const preferredChannelCodeCache = new Map<string, Promise<string | null>>()\n const preferredPriceKindCodeCache = new Map<string, Promise<string | null>>()\n const attributeOptionLabelCache = new Map<string, Promise<Map<string, string>>>()\n const defaultProductSettings = buildDefaultAkeneoMapping('products').settings?.products\n\n function buildCommandContext(): CommandRuntimeContext {\n return {\n container,\n auth: null,\n organizationScope: {\n selectedId: scope.organizationId,\n filterIds: [scope.organizationId],\n allowedIds: [scope.organizationId],\n tenantId: scope.tenantId,\n },\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n }\n\n async function emitAttachmentCrudChange(\n action: 'created' | 'updated' | 'deleted',\n attachment: Attachment,\n ): Promise<void> {\n await emitCrudSideEffects({\n dataEngine,\n action,\n entity: attachment,\n identifiers: {\n id: attachment.id,\n organizationId: attachment.organizationId ?? null,\n tenantId: attachment.tenantId ?? null,\n },\n events: attachmentCrudEvents,\n indexer: attachmentCrudIndexer,\n })\n await dataEngine.flushOrmEntityChanges()\n }\n\n async function executeCommand<TResult>(commandId: string, input: Record<string, unknown>): Promise<TResult> {\n try {\n const executed = await commandBus.execute<Record<string, unknown>, TResult>(commandId, {\n input,\n ctx: buildCommandContext(),\n })\n return executed.result\n } catch (error) {\n const message = error instanceof Error ? error.message : JSON.stringify(error)\n throw new Error(`${commandId} failed: ${message}`)\n }\n }\n\n async function lookupProductBySku(sku: string | null): Promise<string | null> {\n if (!sku) return null\n const product = await findOneWithDecryption(\n em,\n CatalogProduct,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n sku,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n return product?.id ?? null\n }\n\n async function lookupVariantBySku(sku: string | null, productId?: string | null): Promise<string | null> {\n if (!sku) return null\n const variant = await findOneWithDecryption(\n em,\n CatalogProductVariant,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n ...(productId ? { product: productId } : {}),\n sku,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n return variant?.id ?? null\n }\n\n async function resolveExistingProductId(productExternalId: string, sku: string | null): Promise<string | null> {\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product', productExternalId, scope)\n if (mappedId) {\n const mappedProduct = await findOneWithDecryption(\n em,\n CatalogProduct,\n {\n id: mappedId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (mappedProduct) return mappedProduct.id\n }\n\n return lookupProductBySku(sku)\n }\n\n async function resolveExistingVariantId(\n variantExternalId: string,\n sku: string | null,\n productId: string,\n ): Promise<string | null> {\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_variant', variantExternalId, scope)\n if (mappedId) {\n const mappedVariant = await findOneWithDecryption(\n em,\n CatalogProductVariant,\n {\n id: mappedId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product: productId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (mappedVariant) return mappedVariant.id\n }\n\n return lookupVariantBySku(sku, productId)\n }\n\n async function resolveCategoryId(code: string | null | undefined, locale: string): Promise<string | null> {\n if (!code) return null\n if (!categoryCache.has(code)) {\n categoryCache.set(code, (async () => {\n const mapped = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_category', code, scope)\n if (mapped) return mapped\n\n const existing = await findOneWithDecryption(\n em,\n CatalogProductCategory,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n slug: slugifyAkeneoCode(code),\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (existing) {\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_category', existing.id, code, scope)\n return existing.id\n }\n\n const remote = await client.getCategory(code)\n if (!remote) return null\n const result = await upsertCategory(remote, locale)\n return result.localId\n })())\n }\n return categoryCache.get(code) ?? null\n }\n\n async function resolveChannel(code: string, options?: { createIfMissing?: boolean; label?: string | null }): Promise<{ id: string; code: string } | null> {\n const normalizedCode = code.trim().toLowerCase()\n if (!normalizedCode) return null\n const cacheKey = `${normalizedCode}:${options?.createIfMissing ? 'create' : 'read'}:${options?.label ?? ''}`\n if (!channelCache.has(cacheKey)) {\n channelCache.set(cacheKey, (async () => {\n const channel = await findOneWithDecryption(em, SalesChannel, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n code: normalizedCode,\n deletedAt: null,\n isActive: true,\n }, undefined, scope)\n if (channel) {\n return { id: channel.id, code: channel.code ?? normalizedCode }\n }\n if (!options?.createIfMissing) return null\n\n const created = await executeCommand<{ channelId: string }>('sales.channels.create', {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: options.label?.trim() || titleizeCode(normalizedCode),\n code: normalizedCode,\n metadata: {\n source: 'akeneo',\n autoCreatedBy: 'sync_akeneo',\n },\n isActive: true,\n })\n return {\n id: created.channelId,\n code: normalizedCode,\n }\n })())\n }\n return channelCache.get(cacheKey) ?? null\n }\n\n async function resolvePriceKind(code: string): Promise<{ id: string; code: string; displayMode: string } | null> {\n const normalizedCode = code.trim().toLowerCase()\n if (!normalizedCode) return null\n if (!priceKindCache.has(normalizedCode)) {\n priceKindCache.set(normalizedCode, (async () => {\n const priceKind = await findOneWithDecryption(\n em,\n CatalogPriceKind,\n {\n tenantId: scope.tenantId,\n code: normalizedCode,\n deletedAt: null,\n isActive: true,\n },\n undefined,\n scope,\n )\n return priceKind ? { id: priceKind.id, code: priceKind.code, displayMode: priceKind.displayMode } : null\n })())\n }\n return priceKindCache.get(normalizedCode) ?? null\n }\n\n async function resolvePreferredLocalChannelCode(): Promise<string | null> {\n const cacheKey = 'preferred'\n if (!preferredChannelCodeCache.has(cacheKey)) {\n preferredChannelCodeCache.set(cacheKey, (async () => {\n const channels = await findWithDecryption(em, SalesChannel, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n isActive: true,\n }, {\n orderBy: { createdAt: 'asc' },\n }, scope)\n const preferredCodes = ['web', 'online', 'ecommerce', 'default']\n for (const preferredCode of preferredCodes) {\n const match = channels.find((channel) => (channel.code ?? '').trim().toLowerCase() === preferredCode)\n if (match?.code) return match.code\n }\n return channels.find((channel) => typeof channel.code === 'string' && channel.code.trim().length > 0)?.code ?? null\n })())\n }\n return preferredChannelCodeCache.get(cacheKey) ?? null\n }\n\n async function resolvePreferredPriceKindCode(): Promise<string | null> {\n const cacheKey = 'preferred'\n if (!preferredPriceKindCodeCache.has(cacheKey)) {\n preferredPriceKindCodeCache.set(cacheKey, (async () => {\n const priceKinds = await findWithDecryption(em, CatalogPriceKind, {\n tenantId: scope.tenantId,\n deletedAt: null,\n isActive: true,\n }, {\n orderBy: { createdAt: 'asc' },\n }, scope)\n const preferredCodes = ['regular', 'sale', 'base', 'default']\n for (const preferredCode of preferredCodes) {\n const match = priceKinds.find((priceKind) => priceKind.code.trim().toLowerCase() === preferredCode)\n if (match) return match.code\n }\n return priceKinds[0]?.code ?? null\n })())\n }\n return preferredPriceKindCodeCache.get(cacheKey) ?? null\n }\n\n async function ensureEntityFieldsetConfig(entityId: string, fieldset: CustomFieldsetDefinition | null): Promise<void> {\n if (!fieldset) return\n let config = await findOneWithDecryption(em, CustomFieldEntityConfig, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n if (!config) {\n config = em.create(CustomFieldEntityConfig, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n }\n\n const existing = normalizeEntityFieldsetConfig(config.configJson ?? {})\n const remaining = existing.fieldsets.filter((entry) => entry.code !== fieldset.code)\n config.configJson = {\n fieldsets: [...remaining, fieldset],\n singleFieldsetPerRecord: true,\n }\n config.isActive = true\n config.deletedAt = null\n config.updatedAt = new Date()\n em.persist(config)\n await em.flush()\n }\n\n async function upsertCategory(category: AkeneoCategory, locale: string): Promise<UpsertResult> {\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_category', category.code, scope)\n const existingId = mappedId\n ?? (await findOneWithDecryption(\n em,\n CatalogProductCategory,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n slug: slugifyAkeneoCode(category.code),\n deletedAt: null,\n },\n undefined,\n scope,\n ))?.id\n ?? null\n\n const parentId = category.parent ? await resolveCategoryId(category.parent, locale) : null\n const input = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: labelFromLocalizedRecord(category.labels ?? null, locale, category.code),\n slug: slugifyAkeneoCode(category.code),\n description: undefined,\n parentId,\n isActive: true,\n }\n\n if (existingId) {\n await executeCommand('catalog.categories.update', {\n id: existingId,\n ...input,\n })\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_category', existingId, category.code, scope)\n return { localId: existingId, action: 'update' }\n }\n\n const created = await executeCommand<{ categoryId: string }>('catalog.categories.create', input)\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_category', created.categoryId, category.code, scope)\n return { localId: created.categoryId, action: 'create' }\n }\n\n async function buildOptionSchemaDefinition(attribute: AkeneoAttribute, family: AkeneoFamily, locale: string) {\n const inputType = mapAkeneoAttributeInputType(attribute.type)\n if (!inputType) return null\n\n const definition: Record<string, unknown> = {\n code: slugifyAkeneoCode(attribute.code),\n label: labelFromLocalizedRecord(attribute.labels ?? null, locale, attribute.code),\n description: typeof attribute.group === 'string' ? `Akeneo group: ${attribute.group}` : undefined,\n inputType,\n isRequired: familyRequiresAttribute(family, attribute.code),\n }\n\n if (attribute.type === 'pim_catalog_multiselect') {\n definition.isMultiple = true\n }\n\n if (inputType === 'select' && (attribute.type === 'pim_catalog_simpleselect' || attribute.type === 'pim_catalog_multiselect')) {\n const options = await client.listAttributeOptions(attribute.code).catch(() => [])\n definition.choices = options.map((option) => ({\n code: slugifyAkeneoCode(option.code),\n label: labelFromLocalizedRecord(option.labels ?? null, locale, option.code),\n }))\n }\n\n return definition\n }\n\n async function getAttributeOptionLabels(attributeCode: string, locale: string): Promise<Map<string, string>> {\n const cacheKey = `${attributeCode}:${locale}`\n if (!attributeOptionLabelCache.has(cacheKey)) {\n attributeOptionLabelCache.set(cacheKey, (async () => {\n const options = await client.listAttributeOptions(attributeCode).catch(() => [])\n return new Map(\n options.map((option) => [\n option.code,\n labelFromLocalizedRecord(option.labels ?? null, locale, option.code),\n ]),\n )\n })())\n }\n return attributeOptionLabelCache.get(cacheKey) ?? new Map<string, string>()\n }\n\n async function ensureOptionSchemaForFamily(\n family: AkeneoFamily,\n familyVariant: AkeneoFamilyVariant | null,\n includeTextAttributes: boolean,\n includeNumericAttributes: boolean,\n locale: string,\n attributeCodesOverride?: string[] | null,\n ): Promise<UpsertResult | null> {\n const requestedAttributeCodes = Array.isArray(attributeCodesOverride)\n ? dedupeStrings(attributeCodesOverride)\n : null\n const cacheKey = `${family.code}:${familyVariant?.code ?? 'family'}:${locale}:${includeTextAttributes}:${includeNumericAttributes}:${requestedAttributeCodes ? requestedAttributeCodes.join('|') : 'all'}`\n if (!optionSchemaCache.has(cacheKey)) {\n optionSchemaCache.set(cacheKey, (async () => {\n if (requestedAttributeCodes && requestedAttributeCodes.length === 0) {\n return null\n }\n const externalId = familyVariant?.code ?? family.code\n const schemaCode = slugifyAkeneoCode(`akeneo-${externalId}`)\n const mappedId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_option_schema', externalId, scope)\n const existing = mappedId\n ? await findOneWithDecryption(\n em,\n CatalogOptionSchemaTemplate,\n {\n id: mappedId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n : await findOneWithDecryption(\n em,\n CatalogOptionSchemaTemplate,\n {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n code: schemaCode,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n const familyAttributes = Array.isArray(family.attributes) ? family.attributes : []\n const familyVariantAttributes = familyVariant?.variant_attribute_sets?.flatMap((set) => [\n ...(Array.isArray(set.attributes) ? set.attributes : []),\n ...(Array.isArray(set.axes) ? set.axes : []),\n ]) ?? []\n const attributeCodes = requestedAttributeCodes ?? dedupeStrings([...familyAttributes, ...familyVariantAttributes])\n const definitions: Record<string, unknown>[] = []\n const richAttributes: Record<string, unknown> = {}\n for (const code of attributeCodes) {\n const attribute = await client.getAttribute(code)\n if (!attribute) continue\n const inputType = mapAkeneoAttributeInputType(attribute.type)\n if (!inputType) continue\n if ((inputType === 'text' || inputType === 'textarea') && !includeTextAttributes) continue\n if (inputType === 'number' && !includeNumericAttributes) continue\n const definition = await buildOptionSchemaDefinition(attribute, family, locale)\n if (!definition) continue\n definitions.push(definition)\n richAttributes[code] = {\n ...buildAttributeMetadata(attribute, locale),\n validation: buildValidationRules(attribute),\n }\n if (definitions.length >= 64) break\n }\n\n const schemaInput = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: labelFromLocalizedRecord(family.labels ?? null, locale, family.code),\n code: schemaCode,\n description: familyVariant?.code ? `Akeneo family variant ${familyVariant.code}` : `Akeneo family ${family.code}`,\n schema: {\n version: 1,\n name: labelFromLocalizedRecord(family.labels ?? null, locale, family.code),\n description: familyVariant?.code ? `Akeneo family variant ${familyVariant.code}` : `Akeneo family ${family.code}`,\n options: definitions,\n },\n metadata: {\n source: 'akeneo',\n familyCode: family.code,\n familyVariantCode: familyVariant?.code ?? null,\n attributeCodes,\n richAttributes,\n attributeAsLabel: family.attribute_as_label ?? null,\n attributeAsImage: family.attribute_as_image ?? null,\n variantAxes: familyVariant?.variant_attribute_sets?.map((set) => ({\n level: set.level ?? null,\n axes: Array.isArray(set.axes) ? set.axes : [],\n attributes: Array.isArray(set.attributes) ? set.attributes : [],\n })) ?? [],\n },\n isActive: true,\n }\n\n if (existing) {\n await executeCommand('catalog.optionSchemas.update', {\n id: existing.id,\n ...schemaInput,\n })\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_option_schema', existing.id, externalId, scope)\n return { localId: existing.id, action: 'update' }\n }\n\n const created = await executeCommand<{ schemaId: string }>('catalog.optionSchemas.create', schemaInput)\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_option_schema', created.schemaId, externalId, scope)\n return { localId: created.schemaId, action: 'create' }\n })())\n }\n\n return optionSchemaCache.get(cacheKey) ?? null\n }\n\n async function syncMappedCustomFields(\n mapping: AkeneoDataMapping,\n locale: string,\n fieldsetPlan?: AkeneoFieldsetPlan | null,\n options?: { forceRefresh?: boolean },\n ): Promise<CustomFieldSyncItem[]> {\n const settings = mapping.settings?.products\n if (!settings || settings.customFieldMappings.length === 0) return []\n const cacheKey = JSON.stringify({\n customFieldMappings: settings.customFieldMappings.filter((mapping) => !mapping.skip),\n fieldsetPlan,\n locale,\n })\n if (options?.forceRefresh) {\n customFieldSyncCache.delete(cacheKey)\n globalFieldsetAssignmentCache.delete(JSON.stringify({\n customFieldMappings: settings.customFieldMappings.filter((entry) => !entry.skip),\n fieldsetMappings: settings.fieldsetMappings,\n }))\n }\n if (!customFieldSyncCache.has(cacheKey)) {\n customFieldSyncCache.set(cacheKey, (async () => {\n const productFields: Array<CustomFieldDefinition & { sourceMetadata?: Record<string, unknown> }> = []\n const variantFields: Array<CustomFieldDefinition & { sourceMetadata?: Record<string, unknown> }> = []\n const items: CustomFieldSyncItem[] = []\n const globalAssignments = await resolveGlobalFieldsetAssignments(settings)\n const existingDefinitions = await findWithDecryption(em, CustomFieldDef, {\n entityId: { $in: [PRODUCT_ENTITY_ID, VARIANT_ENTITY_ID] } as never,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n const existingFieldsetsByEntityAndKey = new Map<string, string[]>()\n for (const definition of existingDefinitions) {\n const config = safeRecord(definition.configJson)\n existingFieldsetsByEntityAndKey.set(\n `${definition.entityId}:${definition.key}`,\n readConfiguredFieldsets(config),\n )\n }\n\n for (const fieldMapping of settings.customFieldMappings) {\n if (fieldMapping.skip) continue\n const attribute = await client.getAttribute(fieldMapping.attributeCode)\n if (!attribute) continue\n const kind = mapAkeneoAttributeToCustomFieldKind(attribute, fieldMapping.kind)\n if (!kind) continue\n const entityId = fieldMapping.target === 'product' ? PRODUCT_ENTITY_ID : VARIANT_ENTITY_ID\n const normalizedKey = normalizeFieldKey(fieldMapping.fieldKey)\n const currentFieldsetCode = fieldMapping.target === 'product'\n ? fieldsetPlan?.product?.code ?? null\n : fieldsetPlan?.variant?.code ?? null\n const globalFieldsets = fieldMapping.target === 'product'\n ? globalAssignments.product.fieldsetsByKey.get(normalizedKey) ?? []\n : globalAssignments.variant.fieldsetsByKey.get(normalizedKey) ?? []\n const inheritedFieldsets = existingFieldsetsByEntityAndKey.get(`${entityId}:${normalizedKey}`) ?? []\n const effectiveFieldsets = dedupeStrings([\n ...globalFieldsets,\n ...inheritedFieldsets,\n ...(currentFieldsetCode ? [currentFieldsetCode] : []),\n ])\n const options = kind === 'select' && (attribute.type === 'pim_catalog_simpleselect' || attribute.type === 'pim_catalog_multiselect')\n ? await client.listAttributeOptions(attribute.code).catch(() => [])\n : []\n const field: CustomFieldDefinition & { sourceMetadata?: Record<string, unknown> } = {\n key: normalizedKey,\n kind,\n label: labelFromLocalizedRecord(attribute.labels ?? null, locale, fieldMapping.fieldKey),\n description: `Akeneo attribute ${fieldMapping.attributeCode}`,\n fieldset: effectiveFieldsets.length === 1 ? effectiveFieldsets[0] : undefined,\n fieldsets: effectiveFieldsets.length > 0 ? effectiveFieldsets : undefined,\n multi: attribute.type === 'pim_catalog_multiselect' || attribute.type === 'akeneo_reference_entity_collection',\n options: options.map((option) => ({\n value: option.code,\n label: labelFromLocalizedRecord(option.labels ?? null, locale, option.code),\n })),\n filterable: Boolean(attribute.useable_as_grid_filter),\n listVisible: false,\n editor: kind === 'multiline' ? 'markdown' : undefined,\n validation: buildValidationRules(attribute),\n group: attribute.group ? {\n code: normalizeFieldKey(attribute.group),\n title: attribute.group_labels ? labelFromLocalizedRecord(attribute.group_labels, locale, attribute.group) : attribute.group,\n } : undefined,\n sourceMetadata: buildAttributeMetadata(attribute, locale),\n }\n if (fieldMapping.target === 'product') productFields.push(field)\n else variantFields.push(field)\n items.push({\n externalId: `${fieldMapping.target}:${fieldMapping.attributeCode}`,\n action: 'update',\n data: {\n key: field.key,\n target: fieldMapping.target,\n attributeCode: fieldMapping.attributeCode,\n },\n })\n }\n\n const sets = []\n if (productFields.length > 0) {\n sets.push({\n entity: PRODUCT_ENTITY_ID,\n fields: productFields,\n source: 'akeneo',\n })\n }\n if (variantFields.length > 0) {\n sets.push({\n entity: VARIANT_ENTITY_ID,\n fields: variantFields,\n source: 'akeneo',\n })\n }\n\n if (sets.length > 0) {\n const productFieldAssignments = productFields.map((field) => ({\n key: field.key,\n fieldsets: resolveAkeneoFieldsetMemberships(\n existingFieldsetsByEntityAndKey.get(`${PRODUCT_ENTITY_ID}:${field.key}`) ?? [],\n fieldsetPlan?.product?.code ?? null,\n ),\n }))\n const variantFieldAssignments = variantFields.map((field) => ({\n key: field.key,\n fieldsets: resolveAkeneoFieldsetMemberships(\n existingFieldsetsByEntityAndKey.get(`${VARIANT_ENTITY_ID}:${field.key}`) ?? [],\n fieldsetPlan?.variant?.code ?? null,\n ),\n }))\n\n await ensureCustomFieldDefinitions(em, sets, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await Promise.all([\n ensureEntityFieldsetConfig(PRODUCT_ENTITY_ID, fieldsetPlan?.product ?? null),\n ensureEntityFieldsetConfig(VARIANT_ENTITY_ID, fieldsetPlan?.variant ?? null),\n ])\n await Promise.all([\n ensureAkeneoFieldsetAssignments(PRODUCT_ENTITY_ID, productFieldAssignments),\n ensureAkeneoFieldsetAssignments(VARIANT_ENTITY_ID, variantFieldAssignments),\n ])\n await Promise.all([\n reconcileAkeneoFieldsetAssignments(PRODUCT_ENTITY_ID, fieldsetPlan?.product?.code ?? null, productFields.map((field) => field.key)),\n reconcileAkeneoFieldsetAssignments(VARIANT_ENTITY_ID, fieldsetPlan?.variant?.code ?? null, variantFields.map((field) => field.key)),\n ])\n await invalidateDefinitionsCache(cacheService as never, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entityIds: [PRODUCT_ENTITY_ID, VARIANT_ENTITY_ID],\n })\n }\n\n return items\n })())\n }\n return customFieldSyncCache.get(cacheKey) ?? []\n }\n\n async function reconcileAkeneoFieldsetAssignments(\n entityId: string,\n fieldsetCode: string | null,\n desiredFieldKeys: string[],\n ): Promise<void> {\n if (!fieldsetCode) return\n\n const existingDefinitions = await findWithDecryption(em, CustomFieldDef, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n\n const keysToDetach = resolveAkeneoFieldKeysToDetach(\n existingDefinitions.map((definition) => {\n const config = safeRecord(definition.configJson)\n return {\n key: definition.key,\n description: typeof config?.description === 'string' ? config.description : null,\n fieldset: typeof config?.fieldset === 'string' ? config.fieldset : null,\n fieldsets: readConfiguredFieldsets(config),\n }\n }),\n desiredFieldKeys,\n fieldsetCode,\n )\n\n if (keysToDetach.length === 0) return\n\n for (const definition of existingDefinitions) {\n if (!keysToDetach.includes(definition.key)) continue\n const nextConfig = {\n ...(safeRecord(definition.configJson) ?? {}),\n }\n const remainingFieldsets = readConfiguredFieldsets(nextConfig).filter((entry) => entry !== fieldsetCode)\n if (remainingFieldsets.length === 0) {\n delete nextConfig.fieldset\n delete nextConfig.fieldsets\n } else if (remainingFieldsets.length === 1) {\n nextConfig.fieldset = remainingFieldsets[0]\n nextConfig.fieldsets = remainingFieldsets\n } else {\n delete nextConfig.fieldset\n nextConfig.fieldsets = remainingFieldsets\n }\n definition.configJson = nextConfig\n definition.updatedAt = new Date()\n }\n\n await em.flush()\n }\n\n async function ensureAkeneoFieldsetAssignments(\n entityId: string,\n assignments: DesiredFieldsetAssignment[],\n ): Promise<void> {\n const normalizedAssignments = assignments\n .map((assignment) => ({\n key: normalizeFieldKey(assignment.key),\n fieldsets: dedupeStrings(\n assignment.fieldsets\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n ),\n }))\n .filter((assignment) => assignment.key.length > 0 && assignment.fieldsets.length > 0)\n\n const normalizedKeys = normalizedAssignments.map((assignment) => assignment.key)\n if (normalizedKeys.length === 0) return\n\n const fieldsetsByKey = new Map(normalizedAssignments.map((assignment) => [assignment.key, assignment.fieldsets]))\n\n const existingDefinitions = await findWithDecryption(em, CustomFieldDef, {\n entityId,\n key: { $in: normalizedKeys } as never,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n\n let changed = false\n for (const definition of existingDefinitions) {\n const nextConfig = {\n ...(safeRecord(definition.configJson) ?? {}),\n }\n const nextFieldsets = fieldsetsByKey.get(definition.key) ?? []\n if (nextFieldsets.length === 0) continue\n\n const currentFieldsets = readConfiguredFieldsets(nextConfig)\n const currentPrimary = typeof nextConfig.fieldset === 'string' ? nextConfig.fieldset.trim() : ''\n const nextPrimary = nextFieldsets.length === 1 ? nextFieldsets[0] : ''\n const sameMemberships = currentFieldsets.length === nextFieldsets.length\n && currentFieldsets.every((entry, index) => entry === nextFieldsets[index])\n if (sameMemberships && currentPrimary === nextPrimary) continue\n\n if (nextFieldsets.length === 1) {\n nextConfig.fieldset = nextFieldsets[0]\n delete nextConfig.fieldsets\n } else {\n delete nextConfig.fieldset\n nextConfig.fieldsets = nextFieldsets\n }\n definition.configJson = nextConfig\n definition.updatedAt = new Date()\n changed = true\n }\n\n if (changed) {\n await em.flush()\n }\n }\n\n async function applyAkeneoManagedFieldsetAssignments(\n entityId: string,\n assignments: EntityFieldsetAssignments,\n ): Promise<void> {\n const dedupedFieldsets = new Map(assignments.fieldsets.map((fieldset) => [fieldset.code, fieldset]))\n await Promise.all(\n Array.from(dedupedFieldsets.values()).map((fieldset) => ensureEntityFieldsetConfig(entityId, fieldset)),\n )\n\n const definitions = await findWithDecryption(em, CustomFieldDef, {\n entityId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n\n let changed = false\n for (const definition of definitions) {\n const config = safeRecord(definition.configJson)\n const sourceMetadata = safeRecord(config?.sourceMetadata)\n const isAkeneoManaged = sourceMetadata?.provider === 'akeneo'\n || (typeof config?.description === 'string' && config.description.startsWith('Akeneo attribute '))\n if (!isAkeneoManaged) continue\n\n const nextConfig = {\n ...(config ?? {}),\n }\n const nextFieldsets = assignments.fieldsetsByKey.get(definition.key) ?? []\n const currentFieldsets = readConfiguredFieldsets(nextConfig)\n const currentPrimary = typeof nextConfig.fieldset === 'string' ? nextConfig.fieldset.trim() : ''\n const nextPrimary = nextFieldsets.length === 1 ? nextFieldsets[0] : ''\n const sameMemberships = currentFieldsets.length === nextFieldsets.length\n && currentFieldsets.every((entry, index) => entry === nextFieldsets[index])\n if (sameMemberships && currentPrimary === nextPrimary) continue\n\n if (nextFieldsets.length === 0) {\n delete nextConfig.fieldset\n delete nextConfig.fieldsets\n } else if (nextFieldsets.length === 1) {\n nextConfig.fieldset = nextFieldsets[0]\n delete nextConfig.fieldsets\n } else {\n delete nextConfig.fieldset\n nextConfig.fieldsets = nextFieldsets\n }\n\n definition.configJson = nextConfig\n definition.updatedAt = new Date()\n changed = true\n }\n\n if (changed) {\n await em.flush()\n await invalidateDefinitionsCache(cacheService as never, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entityIds: [entityId],\n })\n }\n }\n\n async function reconcileMappedCustomFieldFieldsets(mapping: AkeneoDataMapping): Promise<void> {\n const settings = mapping.settings?.products\n if (!settings || settings.customFieldMappings.length === 0) return\n\n const activeMappings = settings.customFieldMappings.filter((entry) => !entry.skip)\n if (activeMappings.length === 0) return\n\n globalFieldsetAssignmentCache.delete(JSON.stringify({\n customFieldMappings: settings.customFieldMappings.filter((entry) => !entry.skip),\n fieldsetMappings: settings.fieldsetMappings,\n }))\n em.clear()\n const globalAssignments = await resolveGlobalFieldsetAssignments(settings)\n const productAssignments = globalAssignments.product\n const variantAssignments = globalAssignments.variant\n\n if (productAssignments.fieldsets.length > 0 || productAssignments.fieldsetsByKey.size > 0) {\n await applyAkeneoManagedFieldsetAssignments(PRODUCT_ENTITY_ID, productAssignments)\n }\n if (variantAssignments.fieldsets.length > 0 || variantAssignments.fieldsetsByKey.size > 0) {\n await applyAkeneoManagedFieldsetAssignments(VARIANT_ENTITY_ID, variantAssignments)\n }\n }\n\n async function resolveGlobalFieldsetAssignments(\n settings: AkeneoProductMappingSettings,\n ): Promise<ResolvedGlobalFieldsetAssignments> {\n const activeMappings = settings.customFieldMappings.filter((entry) => !entry.skip)\n const cacheKey = JSON.stringify({\n customFieldMappings: activeMappings,\n fieldsetMappings: settings.fieldsetMappings,\n })\n if (!globalFieldsetAssignmentCache.has(cacheKey)) {\n globalFieldsetAssignmentCache.set(cacheKey, (async () => {\n const optionSchemas = await em.getConnection().execute<Array<{\n code: string\n name: string\n description: string | null\n metadata: unknown\n }>>(\n `\n select code, name, description, metadata\n from catalog_product_option_schemas\n where organization_id = ?\n and tenant_id = ?\n and deleted_at is null\n `,\n [scope.organizationId, scope.tenantId],\n )\n const akeneoSchemas: Array<{\n schema: {\n code: string\n name: string\n description: string | null\n }\n metadata: AkeneoOptionSchemaMetadata\n }> = []\n for (const schema of optionSchemas) {\n const metadata = readAkeneoOptionSchemaMetadata(schema.metadata)\n if (!metadata) continue\n akeneoSchemas.push({\n schema: {\n code: schema.code,\n name: schema.name,\n description: schema.description,\n },\n metadata,\n })\n }\n\n const productAssignments: EntityFieldsetAssignments = {\n fieldsets: [],\n fieldsetsByKey: new Map(),\n }\n const variantAssignments: EntityFieldsetAssignments = {\n fieldsets: [],\n fieldsetsByKey: new Map(),\n }\n\n const addFieldsetAssignment = (\n bucket: EntityFieldsetAssignments,\n fieldKey: string,\n fieldset: CustomFieldsetDefinition | null,\n ) => {\n if (!fieldset) return\n const normalizedKey = normalizeFieldKey(fieldKey)\n if (!normalizedKey) return\n const existing = bucket.fieldsetsByKey.get(normalizedKey) ?? []\n bucket.fieldsetsByKey.set(\n normalizedKey,\n resolveAkeneoFieldsetMemberships(existing, fieldset.code),\n )\n if (!bucket.fieldsets.some((entry) => entry.code === fieldset.code)) {\n bucket.fieldsets.push(fieldset)\n }\n }\n\n for (const { schema, metadata } of akeneoSchemas) {\n const fieldsetPlan = buildFieldsetPlanFromOptionSchema({\n schema,\n metadata,\n locale: settings.locale,\n fieldsetMappings: settings.fieldsetMappings,\n })\n if (!fieldsetPlan.fieldset) continue\n\n const schemaMappings = activeMappings.filter((entry) => (\n entry.target === fieldsetPlan.target\n && metadata.attributeCodes.includes(entry.attributeCode)\n ))\n if (schemaMappings.length === 0) continue\n\n const bucket = fieldsetPlan.target === 'product' ? productAssignments : variantAssignments\n for (const fieldMapping of schemaMappings) {\n addFieldsetAssignment(bucket, fieldMapping.fieldKey, fieldsetPlan.fieldset)\n }\n }\n\n return {\n product: productAssignments,\n variant: variantAssignments,\n }\n })())\n }\n\n return globalFieldsetAssignmentCache.get(cacheKey) ?? {\n product: { fieldsets: [], fieldsetsByKey: new Map() },\n variant: { fieldsets: [], fieldsetsByKey: new Map() },\n }\n }\n\n async function upsertAttributeFamily(\n family: AkeneoFamily,\n locale: string,\n includeTextAttributes: boolean,\n includeNumericAttributes: boolean,\n ): Promise<UpsertResult | null> {\n return ensureOptionSchemaForFamily(family, null, includeTextAttributes, includeNumericAttributes, locale)\n }\n\n async function resolveAutoLocalChannelCode(\n akeneoChannel: string | null,\n fallbackChannelCode: string | null,\n createIfMissing: boolean,\n ): Promise<string | null> {\n if (akeneoChannel) {\n const exact = await resolveChannel(akeneoChannel, {\n createIfMissing,\n label: titleizeCode(akeneoChannel),\n })\n if (exact) return exact.code\n\n const aliases = akeneoChannel.trim().toLowerCase() === 'ecommerce'\n ? ['web', 'online', 'default']\n : akeneoChannel.trim().toLowerCase() === 'web'\n ? ['ecommerce', 'online', 'default']\n : []\n for (const alias of aliases) {\n const match = await resolveChannel(alias)\n if (match) return match.code\n }\n }\n return fallbackChannelCode\n }\n\n async function resolveAutoPriceKindCode(attributeCode: string): Promise<string | null> {\n const normalizedCode = attributeCode.trim().toLowerCase()\n const preferredCode = normalizedCode.includes('sale')\n || normalizedCode.includes('promo')\n || normalizedCode.includes('special')\n || normalizedCode.includes('discount')\n ? 'sale'\n : 'regular'\n const preferred = await resolvePriceKind(preferredCode)\n if (preferred) return preferred.code\n return resolvePreferredPriceKindCode()\n }\n\n async function buildAutomaticPriceMappings(params: {\n hierarchy: ResolvedHierarchy\n settings: AkeneoProductMappingSettings\n priceAttributeCodes: string[]\n }): Promise<AkeneoProductMappingSettings['priceMappings']> {\n const fallbackChannelCode = await resolvePreferredLocalChannelCode()\n\n const mappings: AkeneoProductMappingSettings['priceMappings'] = []\n const selectedChannels = resolveImportedAkeneoChannels(params.settings)\n for (const attributeCode of dedupeStrings(params.priceAttributeCodes)) {\n const priceKindCode = await resolveAutoPriceKindCode(attributeCode)\n if (!priceKindCode) continue\n const scopes = collectValueScopes(\n [params.hierarchy.leafValues, params.hierarchy.mergedValues],\n attributeCode,\n )\n const effectiveScopes = scopes.length > 0\n ? scopes\n : [\n ...(selectedChannels.length > 0\n ? selectedChannels\n : [params.settings.channel ?? (params.settings.createMissingChannels ? 'default' : null)]),\n ]\n for (const akeneoChannel of effectiveScopes) {\n if (!shouldImportAkeneoChannel(params.settings, akeneoChannel)) continue\n const localChannelCode = await resolveAutoLocalChannelCode(\n akeneoChannel,\n fallbackChannelCode,\n params.settings.createMissingChannels,\n )\n if (!localChannelCode) continue\n mappings.push({\n attributeCode,\n priceKindCode,\n akeneoChannel,\n localChannelCode,\n })\n }\n }\n\n const seen = new Set<string>()\n return mappings.filter((mapping) => {\n const key = `${mapping.attributeCode}:${mapping.priceKindCode}:${mapping.akeneoChannel ?? ''}:${mapping.localChannelCode}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n async function resolveProductSettings(params: {\n mapping: AkeneoDataMapping\n hierarchy: ResolvedHierarchy\n family: AkeneoFamily | null\n familyVariant: AkeneoFamilyVariant | null\n }): Promise<{\n settings: AkeneoProductMappingSettings\n axisCodes: string[]\n variantAttributeCodes: string[]\n optionSchemaAttributeCodes: string[]\n fieldsetPlan: AkeneoFieldsetPlan\n }> {\n if (!defaultProductSettings) {\n throw new Error('Default Akeneo product mapping is not available')\n }\n\n const baseSettings = params.mapping.settings?.products ?? defaultProductSettings\n const attributeCodes = dedupeStrings([\n ...Object.keys(params.hierarchy.rootValues),\n ...Object.keys(params.hierarchy.leafValues),\n ...Object.keys(params.hierarchy.mergedValues),\n ...(Array.isArray(params.family?.attributes) ? params.family.attributes : []),\n ...(params.familyVariant?.variant_attribute_sets?.flatMap((set) => [\n ...(Array.isArray(set.axes) ? set.axes : []),\n ...(Array.isArray(set.attributes) ? set.attributes : []),\n ]) ?? []),\n ])\n const attributes = (\n await Promise.all(attributeCodes.map((code) => client.getAttribute(code)))\n ).filter((attribute): attribute is AkeneoAttribute => Boolean(attribute))\n\n const inferred = inferAkeneoProductMapping({\n attributes,\n family: params.family,\n familyVariant: params.familyVariant,\n fieldMap: baseSettings.fieldMap,\n explicitCustomFieldMappings: baseSettings.customFieldMappings,\n explicitMediaMappings: baseSettings.mediaMappings,\n })\n\n const priceMappings = baseSettings.priceMappings.length > 0\n ? baseSettings.priceMappings\n : await buildAutomaticPriceMappings({\n hierarchy: params.hierarchy,\n settings: baseSettings,\n priceAttributeCodes: inferred.autoPriceAttributeCodes,\n })\n\n const explicitCustomAttributeCodes = new Set(baseSettings.customFieldMappings.map((entry) => entry.attributeCode))\n const inferredCustomAttributeCodes = new Set(inferred.autoCustomFieldMappings.map((entry) => entry.attributeCode))\n const productAttributes = attributes.filter((attribute) => {\n if (!explicitCustomAttributeCodes.has(attribute.code) && !inferredCustomAttributeCodes.has(attribute.code)) return false\n return params.familyVariant\n ? !inferred.variantAttributeCodes.includes(attribute.code)\n : true\n })\n const variantAttributes = attributes.filter((attribute) => {\n if (!explicitCustomAttributeCodes.has(attribute.code) && !inferredCustomAttributeCodes.has(attribute.code)) return false\n return inferred.variantAttributeCodes.includes(attribute.code)\n })\n const fieldsetPlan = buildFieldsetPlan({\n family: params.family,\n familyVariant: params.familyVariant,\n productAttributes,\n variantAttributes,\n locale: baseSettings.locale,\n fieldsetMappings: baseSettings.fieldsetMappings,\n })\n const availableAttributeCodes = attributes.map((attribute) => attribute.code)\n\n return {\n settings: {\n ...baseSettings,\n fieldMap: inferred.fieldMap,\n customFieldMappings: filterAkeneoAttributeMappingsByAvailableAttributes(\n dedupeCustomFieldMappings([\n ...baseSettings.customFieldMappings,\n ...inferred.autoCustomFieldMappings,\n ]),\n availableAttributeCodes,\n ),\n mediaMappings: filterAkeneoAttributeMappingsByAvailableAttributes(\n dedupeMediaMappings([\n ...baseSettings.mediaMappings,\n ...inferred.autoMediaMappings,\n ]),\n availableAttributeCodes,\n ),\n fieldsetMappings: baseSettings.fieldsetMappings,\n priceMappings,\n },\n axisCodes: inferred.axisCodes,\n variantAttributeCodes: inferred.variantAttributeCodes,\n optionSchemaAttributeCodes: inferred.optionSchemaAttributeCodes,\n fieldsetPlan,\n }\n }\n\n async function resolveProductHierarchy(product: AkeneoProduct): Promise<ResolvedHierarchy> {\n if (!product.parent) {\n return {\n rootExternalId: product.uuid,\n family: product.family ?? null,\n familyVariantCode: null,\n rootValues: mergeValueLayers(product.values),\n leafValues: mergeValueLayers(product.values),\n mergedValues: mergeValueLayers(product.values),\n categories: Array.isArray(product.categories) ? product.categories : [],\n parentChain: [],\n associationSource: product,\n axisCodes: [],\n }\n }\n\n const chain: Array<{ code: string; values: AkeneoValues; categories: string[]; family?: string | null; familyVariant?: string | null }> = []\n let nextCode: string | null = product.parent\n while (nextCode) {\n const model = await client.getProductModel(nextCode)\n if (!model) break\n chain.unshift({\n code: model.code,\n values: mergeValueLayers(model.values),\n categories: Array.isArray(model.categories) ? model.categories : [],\n family: model.family ?? null,\n familyVariant: model.family_variant ?? null,\n })\n nextCode = model.parent ?? null\n }\n\n const root = chain[0]\n return {\n rootExternalId: root?.code ?? product.uuid,\n family: product.family ?? root?.family ?? null,\n familyVariantCode: chain[chain.length - 1]?.familyVariant ?? root?.familyVariant ?? null,\n rootValues: root?.values ?? mergeValueLayers(product.values),\n leafValues: mergeValueLayers(product.values),\n mergedValues: mergeValueLayers(\n ...chain.map((model) => model.values),\n product.values,\n ),\n categories: Array.from(new Set([\n ...chain.flatMap((model) => model.categories),\n ...(product.categories ?? []),\n ])),\n parentChain: chain.map((model) => model.code),\n associationSource: product,\n axisCodes: [],\n }\n }\n\n async function applyCustomFieldMappings(params: {\n mapping: AkeneoDataMapping\n hierarchy: ResolvedHierarchy\n product: AkeneoProduct\n localProductId: string\n localVariantId: string\n fieldsetPlan?: AkeneoFieldsetPlan | null\n }): Promise<void> {\n const settings = params.mapping.settings?.products\n if (!settings || settings.customFieldMappings.length === 0) return\n\n await syncMappedCustomFields(params.mapping, settings.locale, params.fieldsetPlan)\n\n const productCustomFields: Record<string, unknown> = {}\n const variantCustomFields: Record<string, unknown> = {}\n\n for (const fieldMapping of settings.customFieldMappings) {\n if (fieldMapping.skip) continue\n const attribute = await client.getAttribute(fieldMapping.attributeCode)\n if (!attribute) continue\n const kind = mapAkeneoAttributeToCustomFieldKind(attribute, fieldMapping.kind)\n if (!kind) continue\n const sourceLayers = fieldMapping.target === 'product'\n ? [params.hierarchy.rootValues, params.hierarchy.mergedValues]\n : [params.product.values ?? {}, params.hierarchy.mergedValues]\n const rawValue = readLayeredAkeneoValue(sourceLayers, fieldMapping.attributeCode, settings.locale, settings.channel ?? null)\n const value = resolveCustomFieldValue(rawValue, attribute, kind)\n if (value === null || value === undefined || (Array.isArray(value) && value.length === 0)) continue\n if (fieldMapping.target === 'product') {\n productCustomFields[normalizeFieldKey(fieldMapping.fieldKey)] = value\n } else {\n variantCustomFields[normalizeFieldKey(fieldMapping.fieldKey)] = value\n }\n }\n\n await Promise.all([\n setCustomFieldsIfAny({\n dataEngine,\n entityId: PRODUCT_ENTITY_ID,\n recordId: params.localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: productCustomFields,\n }),\n setCustomFieldsIfAny({\n dataEngine,\n entityId: VARIANT_ENTITY_ID,\n recordId: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n values: variantCustomFields,\n }),\n ])\n\n await Promise.all([\n params.fieldsetPlan?.product?.code\n ? executeCommand('catalog.products.update', {\n id: params.localProductId,\n customFieldsetCode: params.fieldsetPlan.product.code,\n })\n : Promise.resolve(),\n params.fieldsetPlan?.variant?.code\n ? executeCommand('catalog.variants.update', {\n id: params.localVariantId,\n customFieldsetCode: params.fieldsetPlan.variant.code,\n })\n : Promise.resolve(),\n ])\n\n if (Object.keys(productCustomFields).length > 0) {\n await emitCatalogQueryIndexEvent(buildCommandContext(), {\n entityType: PRODUCT_ENTITY_ID,\n recordId: params.localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n action: 'updated',\n })\n }\n\n if (Object.keys(variantCustomFields).length > 0) {\n await emitCatalogQueryIndexEvent(buildCommandContext(), {\n entityType: VARIANT_ENTITY_ID,\n recordId: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n action: 'updated',\n })\n }\n }\n\n async function upsertOffersAndPrices(params: {\n mapping: AkeneoDataMapping\n settings: AkeneoProductMappingSettings\n hierarchy: ResolvedHierarchy\n localProductId: string\n localVariantId: string\n resolvedProductTitle: string\n resolvedProductDescription: string | null\n variantExternalId: string\n }): Promise<void> {\n const desiredOffers = new Map<string, DesiredOffer>()\n for (const priceMapping of params.settings.priceMappings) {\n const channel = await resolveChannel(priceMapping.localChannelCode, {\n createIfMissing: params.settings.createMissingChannels,\n label: titleizeCode(priceMapping.localChannelCode),\n })\n const priceKind = await resolvePriceKind(priceMapping.priceKindCode)\n if (!channel || !priceKind) continue\n const akeneoChannel = priceMapping.akeneoChannel ?? params.settings.channel ?? null\n if (!shouldImportAkeneoChannel(params.settings, akeneoChannel)) continue\n const rawPrices = readLayeredAkeneoValue(\n [params.hierarchy.leafValues, params.hierarchy.mergedValues],\n priceMapping.attributeCode,\n params.settings.locale,\n akeneoChannel,\n )\n const entries = parsePriceCollection(rawPrices)\n if (entries.length === 0) continue\n const offerExternalId = `${params.hierarchy.rootExternalId}:offer:${channel.code}`\n const existingOffer = desiredOffers.get(offerExternalId)\n const title = coerceString(readLayeredAkeneoValue(\n [params.hierarchy.rootValues, params.hierarchy.mergedValues],\n params.settings.fieldMap.title,\n params.settings.locale,\n akeneoChannel,\n )) ?? params.resolvedProductTitle\n const description = clampString(\n normalizeMarkdownText(\n coerceString(readLayeredAkeneoValue(\n [params.hierarchy.rootValues, params.hierarchy.mergedValues],\n params.settings.fieldMap.description,\n params.settings.locale,\n akeneoChannel,\n )) ?? params.resolvedProductDescription,\n ),\n 4000,\n )\n const bucket = existingOffer ?? {\n externalId: offerExternalId,\n channelCode: channel.code,\n channelId: channel.id,\n akeneoChannel,\n title,\n description,\n prices: [],\n }\n for (const entry of entries) {\n bucket.prices.push({\n externalId: `${params.variantExternalId}:price:${priceKind.code}:${channel.code}:${entry.currencyCode}`,\n priceKindCode: priceKind.code,\n priceKindId: priceKind.id,\n channelId: channel.id,\n currencyCode: entry.currencyCode,\n amount: entry.amount,\n variantId: params.localVariantId,\n })\n }\n desiredOffers.set(offerExternalId, bucket)\n }\n\n const existingOffers = await findWithDecryption(\n em,\n CatalogOffer,\n {\n product: params.localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n const existingOfferByChannelId = new Map(existingOffers.map((offer) => [offer.channelId, offer]))\n const desiredOfferExternalIds = new Set(desiredOffers.keys())\n\n for (const offer of desiredOffers.values()) {\n const mappedOfferId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_offer', offer.externalId, scope)\n const existingOffer = mappedOfferId\n ? existingOffers.find((entry) => entry.id === mappedOfferId) ?? null\n : existingOfferByChannelId.get(offer.channelId) ?? null\n const input = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n productId: params.localProductId,\n channelId: offer.channelId,\n title: offer.title,\n description: offer.description ?? undefined,\n metadata: {\n source: 'akeneo',\n externalId: offer.externalId,\n channelCode: offer.channelCode,\n akeneoChannel: offer.akeneoChannel,\n },\n isActive: true,\n }\n const offerId = existingOffer\n ? (await executeCommand<{ offerId: string }>('catalog.offers.update', { id: existingOffer.id, ...input })).offerId\n : (await executeCommand<{ offerId: string }>('catalog.offers.create', input)).offerId\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_offer', offerId, offer.externalId, scope)\n\n const existingPrices = await findWithDecryption(\n em,\n CatalogProductPrice,\n {\n offer: offerId,\n variant: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n const desiredPriceExternalIds = new Set(offer.prices.map((price) => price.externalId))\n for (const price of offer.prices) {\n const mappedPriceId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_price', price.externalId, scope)\n const mappedPrice = mappedPriceId\n ? existingPrices.find((entry) => entry.id === mappedPriceId) ?? null\n : null\n const existingPrice = mappedPrice\n ?? existingPrices.find((entry) => (\n resolvePriceVariantId(entry) === price.variantId\n && entry.channelId === price.channelId\n && entry.currencyCode === price.currencyCode\n && entry.kind === price.priceKindCode\n && entry.minQuantity === 1\n ))\n ?? null\n const input = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n productId: params.localProductId,\n variantId: price.variantId,\n offerId,\n priceKindId: price.priceKindId,\n currencyCode: price.currencyCode,\n unitPriceNet: price.amount,\n unitPriceGross: price.amount,\n minQuantity: 1,\n channelId: price.channelId,\n metadata: {\n source: 'akeneo',\n externalId: price.externalId,\n priceKindCode: price.priceKindCode,\n },\n }\n const priceId = existingPrice\n ? (await executeCommand<{ priceId: string }>('catalog.prices.update', { id: existingPrice.id, ...input })).priceId\n : (await executeCommand<{ priceId: string }>('catalog.prices.create', input)).priceId\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_price', priceId, price.externalId, scope)\n }\n\n if (params.settings.reconciliation.deleteMissingPrices) {\n for (const existingPrice of existingPrices) {\n const externalId = await externalIdMappingService.lookupExternalId('sync_akeneo', 'catalog_product_price', existingPrice.id, scope)\n if (externalId && !desiredPriceExternalIds.has(externalId)) {\n await executeCommand('catalog.prices.delete', { id: existingPrice.id })\n }\n }\n }\n }\n\n if (params.settings.reconciliation.deleteMissingOffers) {\n for (const existingOffer of existingOffers) {\n const externalId = await externalIdMappingService.lookupExternalId('sync_akeneo', 'catalog_offer', existingOffer.id, scope)\n if (externalId && !desiredOfferExternalIds.has(externalId)) {\n const offerPrices = await findWithDecryption(\n em,\n CatalogProductPrice,\n { offer: existingOffer.id, organizationId: scope.organizationId, tenantId: scope.tenantId },\n undefined,\n scope,\n )\n const sharedWithOtherVariants = offerPrices.some((price) => {\n const priceVariantId = resolvePriceVariantId(price)\n return priceVariantId !== null && priceVariantId !== params.localVariantId\n })\n if (sharedWithOtherVariants) {\n for (const price of offerPrices) {\n if (resolvePriceVariantId(price) !== params.localVariantId) continue\n const priceExternalId = await externalIdMappingService.lookupExternalId('sync_akeneo', 'catalog_product_price', price.id, scope)\n if (priceExternalId) {\n await executeCommand('catalog.prices.delete', { id: price.id })\n }\n }\n continue\n }\n for (const price of offerPrices) {\n await executeCommand('catalog.prices.delete', { id: price.id })\n }\n await executeCommand('catalog.offers.delete', { id: existingOffer.id })\n }\n }\n }\n }\n\n async function recordRejectedMedia(asset: DesiredAsset, reason: string): Promise<void> {\n const integrationLogService = container.resolve('integrationLogService') as IntegrationLogService\n await integrationLogService.write({\n integrationId: 'sync_akeneo',\n level: 'warn',\n code: 'sync_akeneo.media_rejected',\n message: `Akeneo media ${asset.remote.codeOrUrl} was not imported: ${reason}`,\n scopeEntityType: asset.entityId,\n scopeEntityId: asset.recordId,\n payload: {\n externalId: asset.externalId,\n remoteCode: asset.remote.codeOrUrl,\n kind: asset.kind,\n reason,\n },\n }, scope)\n }\n\n async function upsertAsset(asset: DesiredAsset): Promise<string | null> {\n const existingAttachmentId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'attachment', asset.externalId, scope)\n if (existingAttachmentId) return existingAttachmentId\n\n let binary: Awaited<ReturnType<AkeneoClient['downloadMediaFile']>>\n try {\n binary = await client.downloadMediaFile(asset.remote.codeOrUrl)\n } catch (error) {\n if (!isAkeneoResponseTooLargeError(error)) throw error\n await recordRejectedMedia(asset, 'max_upload_size')\n return null\n }\n const fileName = asset.remote.fileNameHint ?? binary.fileName ?? `akeneo-${randomUUID().slice(0, 8)}`\n const uploadService = container.resolve('attachmentScopedUploadService') as ScopedAttachmentUploadService\n let attachment: Attachment\n try {\n attachment = await uploadService.upload({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n entityId: asset.entityId,\n recordId: asset.recordId,\n fileName,\n declaredMimeType: asset.remote.mimeTypeHint ?? binary.contentType,\n buffer: binary.buffer,\n })\n } catch (error) {\n if (!isScopedAttachmentUploadError(error)) throw error\n if (REJECTED_MEDIA_UPLOAD_CODES.has(error.code)) {\n await recordRejectedMedia(asset, error.code)\n return null\n }\n const { translate } = await resolveTranslations()\n throw new Error(translate(\n 'sync_akeneo.errors.mediaStorageRejected',\n 'Akeneo media {code} was rejected by attachment storage ({reason}).',\n { code: asset.remote.codeOrUrl, reason: error.code },\n ))\n }\n attachment.url = asset.kind === 'image'\n ? buildAttachmentImageUrl(attachment.id, { slug: slugifyAttachmentFileName(attachment.fileName) })\n : buildAttachmentFileUrl(attachment.id)\n attachment.storageMetadata = {\n ...(attachment.storageMetadata ?? {}),\n source: 'akeneo',\n externalId: asset.externalId,\n kind: asset.kind,\n remoteCode: asset.remote.codeOrUrl,\n }\n await em.flush()\n await emitAttachmentCrudChange('updated', attachment)\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'attachment', attachment.id, asset.externalId, scope)\n return attachment.id\n }\n\n async function releaseImportedAttachment(attachment: Attachment): Promise<boolean> {\n const attachmentService = container.resolve('attachmentService') as AttachmentService\n if (!attachmentService.releaseScoped) {\n throw new Error('[internal] attachmentService.releaseScoped is not available')\n }\n try {\n await attachmentService.releaseScoped({\n attachmentId: attachment.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n expectedOwner: { entityId: attachment.entityId, recordId: attachment.recordId },\n expectedAssignment: { type: attachment.entityId, id: attachment.recordId },\n expectedPartitionCode: attachment.partitionCode,\n })\n return true\n } catch (error) {\n if (isCrudHttpError(error) && (error.status === 409 || error.status === 404)) return false\n throw error\n }\n }\n\n async function reconcileAttachments(params: {\n entityId: string\n recordId: string\n desiredAssets: DesiredAsset[]\n reconciliation: AkeneoReconciliationSettings\n }): Promise<{ heroAttachmentId: string | null; heroAttachmentUrl: string | null }> {\n const desiredExternalIds = new Set(params.desiredAssets.map((asset) => asset.externalId))\n let heroAttachmentId: string | null = null\n for (const asset of params.desiredAssets) {\n const attachmentId = await upsertAsset(asset)\n if (!heroAttachmentId && attachmentId && asset.kind === 'image') heroAttachmentId = attachmentId\n }\n const heroAttachmentUrl = heroAttachmentId ? buildAttachmentImageUrl(heroAttachmentId) : null\n\n const existing = await findWithDecryption(em, Attachment, {\n entityId: params.entityId,\n recordId: params.recordId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }, undefined, scope)\n for (const attachment of existing) {\n const metadata = safeRecord(attachment.storageMetadata)\n const externalId = typeof metadata?.externalId === 'string' ? metadata.externalId : null\n const kind = metadata?.kind === 'image' || metadata?.kind === 'file' ? metadata.kind : null\n if (!externalId || !kind) continue\n const shouldDelete = kind === 'image'\n ? params.reconciliation.deleteMissingMedia\n : params.reconciliation.deleteMissingAttachments\n if (!shouldDelete || desiredExternalIds.has(externalId)) continue\n if (!(await releaseImportedAttachment(attachment))) continue\n await emitAttachmentCrudChange('deleted', attachment)\n }\n\n return {\n heroAttachmentId,\n heroAttachmentUrl,\n }\n }\n\n async function syncAssociations(params: {\n product: AkeneoProduct\n localVariantId: string\n localProductId: string\n settings: AkeneoProductMappingSettings\n }): Promise<void> {\n if (!params.settings.syncAssociations) return\n const existing = await findWithDecryption(em, CatalogProductVariantRelation, {\n parentVariant: params.localVariantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }, undefined, scope)\n\n const desired = new Map<string, {\n relationType: 'bundle' | 'grouped'\n childVariantId: string | null\n childProductId: string | null\n associationType: string\n minQuantity: number | null\n }>()\n\n const addDesired = async (associationType: string, externalCandidate: string | null, quantity: number | null, mode: 'product' | 'productModel') => {\n if (!externalCandidate) return\n let childVariantId: string | null = null\n let childProductId: string | null = null\n if (mode === 'product') {\n childVariantId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_variant', externalCandidate, scope)\n ?? await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product_variant', `${externalCandidate}:default`, scope)\n ?? await lookupVariantBySku(externalCandidate)\n childProductId = childVariantId\n ? null\n : await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product', externalCandidate, scope)\n ?? await lookupProductBySku(externalCandidate)\n } else {\n childProductId = await externalIdMappingService.lookupLocalId('sync_akeneo', 'catalog_product', externalCandidate, scope)\n }\n if (!childVariantId && !childProductId) return\n const relationType = relationTypeFromAssociation(associationType)\n const key = `${relationType}:${childVariantId ?? childProductId}`\n desired.set(key, {\n relationType,\n childVariantId,\n childProductId,\n associationType,\n minQuantity: quantity,\n })\n }\n\n for (const [associationType, payload] of Object.entries(params.product.associations ?? {})) {\n for (const productIdentifier of payload.products ?? []) {\n await addDesired(associationType, productIdentifier, null, 'product')\n }\n for (const productModelCode of payload.product_models ?? []) {\n await addDesired(associationType, productModelCode, null, 'productModel')\n }\n }\n\n for (const [associationType, payload] of Object.entries(params.product.quantified_associations ?? {})) {\n for (const productEntry of payload.products ?? []) {\n await addDesired(associationType, coerceString(productEntry.uuid) ?? coerceString(productEntry.identifier), coerceNumber(productEntry.quantity), 'product')\n }\n for (const productModelEntry of payload.product_models ?? []) {\n await addDesired(associationType, coerceString(productModelEntry.code) ?? coerceString(productModelEntry.identifier), coerceNumber(productModelEntry.quantity), 'productModel')\n }\n }\n\n const desiredKeys = new Set(desired.keys())\n // Apply the create/update upserts and the stale-relation removals as a\n // single atomic unit so a product's relation set is never left partially\n // synced. `existing` is an in-memory array (already fetched above), so the\n // `.find()` lookups inside the phase do not run new `em` queries.\n await withAtomicFlush(em, [\n () => {\n for (const entry of desired.values()) {\n const existingRelation = existing.find((relation) => {\n const childVariantId = typeof relation.childVariant === 'string' ? relation.childVariant : relation.childVariant?.id ?? null\n const childProductId = typeof relation.childProduct === 'string' ? relation.childProduct : relation.childProduct?.id ?? null\n return relation.relationType === entry.relationType\n && childVariantId === entry.childVariantId\n && childProductId === entry.childProductId\n })\n if (existingRelation) {\n existingRelation.minQuantity = entry.minQuantity\n existingRelation.metadata = {\n source: 'akeneo',\n associationType: entry.associationType,\n }\n continue\n }\n const relation = em.create(CatalogProductVariantRelation, {\n parentVariant: em.getReference(CatalogProductVariant, params.localVariantId),\n childVariant: entry.childVariantId ? em.getReference(CatalogProductVariant, entry.childVariantId) : null,\n childProduct: entry.childProductId ? em.getReference(CatalogProduct, entry.childProductId) : null,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n relationType: entry.relationType,\n isRequired: false,\n minQuantity: entry.minQuantity,\n maxQuantity: null,\n position: 0,\n metadata: {\n source: 'akeneo',\n associationType: entry.associationType,\n },\n })\n em.persist(relation)\n }\n\n for (const relation of existing) {\n const metadata = safeRecord(relation.metadata)\n if (metadata?.source !== 'akeneo') continue\n const childVariantId = typeof relation.childVariant === 'string' ? relation.childVariant : relation.childVariant?.id ?? null\n const childProductId = typeof relation.childProduct === 'string' ? relation.childProduct : relation.childProduct?.id ?? null\n const key = `${relation.relationType}:${childVariantId ?? childProductId}`\n if (!desiredKeys.has(key)) {\n em.remove(relation)\n }\n }\n },\n ], { transaction: true })\n }\n\n async function upsertProduct(product: AkeneoProduct, mapping: AkeneoDataMapping): Promise<Array<{ externalId: string; action: 'create' | 'update' | 'skip'; data: Record<string, unknown> }>> {\n const family = product.family ? await client.getFamily(product.family) : null\n const hierarchy = await resolveProductHierarchy(product)\n const resolvedFamily = hierarchy.family ? await client.getFamily(hierarchy.family) : family\n const resolvedFamilyVariant = hierarchy.family && hierarchy.familyVariantCode\n ? await client.getFamilyVariant(hierarchy.family, hierarchy.familyVariantCode)\n : null\n const resolvedProductSettings = await resolveProductSettings({\n mapping,\n hierarchy,\n family: resolvedFamily,\n familyVariant: resolvedFamilyVariant,\n })\n const settings = resolvedProductSettings.settings\n const locale = settings.locale\n const channel = settings.channel ?? null\n hierarchy.axisCodes = resolvedProductSettings.axisCodes\n const productFieldsetCode = resolvedProductSettings.fieldsetPlan.product?.code ?? null\n const variantFieldsetCode = resolvedProductSettings.fieldsetPlan.variant?.code ?? null\n\n let optionSchemaId: string | null = null\n if (resolvedFamily && hierarchy.axisCodes.length > 0) {\n optionSchemaId = (await ensureOptionSchemaForFamily(\n resolvedFamily,\n resolvedFamilyVariant ?? null,\n true,\n true,\n locale,\n resolvedProductSettings.optionSchemaAttributeCodes,\n ))?.localId ?? null\n }\n const fieldMap = settings.fieldMap\n const derivedMapping: AkeneoDataMapping = {\n ...mapping,\n fields: buildProductFieldMappings(settings),\n settings: {\n ...(mapping.settings ?? {}),\n products: settings,\n },\n }\n\n const resolvedTitle = coerceString(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.title, locale, channel))\n ?? coerceString(product.identifier)\n ?? hierarchy.rootExternalId\n const resolvedSubtitle = coerceString(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.subtitle, locale, channel))\n const resolvedDescription = clampString(\n normalizeMarkdownText(\n coerceString(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.description, locale, channel)),\n ),\n 4000,\n )\n const resolvedSku = coerceString(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.sku, locale, channel))\n ?? coerceString(product.identifier)\n ?? product.uuid\n const resolvedBarcode = coerceString(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.barcode, locale, channel))\n const resolvedWeight = coerceMetricAmount(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.weight, locale, channel))\n ?? coerceMetricAmount(readLayeredAkeneoValue([hierarchy.rootValues, hierarchy.mergedValues], fieldMap.weight, locale, channel))\n const categoryIds = (\n await Promise.all(hierarchy.categories.map((code) => resolveCategoryId(code, locale)))\n ).filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n const productExternalId = hierarchy.rootExternalId\n const existingProductId = await resolveExistingProductId(\n productExternalId,\n product.parent ? null : resolvedSku,\n )\n\n const productInput = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: resolvedTitle,\n subtitle: resolvedSubtitle ?? undefined,\n description: resolvedDescription ?? undefined,\n sku: product.parent ? undefined : resolvedSku,\n productType: product.parent ? 'configurable' : 'simple',\n optionSchemaId,\n isConfigurable: Boolean(product.parent),\n isActive: product.enabled !== false,\n weightValue: resolvedWeight ?? undefined,\n categoryIds,\n metadata: {\n source: 'akeneo',\n externalId: productExternalId,\n sourceProductUuid: product.uuid,\n family: hierarchy.family,\n familyVariant: hierarchy.familyVariantCode,\n parentChain: hierarchy.parentChain,\n associations: product.associations ?? {},\n quantifiedAssociations: product.quantified_associations ?? {},\n updatedAt: product.updated ?? null,\n },\n customFieldsetCode: productFieldsetCode,\n }\n\n let localProductId: string\n let productAction: 'create' | 'update'\n if (existingProductId) {\n await executeCommand('catalog.products.update', {\n id: existingProductId,\n ...productInput,\n })\n localProductId = existingProductId\n productAction = 'update'\n } else {\n const created = await executeCommand<{ productId?: string; id?: string }>('catalog.products.create', productInput)\n localProductId = created.productId ?? created.id ?? ''\n if (!localProductId) {\n throw new Error(`Akeneo product ${product.uuid} did not return a local product id`)\n }\n productAction = 'create'\n }\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product', localProductId, productExternalId, scope)\n\n const variantExternalId = product.parent ? product.uuid : `${product.uuid}:default`\n const existingVariantId = await resolveExistingVariantId(variantExternalId, resolvedSku, localProductId)\n\n const optionValues =\n hierarchy.axisCodes.length > 0\n ? await (async () => {\n const values: Record<string, string> = {}\n for (const axis of hierarchy.axisCodes) {\n const rawValue = readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], axis, locale, channel)\n const optionLabels = await getAttributeOptionLabels(axis, locale)\n const normalizedValue = normalizeAkeneoSelectValue(rawValue, optionLabels)\n if (normalizedValue) {\n values[slugifyAkeneoCode(axis)] = normalizedValue\n }\n }\n return Object.keys(values).length > 0 ? values : undefined\n })()\n : undefined\n\n const existingDefaultVariant = await findOneWithDecryption(\n em,\n CatalogProductVariant,\n {\n product: localProductId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n isDefault: true,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n const variantName = coerceString(readLayeredAkeneoValue([hierarchy.leafValues, hierarchy.mergedValues], fieldMap.variantName, locale, channel))\n ?? (optionValues && Object.values(optionValues).length > 0 ? Object.values(optionValues).join(' / ') : resolvedTitle)\n\n const variantInput = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n productId: localProductId,\n name: variantName,\n sku: resolvedSku,\n barcode: resolvedBarcode ?? undefined,\n isDefault: existingVariantId ? existingVariantId === existingDefaultVariant?.id : !existingDefaultVariant,\n isActive: product.enabled !== false,\n weightValue: resolvedWeight ?? undefined,\n optionValues: optionValues && Object.keys(optionValues).length > 0 ? optionValues : undefined,\n metadata: {\n source: 'akeneo',\n externalId: variantExternalId,\n sourceProductUuid: product.uuid,\n sourceParentCode: product.parent ?? null,\n associations: product.associations ?? {},\n quantifiedAssociations: product.quantified_associations ?? {},\n updatedAt: product.updated ?? null,\n },\n customFieldsetCode: variantFieldsetCode,\n }\n\n let localVariantId: string\n let variantAction: 'create' | 'update'\n if (existingVariantId) {\n await executeCommand('catalog.variants.update', {\n id: existingVariantId,\n ...variantInput,\n })\n localVariantId = existingVariantId\n variantAction = 'update'\n } else {\n const created = await executeCommand<{ variantId?: string; id?: string }>('catalog.variants.create', variantInput)\n localVariantId = created.variantId ?? created.id ?? ''\n if (!localVariantId) {\n throw new Error(`Akeneo variant ${variantExternalId} did not return a local variant id`)\n }\n variantAction = 'create'\n }\n await externalIdMappingService.storeExternalIdMapping('sync_akeneo', 'catalog_product_variant', localVariantId, variantExternalId, scope)\n\n await applyCustomFieldMappings({\n mapping: derivedMapping,\n hierarchy,\n product,\n localProductId,\n localVariantId,\n fieldsetPlan: resolvedProductSettings.fieldsetPlan,\n })\n await upsertOffersAndPrices({\n mapping: derivedMapping,\n settings,\n hierarchy,\n localProductId,\n localVariantId,\n resolvedProductTitle: resolvedTitle,\n resolvedProductDescription: resolvedDescription,\n variantExternalId,\n })\n\n const desiredAssets: DesiredAsset[] = []\n for (const mediaMapping of settings.mediaMappings) {\n const productScopedValue = readPreferredAkeneoValue(\n hierarchy.rootValues,\n mediaMapping.attributeCode,\n locale,\n channel,\n )\n const variantScopedValue = readPreferredAkeneoValue(\n hierarchy.leafValues,\n mediaMapping.attributeCode,\n locale,\n channel,\n )\n const effectiveTarget = resolveAkeneoMediaTarget({\n mappingTarget: mediaMapping.target,\n attributeCode: mediaMapping.attributeCode,\n variantAttributeCodes: resolvedProductSettings.variantAttributeCodes,\n productScopedValue,\n variantScopedValue,\n })\n const sourceLayers = effectiveTarget === 'product'\n ? [hierarchy.rootValues, hierarchy.mergedValues]\n : [hierarchy.leafValues, hierarchy.mergedValues]\n const rawValue = readLayeredAkeneoValue(sourceLayers, mediaMapping.attributeCode, locale, channel)\n const refs = collectMediaReferences(rawValue)\n refs.forEach((ref, index) => {\n desiredAssets.push({\n externalId: `${effectiveTarget}:${mediaMapping.kind}:${mediaMapping.attributeCode}:${ref.codeOrUrl}:${index}`,\n entityId: effectiveTarget === 'product' ? PRODUCT_ENTITY_ID : VARIANT_ENTITY_ID,\n recordId: effectiveTarget === 'product' ? localProductId : localVariantId,\n kind: mediaMapping.kind,\n remote: ref,\n })\n })\n }\n\n const assetsByTarget = new Map<string, DesiredAsset[]>()\n const pendingVariantHeroUpdates: Array<{\n variantId: string\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n }> = []\n const shouldMirrorVariantHeroToProduct = !product.parent && !hierarchy.familyVariantCode\n let mirroredProductHeroFromVariant: {\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n } | null = null\n for (const asset of desiredAssets) {\n const key = `${asset.entityId}:${asset.recordId}`\n const bucket = assetsByTarget.get(key) ?? []\n bucket.push(asset)\n assetsByTarget.set(key, bucket)\n }\n\n for (const assets of assetsByTarget.values()) {\n const firstAsset = assets[0]\n if (!firstAsset) continue\n const hero = await reconcileAttachments({\n entityId: firstAsset.entityId,\n recordId: firstAsset.recordId,\n desiredAssets: assets,\n reconciliation: settings.reconciliation,\n })\n if (firstAsset.entityId === PRODUCT_ENTITY_ID) {\n await executeCommand('catalog.products.update', {\n id: localProductId,\n defaultMediaId: hero.heroAttachmentId,\n defaultMediaUrl: hero.heroAttachmentUrl,\n })\n } else {\n pendingVariantHeroUpdates.push({\n variantId: localVariantId,\n defaultMediaId: hero.heroAttachmentId,\n defaultMediaUrl: hero.heroAttachmentUrl,\n })\n if (\n shouldMirrorVariantHeroToProduct\n && firstAsset.recordId === localVariantId\n && hero.heroAttachmentId\n && !mirroredProductHeroFromVariant\n ) {\n mirroredProductHeroFromVariant = {\n defaultMediaId: hero.heroAttachmentId,\n defaultMediaUrl: hero.heroAttachmentUrl,\n }\n }\n }\n }\n\n await syncAssociations({\n product,\n localVariantId,\n localProductId,\n settings,\n })\n\n for (const heroUpdate of pendingVariantHeroUpdates) {\n await em.getConnection().execute(\n `\n update catalog_product_variants\n set default_media_id = ?, default_media_url = ?, updated_at = now()\n where id = ? and organization_id = ? and tenant_id = ?\n `,\n [\n heroUpdate.defaultMediaId,\n heroUpdate.defaultMediaUrl,\n heroUpdate.variantId,\n scope.organizationId,\n scope.tenantId,\n ],\n )\n await emitCatalogQueryIndexEvent(buildCommandContext(), {\n entityType: VARIANT_ENTITY_ID,\n recordId: heroUpdate.variantId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n action: 'updated',\n })\n }\n\n if (mirroredProductHeroFromVariant) {\n await executeCommand('catalog.products.update', {\n id: localProductId,\n defaultMediaId: mirroredProductHeroFromVariant.defaultMediaId,\n defaultMediaUrl: mirroredProductHeroFromVariant.defaultMediaUrl,\n })\n }\n\n return [\n {\n externalId: productExternalId,\n action: productAction,\n data: {\n localProductId,\n sku: resolvedSku,\n family: hierarchy.family,\n },\n },\n {\n externalId: variantExternalId,\n action: variantAction,\n data: {\n localVariantId,\n productId: localProductId,\n sku: resolvedSku,\n },\n },\n ]\n }\n\n async function deactivateMappedEntities(entityType: string, seenExternalIds: Set<string>, commandId: string): Promise<void> {\n const mappings = await findWithDecryption(em, SyncExternalIdMapping, {\n integrationId: 'sync_akeneo',\n internalEntityType: entityType,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n for (const mapping of mappings) {\n if (seenExternalIds.has(mapping.externalId)) continue\n await executeCommand(commandId, {\n id: mapping.internalEntityId,\n isActive: false,\n })\n }\n }\n\n async function reconcileCategories(seenExternalIds: Set<string>, locale: string, reconciliation: AkeneoReconciliationSettings): Promise<void> {\n if (!reconciliation.deactivateMissingCategories || seenExternalIds.size === 0) return\n await deactivateMappedEntities('catalog_product_category', seenExternalIds, 'catalog.categories.update')\n }\n\n async function reconcileAttributes(params: {\n seenFamilyExternalIds: Set<string>\n currentCustomFieldKeys: Set<string>\n reconciliation: AkeneoReconciliationSettings\n }): Promise<void> {\n if (!params.reconciliation.deactivateMissingAttributes) return\n if (params.seenFamilyExternalIds.size > 0) {\n await deactivateMappedEntities('catalog_option_schema', params.seenFamilyExternalIds, 'catalog.optionSchemas.update')\n }\n const defs = await findWithDecryption(em, CustomFieldDef, {\n entityId: { $in: [PRODUCT_ENTITY_ID, VARIANT_ENTITY_ID] },\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, undefined, scope)\n for (const def of defs) {\n const sourceMetadata = safeRecord(def.configJson?.sourceMetadata)\n if (sourceMetadata?.provider !== 'akeneo') continue\n if (params.currentCustomFieldKeys.has(`${def.entityId}:${def.key}`)) continue\n def.isActive = false\n }\n await em.flush()\n }\n\n async function reconcileProducts(seenProductExternalIds: Set<string>, seenVariantExternalIds: Set<string>, reconciliation: AkeneoReconciliationSettings): Promise<void> {\n if (!reconciliation.deactivateMissingProducts) return\n if (seenProductExternalIds.size > 0) {\n await deactivateMappedEntities('catalog_product', seenProductExternalIds, 'catalog.products.update')\n }\n if (seenVariantExternalIds.size > 0) {\n await deactivateMappedEntities('catalog_product_variant', seenVariantExternalIds, 'catalog.variants.update')\n }\n }\n\n return {\n upsertCategory,\n upsertAttributeFamily,\n upsertProduct,\n syncMappedCustomFields,\n reconcileMappedCustomFieldFieldsets,\n reconcileCategories,\n reconcileAttributes,\n reconcileProducts,\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["mapping", "options", "input", "relation"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/sync-akeneo",
3
- "version": "0.10.1-develop.7599.1.22c2d6481d",
3
+ "version": "0.10.1-develop.7600.1.57704c3ffb",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -53,18 +53,18 @@
53
53
  }
54
54
  },
55
55
  "dependencies": {
56
- "@open-mercato/core": "0.10.1-develop.7599.1.22c2d6481d",
57
- "@open-mercato/ui": "0.10.1-develop.7599.1.22c2d6481d",
56
+ "@open-mercato/core": "0.10.1-develop.7600.1.57704c3ffb",
57
+ "@open-mercato/ui": "0.10.1-develop.7600.1.57704c3ffb",
58
58
  "node-html-markdown": "^2.0.0"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@mikro-orm/postgresql": "^7.0.14",
62
- "@open-mercato/shared": "0.10.1-develop.7599.1.22c2d6481d",
62
+ "@open-mercato/shared": "0.10.1-develop.7600.1.57704c3ffb",
63
63
  "react": "^19.0.0",
64
64
  "react-dom": "^19.0.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@open-mercato/shared": "0.10.1-develop.7599.1.22c2d6481d",
67
+ "@open-mercato/shared": "0.10.1-develop.7600.1.57704c3ffb",
68
68
  "@types/jest": "^30.0.0",
69
69
  "@types/react": "^19.2.18",
70
70
  "@types/react-dom": "^19.2.5",
@@ -0,0 +1,193 @@
1
+ import { Attachment } from '@open-mercato/core/modules/attachments/data/entities'
2
+ import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
3
+ import { CatalogProduct, CatalogProductVariant } from '@open-mercato/core/modules/catalog/data/entities'
4
+ import { createAkeneoImporter } from '../lib/catalog-importer'
5
+ import { buildDefaultAkeneoMapping, type AkeneoDataMapping, type AkeneoProduct } from '../lib/shared'
6
+
7
+ const mockContainerResolve = jest.fn()
8
+ const mockFindOneWithDecryption = jest.fn()
9
+ const mockFindWithDecryption = jest.fn()
10
+ const mockReleaseScoped = jest.fn()
11
+ const mockDeletePartitionFile = jest.fn()
12
+ const mockEmitCrudSideEffects = jest.fn()
13
+
14
+ jest.mock('@open-mercato/shared/lib/di/container', () => ({
15
+ createRequestContainer: jest.fn(async () => ({
16
+ resolve: mockContainerResolve,
17
+ })),
18
+ }))
19
+
20
+ jest.mock('@open-mercato/shared/lib/encryption/find', () => ({
21
+ findOneWithDecryption: (...args: unknown[]) => mockFindOneWithDecryption(...args),
22
+ findWithDecryption: (...args: unknown[]) => mockFindWithDecryption(...args),
23
+ }))
24
+
25
+ jest.mock('@open-mercato/core/modules/attachments/lib/storage', () => ({
26
+ deletePartitionFile: (...args: unknown[]) => mockDeletePartitionFile(...args),
27
+ storePartitionFile: jest.fn(async () => {
28
+ throw new Error('[internal] no upload expected in test')
29
+ }),
30
+ }))
31
+
32
+ jest.mock('@open-mercato/shared/lib/commands/helpers', () => ({
33
+ ...jest.requireActual('@open-mercato/shared/lib/commands/helpers'),
34
+ emitCrudSideEffects: (...args: unknown[]) => mockEmitCrudSideEffects(...args),
35
+ }))
36
+
37
+ const scope = { organizationId: 'org-1', tenantId: 'tenant-1' }
38
+ const PRODUCT_ID = 'product-1'
39
+ const KEPT_EXTERNAL_ID = 'product:image:main_image:kept.png:0'
40
+
41
+ const SHARED_STORAGE_PATH = 'org-1/tenant-1/shared.png'
42
+
43
+ function storedAttachment(id: string, externalId: string): Attachment {
44
+ return {
45
+ id,
46
+ entityId: 'catalog:catalog_product',
47
+ recordId: PRODUCT_ID,
48
+ organizationId: scope.organizationId,
49
+ tenantId: scope.tenantId,
50
+ partitionCode: 'productsMedia',
51
+ storageDriver: 'local',
52
+ storagePath: SHARED_STORAGE_PATH,
53
+ storageMetadata: { source: 'akeneo', externalId, kind: 'image' },
54
+ } as unknown as Attachment
55
+ }
56
+
57
+ function createMediaWorld(attachments: Attachment[]) {
58
+ const commandBus = {
59
+ execute: jest.fn(async (commandId: string, { input }: { input: Record<string, unknown> }) => {
60
+ switch (commandId) {
61
+ case 'catalog.products.create':
62
+ return { result: { productId: PRODUCT_ID } }
63
+ case 'catalog.products.update':
64
+ return { result: { productId: input.id } }
65
+ case 'catalog.variants.create':
66
+ return { result: { variantId: 'variant-1' } }
67
+ case 'catalog.variants.update':
68
+ return { result: { variantId: input.id } }
69
+ default:
70
+ throw new Error(`[internal] unexpected command: ${commandId}`)
71
+ }
72
+ }),
73
+ }
74
+ const externalIdMappingService = {
75
+ lookupLocalId: jest.fn(async (_integrationId: string, entityType: string, externalId: string) => (
76
+ entityType === 'attachment' && externalId === KEPT_EXTERNAL_ID ? 'attachment-kept' : null
77
+ )),
78
+ lookupExternalId: jest.fn(async () => null),
79
+ storeExternalIdMapping: jest.fn(async () => undefined),
80
+ }
81
+ const dataEngine = { flushOrmEntityChanges: jest.fn(async () => undefined) }
82
+
83
+ mockContainerResolve.mockImplementation((key: string) => {
84
+ if (key === 'em') return { remove: () => ({ flush: async () => undefined }) }
85
+ if (key === 'attachmentService') return { releaseScoped: mockReleaseScoped }
86
+ if (key === 'commandBus') return commandBus
87
+ if (key === 'dataEngine') return dataEngine
88
+ if (key === 'externalIdMappingService') return externalIdMappingService
89
+ if (key === 'cache') throw new Error('[internal] no cache in test')
90
+ throw new Error(`[internal] unexpected dependency: ${key}`)
91
+ })
92
+ mockFindOneWithDecryption.mockImplementation(async (_em: unknown, entity: unknown, where: Record<string, unknown>) => {
93
+ if (entity === CatalogProduct && where.id === PRODUCT_ID) return { id: PRODUCT_ID, deletedAt: null }
94
+ if (entity === CatalogProductVariant && where.product === PRODUCT_ID) return { id: 'variant-1', product: PRODUCT_ID }
95
+ return null
96
+ })
97
+ mockFindWithDecryption.mockImplementation(async (_em: unknown, entity: unknown, where: Record<string, unknown>) => {
98
+ if (entity === Attachment) return attachments.filter((attachment) => attachment.recordId === where.recordId)
99
+ return []
100
+ })
101
+
102
+ const client = {
103
+ getFamily: jest.fn(async () => null),
104
+ getFamilyVariant: jest.fn(async () => null),
105
+ getAttribute: jest.fn(async (code: string) => (
106
+ code === 'main_image'
107
+ ? { code, type: 'pim_catalog_image', localizable: false, scopable: false, labels: {} }
108
+ : null
109
+ )),
110
+ getProductModel: jest.fn(async () => null),
111
+ downloadMediaFile: jest.fn(async () => {
112
+ throw new Error('[internal] no download expected in test')
113
+ }),
114
+ }
115
+ return { client }
116
+ }
117
+
118
+ function buildMediaMapping(): AkeneoDataMapping {
119
+ const base = buildDefaultAkeneoMapping('products')
120
+ const products = base.settings?.products
121
+ if (!products) throw new Error('[internal] default Akeneo product mapping is missing')
122
+ return {
123
+ ...base,
124
+ settings: {
125
+ ...base.settings,
126
+ products: {
127
+ ...products,
128
+ priceMappings: [],
129
+ mediaMappings: [{ attributeCode: 'main_image', target: 'product', kind: 'image' }],
130
+ customFieldMappings: [],
131
+ syncAssociations: false,
132
+ createMissingChannels: false,
133
+ reconciliation: { ...products.reconciliation, deleteMissingMedia: true },
134
+ },
135
+ },
136
+ }
137
+ }
138
+
139
+ const product: AkeneoProduct = {
140
+ uuid: 'uuid-mug',
141
+ identifier: 'MUG',
142
+ parent: null,
143
+ enabled: true,
144
+ values: {
145
+ sku: [{ locale: null, scope: null, data: 'MUG' }],
146
+ main_image: [{ locale: null, scope: null, data: 'kept.png' }],
147
+ },
148
+ }
149
+
150
+ describe('akeneo catalog importer media reconciliation', () => {
151
+ beforeEach(() => {
152
+ mockContainerResolve.mockReset()
153
+ mockFindOneWithDecryption.mockReset()
154
+ mockFindWithDecryption.mockReset()
155
+ mockReleaseScoped.mockReset()
156
+ mockDeletePartitionFile.mockReset()
157
+ mockEmitCrudSideEffects.mockReset()
158
+ })
159
+
160
+ it('releases a stale media row through the attachment service and leaves the stored file to it', async () => {
161
+ const stale = storedAttachment('attachment-stale', 'product:image:main_image:old.png:0')
162
+ const world = createMediaWorld([storedAttachment('attachment-kept', KEPT_EXTERNAL_ID), stale])
163
+ mockReleaseScoped.mockResolvedValue(undefined)
164
+ const importer = await createAkeneoImporter(world.client as never, scope)
165
+
166
+ await importer.upsertProduct(product, buildMediaMapping())
167
+
168
+ expect(mockReleaseScoped).toHaveBeenCalledTimes(1)
169
+ expect(mockReleaseScoped).toHaveBeenCalledWith({
170
+ attachmentId: 'attachment-stale',
171
+ tenantId: scope.tenantId,
172
+ organizationId: scope.organizationId,
173
+ expectedOwner: { entityId: 'catalog:catalog_product', recordId: PRODUCT_ID },
174
+ expectedAssignment: { type: 'catalog:catalog_product', id: PRODUCT_ID },
175
+ expectedPartitionCode: 'productsMedia',
176
+ })
177
+ expect(mockDeletePartitionFile).not.toHaveBeenCalled()
178
+ expect(mockEmitCrudSideEffects).toHaveBeenCalledWith(expect.objectContaining({ action: 'deleted', entity: stale }))
179
+ })
180
+
181
+ it('skips the deleted event without failing the product when a concurrent delete already removed the row', async () => {
182
+ const stale = storedAttachment('attachment-stale', 'product:image:main_image:old.png:0')
183
+ const world = createMediaWorld([stale])
184
+ mockReleaseScoped.mockRejectedValue(new CrudHttpError(404, { error: 'Attachment not found' }))
185
+ const importer = await createAkeneoImporter(world.client as never, scope)
186
+
187
+ await expect(importer.upsertProduct(product, buildMediaMapping())).resolves.toBeDefined()
188
+
189
+ expect(mockReleaseScoped).toHaveBeenCalledTimes(1)
190
+ expect(mockDeletePartitionFile).not.toHaveBeenCalled()
191
+ expect(mockEmitCrudSideEffects).not.toHaveBeenCalledWith(expect.objectContaining({ action: 'deleted' }))
192
+ })
193
+ })
@@ -2405,7 +2405,7 @@ export async function createAkeneoImporter(client: AkeneoClient, scope: ImportSc
2405
2405
  })
2406
2406
  return true
2407
2407
  } catch (error) {
2408
- if (isCrudHttpError(error) && error.status === 409) return false
2408
+ if (isCrudHttpError(error) && (error.status === 409 || error.status === 404)) return false
2409
2409
  throw error
2410
2410
  }
2411
2411
  }