@open-mercato/core 0.9.0 → 0.9.1-develop.7462.1.94c09f158f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/customer_dictionary_entry/index.js +2 -0
- package/dist/generated/entities/customer_dictionary_entry/index.js.map +2 -2
- package/dist/generated/entities/customer_interaction/index.js +2 -0
- package/dist/generated/entities/customer_interaction/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/attachments/api/route.js +29 -3
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/lib/ocrLimits.js +49 -0
- package/dist/modules/attachments/lib/ocrLimits.js.map +7 -0
- package/dist/modules/attachments/lib/ocrQueue.js +76 -2
- package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
- package/dist/modules/attachments/lib/ocrService.js +4 -0
- package/dist/modules/attachments/lib/ocrService.js.map +2 -2
- package/dist/modules/attachments/lib/pdfProcessing.js +14 -2
- package/dist/modules/attachments/lib/pdfProcessing.js.map +2 -2
- package/dist/modules/attachments/lib/scoped-upload-service.js +4 -2
- package/dist/modules/attachments/lib/scoped-upload-service.js.map +2 -2
- package/dist/modules/attachments/lib/textExtraction.js +13 -1
- package/dist/modules/attachments/lib/textExtraction.js.map +2 -2
- package/dist/modules/catalog/commands/categories.js +1 -1
- package/dist/modules/catalog/commands/categories.js.map +2 -2
- package/dist/modules/catalog/commands/productDeleteChildren.js +389 -0
- package/dist/modules/catalog/commands/productDeleteChildren.js.map +7 -0
- package/dist/modules/catalog/commands/products.js +52 -17
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/search.js +3 -1
- package/dist/modules/catalog/search.js.map +2 -2
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +2 -1
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +4 -6
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js +4 -6
- package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +47 -11
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +3 -3
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +10 -7
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js +5 -1
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
- package/dist/modules/communication_channels/lib/inbound-message-origin.js +1 -1
- package/dist/modules/communication_channels/lib/inbound-message-origin.js.map +2 -2
- package/dist/modules/communication_channels/lib/oauth-result.js +12 -0
- package/dist/modules/communication_channels/lib/oauth-result.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-state.js +4 -1
- package/dist/modules/communication_channels/lib/oauth-state.js.map +2 -2
- package/dist/modules/communication_channels/lib/use-connect-channel.js +10 -0
- package/dist/modules/communication_channels/lib/use-connect-channel.js.map +2 -2
- package/dist/modules/customers/api/activity-types/route.js +151 -0
- package/dist/modules/customers/api/activity-types/route.js.map +7 -0
- package/dist/modules/customers/api/deals/[id]/people/route.js +58 -5
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +13 -5
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/route.js +20 -5
- package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +3 -0
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +1 -0
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.meta.js +18 -0
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.meta.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +0 -23
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +15 -17
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/calendar-event-types.js +548 -0
- package/dist/modules/customers/calendar-event-types.js.map +7 -0
- package/dist/modules/customers/commands/dictionaries.js +70 -10
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +187 -22
- package/dist/modules/customers/commands/interactions.js.map +3 -3
- package/dist/modules/customers/components/ActivityTypeEditor.js +288 -0
- package/dist/modules/customers/components/ActivityTypeEditor.js.map +7 -0
- package/dist/modules/customers/components/DictionarySettings.js +3 -1
- package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +391 -297
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +3 -3
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +9 -74
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/TimeGrid.js +20 -16
- package/dist/modules/customers/components/calendar/TimeGrid.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/EventTypePanel.js +218 -0
- package/dist/modules/customers/components/calendar/editor/EventTypePanel.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/LocationField.js +7 -3
- package/dist/modules/customers/components/calendar/editor/LocationField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +5 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PriorityField.js +3 -1
- package/dist/modules/customers/components/calendar/editor/PriorityField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/RepeatField.js +9 -1
- package/dist/modules/customers/components/calendar/editor/RepeatField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/ResourcesField.js +4 -1
- package/dist/modules/customers/components/calendar/editor/ResourcesField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js +15 -7
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/SegmentGroup.js +3 -1
- package/dist/modules/customers/components/calendar/editor/SegmentGroup.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +28 -13
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +3 -3
- package/dist/modules/customers/components/calendar/editor/inputs.js +14 -6
- package/dist/modules/customers/components/calendar/editor/inputs.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/useCalendarCustomFields.js +54 -0
- package/dist/modules/customers/components/calendar/editor/useCalendarCustomFields.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/useEventTypeCatalog.js +82 -0
- package/dist/modules/customers/components/calendar/editor/useEventTypeCatalog.js.map +7 -0
- package/dist/modules/customers/components/calendar/types.js +1 -0
- package/dist/modules/customers/components/calendar/types.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +78 -343
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/CreatePersonDialog.js +12 -11
- package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +7 -3
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealPeopleSection.js +206 -0
- package/dist/modules/customers/components/detail/DealPeopleSection.js.map +7 -0
- package/dist/modules/customers/components/detail/LinkedPeopleSection.js +342 -0
- package/dist/modules/customers/components/detail/LinkedPeopleSection.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonCard.js +5 -2
- package/dist/modules/customers/components/detail/PersonCard.js.map +2 -2
- package/dist/modules/customers/components/linking/adapters/personAdapter.js +3 -0
- package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +2 -2
- package/dist/modules/customers/data/entities.js +6 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +39 -10
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/di.js +20 -1
- package/dist/modules/customers/di.js.map +2 -2
- package/dist/modules/customers/extension-points.js +13 -0
- package/dist/modules/customers/extension-points.js.map +2 -2
- package/dist/modules/customers/lib/calendar/conflicts.js +59 -16
- package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js +34 -16
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
- package/dist/modules/customers/lib/calendar/eventTypeResolver.js +197 -0
- package/dist/modules/customers/lib/calendar/eventTypeResolver.js.map +7 -0
- package/dist/modules/customers/lib/calendar/interactionApplicability.js +67 -0
- package/dist/modules/customers/lib/calendar/interactionApplicability.js.map +7 -0
- package/dist/modules/customers/lib/calendar/mapItem.js +5 -2
- package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
- package/dist/modules/customers/lib/calendar/recurrence.js +62 -1
- package/dist/modules/customers/lib/calendar/recurrence.js.map +2 -2
- package/dist/modules/customers/lib/calendar/timezone.js +111 -0
- package/dist/modules/customers/lib/calendar/timezone.js.map +7 -0
- package/dist/modules/customers/lib/interactionReadModel.js +1 -0
- package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +1 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260928175058_customers.js +17 -0
- package/dist/modules/customers/migrations/Migration20260928175058_customers.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260930110235_customers.js +17 -0
- package/dist/modules/customers/migrations/Migration20260930110235_customers.js.map +7 -0
- package/dist/modules/dictionaries/components/DictionaryTable.js +60 -51
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/messages/subscribers/message-notification.js +13 -1
- package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +201 -53
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +37 -11
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/planner/lib/availabilityMerge.js +101 -38
- package/dist/modules/planner/lib/availabilityMerge.js.map +3 -3
- package/dist/modules/planner/services/plannerAvailabilityService.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +159 -81
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js +7 -0
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +12 -7
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +28 -25
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/generated/entities/customer_dictionary_entry/index.ts +1 -0
- package/generated/entities/customer_interaction/index.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +9 -8
- package/src/modules/attachments/api/route.ts +36 -3
- package/src/modules/attachments/lib/ocrLimits.ts +62 -0
- package/src/modules/attachments/lib/ocrQueue.ts +95 -2
- package/src/modules/attachments/lib/ocrService.ts +4 -0
- package/src/modules/attachments/lib/pdfProcessing.ts +14 -2
- package/src/modules/attachments/lib/scoped-upload-service.ts +4 -2
- package/src/modules/attachments/lib/textExtraction.ts +14 -1
- package/src/modules/auth/i18n/de.json +3 -0
- package/src/modules/auth/i18n/en.json +3 -0
- package/src/modules/auth/i18n/es.json +3 -0
- package/src/modules/auth/i18n/ko.json +3 -0
- package/src/modules/auth/i18n/pl.json +3 -0
- package/src/modules/catalog/commands/categories.ts +1 -1
- package/src/modules/catalog/commands/productDeleteChildren.ts +557 -0
- package/src/modules/catalog/commands/products.ts +58 -17
- package/src/modules/catalog/search.ts +5 -1
- package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +2 -1
- package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +4 -6
- package/src/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.ts +4 -6
- package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +46 -10
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +12 -9
- package/src/modules/communication_channels/commands/deliver-outbound-message.ts +6 -1
- package/src/modules/communication_channels/i18n/de.json +4 -1
- package/src/modules/communication_channels/i18n/en.json +4 -1
- package/src/modules/communication_channels/i18n/es.json +4 -1
- package/src/modules/communication_channels/i18n/ko.json +4 -1
- package/src/modules/communication_channels/i18n/pl.json +4 -1
- package/src/modules/communication_channels/lib/inbound-message-origin.ts +2 -6
- package/src/modules/communication_channels/lib/oauth-result.ts +13 -0
- package/src/modules/communication_channels/lib/oauth-state.ts +4 -1
- package/src/modules/communication_channels/lib/use-connect-channel.ts +10 -0
- package/src/modules/customers/api/activity-types/route.ts +154 -0
- package/src/modules/customers/api/deals/[id]/people/route.ts +82 -3
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +9 -1
- package/src/modules/customers/api/dictionaries/[kind]/route.ts +18 -2
- package/src/modules/customers/api/interactions/route.ts +4 -0
- package/src/modules/customers/api/interactions/tasks/route.ts +1 -0
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.meta.ts +20 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +0 -29
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -17
- package/src/modules/customers/calendar-event-types.ts +674 -0
- package/src/modules/customers/commands/dictionaries.ts +84 -8
- package/src/modules/customers/commands/interactions.ts +244 -21
- package/src/modules/customers/components/ActivityTypeEditor.tsx +239 -0
- package/src/modules/customers/components/DictionarySettings.tsx +5 -3
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +347 -218
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +18 -96
- package/src/modules/customers/components/calendar/TimeGrid.tsx +20 -18
- package/src/modules/customers/components/calendar/editor/EventTypePanel.tsx +230 -0
- package/src/modules/customers/components/calendar/editor/LocationField.tsx +7 -1
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +4 -0
- package/src/modules/customers/components/calendar/editor/PriorityField.tsx +3 -0
- package/src/modules/customers/components/calendar/editor/RepeatField.tsx +10 -0
- package/src/modules/customers/components/calendar/editor/ResourcesField.tsx +4 -0
- package/src/modules/customers/components/calendar/editor/ScheduleSection.tsx +16 -4
- package/src/modules/customers/components/calendar/editor/SegmentGroup.tsx +3 -0
- package/src/modules/customers/components/calendar/editor/hooks.ts +29 -13
- package/src/modules/customers/components/calendar/editor/inputs.tsx +17 -5
- package/src/modules/customers/components/calendar/editor/useCalendarCustomFields.ts +49 -0
- package/src/modules/customers/components/calendar/editor/useEventTypeCatalog.ts +100 -0
- package/src/modules/customers/components/calendar/types.ts +1 -0
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +94 -388
- package/src/modules/customers/components/detail/CreatePersonDialog.tsx +39 -19
- package/src/modules/customers/components/detail/DealForm.tsx +7 -3
- package/src/modules/customers/components/detail/DealPeopleSection.tsx +256 -0
- package/src/modules/customers/components/detail/LinkedPeopleSection.tsx +474 -0
- package/src/modules/customers/components/detail/PersonCard.tsx +12 -4
- package/src/modules/customers/components/detail/types.ts +1 -0
- package/src/modules/customers/components/linking/adapters/personAdapter.tsx +4 -0
- package/src/modules/customers/data/entities.ts +8 -1
- package/src/modules/customers/data/validators.ts +42 -7
- package/src/modules/customers/di.ts +21 -0
- package/src/modules/customers/extension-points.ts +13 -0
- package/src/modules/customers/i18n/de.json +104 -8
- package/src/modules/customers/i18n/en.json +104 -8
- package/src/modules/customers/i18n/es.json +104 -8
- package/src/modules/customers/i18n/ko.json +104 -8
- package/src/modules/customers/i18n/pl.json +104 -8
- package/src/modules/customers/lib/calendar/conflicts.ts +106 -27
- package/src/modules/customers/lib/calendar/editorPayload.ts +39 -19
- package/src/modules/customers/lib/calendar/eventTypeResolver.ts +258 -0
- package/src/modules/customers/lib/calendar/interactionApplicability.ts +99 -0
- package/src/modules/customers/lib/calendar/mapItem.ts +6 -2
- package/src/modules/customers/lib/calendar/recurrence.ts +65 -1
- package/src/modules/customers/lib/calendar/timezone.ts +117 -0
- package/src/modules/customers/lib/interactionReadModel.ts +1 -0
- package/src/modules/customers/lib/todoCompatibility.ts +2 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +34 -0
- package/src/modules/customers/migrations/Migration20260928175058_customers.ts +15 -0
- package/src/modules/customers/migrations/Migration20260930110235_customers.ts +15 -0
- package/src/modules/dictionaries/components/DictionaryTable.tsx +63 -56
- package/src/modules/messages/subscribers/message-notification.ts +13 -3
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +243 -62
- package/src/modules/payment_gateways/lib/gateway-service.ts +39 -12
- package/src/modules/planner/lib/availabilityMerge.ts +106 -41
- package/src/modules/planner/services/plannerAvailabilityService.ts +4 -0
- package/src/modules/sales/components/documents/LineItemDialog.tsx +194 -111
- package/src/modules/sales/components/documents/lineItemUtils.ts +18 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +25 -13
- package/src/modules/sync_excel/lib/adapters/customers.ts +33 -27
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { loadCustomFieldSnapshot } from "@open-mercato/shared/lib/commands/customFieldSnapshots";
|
|
2
|
+
import { setCustomFieldsIfAny } from "@open-mercato/shared/lib/commands/helpers";
|
|
3
|
+
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
4
|
+
import { E } from "../../../generated/entities.ids.generated.js";
|
|
5
|
+
import {
|
|
6
|
+
CatalogOffer,
|
|
7
|
+
CatalogOptionSchemaTemplate,
|
|
8
|
+
CatalogPriceKind,
|
|
9
|
+
CatalogProduct,
|
|
10
|
+
CatalogProductPrice,
|
|
11
|
+
CatalogProductUnitConversion,
|
|
12
|
+
CatalogProductVariant
|
|
13
|
+
} from "../data/entities.js";
|
|
14
|
+
import { cloneJson, emitCatalogQueryIndexEvent } from "./shared.js";
|
|
15
|
+
function refId(ref) {
|
|
16
|
+
if (!ref) return null;
|
|
17
|
+
return typeof ref === "string" ? ref : ref.id;
|
|
18
|
+
}
|
|
19
|
+
function toIso(value) {
|
|
20
|
+
return value ? value.toISOString() : null;
|
|
21
|
+
}
|
|
22
|
+
function toDate(value) {
|
|
23
|
+
return value ? new Date(value) : null;
|
|
24
|
+
}
|
|
25
|
+
function isProductOwnedOptionSchemaTemplate(template) {
|
|
26
|
+
if (!template || typeof template === "string") return false;
|
|
27
|
+
const metadata = template.metadata;
|
|
28
|
+
if (!metadata || typeof metadata !== "object") return false;
|
|
29
|
+
const source = metadata.source;
|
|
30
|
+
return source === "product";
|
|
31
|
+
}
|
|
32
|
+
async function captureProductDeleteChildren(em, owner) {
|
|
33
|
+
const scope = { tenantId: owner.tenantId, organizationId: owner.organizationId };
|
|
34
|
+
const variantRecords = await findWithDecryption(em, CatalogProductVariant, { product: owner.id }, {}, scope);
|
|
35
|
+
const variantIds = variantRecords.map((variant) => variant.id);
|
|
36
|
+
const priceRecords = await findWithDecryption(
|
|
37
|
+
em,
|
|
38
|
+
CatalogProductPrice,
|
|
39
|
+
variantIds.length ? { $or: [{ variant: { $in: variantIds } }, { product: owner.id }] } : { product: owner.id },
|
|
40
|
+
{},
|
|
41
|
+
scope
|
|
42
|
+
);
|
|
43
|
+
const conversionRecords = await findWithDecryption(em, CatalogProductUnitConversion, { product: owner.id }, {}, scope);
|
|
44
|
+
const template = owner.optionSchemaId ? await findOneWithDecryption(em, CatalogOptionSchemaTemplate, { id: owner.optionSchemaId }, {}, scope) : null;
|
|
45
|
+
const variants = [];
|
|
46
|
+
for (const variant of variantRecords) {
|
|
47
|
+
const custom = await loadCustomFieldSnapshot(em, {
|
|
48
|
+
entityId: E.catalog.catalog_product_variant,
|
|
49
|
+
recordId: variant.id,
|
|
50
|
+
tenantId: variant.tenantId,
|
|
51
|
+
organizationId: variant.organizationId
|
|
52
|
+
});
|
|
53
|
+
variants.push({
|
|
54
|
+
id: variant.id,
|
|
55
|
+
productId: refId(variant.product) ?? owner.id,
|
|
56
|
+
name: variant.name ?? null,
|
|
57
|
+
sku: variant.sku ?? null,
|
|
58
|
+
barcode: variant.barcode ?? null,
|
|
59
|
+
gtinType: variant.gtinType ?? null,
|
|
60
|
+
hsCode: variant.hsCode ?? null,
|
|
61
|
+
statusEntryId: variant.statusEntryId ?? null,
|
|
62
|
+
isDefault: variant.isDefault,
|
|
63
|
+
isActive: variant.isActive,
|
|
64
|
+
weightValue: variant.weightValue ?? null,
|
|
65
|
+
weightUnit: variant.weightUnit ?? null,
|
|
66
|
+
dimensions: variant.dimensions ? cloneJson(variant.dimensions) : null,
|
|
67
|
+
metadata: variant.metadata ? cloneJson(variant.metadata) : null,
|
|
68
|
+
taxRateId: variant.taxRateId ?? null,
|
|
69
|
+
taxRate: variant.taxRate ?? null,
|
|
70
|
+
optionValues: variant.optionValues ? cloneJson(variant.optionValues) : null,
|
|
71
|
+
defaultMediaId: variant.defaultMediaId ?? null,
|
|
72
|
+
defaultMediaUrl: variant.defaultMediaUrl ?? null,
|
|
73
|
+
customFieldsetCode: variant.customFieldsetCode ?? null,
|
|
74
|
+
createdAt: variant.createdAt.toISOString(),
|
|
75
|
+
updatedAt: variant.updatedAt.toISOString(),
|
|
76
|
+
deletedAt: toIso(variant.deletedAt),
|
|
77
|
+
custom: Object.keys(custom).length ? custom : null
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const prices = [];
|
|
81
|
+
for (const price of priceRecords) {
|
|
82
|
+
const priceKindId = refId(price.priceKind);
|
|
83
|
+
if (!priceKindId) throw new Error(`[internal] Catalog price ${price.id} has no price kind`);
|
|
84
|
+
prices.push({
|
|
85
|
+
id: price.id,
|
|
86
|
+
variantId: refId(price.variant),
|
|
87
|
+
productId: refId(price.product),
|
|
88
|
+
offerId: refId(price.offer),
|
|
89
|
+
priceKindId,
|
|
90
|
+
currencyCode: price.currencyCode,
|
|
91
|
+
kind: price.kind,
|
|
92
|
+
minQuantity: price.minQuantity,
|
|
93
|
+
maxQuantity: price.maxQuantity ?? null,
|
|
94
|
+
unitPriceNet: price.unitPriceNet ?? null,
|
|
95
|
+
unitPriceGross: price.unitPriceGross ?? null,
|
|
96
|
+
taxRate: price.taxRate ?? null,
|
|
97
|
+
taxAmount: price.taxAmount ?? null,
|
|
98
|
+
channelId: price.channelId ?? null,
|
|
99
|
+
userId: price.userId ?? null,
|
|
100
|
+
userGroupId: price.userGroupId ?? null,
|
|
101
|
+
customerId: price.customerId ?? null,
|
|
102
|
+
customerGroupId: price.customerGroupId ?? null,
|
|
103
|
+
metadata: price.metadata ? cloneJson(price.metadata) : null,
|
|
104
|
+
startsAt: toIso(price.startsAt),
|
|
105
|
+
endsAt: toIso(price.endsAt),
|
|
106
|
+
createdAt: price.createdAt.toISOString(),
|
|
107
|
+
updatedAt: price.updatedAt.toISOString()
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const unitConversions = conversionRecords.map((conversion) => ({
|
|
111
|
+
id: conversion.id,
|
|
112
|
+
productId: refId(conversion.product) ?? owner.id,
|
|
113
|
+
unitCode: conversion.unitCode,
|
|
114
|
+
toBaseFactor: conversion.toBaseFactor,
|
|
115
|
+
sortOrder: conversion.sortOrder,
|
|
116
|
+
isActive: conversion.isActive,
|
|
117
|
+
metadata: conversion.metadata ? cloneJson(conversion.metadata) : null,
|
|
118
|
+
createdAt: conversion.createdAt.toISOString(),
|
|
119
|
+
updatedAt: conversion.updatedAt.toISOString(),
|
|
120
|
+
deletedAt: toIso(conversion.deletedAt)
|
|
121
|
+
}));
|
|
122
|
+
return {
|
|
123
|
+
variants,
|
|
124
|
+
prices,
|
|
125
|
+
unitConversions,
|
|
126
|
+
optionSchemaTemplate: isProductOwnedOptionSchemaTemplate(template) ? {
|
|
127
|
+
id: template.id,
|
|
128
|
+
name: template.name,
|
|
129
|
+
code: template.code,
|
|
130
|
+
description: template.description ?? null,
|
|
131
|
+
schema: cloneJson(template.schema),
|
|
132
|
+
metadata: template.metadata ? cloneJson(template.metadata) : null,
|
|
133
|
+
isActive: template.isActive,
|
|
134
|
+
createdAt: template.createdAt.toISOString(),
|
|
135
|
+
updatedAt: template.updatedAt.toISOString(),
|
|
136
|
+
deletedAt: toIso(template.deletedAt)
|
|
137
|
+
} : null
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function restoreConflict(kind, id) {
|
|
141
|
+
return new Error(`[internal] Cannot restore catalog product ${kind} ${id}: it does not belong to the restored product`);
|
|
142
|
+
}
|
|
143
|
+
function sameScope(row, owner) {
|
|
144
|
+
return row.tenantId === owner.tenantId && row.organizationId === owner.organizationId;
|
|
145
|
+
}
|
|
146
|
+
function asList(value) {
|
|
147
|
+
return Array.isArray(value) ? value : [];
|
|
148
|
+
}
|
|
149
|
+
async function planProductDeleteChildrenRestore(em, owner, children) {
|
|
150
|
+
if (!children) return null;
|
|
151
|
+
const scope = { tenantId: owner.tenantId, organizationId: owner.organizationId };
|
|
152
|
+
const variantSnapshots = asList(children.variants);
|
|
153
|
+
const priceSnapshots = asList(children.prices);
|
|
154
|
+
const conversionSnapshots = asList(children.unitConversions);
|
|
155
|
+
const templateSnapshot = children.optionSchemaTemplate && children.optionSchemaTemplate.id === owner.optionSchemaId ? children.optionSchemaTemplate : null;
|
|
156
|
+
const ownVariantIds = new Set(variantSnapshots.map((variant) => variant.id));
|
|
157
|
+
const offerIds = new Set(owner.offerIds);
|
|
158
|
+
const priceOwned = (price) => price.variantId !== null && ownVariantIds.has(price.variantId) || price.productId === owner.id;
|
|
159
|
+
for (const variant of variantSnapshots) {
|
|
160
|
+
if (variant.productId !== owner.id) throw restoreConflict("variant", variant.id);
|
|
161
|
+
}
|
|
162
|
+
for (const conversion of conversionSnapshots) {
|
|
163
|
+
if (conversion.productId !== owner.id) throw restoreConflict("unit conversion", conversion.id);
|
|
164
|
+
}
|
|
165
|
+
for (const price of priceSnapshots) {
|
|
166
|
+
if (!priceOwned(price)) throw restoreConflict("price", price.id);
|
|
167
|
+
}
|
|
168
|
+
const foreignVariantIds = /* @__PURE__ */ new Set();
|
|
169
|
+
const foreignProductIds = /* @__PURE__ */ new Set();
|
|
170
|
+
const trackVariant = (id) => {
|
|
171
|
+
if (id && !ownVariantIds.has(id)) foreignVariantIds.add(id);
|
|
172
|
+
};
|
|
173
|
+
const trackProduct = (id) => {
|
|
174
|
+
if (id && id !== owner.id) foreignProductIds.add(id);
|
|
175
|
+
};
|
|
176
|
+
for (const price of priceSnapshots) {
|
|
177
|
+
trackVariant(price.variantId);
|
|
178
|
+
trackProduct(price.productId);
|
|
179
|
+
}
|
|
180
|
+
const existingVariants = variantSnapshots.length ? await findWithDecryption(em, CatalogProductVariant, { id: { $in: variantSnapshots.map((entry) => entry.id) } }, {}, scope) : [];
|
|
181
|
+
const existingPrices = priceSnapshots.length ? await findWithDecryption(em, CatalogProductPrice, { id: { $in: priceSnapshots.map((entry) => entry.id) } }, {}, scope) : [];
|
|
182
|
+
const existingConversions = conversionSnapshots.length ? await findWithDecryption(
|
|
183
|
+
em,
|
|
184
|
+
CatalogProductUnitConversion,
|
|
185
|
+
{ id: { $in: conversionSnapshots.map((entry) => entry.id) } },
|
|
186
|
+
{},
|
|
187
|
+
scope
|
|
188
|
+
) : [];
|
|
189
|
+
const existingTemplate = templateSnapshot ? await findOneWithDecryption(em, CatalogOptionSchemaTemplate, { id: templateSnapshot.id }, {}, scope) : null;
|
|
190
|
+
const foreignVariants = foreignVariantIds.size ? await findWithDecryption(
|
|
191
|
+
em,
|
|
192
|
+
CatalogProductVariant,
|
|
193
|
+
{ id: { $in: Array.from(foreignVariantIds) }, tenantId: owner.tenantId, organizationId: owner.organizationId },
|
|
194
|
+
{},
|
|
195
|
+
scope
|
|
196
|
+
) : [];
|
|
197
|
+
const foreignProducts = foreignProductIds.size ? await findWithDecryption(
|
|
198
|
+
em,
|
|
199
|
+
CatalogProduct,
|
|
200
|
+
{ id: { $in: Array.from(foreignProductIds) }, tenantId: owner.tenantId, organizationId: owner.organizationId },
|
|
201
|
+
{},
|
|
202
|
+
scope
|
|
203
|
+
) : [];
|
|
204
|
+
for (const variant of existingVariants) {
|
|
205
|
+
if (!sameScope(variant, owner) || refId(variant.product) !== owner.id) throw restoreConflict("variant", variant.id);
|
|
206
|
+
}
|
|
207
|
+
for (const conversion of existingConversions) {
|
|
208
|
+
if (!sameScope(conversion, owner) || refId(conversion.product) !== owner.id) {
|
|
209
|
+
throw restoreConflict("unit conversion", conversion.id);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (const price of existingPrices) {
|
|
213
|
+
if (!sameScope(price, owner) || !priceOwned({ variantId: refId(price.variant), productId: refId(price.product) })) {
|
|
214
|
+
throw restoreConflict("price", price.id);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (existingTemplate && !sameScope(existingTemplate, owner)) {
|
|
218
|
+
throw restoreConflict("option schema", existingTemplate.id);
|
|
219
|
+
}
|
|
220
|
+
const existingVariantIds = new Set(existingVariants.map((entry) => entry.id));
|
|
221
|
+
const existingPriceIds = new Set(existingPrices.map((entry) => entry.id));
|
|
222
|
+
const existingConversionIds = new Set(existingConversions.map((entry) => entry.id));
|
|
223
|
+
const availableForeignVariantIds = new Set(foreignVariants.map((entry) => entry.id));
|
|
224
|
+
const availableForeignProductIds = new Set(foreignProducts.map((entry) => entry.id));
|
|
225
|
+
const variantAvailable = (id) => id === null || ownVariantIds.has(id) || availableForeignVariantIds.has(id);
|
|
226
|
+
const productAvailable = (id) => id === null || id === owner.id || availableForeignProductIds.has(id);
|
|
227
|
+
return {
|
|
228
|
+
optionSchemaTemplate: templateSnapshot && !existingTemplate ? templateSnapshot : null,
|
|
229
|
+
unitConversions: conversionSnapshots.filter((entry) => !existingConversionIds.has(entry.id)),
|
|
230
|
+
variants: variantSnapshots.filter((entry) => !existingVariantIds.has(entry.id)),
|
|
231
|
+
prices: priceSnapshots.filter(
|
|
232
|
+
(entry) => !existingPriceIds.has(entry.id) && variantAvailable(entry.variantId) && productAvailable(entry.productId)
|
|
233
|
+
).map((entry) => ({ ...entry, offerId: entry.offerId && offerIds.has(entry.offerId) ? entry.offerId : null }))
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function restoreProductOptionSchemaTemplate(em, owner, plan) {
|
|
237
|
+
const snapshot = plan?.optionSchemaTemplate;
|
|
238
|
+
if (!snapshot) return;
|
|
239
|
+
const template = em.create(CatalogOptionSchemaTemplate, {
|
|
240
|
+
id: snapshot.id,
|
|
241
|
+
organizationId: owner.organizationId,
|
|
242
|
+
tenantId: owner.tenantId,
|
|
243
|
+
name: snapshot.name,
|
|
244
|
+
code: snapshot.code,
|
|
245
|
+
description: snapshot.description ?? null,
|
|
246
|
+
schema: cloneJson(snapshot.schema),
|
|
247
|
+
metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,
|
|
248
|
+
isActive: snapshot.isActive,
|
|
249
|
+
createdAt: new Date(snapshot.createdAt),
|
|
250
|
+
updatedAt: new Date(snapshot.updatedAt),
|
|
251
|
+
deletedAt: toDate(snapshot.deletedAt)
|
|
252
|
+
});
|
|
253
|
+
em.persist(template);
|
|
254
|
+
}
|
|
255
|
+
function buildProductDeleteChildrenRestorePhases(em, owner, plan) {
|
|
256
|
+
if (!plan) return [];
|
|
257
|
+
const scope = { organizationId: owner.organizationId, tenantId: owner.tenantId };
|
|
258
|
+
let childEm = null;
|
|
259
|
+
const resolveChildEm = () => {
|
|
260
|
+
childEm ??= em.fork({ keepTransactionContext: true });
|
|
261
|
+
return childEm;
|
|
262
|
+
};
|
|
263
|
+
return [
|
|
264
|
+
async () => {
|
|
265
|
+
const target = resolveChildEm();
|
|
266
|
+
for (const snapshot of plan.unitConversions) {
|
|
267
|
+
target.persist(
|
|
268
|
+
target.create(CatalogProductUnitConversion, {
|
|
269
|
+
id: snapshot.id,
|
|
270
|
+
...scope,
|
|
271
|
+
product: target.getReference(CatalogProduct, snapshot.productId),
|
|
272
|
+
unitCode: snapshot.unitCode,
|
|
273
|
+
toBaseFactor: snapshot.toBaseFactor,
|
|
274
|
+
sortOrder: snapshot.sortOrder,
|
|
275
|
+
isActive: snapshot.isActive,
|
|
276
|
+
metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,
|
|
277
|
+
createdAt: new Date(snapshot.createdAt),
|
|
278
|
+
updatedAt: new Date(snapshot.updatedAt),
|
|
279
|
+
deletedAt: toDate(snapshot.deletedAt)
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
await target.flush();
|
|
284
|
+
},
|
|
285
|
+
async () => {
|
|
286
|
+
const target = resolveChildEm();
|
|
287
|
+
for (const snapshot of plan.variants) {
|
|
288
|
+
target.persist(
|
|
289
|
+
target.create(CatalogProductVariant, {
|
|
290
|
+
id: snapshot.id,
|
|
291
|
+
...scope,
|
|
292
|
+
product: target.getReference(CatalogProduct, snapshot.productId),
|
|
293
|
+
name: snapshot.name ?? null,
|
|
294
|
+
sku: snapshot.sku ?? null,
|
|
295
|
+
barcode: snapshot.barcode ?? null,
|
|
296
|
+
gtinType: snapshot.gtinType ?? null,
|
|
297
|
+
hsCode: snapshot.hsCode ?? null,
|
|
298
|
+
statusEntryId: snapshot.statusEntryId ?? null,
|
|
299
|
+
isDefault: snapshot.isDefault,
|
|
300
|
+
isActive: snapshot.isActive,
|
|
301
|
+
weightValue: snapshot.weightValue ?? null,
|
|
302
|
+
weightUnit: snapshot.weightUnit ?? null,
|
|
303
|
+
dimensions: snapshot.dimensions ? cloneJson(snapshot.dimensions) : null,
|
|
304
|
+
metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,
|
|
305
|
+
taxRateId: snapshot.taxRateId ?? null,
|
|
306
|
+
taxRate: snapshot.taxRate ?? null,
|
|
307
|
+
optionValues: snapshot.optionValues ? cloneJson(snapshot.optionValues) : null,
|
|
308
|
+
defaultMediaId: snapshot.defaultMediaId ?? null,
|
|
309
|
+
defaultMediaUrl: snapshot.defaultMediaUrl ?? null,
|
|
310
|
+
customFieldsetCode: snapshot.customFieldsetCode ?? null,
|
|
311
|
+
createdAt: new Date(snapshot.createdAt),
|
|
312
|
+
updatedAt: new Date(snapshot.updatedAt),
|
|
313
|
+
deletedAt: toDate(snapshot.deletedAt)
|
|
314
|
+
})
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
await target.flush();
|
|
318
|
+
},
|
|
319
|
+
async () => {
|
|
320
|
+
const target = resolveChildEm();
|
|
321
|
+
for (const snapshot of plan.prices) {
|
|
322
|
+
target.persist(
|
|
323
|
+
target.create(CatalogProductPrice, {
|
|
324
|
+
id: snapshot.id,
|
|
325
|
+
...scope,
|
|
326
|
+
variant: snapshot.variantId ? target.getReference(CatalogProductVariant, snapshot.variantId) : null,
|
|
327
|
+
product: snapshot.productId ? target.getReference(CatalogProduct, snapshot.productId) : null,
|
|
328
|
+
offer: snapshot.offerId ? target.getReference(CatalogOffer, snapshot.offerId) : null,
|
|
329
|
+
priceKind: target.getReference(CatalogPriceKind, snapshot.priceKindId),
|
|
330
|
+
currencyCode: snapshot.currencyCode,
|
|
331
|
+
kind: snapshot.kind,
|
|
332
|
+
minQuantity: snapshot.minQuantity,
|
|
333
|
+
maxQuantity: snapshot.maxQuantity ?? null,
|
|
334
|
+
unitPriceNet: snapshot.unitPriceNet ?? null,
|
|
335
|
+
unitPriceGross: snapshot.unitPriceGross ?? null,
|
|
336
|
+
taxRate: snapshot.taxRate ?? null,
|
|
337
|
+
taxAmount: snapshot.taxAmount ?? null,
|
|
338
|
+
channelId: snapshot.channelId ?? null,
|
|
339
|
+
userId: snapshot.userId ?? null,
|
|
340
|
+
userGroupId: snapshot.userGroupId ?? null,
|
|
341
|
+
customerId: snapshot.customerId ?? null,
|
|
342
|
+
customerGroupId: snapshot.customerGroupId ?? null,
|
|
343
|
+
metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,
|
|
344
|
+
startsAt: toDate(snapshot.startsAt),
|
|
345
|
+
endsAt: toDate(snapshot.endsAt),
|
|
346
|
+
createdAt: new Date(snapshot.createdAt),
|
|
347
|
+
updatedAt: new Date(snapshot.updatedAt)
|
|
348
|
+
})
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
await target.flush();
|
|
352
|
+
}
|
|
353
|
+
];
|
|
354
|
+
}
|
|
355
|
+
async function emitProductDeleteChildrenRestoreSideEffects(opts) {
|
|
356
|
+
const { ctx, dataEngine, owner, children, plan } = opts;
|
|
357
|
+
const variants = asList(children?.variants);
|
|
358
|
+
const createdVariantIds = new Set(asList(plan?.variants).map((variant) => variant.id));
|
|
359
|
+
for (const variant of variants) {
|
|
360
|
+
if (!variant.custom || !Object.keys(variant.custom).length) continue;
|
|
361
|
+
await setCustomFieldsIfAny({
|
|
362
|
+
dataEngine,
|
|
363
|
+
entityId: E.catalog.catalog_product_variant,
|
|
364
|
+
recordId: variant.id,
|
|
365
|
+
organizationId: owner.organizationId,
|
|
366
|
+
tenantId: owner.tenantId,
|
|
367
|
+
values: variant.custom
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
for (const variant of variants) {
|
|
371
|
+
await emitCatalogQueryIndexEvent(ctx, {
|
|
372
|
+
entityType: E.catalog.catalog_product_variant,
|
|
373
|
+
recordId: variant.id,
|
|
374
|
+
organizationId: owner.organizationId,
|
|
375
|
+
tenantId: owner.tenantId,
|
|
376
|
+
action: "created",
|
|
377
|
+
...createdVariantIds.has(variant.id) ? {} : { coverageBaseDelta: 0 }
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
export {
|
|
382
|
+
buildProductDeleteChildrenRestorePhases,
|
|
383
|
+
captureProductDeleteChildren,
|
|
384
|
+
emitProductDeleteChildrenRestoreSideEffects,
|
|
385
|
+
isProductOwnedOptionSchemaTemplate,
|
|
386
|
+
planProductDeleteChildrenRestore,
|
|
387
|
+
restoreProductOptionSchemaTemplate
|
|
388
|
+
};
|
|
389
|
+
//# sourceMappingURL=productDeleteChildren.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/catalog/commands/productDeleteChildren.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { loadCustomFieldSnapshot } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n CatalogOffer,\n CatalogOptionSchemaTemplate,\n CatalogPriceKind,\n CatalogProduct,\n CatalogProductPrice,\n CatalogProductUnitConversion,\n CatalogProductVariant,\n} from '../data/entities'\nimport type { CatalogGtinType, CatalogProductOptionSchema } from '../data/types'\nimport { cloneJson, emitCatalogQueryIndexEvent } from './shared'\n\ntype VariantDimensions = NonNullable<CatalogProductVariant['dimensions']>\n\nexport type ProductDeleteVariantSnapshot = {\n id: string\n productId: string\n name: string | null\n sku: string | null\n barcode: string | null\n gtinType: CatalogGtinType | null\n hsCode: string | null\n statusEntryId: string | null\n isDefault: boolean\n isActive: boolean\n weightValue: string | null\n weightUnit: string | null\n dimensions: VariantDimensions | null\n metadata: Record<string, unknown> | null\n taxRateId: string | null\n taxRate: string | null\n optionValues: Record<string, string> | null\n defaultMediaId: string | null\n defaultMediaUrl: string | null\n customFieldsetCode: string | null\n createdAt: string\n updatedAt: string\n deletedAt: string | null\n custom: Record<string, unknown> | null\n}\n\nexport type ProductDeletePriceSnapshot = {\n id: string\n variantId: string | null\n productId: string | null\n offerId: string | null\n priceKindId: string\n currencyCode: string\n kind: string\n minQuantity: number\n maxQuantity: number | null\n unitPriceNet: string | null\n unitPriceGross: string | null\n taxRate: string | null\n taxAmount: string | null\n channelId: string | null\n userId: string | null\n userGroupId: string | null\n customerId: string | null\n customerGroupId: string | null\n metadata: Record<string, unknown> | null\n startsAt: string | null\n endsAt: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport type ProductDeleteUnitConversionSnapshot = {\n id: string\n productId: string\n unitCode: string\n toBaseFactor: string\n sortOrder: number\n isActive: boolean\n metadata: Record<string, unknown> | null\n createdAt: string\n updatedAt: string\n deletedAt: string | null\n}\n\nexport type ProductDeleteOptionSchemaSnapshot = {\n id: string\n name: string\n code: string\n description: string | null\n schema: CatalogProductOptionSchema\n metadata: Record<string, unknown> | null\n isActive: boolean\n createdAt: string\n updatedAt: string\n deletedAt: string | null\n}\n\nexport type ProductDeleteChildrenSnapshot = {\n variants: ProductDeleteVariantSnapshot[]\n prices: ProductDeletePriceSnapshot[]\n unitConversions: ProductDeleteUnitConversionSnapshot[]\n optionSchemaTemplate: ProductDeleteOptionSchemaSnapshot | null\n}\n\nexport type ProductDeleteOwner = {\n id: string\n organizationId: string\n tenantId: string\n optionSchemaId: string | null\n offerIds: string[]\n}\n\nexport type ProductDeleteChildrenRestorePlan = ProductDeleteChildrenSnapshot\n\ntype EntityRef = { id: string } | string | null | undefined\n\nfunction refId(ref: EntityRef): string | null {\n if (!ref) return null\n return typeof ref === 'string' ? ref : ref.id\n}\n\nfunction toIso(value: Date | null | undefined): string | null {\n return value ? value.toISOString() : null\n}\n\nfunction toDate(value: string | null | undefined): Date | null {\n return value ? new Date(value) : null\n}\n\nexport function isProductOwnedOptionSchemaTemplate(\n template: CatalogOptionSchemaTemplate | string | null | undefined,\n): template is CatalogOptionSchemaTemplate {\n if (!template || typeof template === 'string') return false\n const metadata = template.metadata\n if (!metadata || typeof metadata !== 'object') return false\n const source = (metadata as Record<string, unknown>).source\n return source === 'product'\n}\n\nexport async function captureProductDeleteChildren(\n em: EntityManager,\n owner: Pick<ProductDeleteOwner, 'id' | 'organizationId' | 'tenantId' | 'optionSchemaId'>,\n): Promise<ProductDeleteChildrenSnapshot> {\n const scope = { tenantId: owner.tenantId, organizationId: owner.organizationId }\n const variantRecords = await findWithDecryption(em, CatalogProductVariant, { product: owner.id }, {}, scope)\n const variantIds = variantRecords.map((variant) => variant.id)\n const priceRecords = await findWithDecryption(\n em,\n CatalogProductPrice,\n variantIds.length ? { $or: [{ variant: { $in: variantIds } }, { product: owner.id }] } : { product: owner.id },\n {},\n scope,\n )\n const conversionRecords = await findWithDecryption(em, CatalogProductUnitConversion, { product: owner.id }, {}, scope)\n const template = owner.optionSchemaId\n ? await findOneWithDecryption(em, CatalogOptionSchemaTemplate, { id: owner.optionSchemaId }, {}, scope)\n : null\n const variants: ProductDeleteVariantSnapshot[] = []\n for (const variant of variantRecords) {\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.catalog.catalog_product_variant,\n recordId: variant.id,\n tenantId: variant.tenantId,\n organizationId: variant.organizationId,\n })\n variants.push({\n id: variant.id,\n productId: refId(variant.product) ?? owner.id,\n name: variant.name ?? null,\n sku: variant.sku ?? null,\n barcode: variant.barcode ?? null,\n gtinType: variant.gtinType ?? null,\n hsCode: variant.hsCode ?? null,\n statusEntryId: variant.statusEntryId ?? null,\n isDefault: variant.isDefault,\n isActive: variant.isActive,\n weightValue: variant.weightValue ?? null,\n weightUnit: variant.weightUnit ?? null,\n dimensions: variant.dimensions ? cloneJson(variant.dimensions) : null,\n metadata: variant.metadata ? cloneJson(variant.metadata) : null,\n taxRateId: variant.taxRateId ?? null,\n taxRate: variant.taxRate ?? null,\n optionValues: variant.optionValues ? cloneJson(variant.optionValues) : null,\n defaultMediaId: variant.defaultMediaId ?? null,\n defaultMediaUrl: variant.defaultMediaUrl ?? null,\n customFieldsetCode: variant.customFieldsetCode ?? null,\n createdAt: variant.createdAt.toISOString(),\n updatedAt: variant.updatedAt.toISOString(),\n deletedAt: toIso(variant.deletedAt),\n custom: Object.keys(custom).length ? custom : null,\n })\n }\n const prices: ProductDeletePriceSnapshot[] = []\n for (const price of priceRecords) {\n const priceKindId = refId(price.priceKind)\n if (!priceKindId) throw new Error(`[internal] Catalog price ${price.id} has no price kind`)\n prices.push({\n id: price.id,\n variantId: refId(price.variant),\n productId: refId(price.product),\n offerId: refId(price.offer),\n priceKindId,\n currencyCode: price.currencyCode,\n kind: price.kind,\n minQuantity: price.minQuantity,\n maxQuantity: price.maxQuantity ?? null,\n unitPriceNet: price.unitPriceNet ?? null,\n unitPriceGross: price.unitPriceGross ?? null,\n taxRate: price.taxRate ?? null,\n taxAmount: price.taxAmount ?? null,\n channelId: price.channelId ?? null,\n userId: price.userId ?? null,\n userGroupId: price.userGroupId ?? null,\n customerId: price.customerId ?? null,\n customerGroupId: price.customerGroupId ?? null,\n metadata: price.metadata ? cloneJson(price.metadata) : null,\n startsAt: toIso(price.startsAt),\n endsAt: toIso(price.endsAt),\n createdAt: price.createdAt.toISOString(),\n updatedAt: price.updatedAt.toISOString(),\n })\n }\n const unitConversions: ProductDeleteUnitConversionSnapshot[] = conversionRecords.map((conversion) => ({\n id: conversion.id,\n productId: refId(conversion.product) ?? owner.id,\n unitCode: conversion.unitCode,\n toBaseFactor: conversion.toBaseFactor,\n sortOrder: conversion.sortOrder,\n isActive: conversion.isActive,\n metadata: conversion.metadata ? cloneJson(conversion.metadata) : null,\n createdAt: conversion.createdAt.toISOString(),\n updatedAt: conversion.updatedAt.toISOString(),\n deletedAt: toIso(conversion.deletedAt),\n }))\n return {\n variants,\n prices,\n unitConversions,\n optionSchemaTemplate: isProductOwnedOptionSchemaTemplate(template)\n ? {\n id: template.id,\n name: template.name,\n code: template.code,\n description: template.description ?? null,\n schema: cloneJson(template.schema),\n metadata: template.metadata ? cloneJson(template.metadata) : null,\n isActive: template.isActive,\n createdAt: template.createdAt.toISOString(),\n updatedAt: template.updatedAt.toISOString(),\n deletedAt: toIso(template.deletedAt),\n }\n : null,\n }\n}\n\nfunction restoreConflict(kind: string, id: string): Error {\n return new Error(`[internal] Cannot restore catalog product ${kind} ${id}: it does not belong to the restored product`)\n}\n\nfunction sameScope(row: { tenantId: string; organizationId: string }, owner: ProductDeleteOwner): boolean {\n return row.tenantId === owner.tenantId && row.organizationId === owner.organizationId\n}\n\nfunction asList<T>(value: T[] | null | undefined): T[] {\n return Array.isArray(value) ? value : []\n}\n\nexport async function planProductDeleteChildrenRestore(\n em: EntityManager,\n owner: ProductDeleteOwner,\n children: ProductDeleteChildrenSnapshot | null | undefined,\n): Promise<ProductDeleteChildrenRestorePlan | null> {\n if (!children) return null\n const scope = { tenantId: owner.tenantId, organizationId: owner.organizationId }\n const variantSnapshots = asList(children.variants)\n const priceSnapshots = asList(children.prices)\n const conversionSnapshots = asList(children.unitConversions)\n const templateSnapshot =\n children.optionSchemaTemplate && children.optionSchemaTemplate.id === owner.optionSchemaId\n ? children.optionSchemaTemplate\n : null\n const ownVariantIds = new Set(variantSnapshots.map((variant) => variant.id))\n const offerIds = new Set(owner.offerIds)\n\n const priceOwned = (price: { variantId: string | null; productId: string | null }) =>\n (price.variantId !== null && ownVariantIds.has(price.variantId)) || price.productId === owner.id\n\n for (const variant of variantSnapshots) {\n if (variant.productId !== owner.id) throw restoreConflict('variant', variant.id)\n }\n for (const conversion of conversionSnapshots) {\n if (conversion.productId !== owner.id) throw restoreConflict('unit conversion', conversion.id)\n }\n for (const price of priceSnapshots) {\n if (!priceOwned(price)) throw restoreConflict('price', price.id)\n }\n\n const foreignVariantIds = new Set<string>()\n const foreignProductIds = new Set<string>()\n const trackVariant = (id: string | null) => {\n if (id && !ownVariantIds.has(id)) foreignVariantIds.add(id)\n }\n const trackProduct = (id: string | null) => {\n if (id && id !== owner.id) foreignProductIds.add(id)\n }\n for (const price of priceSnapshots) {\n trackVariant(price.variantId)\n trackProduct(price.productId)\n }\n\n const existingVariants = variantSnapshots.length\n ? await findWithDecryption(em, CatalogProductVariant, { id: { $in: variantSnapshots.map((entry) => entry.id) } }, {}, scope)\n : []\n const existingPrices = priceSnapshots.length\n ? await findWithDecryption(em, CatalogProductPrice, { id: { $in: priceSnapshots.map((entry) => entry.id) } }, {}, scope)\n : []\n const existingConversions = conversionSnapshots.length\n ? await findWithDecryption(\n em,\n CatalogProductUnitConversion,\n { id: { $in: conversionSnapshots.map((entry) => entry.id) } },\n {},\n scope,\n )\n : []\n const existingTemplate = templateSnapshot\n ? await findOneWithDecryption(em, CatalogOptionSchemaTemplate, { id: templateSnapshot.id }, {}, scope)\n : null\n const foreignVariants = foreignVariantIds.size\n ? await findWithDecryption(\n em,\n CatalogProductVariant,\n { id: { $in: Array.from(foreignVariantIds) }, tenantId: owner.tenantId, organizationId: owner.organizationId },\n {},\n scope,\n )\n : []\n const foreignProducts = foreignProductIds.size\n ? await findWithDecryption(\n em,\n CatalogProduct,\n { id: { $in: Array.from(foreignProductIds) }, tenantId: owner.tenantId, organizationId: owner.organizationId },\n {},\n scope,\n )\n : []\n\n for (const variant of existingVariants) {\n if (!sameScope(variant, owner) || refId(variant.product) !== owner.id) throw restoreConflict('variant', variant.id)\n }\n for (const conversion of existingConversions) {\n if (!sameScope(conversion, owner) || refId(conversion.product) !== owner.id) {\n throw restoreConflict('unit conversion', conversion.id)\n }\n }\n for (const price of existingPrices) {\n if (!sameScope(price, owner) || !priceOwned({ variantId: refId(price.variant), productId: refId(price.product) })) {\n throw restoreConflict('price', price.id)\n }\n }\n if (existingTemplate && !sameScope(existingTemplate, owner)) {\n throw restoreConflict('option schema', existingTemplate.id)\n }\n\n const existingVariantIds = new Set(existingVariants.map((entry) => entry.id))\n const existingPriceIds = new Set(existingPrices.map((entry) => entry.id))\n const existingConversionIds = new Set(existingConversions.map((entry) => entry.id))\n const availableForeignVariantIds = new Set(foreignVariants.map((entry) => entry.id))\n const availableForeignProductIds = new Set(foreignProducts.map((entry) => entry.id))\n const variantAvailable = (id: string | null) =>\n id === null || ownVariantIds.has(id) || availableForeignVariantIds.has(id)\n const productAvailable = (id: string | null) =>\n id === null || id === owner.id || availableForeignProductIds.has(id)\n\n return {\n optionSchemaTemplate: templateSnapshot && !existingTemplate ? templateSnapshot : null,\n unitConversions: conversionSnapshots.filter((entry) => !existingConversionIds.has(entry.id)),\n variants: variantSnapshots.filter((entry) => !existingVariantIds.has(entry.id)),\n prices: priceSnapshots\n .filter(\n (entry) =>\n !existingPriceIds.has(entry.id) && variantAvailable(entry.variantId) && productAvailable(entry.productId),\n )\n .map((entry) => ({ ...entry, offerId: entry.offerId && offerIds.has(entry.offerId) ? entry.offerId : null })),\n }\n}\n\nexport function restoreProductOptionSchemaTemplate(\n em: EntityManager,\n owner: ProductDeleteOwner,\n plan: ProductDeleteChildrenRestorePlan | null,\n): void {\n const snapshot = plan?.optionSchemaTemplate\n if (!snapshot) return\n const template = em.create(CatalogOptionSchemaTemplate, {\n id: snapshot.id,\n organizationId: owner.organizationId,\n tenantId: owner.tenantId,\n name: snapshot.name,\n code: snapshot.code,\n description: snapshot.description ?? null,\n schema: cloneJson(snapshot.schema),\n metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,\n isActive: snapshot.isActive,\n createdAt: new Date(snapshot.createdAt),\n updatedAt: new Date(snapshot.updatedAt),\n deletedAt: toDate(snapshot.deletedAt),\n })\n em.persist(template)\n}\n\n/**\n * Child rows are created on a fork that shares the undo transaction instead of on the\n * EntityManager holding the restored product: the tenant encryption subscriber walks the\n * loaded graph of every created entity, which is quadratic once a product has hundreds of\n * prices attached to already-managed variants.\n */\nexport function buildProductDeleteChildrenRestorePhases(\n em: EntityManager,\n owner: ProductDeleteOwner,\n plan: ProductDeleteChildrenRestorePlan | null,\n): Array<() => Promise<void>> {\n if (!plan) return []\n const scope = { organizationId: owner.organizationId, tenantId: owner.tenantId }\n let childEm: EntityManager | null = null\n const resolveChildEm = (): EntityManager => {\n childEm ??= em.fork({ keepTransactionContext: true })\n return childEm\n }\n return [\n async () => {\n const target = resolveChildEm()\n for (const snapshot of plan.unitConversions) {\n target.persist(\n target.create(CatalogProductUnitConversion, {\n id: snapshot.id,\n ...scope,\n product: target.getReference(CatalogProduct, snapshot.productId),\n unitCode: snapshot.unitCode,\n toBaseFactor: snapshot.toBaseFactor,\n sortOrder: snapshot.sortOrder,\n isActive: snapshot.isActive,\n metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,\n createdAt: new Date(snapshot.createdAt),\n updatedAt: new Date(snapshot.updatedAt),\n deletedAt: toDate(snapshot.deletedAt),\n }),\n )\n }\n await target.flush()\n },\n async () => {\n const target = resolveChildEm()\n for (const snapshot of plan.variants) {\n target.persist(\n target.create(CatalogProductVariant, {\n id: snapshot.id,\n ...scope,\n product: target.getReference(CatalogProduct, snapshot.productId),\n name: snapshot.name ?? null,\n sku: snapshot.sku ?? null,\n barcode: snapshot.barcode ?? null,\n gtinType: snapshot.gtinType ?? null,\n hsCode: snapshot.hsCode ?? null,\n statusEntryId: snapshot.statusEntryId ?? null,\n isDefault: snapshot.isDefault,\n isActive: snapshot.isActive,\n weightValue: snapshot.weightValue ?? null,\n weightUnit: snapshot.weightUnit ?? null,\n dimensions: snapshot.dimensions ? cloneJson(snapshot.dimensions) : null,\n metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,\n taxRateId: snapshot.taxRateId ?? null,\n taxRate: snapshot.taxRate ?? null,\n optionValues: snapshot.optionValues ? cloneJson(snapshot.optionValues) : null,\n defaultMediaId: snapshot.defaultMediaId ?? null,\n defaultMediaUrl: snapshot.defaultMediaUrl ?? null,\n customFieldsetCode: snapshot.customFieldsetCode ?? null,\n createdAt: new Date(snapshot.createdAt),\n updatedAt: new Date(snapshot.updatedAt),\n deletedAt: toDate(snapshot.deletedAt),\n }),\n )\n }\n await target.flush()\n },\n async () => {\n const target = resolveChildEm()\n for (const snapshot of plan.prices) {\n target.persist(\n target.create(CatalogProductPrice, {\n id: snapshot.id,\n ...scope,\n variant: snapshot.variantId ? target.getReference(CatalogProductVariant, snapshot.variantId) : null,\n product: snapshot.productId ? target.getReference(CatalogProduct, snapshot.productId) : null,\n offer: snapshot.offerId ? target.getReference(CatalogOffer, snapshot.offerId) : null,\n priceKind: target.getReference(CatalogPriceKind, snapshot.priceKindId),\n currencyCode: snapshot.currencyCode,\n kind: snapshot.kind,\n minQuantity: snapshot.minQuantity,\n maxQuantity: snapshot.maxQuantity ?? null,\n unitPriceNet: snapshot.unitPriceNet ?? null,\n unitPriceGross: snapshot.unitPriceGross ?? null,\n taxRate: snapshot.taxRate ?? null,\n taxAmount: snapshot.taxAmount ?? null,\n channelId: snapshot.channelId ?? null,\n userId: snapshot.userId ?? null,\n userGroupId: snapshot.userGroupId ?? null,\n customerId: snapshot.customerId ?? null,\n customerGroupId: snapshot.customerGroupId ?? null,\n metadata: snapshot.metadata ? cloneJson(snapshot.metadata) : null,\n startsAt: toDate(snapshot.startsAt),\n endsAt: toDate(snapshot.endsAt),\n createdAt: new Date(snapshot.createdAt),\n updatedAt: new Date(snapshot.updatedAt),\n }),\n )\n }\n await target.flush()\n },\n ]\n}\n\nexport async function emitProductDeleteChildrenRestoreSideEffects(opts: {\n ctx: CommandRuntimeContext\n dataEngine: DataEngine\n owner: ProductDeleteOwner\n children: ProductDeleteChildrenSnapshot | null | undefined\n plan: ProductDeleteChildrenRestorePlan | null\n}): Promise<void> {\n const { ctx, dataEngine, owner, children, plan } = opts\n const variants = asList(children?.variants)\n const createdVariantIds = new Set(asList(plan?.variants).map((variant) => variant.id))\n for (const variant of variants) {\n if (!variant.custom || !Object.keys(variant.custom).length) continue\n await setCustomFieldsIfAny({\n dataEngine,\n entityId: E.catalog.catalog_product_variant,\n recordId: variant.id,\n organizationId: owner.organizationId,\n tenantId: owner.tenantId,\n values: variant.custom,\n })\n }\n for (const variant of variants) {\n await emitCatalogQueryIndexEvent(ctx, {\n entityType: E.catalog.catalog_product_variant,\n recordId: variant.id,\n organizationId: owner.organizationId,\n tenantId: owner.tenantId,\n action: 'created',\n ...(createdVariantIds.has(variant.id) ? {} : { coverageBaseDelta: 0 }),\n })\n }\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,+BAA+B;AACxC,SAAS,4BAA4B;AAGrC,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,WAAW,kCAAkC;AAsGtD,SAAS,MAAM,KAA+B;AAC5C,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,OAAO,QAAQ,WAAW,MAAM,IAAI;AAC7C;AAEA,SAAS,MAAM,OAA+C;AAC5D,SAAO,QAAQ,MAAM,YAAY,IAAI;AACvC;AAEA,SAAS,OAAO,OAA+C;AAC7D,SAAO,QAAQ,IAAI,KAAK,KAAK,IAAI;AACnC;AAEO,SAAS,mCACd,UACyC;AACzC,MAAI,CAAC,YAAY,OAAO,aAAa,SAAU,QAAO;AACtD,QAAM,WAAW,SAAS;AAC1B,MAAI,CAAC,YAAY,OAAO,aAAa,SAAU,QAAO;AACtD,QAAM,SAAU,SAAqC;AACrD,SAAO,WAAW;AACpB;AAEA,eAAsB,6BACpB,IACA,OACwC;AACxC,QAAM,QAAQ,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAC/E,QAAM,iBAAiB,MAAM,mBAAmB,IAAI,uBAAuB,EAAE,SAAS,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK;AAC3G,QAAM,aAAa,eAAe,IAAI,CAAC,YAAY,QAAQ,EAAE;AAC7D,QAAM,eAAe,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,IACA,WAAW,SAAS,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,GAAG,EAAE,SAAS,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,MAAM,GAAG;AAAA,IAC7G,CAAC;AAAA,IACD;AAAA,EACF;AACA,QAAM,oBAAoB,MAAM,mBAAmB,IAAI,8BAA8B,EAAE,SAAS,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK;AACrH,QAAM,WAAW,MAAM,iBACnB,MAAM,sBAAsB,IAAI,6BAA6B,EAAE,IAAI,MAAM,eAAe,GAAG,CAAC,GAAG,KAAK,IACpG;AACJ,QAAM,WAA2C,CAAC;AAClD,aAAW,WAAW,gBAAgB;AACpC,UAAM,SAAS,MAAM,wBAAwB,IAAI;AAAA,MAC/C,UAAU,EAAE,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ;AAAA,IAC1B,CAAC;AACD,aAAS,KAAK;AAAA,MACZ,IAAI,QAAQ;AAAA,MACZ,WAAW,MAAM,QAAQ,OAAO,KAAK,MAAM;AAAA,MAC3C,MAAM,QAAQ,QAAQ;AAAA,MACtB,KAAK,QAAQ,OAAO;AAAA,MACpB,SAAS,QAAQ,WAAW;AAAA,MAC5B,UAAU,QAAQ,YAAY;AAAA,MAC9B,QAAQ,QAAQ,UAAU;AAAA,MAC1B,eAAe,QAAQ,iBAAiB;AAAA,MACxC,WAAW,QAAQ;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ,eAAe;AAAA,MACpC,YAAY,QAAQ,cAAc;AAAA,MAClC,YAAY,QAAQ,aAAa,UAAU,QAAQ,UAAU,IAAI;AAAA,MACjE,UAAU,QAAQ,WAAW,UAAU,QAAQ,QAAQ,IAAI;AAAA,MAC3D,WAAW,QAAQ,aAAa;AAAA,MAChC,SAAS,QAAQ,WAAW;AAAA,MAC5B,cAAc,QAAQ,eAAe,UAAU,QAAQ,YAAY,IAAI;AAAA,MACvE,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,iBAAiB,QAAQ,mBAAmB;AAAA,MAC5C,oBAAoB,QAAQ,sBAAsB;AAAA,MAClD,WAAW,QAAQ,UAAU,YAAY;AAAA,MACzC,WAAW,QAAQ,UAAU,YAAY;AAAA,MACzC,WAAW,MAAM,QAAQ,SAAS;AAAA,MAClC,QAAQ,OAAO,KAAK,MAAM,EAAE,SAAS,SAAS;AAAA,IAChD,CAAC;AAAA,EACH;AACA,QAAM,SAAuC,CAAC;AAC9C,aAAW,SAAS,cAAc;AAChC,UAAM,cAAc,MAAM,MAAM,SAAS;AACzC,QAAI,CAAC,YAAa,OAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE,oBAAoB;AAC1F,WAAO,KAAK;AAAA,MACV,IAAI,MAAM;AAAA,MACV,WAAW,MAAM,MAAM,OAAO;AAAA,MAC9B,WAAW,MAAM,MAAM,OAAO;AAAA,MAC9B,SAAS,MAAM,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA,cAAc,MAAM;AAAA,MACpB,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB,aAAa,MAAM,eAAe;AAAA,MAClC,cAAc,MAAM,gBAAgB;AAAA,MACpC,gBAAgB,MAAM,kBAAkB;AAAA,MACxC,SAAS,MAAM,WAAW;AAAA,MAC1B,WAAW,MAAM,aAAa;AAAA,MAC9B,WAAW,MAAM,aAAa;AAAA,MAC9B,QAAQ,MAAM,UAAU;AAAA,MACxB,aAAa,MAAM,eAAe;AAAA,MAClC,YAAY,MAAM,cAAc;AAAA,MAChC,iBAAiB,MAAM,mBAAmB;AAAA,MAC1C,UAAU,MAAM,WAAW,UAAU,MAAM,QAAQ,IAAI;AAAA,MACvD,UAAU,MAAM,MAAM,QAAQ;AAAA,MAC9B,QAAQ,MAAM,MAAM,MAAM;AAAA,MAC1B,WAAW,MAAM,UAAU,YAAY;AAAA,MACvC,WAAW,MAAM,UAAU,YAAY;AAAA,IACzC,CAAC;AAAA,EACH;AACA,QAAM,kBAAyD,kBAAkB,IAAI,CAAC,gBAAgB;AAAA,IACpG,IAAI,WAAW;AAAA,IACf,WAAW,MAAM,WAAW,OAAO,KAAK,MAAM;AAAA,IAC9C,UAAU,WAAW;AAAA,IACrB,cAAc,WAAW;AAAA,IACzB,WAAW,WAAW;AAAA,IACtB,UAAU,WAAW;AAAA,IACrB,UAAU,WAAW,WAAW,UAAU,WAAW,QAAQ,IAAI;AAAA,IACjE,WAAW,WAAW,UAAU,YAAY;AAAA,IAC5C,WAAW,WAAW,UAAU,YAAY;AAAA,IAC5C,WAAW,MAAM,WAAW,SAAS;AAAA,EACvC,EAAE;AACF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAsB,mCAAmC,QAAQ,IAC7D;AAAA,MACE,IAAI,SAAS;AAAA,MACb,MAAM,SAAS;AAAA,MACf,MAAM,SAAS;AAAA,MACf,aAAa,SAAS,eAAe;AAAA,MACrC,QAAQ,UAAU,SAAS,MAAM;AAAA,MACjC,UAAU,SAAS,WAAW,UAAU,SAAS,QAAQ,IAAI;AAAA,MAC7D,UAAU,SAAS;AAAA,MACnB,WAAW,SAAS,UAAU,YAAY;AAAA,MAC1C,WAAW,SAAS,UAAU,YAAY;AAAA,MAC1C,WAAW,MAAM,SAAS,SAAS;AAAA,IACrC,IACA;AAAA,EACN;AACF;AAEA,SAAS,gBAAgB,MAAc,IAAmB;AACxD,SAAO,IAAI,MAAM,6CAA6C,IAAI,IAAI,EAAE,8CAA8C;AACxH;AAEA,SAAS,UAAU,KAAmD,OAAoC;AACxG,SAAO,IAAI,aAAa,MAAM,YAAY,IAAI,mBAAmB,MAAM;AACzE;AAEA,SAAS,OAAU,OAAoC;AACrD,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AACzC;AAEA,eAAsB,iCACpB,IACA,OACA,UACkD;AAClD,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,QAAQ,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAC/E,QAAM,mBAAmB,OAAO,SAAS,QAAQ;AACjD,QAAM,iBAAiB,OAAO,SAAS,MAAM;AAC7C,QAAM,sBAAsB,OAAO,SAAS,eAAe;AAC3D,QAAM,mBACJ,SAAS,wBAAwB,SAAS,qBAAqB,OAAO,MAAM,iBACxE,SAAS,uBACT;AACN,QAAM,gBAAgB,IAAI,IAAI,iBAAiB,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;AAC3E,QAAM,WAAW,IAAI,IAAI,MAAM,QAAQ;AAEvC,QAAM,aAAa,CAAC,UACjB,MAAM,cAAc,QAAQ,cAAc,IAAI,MAAM,SAAS,KAAM,MAAM,cAAc,MAAM;AAEhG,aAAW,WAAW,kBAAkB;AACtC,QAAI,QAAQ,cAAc,MAAM,GAAI,OAAM,gBAAgB,WAAW,QAAQ,EAAE;AAAA,EACjF;AACA,aAAW,cAAc,qBAAqB;AAC5C,QAAI,WAAW,cAAc,MAAM,GAAI,OAAM,gBAAgB,mBAAmB,WAAW,EAAE;AAAA,EAC/F;AACA,aAAW,SAAS,gBAAgB;AAClC,QAAI,CAAC,WAAW,KAAK,EAAG,OAAM,gBAAgB,SAAS,MAAM,EAAE;AAAA,EACjE;AAEA,QAAM,oBAAoB,oBAAI,IAAY;AAC1C,QAAM,oBAAoB,oBAAI,IAAY;AAC1C,QAAM,eAAe,CAAC,OAAsB;AAC1C,QAAI,MAAM,CAAC,cAAc,IAAI,EAAE,EAAG,mBAAkB,IAAI,EAAE;AAAA,EAC5D;AACA,QAAM,eAAe,CAAC,OAAsB;AAC1C,QAAI,MAAM,OAAO,MAAM,GAAI,mBAAkB,IAAI,EAAE;AAAA,EACrD;AACA,aAAW,SAAS,gBAAgB;AAClC,iBAAa,MAAM,SAAS;AAC5B,iBAAa,MAAM,SAAS;AAAA,EAC9B;AAEA,QAAM,mBAAmB,iBAAiB,SACtC,MAAM,mBAAmB,IAAI,uBAAuB,EAAE,IAAI,EAAE,KAAK,iBAAiB,IAAI,CAAC,UAAU,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,KAAK,IACzH,CAAC;AACL,QAAM,iBAAiB,eAAe,SAClC,MAAM,mBAAmB,IAAI,qBAAqB,EAAE,IAAI,EAAE,KAAK,eAAe,IAAI,CAAC,UAAU,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,KAAK,IACrH,CAAC;AACL,QAAM,sBAAsB,oBAAoB,SAC5C,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,IAAI,EAAE,KAAK,oBAAoB,IAAI,CAAC,UAAU,MAAM,EAAE,EAAE,EAAE;AAAA,IAC5D,CAAC;AAAA,IACD;AAAA,EACF,IACA,CAAC;AACL,QAAM,mBAAmB,mBACrB,MAAM,sBAAsB,IAAI,6BAA6B,EAAE,IAAI,iBAAiB,GAAG,GAAG,CAAC,GAAG,KAAK,IACnG;AACJ,QAAM,kBAAkB,kBAAkB,OACtC,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,IAAI,EAAE,KAAK,MAAM,KAAK,iBAAiB,EAAE,GAAG,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,IAC7G,CAAC;AAAA,IACD;AAAA,EACF,IACA,CAAC;AACL,QAAM,kBAAkB,kBAAkB,OACtC,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,IAAI,EAAE,KAAK,MAAM,KAAK,iBAAiB,EAAE,GAAG,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,IAC7G,CAAC;AAAA,IACD;AAAA,EACF,IACA,CAAC;AAEL,aAAW,WAAW,kBAAkB;AACtC,QAAI,CAAC,UAAU,SAAS,KAAK,KAAK,MAAM,QAAQ,OAAO,MAAM,MAAM,GAAI,OAAM,gBAAgB,WAAW,QAAQ,EAAE;AAAA,EACpH;AACA,aAAW,cAAc,qBAAqB;AAC5C,QAAI,CAAC,UAAU,YAAY,KAAK,KAAK,MAAM,WAAW,OAAO,MAAM,MAAM,IAAI;AAC3E,YAAM,gBAAgB,mBAAmB,WAAW,EAAE;AAAA,IACxD;AAAA,EACF;AACA,aAAW,SAAS,gBAAgB;AAClC,QAAI,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC,WAAW,EAAE,WAAW,MAAM,MAAM,OAAO,GAAG,WAAW,MAAM,MAAM,OAAO,EAAE,CAAC,GAAG;AACjH,YAAM,gBAAgB,SAAS,MAAM,EAAE;AAAA,IACzC;AAAA,EACF;AACA,MAAI,oBAAoB,CAAC,UAAU,kBAAkB,KAAK,GAAG;AAC3D,UAAM,gBAAgB,iBAAiB,iBAAiB,EAAE;AAAA,EAC5D;AAEA,QAAM,qBAAqB,IAAI,IAAI,iBAAiB,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AAC5E,QAAM,mBAAmB,IAAI,IAAI,eAAe,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACxE,QAAM,wBAAwB,IAAI,IAAI,oBAAoB,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AAClF,QAAM,6BAA6B,IAAI,IAAI,gBAAgB,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACnF,QAAM,6BAA6B,IAAI,IAAI,gBAAgB,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACnF,QAAM,mBAAmB,CAAC,OACxB,OAAO,QAAQ,cAAc,IAAI,EAAE,KAAK,2BAA2B,IAAI,EAAE;AAC3E,QAAM,mBAAmB,CAAC,OACxB,OAAO,QAAQ,OAAO,MAAM,MAAM,2BAA2B,IAAI,EAAE;AAErE,SAAO;AAAA,IACL,sBAAsB,oBAAoB,CAAC,mBAAmB,mBAAmB;AAAA,IACjF,iBAAiB,oBAAoB,OAAO,CAAC,UAAU,CAAC,sBAAsB,IAAI,MAAM,EAAE,CAAC;AAAA,IAC3F,UAAU,iBAAiB,OAAO,CAAC,UAAU,CAAC,mBAAmB,IAAI,MAAM,EAAE,CAAC;AAAA,IAC9E,QAAQ,eACL;AAAA,MACC,CAAC,UACC,CAAC,iBAAiB,IAAI,MAAM,EAAE,KAAK,iBAAiB,MAAM,SAAS,KAAK,iBAAiB,MAAM,SAAS;AAAA,IAC5G,EACC,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,SAAS,MAAM,WAAW,SAAS,IAAI,MAAM,OAAO,IAAI,MAAM,UAAU,KAAK,EAAE;AAAA,EAChH;AACF;AAEO,SAAS,mCACd,IACA,OACA,MACM;AACN,QAAM,WAAW,MAAM;AACvB,MAAI,CAAC,SAAU;AACf,QAAM,WAAW,GAAG,OAAO,6BAA6B;AAAA,IACtD,IAAI,SAAS;AAAA,IACb,gBAAgB,MAAM;AAAA,IACtB,UAAU,MAAM;AAAA,IAChB,MAAM,SAAS;AAAA,IACf,MAAM,SAAS;AAAA,IACf,aAAa,SAAS,eAAe;AAAA,IACrC,QAAQ,UAAU,SAAS,MAAM;AAAA,IACjC,UAAU,SAAS,WAAW,UAAU,SAAS,QAAQ,IAAI;AAAA,IAC7D,UAAU,SAAS;AAAA,IACnB,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,IACtC,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,IACtC,WAAW,OAAO,SAAS,SAAS;AAAA,EACtC,CAAC;AACD,KAAG,QAAQ,QAAQ;AACrB;AAQO,SAAS,wCACd,IACA,OACA,MAC4B;AAC5B,MAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAM,QAAQ,EAAE,gBAAgB,MAAM,gBAAgB,UAAU,MAAM,SAAS;AAC/E,MAAI,UAAgC;AACpC,QAAM,iBAAiB,MAAqB;AAC1C,gBAAY,GAAG,KAAK,EAAE,wBAAwB,KAAK,CAAC;AACpD,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,YAAY;AACV,YAAM,SAAS,eAAe;AAC9B,iBAAW,YAAY,KAAK,iBAAiB;AAC3C,eAAO;AAAA,UACL,OAAO,OAAO,8BAA8B;AAAA,YAC1C,IAAI,SAAS;AAAA,YACb,GAAG;AAAA,YACH,SAAS,OAAO,aAAa,gBAAgB,SAAS,SAAS;AAAA,YAC/D,UAAU,SAAS;AAAA,YACnB,cAAc,SAAS;AAAA,YACvB,WAAW,SAAS;AAAA,YACpB,UAAU,SAAS;AAAA,YACnB,UAAU,SAAS,WAAW,UAAU,SAAS,QAAQ,IAAI;AAAA,YAC7D,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,YACtC,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,YACtC,WAAW,OAAO,SAAS,SAAS;AAAA,UACtC,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAM,OAAO,MAAM;AAAA,IACrB;AAAA,IACA,YAAY;AACV,YAAM,SAAS,eAAe;AAC9B,iBAAW,YAAY,KAAK,UAAU;AACpC,eAAO;AAAA,UACL,OAAO,OAAO,uBAAuB;AAAA,YACnC,IAAI,SAAS;AAAA,YACb,GAAG;AAAA,YACH,SAAS,OAAO,aAAa,gBAAgB,SAAS,SAAS;AAAA,YAC/D,MAAM,SAAS,QAAQ;AAAA,YACvB,KAAK,SAAS,OAAO;AAAA,YACrB,SAAS,SAAS,WAAW;AAAA,YAC7B,UAAU,SAAS,YAAY;AAAA,YAC/B,QAAQ,SAAS,UAAU;AAAA,YAC3B,eAAe,SAAS,iBAAiB;AAAA,YACzC,WAAW,SAAS;AAAA,YACpB,UAAU,SAAS;AAAA,YACnB,aAAa,SAAS,eAAe;AAAA,YACrC,YAAY,SAAS,cAAc;AAAA,YACnC,YAAY,SAAS,aAAa,UAAU,SAAS,UAAU,IAAI;AAAA,YACnE,UAAU,SAAS,WAAW,UAAU,SAAS,QAAQ,IAAI;AAAA,YAC7D,WAAW,SAAS,aAAa;AAAA,YACjC,SAAS,SAAS,WAAW;AAAA,YAC7B,cAAc,SAAS,eAAe,UAAU,SAAS,YAAY,IAAI;AAAA,YACzE,gBAAgB,SAAS,kBAAkB;AAAA,YAC3C,iBAAiB,SAAS,mBAAmB;AAAA,YAC7C,oBAAoB,SAAS,sBAAsB;AAAA,YACnD,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,YACtC,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,YACtC,WAAW,OAAO,SAAS,SAAS;AAAA,UACtC,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAM,OAAO,MAAM;AAAA,IACrB;AAAA,IACA,YAAY;AACV,YAAM,SAAS,eAAe;AAC9B,iBAAW,YAAY,KAAK,QAAQ;AAClC,eAAO;AAAA,UACL,OAAO,OAAO,qBAAqB;AAAA,YACjC,IAAI,SAAS;AAAA,YACb,GAAG;AAAA,YACH,SAAS,SAAS,YAAY,OAAO,aAAa,uBAAuB,SAAS,SAAS,IAAI;AAAA,YAC/F,SAAS,SAAS,YAAY,OAAO,aAAa,gBAAgB,SAAS,SAAS,IAAI;AAAA,YACxF,OAAO,SAAS,UAAU,OAAO,aAAa,cAAc,SAAS,OAAO,IAAI;AAAA,YAChF,WAAW,OAAO,aAAa,kBAAkB,SAAS,WAAW;AAAA,YACrE,cAAc,SAAS;AAAA,YACvB,MAAM,SAAS;AAAA,YACf,aAAa,SAAS;AAAA,YACtB,aAAa,SAAS,eAAe;AAAA,YACrC,cAAc,SAAS,gBAAgB;AAAA,YACvC,gBAAgB,SAAS,kBAAkB;AAAA,YAC3C,SAAS,SAAS,WAAW;AAAA,YAC7B,WAAW,SAAS,aAAa;AAAA,YACjC,WAAW,SAAS,aAAa;AAAA,YACjC,QAAQ,SAAS,UAAU;AAAA,YAC3B,aAAa,SAAS,eAAe;AAAA,YACrC,YAAY,SAAS,cAAc;AAAA,YACnC,iBAAiB,SAAS,mBAAmB;AAAA,YAC7C,UAAU,SAAS,WAAW,UAAU,SAAS,QAAQ,IAAI;AAAA,YAC7D,UAAU,OAAO,SAAS,QAAQ;AAAA,YAClC,QAAQ,OAAO,SAAS,MAAM;AAAA,YAC9B,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,YACtC,WAAW,IAAI,KAAK,SAAS,SAAS;AAAA,UACxC,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAM,OAAO,MAAM;AAAA,IACrB;AAAA,EACF;AACF;AAEA,eAAsB,4CAA4C,MAMhD;AAChB,QAAM,EAAE,KAAK,YAAY,OAAO,UAAU,KAAK,IAAI;AACnD,QAAM,WAAW,OAAO,UAAU,QAAQ;AAC1C,QAAM,oBAAoB,IAAI,IAAI,OAAO,MAAM,QAAQ,EAAE,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;AACrF,aAAW,WAAW,UAAU;AAC9B,QAAI,CAAC,QAAQ,UAAU,CAAC,OAAO,KAAK,QAAQ,MAAM,EAAE,OAAQ;AAC5D,UAAM,qBAAqB;AAAA,MACzB;AAAA,MACA,UAAU,EAAE,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,MAClB,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH;AACA,aAAW,WAAW,UAAU;AAC9B,UAAM,2BAA2B,KAAK;AAAA,MACpC,YAAY,EAAE,QAAQ;AAAA,MACtB,UAAU,QAAQ;AAAA,MAClB,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,QAAQ;AAAA,MACR,GAAI,kBAAkB,IAAI,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,mBAAmB,EAAE;AAAA,IACtE,CAAC;AAAA,EACH;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -56,6 +56,14 @@ import {
|
|
|
56
56
|
findWithDecryption,
|
|
57
57
|
findOneWithDecryption
|
|
58
58
|
} from "@open-mercato/shared/lib/encryption/find";
|
|
59
|
+
import {
|
|
60
|
+
buildProductDeleteChildrenRestorePhases,
|
|
61
|
+
captureProductDeleteChildren,
|
|
62
|
+
emitProductDeleteChildrenRestoreSideEffects,
|
|
63
|
+
isProductOwnedOptionSchemaTemplate,
|
|
64
|
+
planProductDeleteChildrenRestore,
|
|
65
|
+
restoreProductOptionSchemaTemplate
|
|
66
|
+
} from "./productDeleteChildren.js";
|
|
59
67
|
import { canonicalizeUnitCode } from "../lib/unitCodes.js";
|
|
60
68
|
import {
|
|
61
69
|
resolveCanonicalUnitCode
|
|
@@ -119,6 +127,13 @@ function resolveUnitPriceInput(parsed) {
|
|
|
119
127
|
baseProvided
|
|
120
128
|
};
|
|
121
129
|
}
|
|
130
|
+
const PRODUCT_DELETE_CACHE_ALIASES = [
|
|
131
|
+
"catalog.product",
|
|
132
|
+
"catalog.variant",
|
|
133
|
+
"catalog.price",
|
|
134
|
+
"catalog.product.unit.conversion",
|
|
135
|
+
"catalog.optionschema"
|
|
136
|
+
];
|
|
122
137
|
const productCrudEvents = {
|
|
123
138
|
module: "catalog",
|
|
124
139
|
entity: "product",
|
|
@@ -695,13 +710,6 @@ async function emitProductVariantCleanupSideEffects(opts) {
|
|
|
695
710
|
});
|
|
696
711
|
}
|
|
697
712
|
}
|
|
698
|
-
function isProductOwnedOptionSchemaTemplate(template) {
|
|
699
|
-
if (!template || typeof template === "string") return false;
|
|
700
|
-
const metadata = template.metadata;
|
|
701
|
-
if (!metadata || typeof metadata !== "object") return false;
|
|
702
|
-
const source = metadata.source;
|
|
703
|
-
return source === "product";
|
|
704
|
-
}
|
|
705
713
|
async function resolveOptionSchemaTemplateForRemoval(em, product) {
|
|
706
714
|
const template = product.optionSchemaTemplate;
|
|
707
715
|
if (!isProductOwnedOptionSchemaTemplate(template)) {
|
|
@@ -1663,11 +1671,14 @@ const deleteProductCommand = {
|
|
|
1663
1671
|
const id = requireId(input, "Product id is required");
|
|
1664
1672
|
const em = ctx.container.resolve("em");
|
|
1665
1673
|
const snapshot = await loadProductSnapshot(em, id);
|
|
1666
|
-
if (snapshot) {
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1674
|
+
if (!snapshot) return {};
|
|
1675
|
+
ensureTenantScope(ctx, snapshot.tenantId);
|
|
1676
|
+
ensureOrganizationScope(ctx, snapshot.organizationId);
|
|
1677
|
+
const snapshots = {
|
|
1678
|
+
before: snapshot,
|
|
1679
|
+
children: await captureProductDeleteChildren(em.fork(), snapshot)
|
|
1680
|
+
};
|
|
1681
|
+
return snapshots;
|
|
1671
1682
|
},
|
|
1672
1683
|
async execute(input, ctx) {
|
|
1673
1684
|
const id = requireId(input, "Product id is required");
|
|
@@ -1760,17 +1771,35 @@ const deleteProductCommand = {
|
|
|
1760
1771
|
snapshotBefore: before,
|
|
1761
1772
|
payload: {
|
|
1762
1773
|
undo: {
|
|
1763
|
-
before
|
|
1774
|
+
before,
|
|
1775
|
+
children: snapshots.children ?? null
|
|
1764
1776
|
}
|
|
1765
|
-
}
|
|
1777
|
+
},
|
|
1778
|
+
context: { cacheAliases: [...PRODUCT_DELETE_CACHE_ALIASES] }
|
|
1766
1779
|
};
|
|
1767
1780
|
},
|
|
1768
1781
|
undo: async ({ logEntry, ctx }) => {
|
|
1769
1782
|
const payload = extractUndoPayload(logEntry);
|
|
1770
1783
|
const before = payload?.before;
|
|
1771
1784
|
if (!before) return;
|
|
1785
|
+
ensureTenantScope(ctx, before.tenantId);
|
|
1786
|
+
ensureOrganizationScope(ctx, before.organizationId);
|
|
1772
1787
|
const em = ctx.container.resolve("em").fork();
|
|
1788
|
+
const children = payload?.children ?? null;
|
|
1789
|
+
const owner = {
|
|
1790
|
+
id: before.id,
|
|
1791
|
+
organizationId: before.organizationId,
|
|
1792
|
+
tenantId: before.tenantId,
|
|
1793
|
+
optionSchemaId: before.optionSchemaId ?? null,
|
|
1794
|
+
offerIds: (before.offers ?? []).map((offer) => offer.id)
|
|
1795
|
+
};
|
|
1773
1796
|
let record = await findOneWithDecryption(em, CatalogProduct, { id: before.id });
|
|
1797
|
+
const childrenPlan = await planProductDeleteChildrenRestore(
|
|
1798
|
+
em,
|
|
1799
|
+
owner,
|
|
1800
|
+
children
|
|
1801
|
+
);
|
|
1802
|
+
restoreProductOptionSchemaTemplate(em, owner, childrenPlan);
|
|
1774
1803
|
if (!record) {
|
|
1775
1804
|
record = em.create(CatalogProduct, {
|
|
1776
1805
|
id: before.id,
|
|
@@ -1807,8 +1836,6 @@ const deleteProductCommand = {
|
|
|
1807
1836
|
});
|
|
1808
1837
|
em.persist(record);
|
|
1809
1838
|
}
|
|
1810
|
-
ensureTenantScope(ctx, before.tenantId);
|
|
1811
|
-
ensureOrganizationScope(ctx, before.organizationId);
|
|
1812
1839
|
applyProductSnapshot(em, record, before);
|
|
1813
1840
|
await withAtomicFlush(
|
|
1814
1841
|
em,
|
|
@@ -1816,7 +1843,8 @@ const deleteProductCommand = {
|
|
|
1816
1843
|
() => em.flush(),
|
|
1817
1844
|
() => restoreOffersFromSnapshot(em, record, before.offers),
|
|
1818
1845
|
() => syncCategoryAssignments(em, record, before.categoryIds),
|
|
1819
|
-
() => syncProductTags(em, record, before.tags)
|
|
1846
|
+
() => syncProductTags(em, record, before.tags),
|
|
1847
|
+
...buildProductDeleteChildrenRestorePhases(em, owner, childrenPlan)
|
|
1820
1848
|
],
|
|
1821
1849
|
{ transaction: true }
|
|
1822
1850
|
);
|
|
@@ -1831,6 +1859,13 @@ const deleteProductCommand = {
|
|
|
1831
1859
|
values: before.custom
|
|
1832
1860
|
});
|
|
1833
1861
|
}
|
|
1862
|
+
await emitProductDeleteChildrenRestoreSideEffects({
|
|
1863
|
+
ctx,
|
|
1864
|
+
dataEngine,
|
|
1865
|
+
owner,
|
|
1866
|
+
children,
|
|
1867
|
+
plan: childrenPlan
|
|
1868
|
+
});
|
|
1834
1869
|
await emitProductCrudUndoChange({
|
|
1835
1870
|
dataEngine,
|
|
1836
1871
|
action: "created",
|