@open-mercato/core 0.9.1-develop.7532.1.8eac7e198f → 0.9.1-develop.7536.1.f9a5776a07
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/auth/api/logout.js +8 -5
- package/dist/modules/auth/api/logout.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js +5 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/commands/currencies.js +399 -137
- package/dist/modules/currencies/commands/currencies.js.map +2 -2
- package/dist/modules/currencies/lib/seeds.js +2 -0
- package/dist/modules/currencies/lib/seeds.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +10 -3
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/interactionRestoreDetails.js +75 -0
- package/dist/modules/customers/commands/interactionRestoreDetails.js.map +7 -0
- package/dist/modules/customers/commands/people.js +10 -3
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/api/logout.ts +9 -5
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +5 -1
- package/src/modules/currencies/commands/currencies.ts +475 -168
- package/src/modules/currencies/i18n/de.json +4 -0
- package/src/modules/currencies/i18n/en.json +4 -0
- package/src/modules/currencies/i18n/es.json +4 -0
- package/src/modules/currencies/i18n/ko.json +4 -0
- package/src/modules/currencies/i18n/pl.json +4 -0
- package/src/modules/currencies/lib/seeds.ts +2 -0
- package/src/modules/customers/commands/companies.ts +16 -4
- package/src/modules/customers/commands/interactionRestoreDetails.ts +110 -0
- package/src/modules/customers/commands/people.ts +16 -4
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"currencies.create.title": "Währung erstellen",
|
|
7
7
|
"currencies.currencies.update": "Währung aktualisieren",
|
|
8
8
|
"currencies.edit.title": "Währung bearbeiten",
|
|
9
|
+
"currencies.errors.baseCurrencyUnset": "Wählen Sie stattdessen eine andere Währung als Basiswährung, anstatt sie zu entfernen.",
|
|
10
|
+
"currencies.errors.undoHasRates": "Diese Änderung kann nicht rückgängig gemacht werden, da inzwischen Wechselkurse diese Währung verwenden. Löschen oder deaktivieren Sie diese Wechselkurse zuerst.",
|
|
11
|
+
"currencies.errors.undoWouldClearBase": "Diese Änderung kann nicht rückgängig gemacht werden, da die Organisation sonst keine Basiswährung hätte.",
|
|
9
12
|
"currencies.exchange_rates.update": "Wechselkurs aktualisieren",
|
|
10
13
|
"currencies.fetch.description": "Verwalten Sie den automatischen Abruf von Währungskursen von externen Anbietern",
|
|
11
14
|
"currencies.fetch.disabled": "Deaktiviert",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"currencies.form.field.decimalSeparator": "Dezimaltrennzeichen",
|
|
55
58
|
"currencies.form.field.isActive": "Aktiv",
|
|
56
59
|
"currencies.form.field.isBase": "Basiswährung",
|
|
60
|
+
"currencies.form.field.isBaseLocked": "Dies ist die Basiswährung. Um sie zu ändern, legen Sie eine andere Währung als Basis fest.",
|
|
57
61
|
"currencies.form.field.name": "Währungsname",
|
|
58
62
|
"currencies.form.field.namePlaceholder": "US-Dollar",
|
|
59
63
|
"currencies.form.field.symbol": "Symbol",
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"currencies.create.title": "Create Currency",
|
|
7
7
|
"currencies.currencies.update": "Update currency",
|
|
8
8
|
"currencies.edit.title": "Edit Currency",
|
|
9
|
+
"currencies.errors.baseCurrencyUnset": "Choose another currency as the base instead of clearing it.",
|
|
10
|
+
"currencies.errors.undoHasRates": "This change can't be undone because exchange rates now use this currency. Delete or deactivate those exchange rates first.",
|
|
11
|
+
"currencies.errors.undoWouldClearBase": "This change can't be undone because it would leave the organization without a base currency.",
|
|
9
12
|
"currencies.exchange_rates.update": "Update exchange rate",
|
|
10
13
|
"currencies.fetch.description": "Manage automatic currency exchange rate fetching from external providers",
|
|
11
14
|
"currencies.fetch.disabled": "Disabled",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"currencies.form.field.decimalSeparator": "Decimal Separator",
|
|
55
58
|
"currencies.form.field.isActive": "Active",
|
|
56
59
|
"currencies.form.field.isBase": "Base Currency",
|
|
60
|
+
"currencies.form.field.isBaseLocked": "This is the base currency. To change it, set another currency as the base.",
|
|
57
61
|
"currencies.form.field.name": "Currency Name",
|
|
58
62
|
"currencies.form.field.namePlaceholder": "US Dollar",
|
|
59
63
|
"currencies.form.field.symbol": "Symbol",
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"currencies.create.title": "Crear Moneda",
|
|
7
7
|
"currencies.currencies.update": "Actualizar moneda",
|
|
8
8
|
"currencies.edit.title": "Editar Moneda",
|
|
9
|
+
"currencies.errors.baseCurrencyUnset": "Elija otra moneda como base en lugar de quitarla.",
|
|
10
|
+
"currencies.errors.undoHasRates": "Este cambio no se puede deshacer porque ahora hay tipos de cambio que usan esta moneda. Elimine o desactive primero esos tipos de cambio.",
|
|
11
|
+
"currencies.errors.undoWouldClearBase": "Este cambio no se puede deshacer porque dejaría a la organización sin moneda base.",
|
|
9
12
|
"currencies.exchange_rates.update": "Actualizar tipo de cambio",
|
|
10
13
|
"currencies.fetch.description": "Gestionar la obtención automática de tipos de cambio desde proveedores externos",
|
|
11
14
|
"currencies.fetch.disabled": "Deshabilitado",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"currencies.form.field.decimalSeparator": "Separador Decimal",
|
|
55
58
|
"currencies.form.field.isActive": "Activa",
|
|
56
59
|
"currencies.form.field.isBase": "Moneda Base",
|
|
60
|
+
"currencies.form.field.isBaseLocked": "Esta es la moneda base. Para cambiarla, establezca otra moneda como base.",
|
|
57
61
|
"currencies.form.field.name": "Nombre de Moneda",
|
|
58
62
|
"currencies.form.field.namePlaceholder": "Dólar estadounidense",
|
|
59
63
|
"currencies.form.field.symbol": "Símbolo",
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"currencies.create.title": "통화 생성",
|
|
7
7
|
"currencies.currencies.update": "통화 수정",
|
|
8
8
|
"currencies.edit.title": "통화 편집",
|
|
9
|
+
"currencies.errors.baseCurrencyUnset": "기준 통화를 해제하는 대신 다른 통화를 기준 통화로 선택하세요.",
|
|
10
|
+
"currencies.errors.undoHasRates": "이제 이 통화를 사용하는 환율이 있어 이 변경을 취소할 수 없습니다. 먼저 해당 환율을 삭제하거나 비활성화하세요.",
|
|
11
|
+
"currencies.errors.undoWouldClearBase": "이 변경을 취소하면 조직에 기준 통화가 없게 되므로 취소할 수 없습니다.",
|
|
9
12
|
"currencies.exchange_rates.update": "환율 수정",
|
|
10
13
|
"currencies.fetch.description": "외부 제공업체로부터 자동 환율 가져오기를 관리합니다",
|
|
11
14
|
"currencies.fetch.disabled": "비활성화됨",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"currencies.form.field.decimalSeparator": "소수 구분 기호",
|
|
55
58
|
"currencies.form.field.isActive": "활성",
|
|
56
59
|
"currencies.form.field.isBase": "기준 통화",
|
|
60
|
+
"currencies.form.field.isBaseLocked": "기준 통화입니다. 변경하려면 다른 통화를 기준 통화로 설정하세요.",
|
|
57
61
|
"currencies.form.field.name": "통화 이름",
|
|
58
62
|
"currencies.form.field.namePlaceholder": "미국 달러",
|
|
59
63
|
"currencies.form.field.symbol": "기호",
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"currencies.create.title": "Utwórz Walutę",
|
|
7
7
|
"currencies.currencies.update": "Aktualizuj walutę",
|
|
8
8
|
"currencies.edit.title": "Edytuj Walutę",
|
|
9
|
+
"currencies.errors.baseCurrencyUnset": "Zamiast odznaczać walutę bazową, wybierz inną walutę jako bazową.",
|
|
10
|
+
"currencies.errors.undoHasRates": "Tej zmiany nie można cofnąć, ponieważ kursy wymiany korzystają teraz z tej waluty. Najpierw usuń lub dezaktywuj te kursy wymiany.",
|
|
11
|
+
"currencies.errors.undoWouldClearBase": "Tej zmiany nie można cofnąć, ponieważ organizacja zostałaby bez waluty bazowej.",
|
|
9
12
|
"currencies.exchange_rates.update": "Aktualizuj kurs wymiany",
|
|
10
13
|
"currencies.fetch.description": "Zarządzaj automatycznym pobieraniem kursów walut od zewnętrznych dostawców",
|
|
11
14
|
"currencies.fetch.disabled": "Wyłączony",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"currencies.form.field.decimalSeparator": "Separator Dziesiętny",
|
|
55
58
|
"currencies.form.field.isActive": "Aktywna",
|
|
56
59
|
"currencies.form.field.isBase": "Waluta Bazowa",
|
|
60
|
+
"currencies.form.field.isBaseLocked": "To jest waluta bazowa. Aby ją zmienić, ustaw inną walutę jako bazową.",
|
|
57
61
|
"currencies.form.field.name": "Nazwa Waluty",
|
|
58
62
|
"currencies.form.field.namePlaceholder": "Dolar amerykański",
|
|
59
63
|
"currencies.form.field.symbol": "Symbol",
|
|
@@ -126,6 +126,7 @@ export async function seedExampleCurrencies(em: EntityManager, scope: CurrencySe
|
|
|
126
126
|
for (const entry of existingEntries) {
|
|
127
127
|
existingMap.set(entry.code, entry)
|
|
128
128
|
}
|
|
129
|
+
const hasLiveBase = existingEntries.some((entry) => entry.isBase && !entry.deletedAt)
|
|
129
130
|
|
|
130
131
|
let touched = false
|
|
131
132
|
for (const curr of SEED_CURRENCIES) {
|
|
@@ -143,6 +144,7 @@ export async function seedExampleCurrencies(em: EntityManager, scope: CurrencySe
|
|
|
143
144
|
tenantId: scope.tenantId,
|
|
144
145
|
organizationId: scope.organizationId,
|
|
145
146
|
...curr,
|
|
147
|
+
isBase: curr.isBase && !hasLiveBase,
|
|
146
148
|
createdAt: new Date(),
|
|
147
149
|
updatedAt: new Date(),
|
|
148
150
|
})
|
|
@@ -26,6 +26,12 @@ import {
|
|
|
26
26
|
CustomerPersonProfile,
|
|
27
27
|
CustomerTagAssignment,
|
|
28
28
|
} from '../data/entities'
|
|
29
|
+
import {
|
|
30
|
+
captureInteractionRestoreDetails,
|
|
31
|
+
omitInteractionRestoreDetails,
|
|
32
|
+
restoreInteractionRestoreDetails,
|
|
33
|
+
type InteractionRestoreDetails,
|
|
34
|
+
} from './interactionRestoreDetails'
|
|
29
35
|
import {
|
|
30
36
|
companyCreateSchema,
|
|
31
37
|
companyUpdateSchema,
|
|
@@ -189,7 +195,7 @@ type CompanyInteractionSnapshot = {
|
|
|
189
195
|
updatedAt: Date
|
|
190
196
|
deletedAt: Date | null
|
|
191
197
|
custom?: Record<string, unknown>
|
|
192
|
-
}
|
|
198
|
+
} & InteractionRestoreDetails
|
|
193
199
|
|
|
194
200
|
type CompanySnapshot = {
|
|
195
201
|
entity: {
|
|
@@ -246,7 +252,11 @@ type CompanyUndoPayload = {
|
|
|
246
252
|
after?: CompanySnapshot | null
|
|
247
253
|
}
|
|
248
254
|
|
|
249
|
-
async function loadCompanySnapshot(
|
|
255
|
+
async function loadCompanySnapshot(
|
|
256
|
+
em: EntityManager,
|
|
257
|
+
id: string,
|
|
258
|
+
options: { includeInteractionRestoreDetails?: boolean } = {},
|
|
259
|
+
): Promise<CompanySnapshot | null> {
|
|
250
260
|
const entity = await em.findOne(CustomerEntity, { id, deletedAt: null })
|
|
251
261
|
if (!entity || entity.kind !== 'company') return null
|
|
252
262
|
const profile = await em.findOne(CustomerCompanyProfile, { entity })
|
|
@@ -408,6 +418,7 @@ async function loadCompanySnapshot(em: EntityManager, id: string): Promise<Compa
|
|
|
408
418
|
createdAt: interaction.createdAt,
|
|
409
419
|
updatedAt: interaction.updatedAt,
|
|
410
420
|
deletedAt: interaction.deletedAt ?? null,
|
|
421
|
+
...(options.includeInteractionRestoreDetails ? captureInteractionRestoreDetails(interaction) : {}),
|
|
411
422
|
custom: await loadCustomFieldSnapshot(em, {
|
|
412
423
|
entityId: INTERACTION_ENTITY_ID,
|
|
413
424
|
recordId: interaction.id,
|
|
@@ -998,7 +1009,7 @@ const deleteCompanyCommand: CommandHandler<{ body?: Record<string, unknown>; que
|
|
|
998
1009
|
async prepare(input, ctx) {
|
|
999
1010
|
const id = requireId(input, 'Company id required')
|
|
1000
1011
|
const em = (ctx.container.resolve('em') as EntityManager)
|
|
1001
|
-
const snapshot = await loadCompanySnapshot(em, id)
|
|
1012
|
+
const snapshot = await loadCompanySnapshot(em, id, { includeInteractionRestoreDetails: true })
|
|
1002
1013
|
return snapshot ? { before: snapshot } : {}
|
|
1003
1014
|
},
|
|
1004
1015
|
async execute(input, ctx) {
|
|
@@ -1182,7 +1193,7 @@ const deleteCompanyCommand: CommandHandler<{ body?: Record<string, unknown>; que
|
|
|
1182
1193
|
resourceId: before.entity.id,
|
|
1183
1194
|
tenantId: before.entity.tenantId,
|
|
1184
1195
|
organizationId: before.entity.organizationId,
|
|
1185
|
-
snapshotBefore: before,
|
|
1196
|
+
snapshotBefore: omitInteractionRestoreDetails(before),
|
|
1186
1197
|
payload: {
|
|
1187
1198
|
undo: {
|
|
1188
1199
|
before,
|
|
@@ -1421,6 +1432,7 @@ const deleteCompanyCommand: CommandHandler<{ body?: Record<string, unknown>; que
|
|
|
1421
1432
|
source: interaction.source,
|
|
1422
1433
|
appearanceIcon: interaction.appearanceIcon,
|
|
1423
1434
|
appearanceColor: interaction.appearanceColor,
|
|
1435
|
+
...restoreInteractionRestoreDetails(interaction),
|
|
1424
1436
|
createdAt: interaction.createdAt,
|
|
1425
1437
|
updatedAt: interaction.updatedAt,
|
|
1426
1438
|
deletedAt: interaction.deletedAt,
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { reviveSnapshotDates } from '@open-mercato/shared/lib/commands/undo'
|
|
2
|
+
import type { CustomerInteraction } from '../data/entities'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Interaction columns a Person/Company delete snapshot must carry so that undo can recreate each interaction
|
|
6
|
+
* exactly as it was. Every key is optional because delete logs written before these columns were captured
|
|
7
|
+
* do not contain them.
|
|
8
|
+
*/
|
|
9
|
+
export type InteractionRestoreDetails = {
|
|
10
|
+
externalMessageId?: string | null
|
|
11
|
+
channelProviderKey?: string | null
|
|
12
|
+
channelId?: string | null
|
|
13
|
+
durationMinutes?: number | null
|
|
14
|
+
location?: string | null
|
|
15
|
+
allDay?: boolean | null
|
|
16
|
+
recurrenceRule?: string | null
|
|
17
|
+
recurrenceEnd?: Date | string | null
|
|
18
|
+
participants?: CustomerInteraction['participants']
|
|
19
|
+
reminderMinutes?: number | null
|
|
20
|
+
visibility?: string | null
|
|
21
|
+
linkedEntities?: CustomerInteraction['linkedEntities']
|
|
22
|
+
guestPermissions?: CustomerInteraction['guestPermissions']
|
|
23
|
+
pinned?: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const INTERACTION_RESTORE_DETAIL_KEYS = [
|
|
27
|
+
'externalMessageId',
|
|
28
|
+
'channelProviderKey',
|
|
29
|
+
'channelId',
|
|
30
|
+
'durationMinutes',
|
|
31
|
+
'location',
|
|
32
|
+
'allDay',
|
|
33
|
+
'recurrenceRule',
|
|
34
|
+
'recurrenceEnd',
|
|
35
|
+
'participants',
|
|
36
|
+
'reminderMinutes',
|
|
37
|
+
'visibility',
|
|
38
|
+
'linkedEntities',
|
|
39
|
+
'guestPermissions',
|
|
40
|
+
'pinned',
|
|
41
|
+
] as const satisfies ReadonlyArray<keyof InteractionRestoreDetails>
|
|
42
|
+
|
|
43
|
+
export function captureInteractionRestoreDetails(interaction: CustomerInteraction): Required<InteractionRestoreDetails> {
|
|
44
|
+
return {
|
|
45
|
+
externalMessageId: interaction.externalMessageId ?? null,
|
|
46
|
+
channelProviderKey: interaction.channelProviderKey ?? null,
|
|
47
|
+
channelId: interaction.channelId ?? null,
|
|
48
|
+
durationMinutes: interaction.durationMinutes ?? null,
|
|
49
|
+
location: interaction.location ?? null,
|
|
50
|
+
allDay: interaction.allDay ?? null,
|
|
51
|
+
recurrenceRule: interaction.recurrenceRule ?? null,
|
|
52
|
+
recurrenceEnd: interaction.recurrenceEnd ?? null,
|
|
53
|
+
participants: interaction.participants ?? null,
|
|
54
|
+
reminderMinutes: interaction.reminderMinutes ?? null,
|
|
55
|
+
visibility: interaction.visibility ?? null,
|
|
56
|
+
linkedEntities: interaction.linkedEntities ?? null,
|
|
57
|
+
guestPermissions: interaction.guestPermissions ?? null,
|
|
58
|
+
pinned: interaction.pinned === true,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A delete log written before visibility was captured cannot tell whether an email was private. An email that
|
|
64
|
+
* has an author is restored private: its author still reads it and can share it again. An email without an
|
|
65
|
+
* author keeps the previous behaviour, because a private row without an author is readable and changeable by
|
|
66
|
+
* nobody.
|
|
67
|
+
*/
|
|
68
|
+
function resolveRestoredVisibility(snapshot: { interactionType: string; authorUserId: string | null } & InteractionRestoreDetails): string | null {
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(snapshot, 'visibility')) return snapshot.visibility ?? null
|
|
70
|
+
return snapshot.interactionType === 'email' && snapshot.authorUserId ? 'private' : null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function restoreInteractionRestoreDetails(
|
|
74
|
+
snapshot: { interactionType: string; authorUserId: string | null } & InteractionRestoreDetails,
|
|
75
|
+
) {
|
|
76
|
+
const { recurrenceEnd } = reviveSnapshotDates({ recurrenceEnd: snapshot.recurrenceEnd ?? null }, ['recurrenceEnd'])
|
|
77
|
+
return {
|
|
78
|
+
externalMessageId: snapshot.externalMessageId ?? null,
|
|
79
|
+
channelProviderKey: snapshot.channelProviderKey ?? null,
|
|
80
|
+
channelId: snapshot.channelId ?? null,
|
|
81
|
+
durationMinutes: snapshot.durationMinutes ?? null,
|
|
82
|
+
location: snapshot.location ?? null,
|
|
83
|
+
allDay: snapshot.allDay ?? null,
|
|
84
|
+
recurrenceRule: snapshot.recurrenceRule ?? null,
|
|
85
|
+
recurrenceEnd: recurrenceEnd as Date | null,
|
|
86
|
+
participants: snapshot.participants ?? null,
|
|
87
|
+
reminderMinutes: snapshot.reminderMinutes ?? null,
|
|
88
|
+
visibility: resolveRestoredVisibility(snapshot),
|
|
89
|
+
linkedEntities: snapshot.linkedEntities ?? null,
|
|
90
|
+
guestPermissions: snapshot.guestPermissions ?? null,
|
|
91
|
+
pinned: snapshot.pinned === true,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The delete log's `snapshotBefore` is what the audit log shows; the restore details stay in the undo payload only.
|
|
97
|
+
*/
|
|
98
|
+
export function omitInteractionRestoreDetails<TSnapshot extends { interactions?: ReadonlyArray<InteractionRestoreDetails> }>(
|
|
99
|
+
snapshot: TSnapshot,
|
|
100
|
+
): TSnapshot {
|
|
101
|
+
if (!Array.isArray(snapshot.interactions)) return snapshot
|
|
102
|
+
return {
|
|
103
|
+
...snapshot,
|
|
104
|
+
interactions: snapshot.interactions.map((interaction) => {
|
|
105
|
+
const visible: Record<string, unknown> = { ...interaction }
|
|
106
|
+
for (const key of INTERACTION_RESTORE_DETAIL_KEYS) delete visible[key]
|
|
107
|
+
return visible
|
|
108
|
+
}),
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -24,6 +24,12 @@ import {
|
|
|
24
24
|
CustomerPersonProfile,
|
|
25
25
|
CustomerTagAssignment,
|
|
26
26
|
} from '../data/entities'
|
|
27
|
+
import {
|
|
28
|
+
captureInteractionRestoreDetails,
|
|
29
|
+
omitInteractionRestoreDetails,
|
|
30
|
+
restoreInteractionRestoreDetails,
|
|
31
|
+
type InteractionRestoreDetails,
|
|
32
|
+
} from './interactionRestoreDetails'
|
|
27
33
|
import { resolvePersonCustomFieldRouting, CUSTOMER_ENTITY_ID, PERSON_ENTITY_ID } from '../lib/customFieldRouting'
|
|
28
34
|
import { CustomFieldValue } from '@open-mercato/core/modules/entities/data/entities'
|
|
29
35
|
import {
|
|
@@ -133,7 +139,7 @@ type PersonInteractionSnapshot = {
|
|
|
133
139
|
updatedAt: Date
|
|
134
140
|
deletedAt: Date | null
|
|
135
141
|
custom?: Record<string, unknown>
|
|
136
|
-
}
|
|
142
|
+
} & InteractionRestoreDetails
|
|
137
143
|
|
|
138
144
|
type PersonSnapshot = {
|
|
139
145
|
entity: {
|
|
@@ -380,7 +386,11 @@ function serializePersonSnapshot(
|
|
|
380
386
|
}
|
|
381
387
|
}
|
|
382
388
|
|
|
383
|
-
async function loadPersonSnapshot(
|
|
389
|
+
async function loadPersonSnapshot(
|
|
390
|
+
em: EntityManager,
|
|
391
|
+
entityId: string,
|
|
392
|
+
options: { includeInteractionRestoreDetails?: boolean } = {},
|
|
393
|
+
): Promise<PersonSnapshot | null> {
|
|
384
394
|
const entity = await em.findOne(CustomerEntity, { id: entityId, deletedAt: null })
|
|
385
395
|
if (!entity || entity.kind !== 'person') return null
|
|
386
396
|
const profile = await findOneWithDecryption(
|
|
@@ -455,6 +465,7 @@ async function loadPersonSnapshot(em: EntityManager, entityId: string): Promise<
|
|
|
455
465
|
createdAt: interaction.createdAt,
|
|
456
466
|
updatedAt: interaction.updatedAt,
|
|
457
467
|
deletedAt: interaction.deletedAt ?? null,
|
|
468
|
+
...(options.includeInteractionRestoreDetails ? captureInteractionRestoreDetails(interaction) : {}),
|
|
458
469
|
custom: await loadCustomFieldSnapshot(em, {
|
|
459
470
|
entityId: INTERACTION_ENTITY_ID,
|
|
460
471
|
recordId: interaction.id,
|
|
@@ -1231,7 +1242,7 @@ const deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; quer
|
|
|
1231
1242
|
async prepare(input, ctx) {
|
|
1232
1243
|
const id = requireId(input, 'Person id required')
|
|
1233
1244
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
1234
|
-
const snapshot = await loadPersonSnapshot(em, id)
|
|
1245
|
+
const snapshot = await loadPersonSnapshot(em, id, { includeInteractionRestoreDetails: true })
|
|
1235
1246
|
return snapshot ? { before: snapshot } : {}
|
|
1236
1247
|
},
|
|
1237
1248
|
async execute(input, ctx) {
|
|
@@ -1355,7 +1366,7 @@ const deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; quer
|
|
|
1355
1366
|
resourceId: before.entity.id,
|
|
1356
1367
|
tenantId: before.entity.tenantId,
|
|
1357
1368
|
organizationId: before.entity.organizationId,
|
|
1358
|
-
snapshotBefore: before,
|
|
1369
|
+
snapshotBefore: omitInteractionRestoreDetails(before),
|
|
1359
1370
|
payload: {
|
|
1360
1371
|
undo: {
|
|
1361
1372
|
before,
|
|
@@ -1646,6 +1657,7 @@ const deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; quer
|
|
|
1646
1657
|
source: interaction.source,
|
|
1647
1658
|
appearanceIcon: interaction.appearanceIcon,
|
|
1648
1659
|
appearanceColor: interaction.appearanceColor,
|
|
1660
|
+
...restoreInteractionRestoreDetails(interaction),
|
|
1649
1661
|
createdAt: interaction.createdAt,
|
|
1650
1662
|
updatedAt: interaction.updatedAt,
|
|
1651
1663
|
deletedAt: interaction.deletedAt,
|